2019년 4월 1일 월요일

Wemos D1 mini ESP8266 WiFiClient NonBlocking

Wemos D1 mini : 저렴한 가격 + 작은 크기 + WiFi + Arduino

WiFi 로 Server 에 접속할때 connect 명령에서 최대 5초간 멈춤이 발생한다.
NonBlocking, Asynchronous connect 명령을 만들었다.

해결방법:

esp8266 라이브러리 폴더를 찾는다.
C:/Users/UserID/AppData/Local/Arduino15/packages/esp8266/hardware/esp8266/2.5.0/libraries/ESP8266WiFi/src

1. WiFiClient.h 59line 에 추가.
    int connectAsync(const char* host, uint16_t port);
    int connectCheck();

2. WiFiClient.cpp 182line 에 추가.
    int WiFiClient::connectAsync(const char* host, uint16_t port) {
        IPAddress ip;
        if (!WiFi.hostByName(host, ip, _timeout)) return 0;
        if (_client) {
            stop();
            _client->unref();
            _client = nullptr;
        }
    #if LWIP_VERSION_MAJOR == 1
        netif* interface = ip_route(ip);
        if (!interface) {
            DEBUGV("no route to host\r\n");
            return 0;
        }
    #endif
        tcp_pcb* pcb = tcp_new();
        if (!pcb) return 0;
        if (_localPort > 0)  pcb->local_port = _localPort++;
        _client = new ClientContext(pcb, nullptr, nullptr);
        _client->ref();
        _client->setTimeout(_timeout);
        int res = _client->connectAsync(ip, port);
        if (res == 0) {
            _client->unref();
            _client = nullptr;
            return 0;
        }
        return 1;
    }
    int WiFiClient::connectCheck() {
        int res = _client->connectCheck();
        if (res == 0) return 0;
        if (res == -1) {
            _client->unref();
            _client = nullptr;
            return -1;
        }
        setSync(defaultSync);
        setNoDelay(defaultNoDelay);
        return 1;
    }

3. include/ClientContext.h 147line 에 추가.
    int connectAsync(CONST ip_addr_t* addr, uint16_t port) {
        err_t err = tcp_connect (_pcb, addr, port, &ClientContext::_s_connected);
        if (err != ERR_OK) return 0;
        _op_start_time = millis();
        return 1;
    }
    int connectCheck() {
        if (!_pcb) return -1;
        if (_pcb->state == ESTABLISHED) return 1;
        if (millis() - _op_start_time < _timeout_ms) return 0;
        abort();
        return -1;
    }

4. include/ClientContext.h 수정
    함수
        err_t _connected(struct tcp_pcb *pcb, err_t err)
    
        assert(_connect_pending);
        esp_schedule();
    
        if (_connect_pending) esp_schedule();
    로 변경

사용방법:

    WiFiClient client;
    int rv;
    if (client.connectAsync ("192.168.1.2", 123) == 0) return -1;
    do {
        rv = client.connectCheck ();
        if (rv == -1) return -1;
        if (rv ==  1) break;
        delay (1);
    } while (rv == 0);
    
    len = client.available ();
    if (0 < len) len = client.read (buff, len);
    
    len = client.availableForWrite ();
    if (0 < len) len = client.write (buff, len);

댓글 없음: