Как подружить websocketsserver с esp8266httpclient?

Тема в разделе "ESP8266, ESP32", создана пользователем Vovka, 27 янв 2022.

  1. Vovka

    Vovka Гик

    Суть в следующем: соединение по сокету рвется после http-запроса к сайту.
    Вот создал тестовый пример:
    Код (C++):
    #define W_NAME    "*****"
    #define W_PASSW    "*****"
    #define W_SITE    "test.com"
    #define W_SITE_PORT    80

    #include <Wire.h>
    #include <ESP8266WiFi.h>

    #include <WebSocketsServer.h>
    #include <Hash.h>
    WebSocketsServer webSocket = WebSocketsServer(81);
    void webSocketEvent(uint8_t num                    // IP
                                            , WStype_t type            // тип сообщения
                                            , uint8_t *payload    // сообщение
                                            , size_t length            // длина сообщения
        ) {
        String s;
        switch(type) {
        case WStype_DISCONNECTED: {    Serial.printf("webSocketEvent([%u]): Disconnected!\n", num);    break;    }
            case WStype_CONNECTED: {
                IPAddress ip = webSocket.remoteIP(num);
                Serial.printf("webSocketEvent([%u]): Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);
                webSocket.sendTXT(num, "Connected!!!");    break; }
            case WStype_TEXT:{
                Serial.printf("webSocketEvent([%u]): get Text: %s\n", num, payload);
                if( length>6 && (strcmp((const char *)payload,"ws:ping")==0)){
                    Serial.printf("webSocketEvent([%u]) send Text: %s\n", num, "esp:pong" );
                    webSocket.sendTXT(num, "esp:pong");
                    break;
                }
                // send message to client
                s = "message here: ";    s.concat( (const char *)payload, length );    webSocket.sendTXT(num, s);
    //            webSocket.broadcastTXT("message here");    // send data to all connected clients
                break;
            }
            case WStype_BIN: {
                Serial.printf("webSocketEvent([%u]): get binary length: %u\n", num, length);
                hexdump(payload, length);
                // send message to client
                webSocket.sendBIN(num, payload, length);
                break;
            }
        }
    }

    #include <ESP8266WiFiMulti.h>
    ESP8266WiFiMulti WiFiMulti;
    #include <ESP8266WebServer.h>
    ESP8266WebServer HTTP(80);
    //#include <ESP8266HTTPUpdateServer.h>    // для обновления через WEB
    //ESP8266HTTPUpdateServer httpUpdater;
    #include <ESP8266HTTPClient.h>
    HTTPClient http;

    #include "web.h"
    void handleNotFound(){
        String s;
        s = FPSTR(_htm_test);
        HTTP.send(200, "text/html", s );
    }

    static bool b1sec = false;
    static bool b20sec = false;
    static os_timer_t timer1s;
    static char count20s = 20;
    void timer1s_func()
    {
        b1sec = true;
        if( !b20sec ) {
            if( count20s ) count20s--;
            if( !count20s ) { count20s = 20; b20sec = true; }
        }
    }

    void setup()
    {
        Serial.begin(19200);
        // Serial.setDebugOutput(true);
        Serial.println();
        Serial.println();
        Serial.println();
        for(uint8_t t = 5; t > 0; t--) {
            Serial.printf("[SETUP] WAIT %d...\n", t);
            Serial.flush();
            delay(1000);
        }
        WiFiMulti.addAP( W_NAME, W_PASSW );

        WiFi.config(IPAddress(192, 168, 1, 254), IPAddress(192, 168, 1, 1), IPAddress(255, 255, 255, 0));

        Serial.print( "SETUP(). Go connect router" );
        while( WiFiMulti.run() != WL_CONNECTED ) {
            Serial.print("."); delay(1000);
        }
        Serial.print(" OK. IP="); Serial.println( WiFi.localIP() );

    //    httpUpdater.setup(&HTTP, "/upd", "admin", "admin" ); // для ОТА

        HTTP.onNotFound(handleNotFound);
        // Запускаем HTTP сервер
        HTTP.begin();
        webSocket.begin();
        webSocket.onEvent(webSocketEvent);

        // запустим таймер 1сек
        os_timer_disarm(&timer1s);
        os_timer_setfn(&timer1s, (os_timer_func_t *)&timer1s_func, NULL);
        os_timer_arm(&timer1s, 1000, 1);    // 1000 миллисекунд=1cек, 1 - многократно. 0 -однократно.
    }

    void loop()
    {
        String s;

        // ожидание WiFi соединения
        if( WiFiMulti.run() == WL_CONNECTED ) {
            HTTP.handleClient();
            webSocket.loop();
            if( b1sec ) {
                time_t t;
                tm *pt;
                t = time(nullptr);    pt = localtime(&t);
                s  = String( pt->tm_hour ); s += ":";
                s += String( pt->tm_min  ); s += ":";
                s += String( pt->tm_sec  ); s += " ";
                s += String( pt->tm_mday ); s += ".";
                s += String( pt->tm_mon+1); s += ".";
                s += String( pt->tm_year );
                webSocket.broadcastTXT( s ); // все подключившимся
                Serial.println( s );
                b1sec = false;
            }
            if( b20sec ) {
                Serial.print("[HTTP] begin...\n");
                if( http.begin( W_SITE, W_SITE_PORT, "/esp.php") ) {
                    Serial.print("[HTTP] GET...\n");
                    int httpCode = http.GET();
                    if( httpCode ) {
                        // HTTP header has been send and Server response header has been handled
                        Serial.printf("[HTTP] GET... code: %d\n", httpCode);
                        // файл найден на сервере
                        if( httpCode == 200 ) {
                            String payload = http.getString();
                            Serial.println( payload );
                            webSocket.broadcastTXT( payload );
                        }
                    } else {
                        Serial.print("[HTTP] GET... failed, no connection or no HTTP server\n");
                    }
                    http.end();
                }
                b20sec = false;
            }
        }

    }
    Код (C++):
    const char _htm_test[] PROGMEM = R"rawliteral(
    <!DOCTYPE HTML><html><head>
    <meta http-equiv='Content-Type' content='text/html; charset=windows-1251'>
    <meta http-equiv='Content-Language' content='ru'>
    <meta name='viewport' content='width=device-width,initial-scale=1'>
    <meta http-equiv='pragma' content='no-cache'>
    <meta http-equiv='cache-control' content='no-cache'>
    <title>TEST</title>
    <script language='javascript'>
    function startWebsocket() {
        var adr='ws://192.168.1.254:81/';
        var connection = new WebSocket(adr);
        var wsstat=-1; //Статус подключения
        var wsp=0;
        var idd=document.getElementById('lans');
        idd.innerHTML='Попытка подключения...';
        function wsping(){
            if(wsstat!=connection.readyState){
                wsstat=connection.readyState;
                switch(wsstat){
                    case 0: idd.innerHTML='Соединение ещё не открыто';break;
                    case 1: idd.innerHTML=''; break;
                    case 2: idd.innerHTML='Соединение в процессе закрытия';break;
                    case 3: idd.innerHTML='Соединение закрыто или не может открыться';break;
                }
            }
            connection.send('ws:ping');
            wsp=setTimeout(wsping, 2500);
        }
        connection.onopen = function () {
            idd.innerHTML='подключено';
            wsp=setTimeout(wsping, 2500);
        };
        connection.onclose = function(evt) {
         if(wsp)clearTimeout(wsp);wsp=0;wsstat=0;
         idd.innerHTML= 'WebSocket CLOSED: ('+evt.code+') '+evt.reason;
         connection=0;setTimeout(startWebsocket, 5000);
        };
        connection.onerror = function (error) {
            idd.innerHTML = 'WebSocket Error: ' + error.message;
        };
        connection.onmessage = function (evt) {
            var data=evt.data;
            if(typeof(data)=='string'&&data!=='esp:pong') idd.innerHTML=data;
            clearTimeout(wsp);wsp=setTimeout(wsping, 2500);
        };
    }
    window.onload=function(){startWebsocket()};
    </script>
    </head><body>
    <h3>T е с т</h3>
    <span id='lans'>&nbsp;</span>
    </body></html>
    )rawliteral"
    ;
    Когда заходим по IP, есп выдает html-страничку, которае делает соединение с есп по сокету. есп раз в секунду (для наглядности) отправляет время-дату.
    Все работает, пока есп не отсчитает 20 секунд (продовал и другое время) и делает http-запрос к сайту в интернете. После этого соединение по сокету обрывается!
    Как это исправить?