Splitted wifi and mqtt connect states to make the connections more robust. Protect the mqtt connection request against requests when a request is already done or in progress.

Tue, 04 Apr 2023 20:57:49 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Tue, 04 Apr 2023 20:57:49 +0200
changeset 15
64028e178ff1
parent 14
2a9f67ecbc72
child 16
b3e96bbe4ce4

Splitted wifi and mqtt connect states to make the connections more robust. Protect the mqtt connection request against requests when a request is already done or in progress.

main/iotbalkon.c file | annotate | diff | comparison | revisions
main/task_mqtt.c file | annotate | diff | comparison | revisions
main/task_mqtt.h file | annotate | diff | comparison | revisions
main/task_wifi.c file | annotate | diff | comparison | revisions
--- a/main/iotbalkon.c	Tue Apr 04 14:33:26 2023 +0200
+++ b/main/iotbalkon.c	Tue Apr 04 20:57:49 2023 +0200
@@ -12,10 +12,12 @@
  */
 typedef enum {
     State_Init = 0,
-    State_Connect,
+    State_Connect_Wifi,
+    State_Connect_MQTT,
     State_Working,
     State_WorkDone,
-    State_Stop,
+    State_Disconnect_MQTT,
+    State_Disconnect_Wifi,
     State_Wait,
     State_Measure,
     State_GoSleep
@@ -50,7 +52,6 @@
 uint8_t					loops = 0;
 uint8_t					ST_LOOPS = 6;
 
-bool					WorkAgain = false;
 int					DisCounter = 0;
 
 extern BMP280_State			*bmp280_state;			///< I2C state
@@ -215,7 +216,7 @@
     if (xSemaphoreTake(xSemaphoreBMP280, 25) == pdTRUE) {
 	temperature = bmp280_state->temperature;
 	pressure = bmp280_state->pressure / 100.0;
-	ESP_LOGI(TAG, "Temperature: %.3f Pressure: %.1f hPa\n", temperature, pressure);
+	ESP_LOGI(TAG, "Temperature: %.2f Pressure: %.1f hPa", temperature, pressure);
 	xSemaphoreGive(xSemaphoreBMP280);
     } else {
 	ESP_LOGE(TAG, "Can't lock xSemaphoreBMP280");
@@ -272,8 +273,8 @@
     m_Time[loopno] = ms - gLastTime;
     gLastTime = ms;
 
-    ESP_LOGI(TAG, "Measure: %d  Valid: %s  Solar: %.4fV %.4fmA  Battery: %.4fV %.4fmA  time %llu",
-		  loopno, (m_Valid[loopno]) ? "true":"false", s_Volts[loopno], s_Current[loopno], b_Volts[loopno], b_Current[loopno], m_Time[loopno]);
+    ESP_LOGI(TAG, "Measure: %d  Valid: %s  Battery: %.3fV %.1fmA  Solar: %.3fV %.1fmA  time %llu",
+		  loopno, (m_Valid[loopno]) ? "true":"false", b_Volts[loopno], b_Current[loopno], s_Volts[loopno], s_Current[loopno], m_Time[loopno]);
 
     if (loopno < (MAX_LOOPS - 1))
 	loopno++;
@@ -441,30 +442,57 @@
 	    case State_Init:		getTempBaro();
 					getLightValues();
 					getVoltsCurrent();
-					State = State_Connect;
+					State = State_Connect_Wifi;
 					DisCounter = 0;
 					request_WiFi(true);
 		    			break;
 
-	    case State_Connect:		if (ready_WiFi() && ready_mqtt()) {
-					    State = State_Working;
+	    case State_Connect_Wifi:	if (ready_WiFi()) {
+					    State = State_Connect_MQTT;
+					    /*
+					     * Give the network stack a bit more time to setup
+					     */
+					    vTaskDelay(250 / portTICK_PERIOD_MS);
+					    request_mqtt(true);
 					    Alarm &= ~AL_NOWIFI;
-					    ESP_LOGI(TAG, "Connected counter %d", DisCounter);
+					    ESP_LOGI(TAG, "Connected counter WiFi %d", DisCounter);
 					    DisCounter = 0;
 					} else {
+					    /*
+					     * 30 seconds connection try.
+					     */
 					    DisCounter++;
+					    vTaskDelay(1000 / portTICK_PERIOD_MS);
+					    ESP_LOGI(TAG, "* Counter WiFi %d", DisCounter);
 					    if (DisCounter > 30) {
 						Alarm |= AL_NOWIFI;
 						request_WiFi(false);
 						State = State_Init;
+						vTaskDelay(4000 / portTICK_PERIOD_MS);
 					    }
-					    vTaskDelay(2000 / portTICK_PERIOD_MS);
 					}
 					break;
 
-	    case State_Working:		WorkAgain = false;
+	    case State_Connect_MQTT:	if (ready_mqtt()) {
+					    State = State_Working;
+					    ESP_LOGI(TAG, "Connected counter MQTT %d", DisCounter);
+                                            DisCounter = 0;
+					} else {
+					    DisCounter++;
+					    if (DisCounter > 60) {
+						request_mqtt(false);
+						request_WiFi(false);
+						State = State_Init;
+						vTaskDelay(2000 / portTICK_PERIOD_MS);
+					    }
+					    vTaskDelay(1000 / portTICK_PERIOD_MS);
+					}
+					break;
 
-      					// Measure
+	    case State_Working:		/*
+					 * The final measure power usage.
+					 * This one should include the WiFi usage current.
+					 */
 					getVoltsCurrent();
 					solarVolts = solarCurrent = solarPower = batteryVolts = batteryCurrent = batteryPower = 0;
 					loops = 0;
@@ -517,11 +545,11 @@
 					    ESP_LOGI(TAG, "Battery Volts: %.4fV Current %.4fmA Power %.4fmW", batteryVolts, batteryCurrent, batteryPower);
 
         				    /*   Check alarm conditions */
-					    if (batteryState <= 10) {
-					    	Alarm |= AL_ACCULOW;
-					    } else {
+//					    if (batteryState <= 10) {
+//					    	Alarm |= AL_ACCULOW;
+//					    } else {
 					    	Alarm &= ~AL_ACCULOW;
-					    }
+//					    }
       					}
 					getTempBaro();
       					publish();
@@ -529,36 +557,33 @@
       					gTimeNext = millis() + SUB_TIME;
 					break;
 
-	    case State_WorkDone:	vTaskDelay(2 / portTICK_PERIOD_MS);
-					// Hang around for a while to process the subscriptions.
-      					if (WorkAgain) {
-					    // Some command was executed.
-					    State = State_Working;
-					}
+	    case State_WorkDone:	vTaskDelay(20 / portTICK_PERIOD_MS);
 					if (gTimeInMillis > gTimeNext) {
-					    State = State_Stop;
+					    State = State_Disconnect_MQTT;
+					    request_mqtt(false);
 					}
 					break;
 
-	    case State_Stop:		request_WiFi(false);
+	    case State_Disconnect_MQTT:	wait_mqtt(10000);
+					State = State_Disconnect_Wifi;
+					break;
+
+	    case State_Disconnect_Wifi:	request_WiFi(false);
       					// // Reset values for average current measurement.
       					// HaveIP = false;
 					loopno = 0;
 					gLastTime = millis();
-					vTaskDelay(10 / portTICK_PERIOD_MS);
-					// #if defined(ARDUINO_ESP8266_WEMOS_D1MINI)
-      					// WiFi.forceSleepBegin(0);  // 0 == forever
-					// #endif
+					//vTaskDelay(10 / portTICK_PERIOD_MS);
 
 					/*
       					 *  If any output is on, use 6 10 seconds loops.
       					 *  If nothing on, do a deep sleep.
       					 */
-					// if (EEPROM.read(EM_Relay1) || EEPROM.read(EM_Relay2) || EEPROM.read(EM_Dimmer3) || EEPROM.read(EM_Dimmer4)) {
+					if (Relay1 || Relay2 || Dimmer3 || Dimmer4) {
         				//    if (EEPROM.read(EM_DS_Active)) {
           				//	EEPROM.write(EM_DS_Active, 0);
           				//	EEPROM.commit();
-        				//    }
+        				}
 
         				//    // Active mode, 60 seconds loop
 					ST_LOOPS = 6;
@@ -583,20 +608,6 @@
         				//    }
         				//    State = State_GoSleep;
       					// }
-      					/*
-      					 * Update CRC and write rtcData.
-      					 */
-      					// rtcData.crc32 = calculateCRC32((uint8_t*) &rtcData.data, sizeof(rtcData)-4);
-					// #if defined(ARDUINO_ESP8266_WEMOS_D1MINI)
-      					// if (ESP.rtcUserMemoryWrite(0, (uint32_t*) &rtcData, sizeof(rtcData))) {
-					// #if Debug == true
-        				//    Serial.print("Write: ");
-        				//    printMemory();
-					// #endif
-      					// } else {
-        				//    Serial.println("Write error rtcData");
-      					// }
-					// #endif
 					break;
 
 	    case State_Wait:		if (gTimeInMillis > gTimeNext) {
@@ -613,7 +624,7 @@
 					if (loopno >= ST_LOOPS) {
 					    ESP_LOGI(TAG, "Enough loops, do connect");
         				    getLightValues();
-					    State = State_Connect;
+					    State = State_Connect_Wifi;
 					    DisCounter = 0;
 					    request_WiFi(true);
 					} else {
--- a/main/task_mqtt.c	Tue Apr 04 14:33:26 2023 +0200
+++ b/main/task_mqtt.c	Tue Apr 04 20:57:49 2023 +0200
@@ -47,12 +47,23 @@
 extern uint8_t			Dimmer4;
 
 
-void connect_mqtt(bool state)
+void request_mqtt(bool state)
 {
-    if (state)
-    	xEventGroupSetBits(xEventGroupMQTT, TASK_MQTT_CONNECT);
-    else
-    	xEventGroupSetBits(xEventGroupMQTT, TASK_MQTT_DISCONNECT);
+    if (state) {
+	if (xEventGroupGetBits(xEventGroupMQTT) & TASK_MQTT_CONNECTED) {
+	    ESP_LOGW(TAG, "request_mqtt(true) but already connected");
+	} else {
+    	    xEventGroupSetBits(xEventGroupMQTT, TASK_MQTT_CONNECT);
+	}
+    } else {
+	if (xEventGroupGetBits(xEventGroupMQTT) & TASK_MQTT_DISCONNECT) {
+	    ESP_LOGW(TAG, "request_mqtt(false) already in progress");
+	} else if (! (xEventGroupGetBits(xEventGroupMQTT) & TASK_MQTT_CONNECTED)) {
+	    ESP_LOGW(TAG, "request_mqtt(false) but already disconnected");
+	} else {
+    	    xEventGroupSetBits(xEventGroupMQTT, TASK_MQTT_DISCONNECT);
+	}
+    }
 }
 
 
@@ -446,7 +457,7 @@
 	    xEventGroupClearBits(xEventGroupMQTT, TASK_MQTT_CONNECT);
 
 	} else if (uxBits & TASK_MQTT_DISCONNECT) {
-	    ESP_LOGI(TAG, "Request MQTT disconnect");
+	    ESP_LOGI(TAG, "Request MQTT disconnect start");
 	    /*
 	     * Unsubscribe if connected
 	     */
@@ -479,7 +490,10 @@
                 ESP_LOGI(TAG, "stopped");
             }
 
+	    xEventGroupClearBits(xEventGroupMQTT, TASK_MQTT_CONNECTED);
+	    xEventGroupSetBits(xEventGroupMQTT, TASK_MQTT_DISCONNECTED);
 	    xEventGroupClearBits(xEventGroupMQTT, TASK_MQTT_DISCONNECT);
+	    ESP_LOGI(TAG, "Request MQTT disconnect done");
 	}
     }
 }
--- a/main/task_mqtt.h	Tue Apr 04 14:33:26 2023 +0200
+++ b/main/task_mqtt.h	Tue Apr 04 20:57:49 2023 +0200
@@ -12,7 +12,7 @@
  * @brief Request a MQTT connection
  * @param state Request of disconnect a connection.
  */
-void connect_mqtt(bool state);
+void request_mqtt(bool state);
 
 
 /**
--- a/main/task_wifi.c	Tue Apr 04 14:33:26 2023 +0200
+++ b/main/task_wifi.c	Tue Apr 04 20:57:49 2023 +0200
@@ -42,7 +42,7 @@
 
 bool ready_WiFi(void)
 {
-    if (wifi_state->STA_connected && wifi_state->STA_online)
+    if ((xEventGroupGetBits(xEventGroupWifi) & (TASK_WIFI_STA_CONNECTED | TASK_WIFI_HAS_IP)) == (TASK_WIFI_STA_CONNECTED | TASK_WIFI_HAS_IP))
         return true;
     return false;
 }
@@ -72,7 +72,6 @@
 #ifdef CONFIG_CODE_TESTING
 		ESP_ERROR_CHECK(esp_netif_set_hostname(sta_netif, "wemos"));
 #endif
-//        	ESP_ERROR_CHECK(esp_wifi_connect());
 		break;
 
 	case WIFI_EVENT_STA_CONNECTED: {
@@ -93,9 +92,11 @@
 	    }
 
 	case WIFI_EVENT_STA_DISCONNECTED: {
-		ESP_LOGI(TAG, "Event STA disconnected");
-//		wifi_event_sta_disconnected_t* disconnected = (wifi_event_sta_disconnected_t*) event_data;
-//                ESP_LOGI(TAG, "Event STA disconnected, reason:%d", disconnected->reason);
+		wifi_event_sta_disconnected_t* disconnected = (wifi_event_sta_disconnected_t*) event_data;
+
+                ESP_LOGI(TAG, "Event STA disconnected, reason: %d", disconnected->reason);
+		if (disconnected->reason != 8)
+		    request_mqtt(false);
                 if (xSemaphoreTake(xSemaphoreWiFi, 35) == pdTRUE) {
                     wifi_state->STA_connected = false;
                     wifi_state->STA_online = false;
@@ -103,8 +104,6 @@
                 } else {
 		    ESP_LOGE(TAG, "wifi_event_handler() lock error WIFI_EVENT_STA_DISCONNECTED");
 		}
-		if (ready_mqtt())
-		    connect_mqtt(false);
                 xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED);
                 xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED);
 		break;
@@ -135,7 +134,6 @@
 		} else {
 			ESP_LOGE(TAG, "got_ip_event_handler() lock error IP_EVENT_STA_GOT_IP");
 		}
-		connect_mqtt(true);
 		break;
 
 	case IP_EVENT_STA_LOST_IP:
@@ -150,8 +148,6 @@
 		} else {
 			ESP_LOGE(TAG, "got_ip_event_handler() lock error IP_EVENT_STA_LOST_IP");
 		}
-		if (ready_mqtt())
-		    connect_mqtt(false);
 		break;
 
 	default:
@@ -215,8 +211,6 @@
 	     * user requested a disconnect, this will in effect disconnect the wifi
 	     */
 	    ESP_LOGI(TAG, "Request STA disconnect");
-	    connect_mqtt(false);
-	    wait_mqtt(10000);
 	    ESP_ERROR_CHECK(esp_wifi_disconnect());
 	    xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED, pdFALSE, pdTRUE, portMAX_DELAY );
 

mercurial