MQTT: How to handle wifi disconnection

Gustav
Posts: 7
Joined: Tue Aug 18, 2020 7:57 am

MQTT: How to handle wifi disconnection

Postby Gustav » Sun Feb 28, 2021 3:26 pm

Hello everyone!

I don't know why, but since I started using esp idf 4.1.1 I started losing wifi connection around every hour, but that's not a big deal, I handle the disconnection and reconnect exactly as the wifi sta examples shows.
But since I started experimenting with MQTT I can't get it to restart properly, this is a typical log of the disconnection:

Code: Select all

I (3461644) wifi:bcn_timout,ap_probe_send_start
I (3464144) wifi:ap_probe_send over, resett wifi status to disassoc
I (3464144) wifi:state: run -> init (c800)
I (3464144) wifi:pm stop, total sleep time: 3281634372 us / 3454130616 us

I (3464154) wifi:new:<7,0>, old:<7,0>, ap:<255,255>, sta:<7,0>, prof:1
E (3464164) TRANS_SSL: ssl_poll_read select error 113, errno = Software caused connection abort, fd = 54
E (3464164) TRANS_SSL: ssl_poll_write select error 0, errno = Success, fd = 54
E (3464164) MQTT_CLIENT: Poll read error: 0, aborting connection
W (3464174) TRANS_SSL: Poll timeout or error, errno=Success, fd=54, timeout_ms=10000
I (3464194) MQTT_SERVICE: MQTT_EVENT_ERROR
E (3464194) MQTT_CLIENT: Error write data or timeout, written len = -1, errno=0
E (3464204) MQTT_CLIENT: Error sending disconnect message
I (3464214) MQTT_SERVICE: MQTT_EVENT_DISCONNECTED
I (3464224) wifi station: retry to connect to the AP
I (3464224) wifi station: connect to the AP fail
I (3464344) wifi:new:<7,0>, old:<7,0>, ap:<255,255>, sta:<7,0>, prof:1
I (3464344) wifi:state: init -> auth (b0)
I (3464344) wifi:state: auth -> assoc (0)
I (3464354) wifi:state: assoc -> run (10)
I (3464364) wifi:connected with myAccesPoint, aid = 1, channel 7, BW20, bssid = b8:27:eb:cb:43:9f
I (3464364) wifi:security: WPA2-PSK, phy: bgn, rssi: -24
I (3464364) wifi:pm start, type: 1

I (3464444) wifi:AP's beacon interval = 102400 us, DTIM period = 2
I (3464954) esp_netif_handlers: sta ip: 192.168.1.5, mask: 255.255.255.0, gw: 192.168.1.1
wifi station  We have now connected to a station and can do things...
I (3465004) STORAGE: Loading ca.crt ... 
I (3465124) STORAGE: Loading esp.crt ... 
I (3465234) STORAGE: Loading esp.key ... 
I (3465324) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
I (3465324) MQTT_SERVICE: Other event id:7
I (3465334) MQTT_SERVICE: MQTT task created
E (3465384) esp-tls-mbedtls: mbedtls_ssl_setup returned -0x7f00
E (3465384) esp-tls: create_ssl_handle failed
E (3465384) esp-tls: Failed to open new connection
E (3465394) TRANS_SSL: Failed to open a new connection
E (3465404) MQTT_CLIENT: Error transport connect
I (3465404) MQTT_SERVICE: MQTT_EVENT_ERROR
I (3465414) MQTT_SERVICE: MQTT_EVENT_DISCONNECTED
I (3480414) MQTT_SERVICE: Other event id:7
E (3480444) esp-tls-mbedtls: mbedtls_ssl_setup returned -0x7f00
E (3480444) esp-tls: create_ssl_handle failed
E (3480444) esp-tls: Failed to open new connection
E (3480454) TRANS_SSL: Failed to open a new connection
E (3480454) MQTT_CLIENT: Error transport connect
I (3480464) MQTT_SERVICE: MQTT_EVENT_ERROR
I (3480464) MQTT_SERVICE: MQTT_EVENT_DISCONNECTED
[..]
this is what I do to handle wifi disconnection and MQTT disconnection:

Code: Select all

static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    }
    else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {

    	mqttServiceStop();

        if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {
            esp_wifi_connect();
            s_retry_num++;
            ESP_LOGI(TAG, "retry to connect to the AP");
        }
        else {
            xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
        }
        ESP_LOGI(TAG,"connect to the AP fail");
    }
    else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        printf(TAG, "Our IP address is:%s \n", ip4addr_ntoa(&event->ip_info.ip));
        printf("  We have now connected to a station and can do things...\n");
        s_retry_num = 0;
        xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
        mqttServiceStart();
    }
}

where mqttServiceStart and Stop are:

Code: Select all

 
 void mqttServiceInit(){
	
	//certificates loaded from SDcard
	const char *ca_cert = loadCert("ca.crt");
	const char *esp_cert = loadCert("esp.crt");
	const char *esp_key= loadCert("esp.key");

	const esp_mqtt_client_config_t mqtt_cfg = {
		.host = "mosquitto",
		.port = 8883,
		.transport = MQTT_TRANSPORT_OVER_SSL,
		.event_handle = mqtt_event_handler,
		.cert_pem = ca_cert,
		.client_cert_pem = esp_cert,
		.client_key_pem = esp_key,
		.username = "espuser",
		.password = "espassword"
	};

	//myMQTTclient is a global variable
	myMQTTclient = esp_mqtt_client_init(&mqtt_cfg);

}
 
 
void mqttServiceStart(){
    mqttServiceInit();
    esp_mqtt_client_start(myMQTTclient);
    xTaskCreate(mqttTask, "mqtt_task", 8192, NULL, 3, &mqttTaskHandle); //this is a task that periodically posts sensors values to topics
}

void mqttServiceStop(){

	if( mqttTaskHandle != NULL ){
		 vTaskDelete(mqttTaskHandle);
		 mqttTaskHandle = NULL;
		 esp_mqtt_client_stop(myMQTTclient);
	}
}
I've been trying to fix this for days, but I'm missing something.
How can safely reconnect wifi and MQTT if I loose wifi connection.

Thanks in advance for your help!

Gustav

Gustav
Posts: 7
Joined: Tue Aug 18, 2020 7:57 am

Re: MQTT: How to handle wifi disconnection

Postby Gustav » Tue Mar 02, 2021 7:05 pm

If you stumble upon this topic the first thing you should know is that this line in the log is the key:

Code: Select all

mbedtls_ssl_setup returned -0x7f00
According to ssl.h it means MBEDTLS_ERR_SSL_ALLOC_FAILED which means Memory allocation failed.

So I discovered that using cJson to create my mqtt messages was causing a memory leak. I still don't know where exactly, since I used all the delete needed, but apparently not enough. removing cJson and formatting my messages using strings (tedious) fixed the memory leak, and fixing the memory leak incidentally fixed (or for the time being, at least mitigated) the wifi disconnection.

Although the problem itself is fixed, my question still stands because in case of a disconnection and reconnection, I can see that the free heap is less than before the disconnection. In case of an unstable wifi connection this will eventually fill the heap returning to the original problem.

Thanks to anyone that will help me

chegewara
Posts: 2362
Joined: Wed Jun 14, 2017 9:00 pm

Re: MQTT: How to handle wifi disconnection

Postby chegewara » Tue Mar 02, 2021 7:31 pm

You seems to have "mqttTask" which is probably the cause of memory leak. Task on deletion will free task stack, but any memory allocation in task, static variables are not releasing memory.
Gustav wrote: How can safely reconnect wifi and MQTT if I loose wifi connection.
I think you dont have to delete task and recreate it after reconnect wifi, mqtt stack should try to reconnect.

Who is online

Users browsing this forum: No registered users and 275 guests