From 9b620fda5ed66542b409a101ee961fc80c73efec Mon Sep 17 00:00:00 2001 From: Mit4el Date: Sat, 15 Feb 2025 00:20:44 +0300 Subject: [PATCH] new WiFi async connect --- include/Const.h | 3 + include/utils/WiFiUtils.h | 12 +- src/Main.cpp | 5 +- src/WsServer.cpp | 4 +- .../sensors/ModbusRTUasync/modinfo.json | 3 - src/utils/WiFiUtils.cpp | 452 ++++++++++++++---- tools/patch32_ws.py | 2 +- 7 files changed, 367 insertions(+), 114 deletions(-) diff --git a/include/Const.h b/include/Const.h index ca9718bb..691983f0 100644 --- a/include/Const.h +++ b/include/Const.h @@ -108,6 +108,9 @@ WEB_SOCKETS_FRAME_SIZE создан для того что бы не загру enum TimerTask_t { WIFI_SCAN, WIFI_MQTT_CONNECTION_CHECK, +#ifndef ESP8266 + WIFI_CONN, +#endif TIME, // TIME_SYNC, // не используется // UPTIME, // не используется diff --git a/include/utils/WiFiUtils.h b/include/utils/WiFiUtils.h index 593a39f1..96fed80f 100644 --- a/include/utils/WiFiUtils.h +++ b/include/utils/WiFiUtils.h @@ -4,11 +4,19 @@ #include "MqttClient.h" boolean isNetworkActive(); uint8_t getNumAPClients(); +#ifdef ESP8266 void routerConnect(); -bool startAPMode(); boolean RouterFind(std::vector jArray); +#else +void handleScanResults(); +void WiFiUtilsItit(); +void connectToNextNetwork(); +void checkConnection(); +void ScanAsync(); +bool startAPMode(); +#endif uint8_t RSSIquality(); -extern void wifiSignalInit(); +//extern void wifiSignalInit(); #ifdef LIBRETINY String httpGetString(HTTPClient &http); #endif \ No newline at end of file diff --git a/src/Main.cpp b/src/Main.cpp index cf82ef14..e95706dc 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -200,8 +200,11 @@ void setup() { initErrorMarker(SETUPINET_ERRORMARKER); // подключаемся к роутеру +#ifdef ESP8266 routerConnect(); - +#else + WiFiUtilsItit(); +#endif // инициализация асинхронного веб сервера и веб сокетов #ifdef ASYNC_WEB_SERVER asyncWebServerInit(); diff --git a/src/WsServer.cpp b/src/WsServer.cpp index ad3e6bc5..a711a3ce 100644 --- a/src/WsServer.cpp +++ b/src/WsServer.cpp @@ -61,7 +61,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length) //----------------------------------------------------------------------// if (headerStr == "p|") { standWebSocket.sendTXT(num, "p|"); - Serial.printf("Ping client: %u\n", num); + //Serial.printf("Ping client: %u\n", num); ws_clients[num]=1; } // публикация всех виджетов @@ -175,7 +175,9 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length) if (headerStr == "/scan|") { std::vector jArray; jsonReadArray(settingsFlashJson, "routerssid", jArray); +#ifdef ESP8266 RouterFind(jArray); +#endif sendStringToWs("ssidli", ssidListHeapJson, num); } diff --git a/src/modules/sensors/ModbusRTUasync/modinfo.json b/src/modules/sensors/ModbusRTUasync/modinfo.json index 88afa653..429f6059 100644 --- a/src/modules/sensors/ModbusRTUasync/modinfo.json +++ b/src/modules/sensors/ModbusRTUasync/modinfo.json @@ -98,9 +98,6 @@ "usedLibs": { "esp32*": [ "https://github.com/eModBus/eModBus" - ], - "esp82*": [ - "https://github.com/eModBus/eModBus" ] } } \ No newline at end of file diff --git a/src/utils/WiFiUtils.cpp b/src/utils/WiFiUtils.cpp index 429b5164..7b2c2441 100644 --- a/src/utils/WiFiUtils.cpp +++ b/src/utils/WiFiUtils.cpp @@ -3,17 +3,276 @@ #if defined(ESP32) #include #endif -#define TRIESONE 25 // количество попыток подключения к одной сети из несколких -#define TRIES 40 // количество попыток подключения сети если она одна -/* -IPAddress stringToIp(String strIp) +#define TRIESONE 20 // количество секунд ожидания подключения к одной сети из несколких +#define TRIES 30 // количество секунд ожидания подключения сети если она одна + +#ifndef ESP8266 +std::vector _ssidList; +std::vector _passwordList; +volatile bool scanInProgress = false; +// номер сети, для перебирания в момент подключения к сетям из массива +volatile uint8_t currentNetwork = 0; +volatile bool wifiConnecting = false; +volatile uint8_t connectionAttempts = 0; +//------------------------------------------ +// Обработчики событий Wi-Fi +//------------------------------------------ +void WiFiEvent(arduino_event_t *event) { - IPAddress ip; - ip.fromString(strIp); - return ip; -} */ + switch (event->event_id) + { +#if defined(LIBRETINY) || defined(esp32c6_4mb) || defined(esp32c6_8mb) + case ARDUINO_EVENT_WIFI_STA_CONNECTED: +#else + case SYSTEM_EVENT_STA_CONNECTED: +#endif + // Подключились к STA + SerialPrint("i", "WIFI", "Connected to AP: " + WiFi.SSID()); + // TODO если подключились, но не получили IP что будет? + break; +#if defined(LIBRETINY) || defined(esp32c6_4mb) || defined(esp32c6_8mb) + case ARDUINO_EVENT_WIFI_STA_GOT_IP: +#else + case SYSTEM_EVENT_STA_GOT_IP: +#endif + // Получили IP от роутера + // wifiReconnectTicker.detach(); + ts.remove(WIFI_SCAN); + ts.remove(WIFI_CONN); +#ifdef LIBRETINY + SerialPrint("i", "WIFI", "http://" + ipToString(WiFi.localIP())); + jsonWriteStr(settingsFlashJson, "ip", ipToString(WiFi.localIP())); +#else + SerialPrint("i", "WIFI", "http://" + WiFi.localIP().toString()); + jsonWriteStr(settingsFlashJson, "ip", WiFi.localIP().toString()); +#endif + // запускаем MQTT + mqttInit(); + SerialPrint("i", F("WIFI"), F("Network Init")); + // Отключаем AP при успешном подключении + WiFi.softAPdisconnect(true); + break; +#if defined(LIBRETINY) || defined(esp32c6_4mb) || defined(esp32c6_8mb) + case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: +#else + case SYSTEM_EVENT_STA_DISCONNECTED: +#endif + // Отключились от STA + SerialPrint("i", "WIFI", "Disconnected from STA"); + // Завершаем задачу проверки сети + ts.remove(WIFI_CONN); + if (wifiConnecting) + { // если у нас ещё не закончились попытки подключения, то перезапускаем задачу + Serial.print("."); + checkConnection(); + // wifiReconnectTicker.once_ms(WIFI_CHECK_INTERVAL, checkConnection); + } + else + { // если попытки подключения исчерпаны, то переходим в AP + startAPMode(); + } + break; +#if defined(LIBRETINY) || defined(esp32c6_4mb) || defined(esp32c6_8mb) + case ARDUINO_EVENT_WIFI_SCAN_DONE: +#else + case SYSTEM_EVENT_SCAN_DONE: +#endif + // Завершилось сканирование сетей + Serial.println("Scan completed"); + scanInProgress = false; + handleScanResults(); + break; + } +} +//------------------------------------------ +// Обработка результатов сканирования +//------------------------------------------ +void handleScanResults() +{ + ssidListHeapJson = "{}"; + _ssidList.clear(); + _passwordList.clear(); + jsonReadArray(settingsFlashJson, "routerssid", _ssidList); + jsonReadArray(settingsFlashJson, "routerpass", _passwordList); + int16_t numNetworks = WiFi.scanComplete(); + if (numNetworks <= 0) + { + SerialPrint("i", "WIFI", "no networks found"); + return; + } + + // Ищем известные сети + int connectNumNet = -1; + // SerialPrint("i", "WIFI", "Count found: "+numNetworks); + for (int n = 0; n < numNetworks; ++n) + { + String ssid = WiFi.SSID(n); + jsonWriteStr_(ssidListHeapJson, String(n), ssid); + for (size_t i = 0; i < _ssidList.size(); i++) + { + if (ssid == _ssidList[i]) + { + Serial.printf("Found known network: %s\n", _ssidList[i]); + if (connectNumNet < 0) + connectNumNet = i; + } + } + + // if + } + SerialPrint("i", "WIFI", "Scan Found: " + ssidListHeapJson); + if (connectNumNet >= 0) + { + // ts.remove(WIFI_SCAN); + connectToNextNetwork(); + } + // checkConnection(); + // connectToSTA(_ssidList[connectNumNet], _passwordList[connectNumNet]); + WiFi.scanDelete(); +} + +void WiFiUtilsItit() +{ +#if !defined LIBRETINY +#if defined(esp32c6_4mb) || defined(esp32c6_8mb) + WiFi.setAutoReconnect(false); +#else + WiFi.setAutoConnect(false); +#endif + WiFi.persistent(false); + WiFi.setSleep(true); +#endif + WiFi.mode(WIFI_STA); + WiFi.onEvent(WiFiEvent); + jsonReadArray(settingsFlashJson, "routerssid", _ssidList); + jsonReadArray(settingsFlashJson, "routerpass", _passwordList); + + if (_ssidList.empty() || _passwordList.empty()) + { + SerialPrint("E", "WIFI", "No networks configured"); + startAPMode(); + return; + } + currentNetwork = 0; + connectionAttempts = 0; + connectToNextNetwork(); +} + +void connectToNextNetwork() +{ + // все сети перебрали + if (currentNetwork >= _ssidList.size()) + { + SerialPrint("i", "WIFI", "All networks tried"); + ts.remove(WIFI_CONN); + startAPMode(); + return; + } + + wifiConnecting = true; + // connectionAttempts++; + + const char *ssid = _ssidList[currentNetwork].c_str(); + const char *pass = _passwordList[currentNetwork].c_str(); + // Пробуем подключиться к сети + SerialPrint("i", "WIFI", "Connecting to: " + String(ssid)); + WiFi.begin(ssid, pass); + +#if defined(ESP32) + WiFi.setTxPower(WIFI_POWER_19_5dBm); +#elif defined(ESP8266) + WiFi.setOutputPower(20.5); +#endif + // проверяем статус подключения и перебираем сети если таймаут не вышел + checkConnection(); + + // wifiReconnectTicker.once_ms(WIFI_CHECK_INTERVAL, checkConnection); +} + +void checkConnection() +{ + ts.add( + WIFI_CONN, 1000, + [&](void *) + { + connectionAttempts++; + if (WiFi.status() == WL_CONNECTED) + { + connectionAttempts = 0; + wifiConnecting = false; + return; + } + + if (connectionAttempts >= (_ssidList.size() > 1 ? TRIESONE : TRIES)) + { + SerialPrint("i", "WIFI", "Max attempts reached"); + currentNetwork++; + connectionAttempts = 0; + wifiConnecting = false; + } + + if (wifiConnecting) + { +#ifdef ESP8266 + if (WiFi.status() == WL_CONNECT_FAILED || WiFi.status() == WL_WRONG_PASSWORD) +#else + if (WiFi.status() == WL_CONNECT_FAILED) +#endif + { + SerialPrint("E", "WIFI", "Connection failed, wrong password?"); + jsonWriteInt(errorsHeapJson, "passer", 1); + currentNetwork++; + connectionAttempts = 0; + } + + // wifiReconnectTicker.once_ms(WIFI_CHECK_INTERVAL, checkConnection); + } + + if (!wifiConnecting) + { + connectToNextNetwork(); + } + }, + nullptr, true); +} + +//------------------------------------------ +// Неблокирующее подключение к STA +//------------------------------------------ +void connectToSTA(const char *ssid, const char *pass) +{ + if (isNetworkActive()) + return; + SerialPrint("i", "WIFI", "Connecting to ... " + String(ssid)); + // SerialPrint("i", "WIFI", "pass connect: " + _passwordList[i]); + WiFi.begin(ssid, pass); +#if defined(ESP32) + WiFi.setTxPower(WIFI_POWER_19_5dBm); +#elif defined(ESP8266) + WiFi.setOutputPower(20.5); +#endif +} + +void ScanAsync() +{ + // bool res = false; + int n = WiFi.scanComplete(); + SerialPrint("i", "WIFI", "scan result: " + String(n, DEC)); + + if (n == -1) + { // Сканирование все еще выполняется + SerialPrint("i", "WIFI", "scanning in progress"); + } + else + { + SerialPrint("i", "WIFI", "start scanning"); + WiFi.scanNetworks(true, false); + } +} +#else +// ESP8266 void routerConnect() { #if !defined LIBRETINY @@ -126,9 +385,14 @@ void routerConnect() } SerialPrint("i", F("WIFI"), F("Network Init")); } - +#endif bool startAPMode() { +#ifndef ESP8266 + wifiConnecting = false; + currentNetwork = 0; + connectionAttempts = 0; +#endif SerialPrint("i", "WIFI", "AP Mode"); WiFi.disconnect(); @@ -137,9 +401,9 @@ bool startAPMode() String _ssidAP = jsonReadStr(settingsFlashJson, "apssid"); String _passwordAP = jsonReadStr(settingsFlashJson, "appass"); if (_passwordAP == "") - WiFi.softAP(_ssidAP.c_str()); + WiFi.softAP(_ssidAP.c_str(), NULL, 6); else - WiFi.softAP(_ssidAP.c_str(), _passwordAP.c_str()); + WiFi.softAP(_ssidAP.c_str(), _passwordAP.c_str(), 6); IPAddress myIP = WiFi.softAPIP(); #ifdef LIBRETINY SerialPrint("i", "WIFI", "AP IP: " + ipToString(myIP)); @@ -154,6 +418,7 @@ bool startAPMode() WIFI_SCAN, 30 * 1000, [&](void *) { +#ifdef ESP8266 std::vector jArray; jsonReadArray(settingsFlashJson, "routerssid", jArray); for (int8_t i = 0; i < jArray.size(); i++) @@ -166,59 +431,16 @@ bool startAPMode() WiFi.scanDelete(); routerConnect(); } +#else + ScanAsync(); +#endif }, nullptr, true); } return true; } -#if defined (LIBRETINY) -boolean RouterFind(std::vector jArray) -{ - bool res = false; - int n = WiFi.scanComplete(); - SerialPrint("i", "WIFI", "scan result: " + String(n, DEC)); - if (n == -2) - { // Сканирование не было запущено, запускаем - SerialPrint("i", "WIFI", "start scanning"); - n = WiFi.scanNetworks(false, false); // async, show_hidden - SerialPrint("i", "WIFI", "scan result: " + String(n, DEC)); - } - - else if (n == -1) - { // Сканирование все еще выполняется - SerialPrint("i", "WIFI", "scanning in progress"); - } - - else if (n == 0) - { // ни одна сеть не найдена - SerialPrint("i", "WIFI", "no networks found"); - n = WiFi.scanNetworks(false, false); - SerialPrint("i", "WIFI", "scan result: " + String(n, DEC)); - } - - if (n > 0) - { - for (int8_t i = 0; i < n; i++) - { - for (int8_t k = 0; k < jArray.size(); k++) - { - if (WiFi.SSID(i) == jArray[k]) - { - res = true; - } - } - // SerialPrint("i", "WIFI", (res ? "*" : "") + String(i, DEC) + ") " + WiFi.SSID(i)); - jsonWriteStr_(ssidListHeapJson, String(i), WiFi.SSID(i)); - - // String(WiFi.RSSI(i) - } - } - SerialPrint("i", "WIFI", ssidListHeapJson); - WiFi.scanDelete(); - return res; -} -#elif defined (ESP8266) || defined (ESP32) +#if defined(ESP8266) boolean RouterFind(std::vector jArray) { bool res = false; @@ -264,67 +486,85 @@ boolean RouterFind(std::vector jArray) } #endif -boolean isNetworkActive() { - return WiFi.status() == WL_CONNECTED; +boolean isNetworkActive() +{ + return WiFi.status() == WL_CONNECTED; } -uint8_t getNumAPClients() { - return WiFi.softAPgetStationNum(); +uint8_t getNumAPClients() +{ + return WiFi.softAPgetStationNum(); } -uint8_t RSSIquality() { - uint8_t res = 0; - if (isNetworkActive()) { - int rssi = WiFi.RSSI(); - if (rssi >= -50) { - res = 6; //"Excellent"; - } else if (rssi < -50 && rssi >= -60) { - res = 5; //"Very good"; - } else if (rssi < -60 && rssi >= -70) { - res = 4; //"Good"; - } else if (rssi < -70 && rssi >= -80) { - res = 3; //"Low"; - } else if (rssi < -80 && rssi > -100) { - res = 2; //"Very low"; - } else if (rssi <= -100) { - res = 1; //"No signal"; - } +uint8_t RSSIquality() +{ + uint8_t res = 0; + if (isNetworkActive()) + { + int rssi = WiFi.RSSI(); + if (rssi >= -50) + { + res = 6; //"Excellent"; } - return res; + else if (rssi < -50 && rssi >= -60) + { + res = 5; //"Very good"; + } + else if (rssi < -60 && rssi >= -70) + { + res = 4; //"Good"; + } + else if (rssi < -70 && rssi >= -80) + { + res = 3; //"Low"; + } + else if (rssi < -80 && rssi > -100) + { + res = 2; //"Very low"; + } + else if (rssi <= -100) + { + res = 1; //"No signal"; + } + } + return res; } #ifdef LIBRETINY String httpGetString(HTTPClient &http) { - String payload = ""; - int len = http.getSize(); - uint8_t buff[128] = { 0 }; - WiFiClient * stream = http.getStreamPtr(); + String payload = ""; + int len = http.getSize(); + uint8_t buff[128] = {0}; + WiFiClient *stream = http.getStreamPtr(); - // read all data from server - while(http.connected() && (len > 0 || len == -1)) { - // get available data size - size_t size = stream->available(); + // read all data from server + while (http.connected() && (len > 0 || len == -1)) + { + // get available data size + size_t size = stream->available(); - if(size) { - // read up to 128 byte - int c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size)); + if (size) + { + // read up to 128 byte + int c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size)); - // write it to Serial - // Serial.write(buff,c); - - //payload += String((char*)buff); - char charBuff[c + 1]; // Create a character array with space for null terminator - memcpy(charBuff, buff, c); // Copy the data to the character array - charBuff[c] = '\0'; // Null-terminate the character array - payload += String(charBuff); // Append the character array to the payload + // write it to Serial + // Serial.write(buff,c); - if(len > 0) { - len -= c; - } - } - delay(1); - } - return payload; + // payload += String((char*)buff); + char charBuff[c + 1]; // Create a character array with space for null terminator + memcpy(charBuff, buff, c); // Copy the data to the character array + charBuff[c] = '\0'; // Null-terminate the character array + payload += String(charBuff); // Append the character array to the payload + + if (len > 0) + { + len -= c; + } + } + delay(1); + } + return payload; } #endif \ No newline at end of file diff --git a/tools/patch32_ws.py b/tools/patch32_ws.py index 86df29dc..33214618 100644 --- a/tools/patch32_ws.py +++ b/tools/patch32_ws.py @@ -26,7 +26,7 @@ try: oldData = fr.read() if not 'if WIFI_CLIENT_MAX_WRITE_RETRY (10)' in oldData: shutil.copyfile(mainPyPath, mainPyPath+'.bak') - newData = oldData.replace('#define WIFI_CLIENT_MAX_WRITE_RETRY (10)', '#define WIFI_CLIENT_MAX_WRITE_RETRY (2)') + newData = oldData.replace('#define WIFI_CLIENT_MAX_WRITE_RETRY (10)', '#define WIFI_CLIENT_MAX_WRITE_RETRY (5)') newData = newData.replace('#define WIFI_CLIENT_SELECT_TIMEOUT_US (1000000)', '#define WIFI_CLIENT_SELECT_TIMEOUT_US (500000)') with open(mainPyPath, 'w') as fw: fw.write(newData)