From bd72075349eb9aaa3fd546b05252e8da2befb9f7 Mon Sep 17 00:00:00 2001 From: Florian <1technophile@users.noreply.github.com> Date: Sat, 28 Mar 2020 20:46:30 -0500 Subject: [PATCH] refactor connection mng on ESP32 and ESP8266 (#575) enable after ATTEMPTS_BEFORE_BG and ATTEMPTS_BEFORE_BG to try another Wifi protocol #563 --- main/User_config.h | 22 ++++- main/main.ino | 225 ++++++++++++++++++++++++++++----------------- 2 files changed, 162 insertions(+), 85 deletions(-) diff --git a/main/User_config.h b/main/User_config.h index 3db9031..e9738ee 100644 --- a/main/User_config.h +++ b/main/User_config.h @@ -84,7 +84,7 @@ /*-------------DEFINE YOUR ADVANCED NETWORK PARAMETERS BELOW----------------*/ //#define MDNS_SD //uncomment if you want to use mdns for discovering automatically your ip server, please note that MDNS with ESP32 can cause the BLE to not work -#define maxMQTTretry 10 //maximum MQTT connection attempts before going to wifimanager setup if never connected once +#define maxConnectionRetry 10 //maximum MQTT connection attempts before going to wifimanager setup if never connected once //set minimum quality of signal so it ignores AP's under that quality #define MinimumWifiSignalQuality 8 @@ -106,6 +106,26 @@ char mqtt_port[6] = "1883"; char mqtt_topic[mqtt_topic_max_size] = Base_Topic; char gateway_name[parameters_size * 2] = Gateway_Name; +#if defined(ESP8266)||defined(ESP32) + #include "esp_wifi.h" + #define ATTEMPTS_BEFORE_BG 10 // Number of wifi connection attempts before going to BG protocol + #define ATTEMPTS_BEFORE_B 20 // Number of wifi connection attempts before going to B protocol +#endif + +// WIFI mode, uncomment to force a wifi mode, if not uncommented the ESP will connect without a mode forced +// if there is a reconnection issue it will try to connect with G mode and if not working with B mode +#ifdef ESP32 + uint8_t wifiProtocol = 0; // default mode, automatic selection + //uint8_t wifiProtocol = WIFI_PROTOCOL_11B; + //uint8_t wifiProtocol = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G; // can't have only one https://github.com/espressif/esp-idf/issues/702 + //uint8_t wifiProtocol = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N; // can't have only one https://github.com/espressif/esp-idf/issues/702 +#elif ESP8266 + uint8_t wifiProtocol = 0; // default mode, automatic selection + //uint8_t wifiProtocol = WIFI_PHY_MODE_11B; + //uint8_t wifiProtocol = WIFI_PHY_MODE_11G; + //uint8_t wifiProtocol = WIFI_PHY_MODE_11N; +#endif + /*-------------DEFINE THE MODULES YOU WANT BELOW----------------*/ //Addons and module management, uncomment the Z line corresponding to the module you want to use diff --git a/main/main.ino b/main/main.ino index 049449c..30f6014 100644 --- a/main/main.ino +++ b/main/main.ino @@ -116,8 +116,8 @@ unsigned long ReceivedSignal[array_size][2] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}}; void callback(char *topic, byte *payload, unsigned int length); bool connectedOnce = false; //indicate if we have been connected once to MQTT - -int failure_number = 0; // number of failure connecting to MQTT +int failure_number_ntwk = 0; // number of failure connecting to network +int failure_number_mqtt = 0; // number of failure connecting to MQTT #ifdef ESP32 #include @@ -125,6 +125,7 @@ int failure_number = 0; // number of failure connecting to MQTT #include #include #include + #include "esp_wifi.h" WiFiClient eClient; #include #ifdef MDNS_SD @@ -133,6 +134,7 @@ int failure_number = 0; // number of failure connecting to MQTT #elif defined(ESP8266) #include #include + #include "esp_wifi.h" #include #include #include @@ -151,7 +153,6 @@ PubSubClient client(eClient); //MQTT last attemps reconnection date unsigned long lastMQTTReconnectAttempt = 0; -unsigned long lastNTWKReconnectAttempt = 0; void revert_hex_data(char *in, char *out, int l) { @@ -439,7 +440,66 @@ bool cmpToMainTopic(char * topicOri, char * toAdd){ } } -void reconnect() +void disconnection_handling( int failure_number){ + Log.trace(F("disconnection_handling, failed %d times" CR), failure_number); + if (failure_number > maxConnectionRetry && !connectedOnce) + { + #if defined(ESP8266) || defined(ESP32) + #ifndef ESPWifiManualSetup + Log.error(F("Failed connecting 1st time to mqtt, reset wifi manager & erase network credentials" CR)); + setup_wifimanager(true); + #else + Log.error(F("Failed connecting 1st time to mqtt, restarting ESP" CR)); + #ifdef ESP32 + ESP.restart(); + #endif + #ifdef ESP8266 + ESP.reset(); + #endif + #endif + #endif + } + else if (failure_number <= maxConnectionRetry + ATTEMPTS_BEFORE_BG && connectedOnce) + { + Log.warning(F("Attempt to reinit wifi: %d" CR), wifiProtocol); + reinit_wifi(); + } + else if (failure_number > maxConnectionRetry + ATTEMPTS_BEFORE_BG && failure_number <= maxConnectionRetry + ATTEMPTS_BEFORE_B ) // After maxConnectionRetry + ATTEMPTS_BEFORE_BG try to connect with BG protocol + { + #ifdef ESP32 + wifiProtocol = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G; + #endif + #ifdef ESP8266 + wifiProtocol = WIFI_PHY_MODE_11G; + #endif + Log.warning(F("Wifi Protocol changed to WIFI_11G: %d" CR), wifiProtocol); + reinit_wifi(); + } + else if (failure_number > maxConnectionRetry + ATTEMPTS_BEFORE_B && failure_number <= maxConnectionRetry + ATTEMPTS_BEFORE_B + ATTEMPTS_BEFORE_BG ) // After maxConnectionRetry + ATTEMPTS_BEFORE_B try to connect with B protocol + { + #ifdef ESP32 + wifiProtocol = WIFI_PROTOCOL_11B; + #endif + #ifdef ESP8266 + wifiProtocol = WIFI_PHY_MODE_11B; + #endif + Log.warning(F("Wifi Protocol changed to WIFI_11B: %d" CR), wifiProtocol); + reinit_wifi(); + } + else if (failure_number > maxConnectionRetry + ATTEMPTS_BEFORE_B + ATTEMPTS_BEFORE_BG ) // After maxConnectionRetry + ATTEMPTS_BEFORE_B try to connect with B protocol + { + #ifdef ESP32 + wifiProtocol = 0; + #endif + #ifdef ESP8266 + wifiProtocol = 0; + #endif + Log.warning(F("Wifi Protocol reverted to normal mode: %d" CR), wifiProtocol); + reinit_wifi(); + } +} + +void connectMQTT() { #ifndef ESPWifiManualSetup @@ -458,7 +518,7 @@ void reconnect() if (client.connect(gateway_name, mqtt_user, mqtt_pass, topic, will_QoS, will_Retain, will_Message)) { Log.notice(F("Connected to broker" CR)); - failure_number = 0; + failure_number_mqtt = 0; // Once connected, publish an announcement... pub(will_Topic, Gateway_AnnouncementMsg, will_Retain); // publish version @@ -480,23 +540,11 @@ void reconnect() } else { - failure_number++; // we count the failure - Log.warning(F("failure_number: %d" CR),failure_number); - if (failure_number > maxMQTTretry && !connectedOnce) - { - #ifndef ESPWifiManualSetup - #if defined(ESP8266) || defined(ESP32) - Log.error(F("Failed connecting 1st time to mqtt, reset wifi manager & erase network credentials" CR)); - setup_wifimanager(true); - #endif - #endif - } + failure_number_mqtt++; // we count the failure + Log.warning(F("failure_number_mqtt: %d" CR),failure_number_mqtt); Log.warning(F("failed, rc=%d" CR),client.state()); delay(5000); -// On ESP32 force wifi begin https://github.com/espressif/arduino-esp32/issues/2501 - #if defined(ESP32) - WiFi.begin(); - #endif + disconnection_handling(failure_number_mqtt); } } } @@ -526,30 +574,7 @@ void setup_parameters() strcat(mqtt_topic, gateway_name); } -void setup() -{ - //Launch serial for debugging purposes - Serial.begin(SERIAL_BAUD); - Log.begin(LOG_LEVEL, &Serial); - Log.notice(F(CR "************* WELCOME TO OpenMQTTGateway **************" CR)); - -#if defined(ESP8266) || defined(ESP32) - #ifdef ESP8266 - #ifndef ZgatewaySRFB // if we are not in sonoff rf bridge case we apply the ESP8266 pin optimization - Serial.end(); - Serial.begin(SERIAL_BAUD, SERIAL_8N1, SERIAL_TX_ONLY); // enable on ESP8266 to free some pin - #endif - #endif - - #if defined(ESPWifiManualSetup) - setup_wifi(); - #else - setup_wifimanager(false); - #endif - - Log.trace(F("OpenMQTTGateway mac: %s" CR),WiFi.macAddress().c_str()); - Log.trace(F("OpenMQTTGateway ip: %s" CR),WiFi.localIP().toString().c_str()); - +void setOTA(){ // Port defaults to 8266 ArduinoOTA.setPort(ota_port); @@ -582,6 +607,35 @@ void setup() Log.error(F("End Failed" CR)); }); ArduinoOTA.begin(); +} + +void setup() +{ + //Launch serial for debugging purposes + Serial.begin(SERIAL_BAUD); + Log.begin(LOG_LEVEL, &Serial); + Log.notice(F(CR "************* WELCOME TO OpenMQTTGateway **************" CR)); + +#if defined(ESP8266) || defined(ESP32) + #ifdef ESP8266 + #ifndef ZgatewaySRFB // if we are not in sonoff rf bridge case we apply the ESP8266 pin optimization + Serial.end(); + Serial.begin(SERIAL_BAUD, SERIAL_8N1, SERIAL_TX_ONLY); // enable on ESP8266 to free some pin + #endif + #endif + + Log.trace(F("OpenMQTTGateway Wifi protocol used: %d" CR), wifiProtocol); + + #if defined(ESPWifiManualSetup) + setup_wifi(); + #else + setup_wifimanager(false); + #endif + + Log.trace(F("OpenMQTTGateway mac: %s" CR),WiFi.macAddress().c_str()); + Log.trace(F("OpenMQTTGateway ip: %s" CR),WiFi.localIP().toString().c_str()); + + setOTA(); #else // In case of arduino platform @@ -624,7 +678,6 @@ void setup() delay(1500); lastMQTTReconnectAttempt = 0; - lastNTWKReconnectAttempt = 0; #ifdef ZsensorBME280 setupZsensorBME280(); @@ -703,9 +756,11 @@ void setup() #if defined(ESPWifiManualSetup) void setup_wifi() { + delay(10); - int failureAttempt = 0; //DIRTY FIX ESP32 waiting for https://github.com/espressif/arduino-esp32/issues/653 WiFi.mode(WIFI_STA); + if (!wifiProtocol) forceWifiProtocol(); + // We start by connecting to a WiFi network Log.trace(F("Connecting to %s" CR),wifi_ssid); #ifdef ESPWifiAdvancedSetup @@ -726,9 +781,8 @@ void setup_wifi() { delay(500); Log.trace(F("." CR)); - failureAttempt++; //DIRTY FIX ESP32 - if (failureAttempt > 30) - setup_wifi(); //DIRTY FIX ESP32 + failure_number_ntwk++; + disconnection_handling(failure_number_ntwk); } Log.notice(F("WiFi ok with manual config credentials" CR)); } @@ -789,16 +843,28 @@ void eraseAndRestart() #endif } +void forceWifiProtocol(){ +#ifdef ESP32 + Log.trace(F("ESP32: Forcing to wifi %d" CR), wifiProtocol); + esp_wifi_set_protocol(WIFI_IF_STA, wifiProtocol); +#elif ESP8266 + Log.trace(F("ESP8266: Forcing to wifi %d" CR), wifiProtocol); + WiFi.setPhyMode(wifiProtocol); +#endif +} + void setup_wifimanager(bool reset_settings) { pinMode(TRIGGER_PIN, INPUT_PULLUP); + delay(10); + WiFi.mode(WIFI_STA); + if (!wifiProtocol) forceWifiProtocol(); + if (reset_settings) eraseAndRestart(); - WiFi.mode(WIFI_STA); - //read configuration from FS json Log.trace(F("mounting FS..." CR)); @@ -898,7 +964,7 @@ void setup_wifimanager(bool reset_settings) { Log.warning(F("failed to connect and hit timeout" CR)); delay(3000); -//reset and try again, or maybe put it to deep sleep +//reset and try again #if defined(ESP8266) ESP.reset(); #else @@ -943,6 +1009,17 @@ void setup_wifimanager(bool reset_settings) //end save } } + +void reinit_wifi() +{ + + delay(10); + WiFi.mode(WIFI_STA); + if (!wifiProtocol) forceWifiProtocol(); + WiFi.begin(); + +} + #else // Arduino case void setup_ethernet() { @@ -1023,7 +1100,7 @@ void loop() if ((Ethernet.hardwareStatus() != EthernetW5100 && Ethernet.linkStatus() == LinkON) || (Ethernet.hardwareStatus() == EthernetW5100)) { //we are able to detect disconnection only on w5200 and w5500 #endif - lastNTWKReconnectAttempt = 0; + failure_number_ntwk = 0; if (client.connected()) { @@ -1032,7 +1109,7 @@ void loop() #endif connectedOnce = true; - lastMQTTReconnectAttempt = 0; + failure_number_ntwk = 0; client.loop(); @@ -1117,40 +1194,19 @@ void loop() } else { - if (now - lastMQTTReconnectAttempt > 5000) - { - lastMQTTReconnectAttempt = now; - reconnect(); - } + connectMQTT(); } } else { // disconnected from network - if (now - lastNTWKReconnectAttempt > 10000) - { - lastNTWKReconnectAttempt = now; - #if defined(ESP8266) || defined(ESP32) - Log.warning(F("wifi disconnected" CR)); - delay(10000); // add a delay to avoid ESP32 crash and reset - #if defined(ESPWifiManualSetup) - Log.notice(F("restarting ESP" CR)); - #ifdef ESP32 - ESP.restart(); - #endif - #ifdef ESP8266 - ESP.reset(); - #endif - #else - if (!connectedOnce) - { - Log.notice(F("reseting wifi manager" CR)); - setup_wifimanager(true); // if we didn't connected once to mqtt we reset and start in AP mode again to have a chance to change the parameters - } - #endif - #else - Log.warning(F("eth disconnected" CR)); - #endif - } + #if defined(ESP8266) || defined(ESP32) + Log.warning(F("wifi disconnected" CR)); + delay(10000); // add a delay to avoid ESP32 crash and reset + failure_number_ntwk++; + disconnection_handling(failure_number_ntwk); + #else + Log.warning(F("eth disconnected" CR)); + #endif } } @@ -1178,6 +1234,7 @@ void stateMeasures() SYSdata["ip"] = ip2CharArray(WiFi.localIP()); String mac = WiFi.macAddress(); SYSdata["mac"] = (char *)mac.c_str(); + SYSdata["wifiPrt"] = (int)wifiProtocol; #else SYSdata["ip"] = ip2CharArray(Ethernet.localIP()); #endif