• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Как подружить WebSocketsServer с ESP8266HTTPClient?

Vovka

Member
Суть в следующем: соединение по сокету рвется после http-запроса к сайту.
Вот создал тестовый пример:
Код:
#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;
        }
    }

}
Код:
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-запрос к сайту в интернете. После этого соединение по сокету обрывается!
Как это исправить?
 
Сверху Снизу