Skip to content

Commit

Permalink
Fix WiFi connection and reconnection melkati#206
Browse files Browse the repository at this point in the history
Add incremental retry times for troubled WIFI connection
Improve WiFi debug logging
  • Loading branch information
melkati committed Apr 14, 2024
1 parent fe14763 commit 91028e8
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 132 deletions.
60 changes: 33 additions & 27 deletions CO2_Gadget.ino
Original file line number Diff line number Diff line change
Expand Up @@ -48,24 +48,42 @@ String wifiPass = WIFI_PW_CREDENTIALS;
String MACAddress = "Unset";
uint8_t peerESPNowAddress[] = ESPNOW_PEER_MAC_ADDRESS;

// Communication options
// BLE options
bool activeBLE = true;

// WIFI options
bool activeWIFI = true;
bool activeMQTT = true;
bool activeESPNOW = false;
bool activeOTA = false;
bool troubledWIFI = false; // There are problems connecting to WIFI. Temporary suspend WIFI
bool troubledMQTT = false; // There are problems connecting to MQTT. Temporary suspend MQTT
bool troubledESPNOW = false; // There are problems connecting to ESP-NOW. Temporary suspend ESP-NOW
uint64_t timeTroubledWIFI = 0; // Time since WIFI is troubled
uint64_t timeTroubledMQTT = 0; // Time since MQTT is troubled
uint64_t timeToRetryTroubledWIFI = 300; // Time in seconds to retry WIFI connection after it is troubled
uint64_t timeToRetryTroubledMQTT = 900; // Time in seconds to retry MQTT connection after it is troubled (no need to retry so often as it retries automatically after WiFi is connected)
bool troubledWIFI = false; // There are problems connecting to WIFI. Temporary suspend WIFI
uint64_t timeTroubledWIFI = 0; // Time since WIFI is troubled
uint64_t timeToRetryTroubledWIFI = 60; // Time in seconds to retry WIFI connection after it is troubled (will increase as it keeps retrying)
uint64_t timeToRetryIncrementTroubledWIFI = 15; // Time in seconds to increment the time to retry WIFI connection after it is troubled
uint64_t maxTimeToRetryTroubledWIFI = 90; // Maximum time in seconds to retry WIFI connection after it is troubled
uint16_t WiFiConnectionRetries = 0;
uint16_t maxWiFiConnectionRetries = 20;
bool mqttDiscoverySent = false;
bool wifiChanged = false;

// MQTT options
bool activeMQTT = true;
bool troubledMQTT = false; // There are problems connecting to MQTT. Temporary suspend MQTT
uint64_t timeTroubledMQTT = 0; // Time since MQTT is troubled
uint64_t timeToRetryTroubledMQTT = 900; // Time in seconds to retry MQTT connection after it is troubled (no need to retry so often as it retries automatically everytime WiFi is connected)
bool mqttDiscoverySent = false;
uint16_t timeBetweenMQTTPublish = 60; // Time in seconds between MQTT transmissions
uint16_t timeToKeepAliveMQTT = 3600; // Maximum time in seconds between MQTT transmissions - Default: 1 Hour
uint64_t lastTimeMQTTPublished = 0; // Time of last MQTT transmission

// ESP-NOW options
bool activeESPNOW = false;
bool troubledESPNOW = false; // There are problems connecting to ESP-NOW. Temporary suspend ESP-NOW
uint8_t channelESPNow = 1;
uint16_t boardIdESPNow = 0;
uint16_t timeBetweenESPNowPublish = 60; // Time in seconds between ESP-NOW transmissions
uint16_t timeToKeepAliveESPNow = 3600; // Maximum time in seconds between ESP-NOW transmissions - Default: 1 Hour
uint64_t lastTimeESPNowPublished = 0; // Time of last ESP-NOW transmission

// OTA options
bool activeOTA = false;

// Display and menu options
uint16_t DisplayBrightness = 100;
bool displayReverse = false;
Expand All @@ -91,8 +109,6 @@ uint16_t toneBuzzerBeep = BUZZER_TONE_MED;
uint16_t durationBuzzerBeep = DURATION_BEEP_MEDIUM;
int16_t timeBetweenBuzzerBeeps = -1;

uint8_t channelESPNow = 1;
uint16_t boardIdESPNow = 0;
uint64_t timeInitializationCompleted = 0;

// Variables for Battery reading
Expand All @@ -103,22 +119,12 @@ uint16_t batteryDischargedMillivolts = 3200; // Voltage of battery when we co
uint16_t batteryFullyChargedMillivolts = 4200; // Voltage of battery when it is considered fully charged (100%).

// Variables to control automatic display off to save power
bool workingOnExternalPower = true; // True if working on external power (USB connected)
uint32_t actualDisplayBrightness = 0; // To know if it's on or off
bool workingOnExternalPower = true; // True if working on external power (USB connected)
uint32_t actualDisplayBrightness = 0; // To know if it's on or off
bool displayOffOnExternalPower = false;
uint16_t timeToDisplayOff = 0; // Time in seconds to turn off the display to save power.
volatile uint64_t lastTimeButtonPressed = 0; // Last time stamp button up was pressed

// Variables for MQTT timming
uint16_t timeBetweenMQTTPublish = 60; // Time in seconds between MQTT transmissions
uint16_t timeToKeepAliveMQTT = 3600; // Maximum time in seconds between MQTT transmissions - Default: 1 Hour
uint64_t lastTimeMQTTPublished = 0; // Time of last MQTT transmission

// Variables for ESP-NOW timming
uint16_t timeBetweenESPNowPublish = 60; // Time in seconds between ESP-NOW transmissions
uint16_t timeToKeepAliveESPNow = 3600; // Maximum time in seconds between ESP-NOW transmissions - Default: 1 Hour
uint64_t lastTimeESPNowPublished = 0; // Time of last ESP-NOW transmission

// Variables for color and output ranges
uint16_t co2OrangeRange = 700;
uint16_t co2RedRange = 1000;
Expand Down Expand Up @@ -444,7 +450,7 @@ void adjustBrightnessLoop() {
if ((!displayOffOnExternalPower) && (workingOnExternalPower)) {
setDisplayBrightness(DisplayBrightness);
}
if (timeToDisplayOff==0) {
if (timeToDisplayOff == 0) {
setDisplayBrightness(DisplayBrightness);
}
return;
Expand Down
224 changes: 120 additions & 104 deletions CO2_Gadget_WIFI.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,67 +359,67 @@ void printWiFiStatus() { // Print wifi status on serial monitor
}

String getWiFiDisconnectReason(uint8_t reason) {
switch (reason) {
case WIFI_REASON_AUTH_EXPIRE:
return "Auth Expired";
case WIFI_REASON_AUTH_LEAVE:
return "Auth Leave";
case WIFI_REASON_ASSOC_EXPIRE:
return "Association Expired";
case WIFI_REASON_ASSOC_TOOMANY:
return "Too Many Associations";
case WIFI_REASON_NOT_AUTHED:
return "Not Authenticated";
case WIFI_REASON_NOT_ASSOCED:
return "Not Associated";
case WIFI_REASON_ASSOC_LEAVE:
return "Association Leave";
case WIFI_REASON_ASSOC_NOT_AUTHED:
return "Association not Authenticated";
case WIFI_REASON_DISASSOC_PWRCAP_BAD:
return "Disassociate Power Cap Bad";
case WIFI_REASON_DISASSOC_SUPCHAN_BAD:
return "Disassociate Supported Channel Bad";
case WIFI_REASON_IE_INVALID:
return "IE Invalid";
case WIFI_REASON_MIC_FAILURE:
return "Mic Failure";
case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT:
return "4-Way Handshake Timeout";
case WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT:
return "Group Key Update Timeout";
case WIFI_REASON_IE_IN_4WAY_DIFFERS:
return "IE In 4-Way Handshake Differs";
case WIFI_REASON_GROUP_CIPHER_INVALID:
return "Group Cipher Invalid";
case WIFI_REASON_PAIRWISE_CIPHER_INVALID:
return "Pairwise Cipher Invalid";
case WIFI_REASON_AKMP_INVALID:
return "AKMP Invalid";
case WIFI_REASON_UNSUPP_RSN_IE_VERSION:
return "Unsupported RSN IE version";
case WIFI_REASON_INVALID_RSN_IE_CAP:
return "Invalid RSN IE Cap";
case WIFI_REASON_802_1X_AUTH_FAILED:
return "802.1x Authentication Failed";
case WIFI_REASON_CIPHER_SUITE_REJECTED:
return "Cipher Suite Rejected";
case WIFI_REASON_BEACON_TIMEOUT:
return "Beacon Timeout";
case WIFI_REASON_NO_AP_FOUND:
return "AP Not Found";
case WIFI_REASON_AUTH_FAIL:
return "Authentication Failed";
case WIFI_REASON_ASSOC_FAIL:
return "Association Failed";
case WIFI_REASON_HANDSHAKE_TIMEOUT:
return "Handshake Failed";
case WIFI_REASON_CONNECTION_FAIL:
return "Connection Failed";
case WIFI_REASON_UNSPECIFIED:
default:
return "Unspecified";
}
switch (reason) {
case WIFI_REASON_AUTH_EXPIRE:
return "Auth Expired";
case WIFI_REASON_AUTH_LEAVE:
return "Auth Leave";
case WIFI_REASON_ASSOC_EXPIRE:
return "Association Expired";
case WIFI_REASON_ASSOC_TOOMANY:
return "Too Many Associations";
case WIFI_REASON_NOT_AUTHED:
return "Not Authenticated";
case WIFI_REASON_NOT_ASSOCED:
return "Not Associated";
case WIFI_REASON_ASSOC_LEAVE:
return "Association Leave";
case WIFI_REASON_ASSOC_NOT_AUTHED:
return "Association not Authenticated";
case WIFI_REASON_DISASSOC_PWRCAP_BAD:
return "Disassociate Power Cap Bad";
case WIFI_REASON_DISASSOC_SUPCHAN_BAD:
return "Disassociate Supported Channel Bad";
case WIFI_REASON_IE_INVALID:
return "IE Invalid";
case WIFI_REASON_MIC_FAILURE:
return "Mic Failure";
case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT:
return "4-Way Handshake Timeout";
case WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT:
return "Group Key Update Timeout";
case WIFI_REASON_IE_IN_4WAY_DIFFERS:
return "IE In 4-Way Handshake Differs";
case WIFI_REASON_GROUP_CIPHER_INVALID:
return "Group Cipher Invalid";
case WIFI_REASON_PAIRWISE_CIPHER_INVALID:
return "Pairwise Cipher Invalid";
case WIFI_REASON_AKMP_INVALID:
return "AKMP Invalid";
case WIFI_REASON_UNSUPP_RSN_IE_VERSION:
return "Unsupported RSN IE version";
case WIFI_REASON_INVALID_RSN_IE_CAP:
return "Invalid RSN IE Cap";
case WIFI_REASON_802_1X_AUTH_FAILED:
return "802.1x Authentication Failed";
case WIFI_REASON_CIPHER_SUITE_REJECTED:
return "Cipher Suite Rejected";
case WIFI_REASON_BEACON_TIMEOUT:
return "Beacon Timeout";
case WIFI_REASON_NO_AP_FOUND:
return "AP Not Found";
case WIFI_REASON_AUTH_FAIL:
return "Authentication Failed";
case WIFI_REASON_ASSOC_FAIL:
return "Association Failed";
case WIFI_REASON_HANDSHAKE_TIMEOUT:
return "Handshake Failed";
case WIFI_REASON_CONNECTION_FAIL:
return "Connection Failed";
case WIFI_REASON_UNSPECIFIED:
default:
return "Unspecified";
}
}

void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
Expand Down Expand Up @@ -566,6 +566,23 @@ bool checkStringIsNumerical(String myString) {
}

void WiFiStationConnected(WiFiEvent_t event, WiFiEventInfo_t info) {
static bool firstConnect = true;
#ifdef WIFI_PRIVACY
Serial.println("-->[WiFi] Connected to WiFi access point (SSID: " + WiFi.SSID() + ")");
#else
Serial.println("-->[WiFi] Connected to WiFi access point (SSID: " + wifiSSID + " Password: " + wifiPass + ")");
#endif
if (firstConnect) {
firstConnect = false;
delay(150); // Wait for the IP to be assigned
Serial.print("");
printLargeASCII(WiFi.localIP().toString().c_str());
Serial.print("");
} else {
Serial.print("-->[WiFi] IP address: ");
Serial.println(WiFi.localIP());
}
Serial.flush();
}

void WiFiStationGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
Expand All @@ -581,24 +598,19 @@ void WiFiStationGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {

void WiFiStationDisconnected(WiFiEvent_t event, WiFiEventInfo_t info) {
++WiFiConnectionRetries;
Serial.println("-->[WiFi] Disconnected. Reason for disconnection: " + getWiFiDisconnectReason(info.wifi_sta_disconnected.reason));
Serial.println("-->[WiFi] Disconnected from WiFi access point. Reason: " + getWiFiDisconnectReason(info.wifi_sta_disconnected.reason) + " (" + String(info.wifi_sta_disconnected.reason) + ") Retries: " + String(WiFiConnectionRetries) + " of " + String(maxWiFiConnectionRetries));
#ifdef DEBUG_WIFI_EVENTS
Serial.println("-->[WiFi-event] Disconnected from WiFi access point");
Serial.print("-->[WiFi-event] WiFi lost connection. Reason: ");
Serial.println(info.wifi_sta_disconnected.reason);
Serial.print("-->[WiFi-event] Retries: ");
Serial.print(WiFiConnectionRetries);
Serial.print(" of ");
Serial.println(maxWiFiConnectionRetries);
// Serial.print("-->[WiFi-event] Retries: ");
// Serial.print(WiFiConnectionRetries);
// Serial.print(" of ");
// Serial.println(maxWiFiConnectionRetries);
#endif

if (WiFiConnectionRetries >= maxWiFiConnectionRetries) {
disableWiFi();
troubledWIFI = true;
timeTroubledWIFI = millis();
#ifdef DEBUG_WIFI_EVENTS
Serial.printf("-->[WiFi-event] Not possible to connect to WiFi after %d tries. Will try later.\n", WiFiConnectionRetries);
#endif
Serial.println("-->[WiFi] Not possible to connect to WiFi after " + String(WiFiConnectionRetries) + " retries. Will try again in " + String(timeToRetryTroubledWIFI) + " seconds.");
}
}

Expand Down Expand Up @@ -752,38 +764,39 @@ bool connectToWiFi() {

WiFi.begin(wifiSSID.c_str(), wifiPass.c_str());

// Wait for connection until maxWiFiConnectionRetries or WiFi is connected
while (WiFi.status() != WL_CONNECTED && WiFiConnectionRetries < maxWiFiConnectionRetries) {
if (TimePeriodIsOver(checkTimer, 500)) { // Once every 500 miliseconds
Serial.print(".");
WiFiConnectionRetries++;
if (WiFiConnectionRetries > maxWiFiConnectionRetries) {
Serial.println();
Serial.print("not connected ");
}
}
yield();
}

if ((WiFiConnectionRetries > maxWiFiConnectionRetries) && (WiFi.status() != WL_CONNECTED)) {
disableWiFi();
troubledWIFI = true;
timeTroubledWIFI = millis();
// Serial.printf("-->[WiFi] Not possible to connect to WiFi after %d tries. Will try later.\n", WiFiConnectionRetries);
Serial.println("-->[WiFi] Not possible to connect to WiFi after " + String(WiFiConnectionRetries) + " tries. Will try later.");
}

if (troubledWIFI) {
Serial.println("");
return false;
} else {
Serial.println("");
Serial.print("-->[WiFi] MAC: ");
Serial.println(MACAddress);
Serial.print("-->[WiFi] WiFi connected - IP = ");
Serial.println(WiFi.localIP());
return true;
}
// // Wait for connection until maxWiFiConnectionRetries or WiFi is connected
// while (WiFi.status() != WL_CONNECTED && WiFiConnectionRetries < maxWiFiConnectionRetries) {
// if (TimePeriodIsOver(checkTimer, 1000)) { // Once every 1000 miliseconds
// Serial.print(".");
// WiFiConnectionRetries++;
// if (WiFiConnectionRetries > maxWiFiConnectionRetries) {
// Serial.println();
// Serial.print("not connected ");
// }
// }
// yield();
// }

// if ((WiFiConnectionRetries > maxWiFiConnectionRetries) && (WiFi.status() != WL_CONNECTED)) {
// disableWiFi();
// troubledWIFI = true;
// timeTroubledWIFI = millis();
// // Serial.printf("-->[WiFi] Not possible to connect to WiFi after %d tries. Will try later.\n", WiFiConnectionRetries);
// Serial.println("-->[WiFi] Not possible to connect to WiFi after " + String(WiFiConnectionRetries) + " tries. Will try later.");
// }

// if (troubledWIFI) {
// Serial.println("");
// return false;
// } else {
// Serial.println("");
// Serial.print("-->[WiFi] MAC: ");
// Serial.println(MACAddress);
// Serial.print("-->[WiFi] WiFi connected - IP = ");
// Serial.println(WiFi.localIP());
// return true;
// }
return (WiFi.status() == WL_CONNECTED);
}

void initOTA() {
Expand Down Expand Up @@ -820,6 +833,9 @@ void initWifi() {

void wifiClientLoop() {
if (activeWIFI && troubledWIFI && (millis() - timeTroubledWIFI >= timeToRetryTroubledWIFI * 1000)) {
if (timeToRetryTroubledWIFI < maxTimeToRetryTroubledWIFI) {
timeToRetryTroubledWIFI = timeToRetryTroubledWIFI + timeToRetryIncrementTroubledWIFI; // Everytime we retry, we add 15 seconds to the retry time (until 900 seconds = 15 minutes)
}
initWifi();
}

Expand Down
3 changes: 2 additions & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ build_flags =

-D MQTT_BROKER_SERVER="\"192.168.1.145"\"
-D CO2_GADGET_VERSION="\"0.12."\"
-D CO2_GADGET_REV="\"022"\"
-D CO2_GADGET_REV="\"023"\"
-D CORE_DEBUG_LEVEL=0
-DCACHE_DIR=".pio/build"
-DBUZZER_PIN=2 ; ESP32 pin GPIO13 connected to piezo buzzer
Expand All @@ -67,6 +67,7 @@ build_flags =
-DMQTT_DISCOVERY_PREFIX="\"homeassistant/\""
-DESPNOW_PEER_MAC_ADDRESS="{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}" ; MAC Address of the ESP-NOW receiver (STA MAC). For unicast use peer address, as: {0xE8, 0x68, 0xE7, 0x0F, 0x08, 0x90}
-DESPNOW_WIFI_CH=1 ; ESP-NOW WiFi Channel. Must be same as gateway
; -DDEBUG_WIFI_EVENTS
; -DDEBUG_ARDUINOMENU
; -DMENU_DEBUG ; Needs streamFlow library
-Os ; Optimize compilation for use memory
Expand Down

0 comments on commit 91028e8

Please sign in to comment.