Good morning. I am writing to you due to a strange error I am encountering when sending MQTT with statuses from an ESP32. The device is a device that works as a gateway and reports status from different peripheral devices every 10 seconds.
My main problem is that, randomly after a while the device gets disconnected from Losant and is unable to reconnect using the functions of the examples. After a thorough debugging, using the functions that allow me to get the error code from the MQTT client
Serial.println(device.mqttClient.lastError());
Serial.println(device.mqttClient.returnCode())
I find that the error that is occurring is as follows:
LWMQTT_CONNECTION_DENIED = -10,
LWMQTT_NOT_AUTHORIZED = 5,
(lwmqtt/lwmqtt.h at master · 256dpi/lwmqtt · GitHub)
(lwmqtt/lwmqtt.h at master · 256dpi/lwmqtt · GitHub)
The device, however, as soon as I plug it in it connects to Losant and is sending data after quite a long time. I attach a screenshot of a dashboard where you can see that the error appears after several hours of sending (usually the disconnection occurs after 2-3 hours of sending, holding even up to 8 hours).
Reviewing other topics in the forum, I have changed the flag MQTT_MAX_PACKET_SIZE to a value of 256. I have also monitored the Heap memory and it never goes below 200,000.
On the other hand, since I use an ESP32, I have encrypted the Losant certificate so that I can send MQTT securely. I set this certificate using the function
wifiClient.setCACert(root_ca_mqtt_losant);
where root_ca_mqtt_losant =
"-----BEGIN CERTIFICATE-----\n"
"MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\n"
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n"
"QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\n"
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n"
"b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n"
"9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\n"
"CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\n"
"nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n"
"43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\n"
"T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\n"
"gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\n"
"BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\n"
"TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\n"
"DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\n"
"hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n"
"06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\n"
"PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\n"
"YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\n"
"CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n"
"-----END CERTIFICATE-----";
If I do not perform this operation, it is impossible for me to connect securely to Losant (connectSecure() does not work, and it is essential for my project that the MQTTs are secure). I don’t know how important this step can be, but I comment it just in case.
My code, removing parts not related to this problem, has the following form:
#include <Arduino.h>
#include <WiFi.h>
#include "WiFiClientSecure.h"
#include <Losant.h>
#include <ModbusIP_ESP8266.h>
#include <EEPROM.h>
#include <certificates.h>
#include <secrets.h>
#define DEBUG true
//WiFi credentials
const char *SSID = SSID_SECRET;
const char *PASS = PASS_SECRET;
//Losant credentials
const char *LOSANT_ID = ID;
const char *LOSANT_KEY = KEY;
const char *LOSANT_SECRET = SECRET;
WiFiClientSecure wifiClient; //Initialize Secure WiFi Client
LosantDevice device(LOSANT_ID); //Initialize Losant Device
//Auxiliar functions declaration
void wifiConnect();
void WiFiStationDisconnected(WiFiEvent_t event, WiFiEventInfo_t info);
void LosantReconnect();
void setup()
{
#if DEBUG
Serial.begin(9600);
#endif
WiFi.config(ip, gateway, subnet, dns); //Set IP of the device
wifiConnect();
}
void loop()
{
unsigned long currentMillis = millis();
while (currentMillis - previousMillis >= FREQUENCY_CONSULT) //the devices are consulted sequentially every 10 seconds, one device after the other
{
#if DEBUG
Serial.println(ESP.getFreeHeap());
#endif
previousMillis = currentMillis;
LosantReconnect();
device.loop();
delay(10);
//OBTAIN DATA FROM MODBUS TCP
#if DEBUG
Serial.println("Sending data to Losant.");
Serial.println();
#endif
//JSON parser document
StaticJsonDocument<250> doc; //Important to set a value that is larger than the payload we want to send
JsonObject data = doc.to<JsonObject>();
//Currents
data["cL1"] = finalRegisters[0]; //currentL1
data["cL2"] = finalRegisters[1]; //currentL2
data["cL3"] = finalRegisters[2]; //currentL3
data["sC"] = finalRegisters[3]; //Sum currents
//Power
data["rP"] = finalRegisters[4]; //real power
data["aP"] = finalRegisters[5]; //apparent power
data["rcP"] = finalRegisters[6]; //reactive power
//Energy
data["rE"] = finalRegisters[7]; //real energy
data["aE"] = finalRegisters[8]; //apparent energy
data["rcE"] = finalRegisters[9]; //reactive energy
//Harmonics
data["hL1N"] = finalRegisters[10]; //harmonicL1N
data["hL2N"] = finalRegisters[11]; //harmonicL2N
data["hL3N"] = finalRegisters[12]; //harmonicL3N
device.setId(perifericalId); //With this function we determine the ID of the periferical device to send data to Losant.
device.sendState(data); //Send data to Losant
}
device.loop();
delay(10);
}
}
}
}
void wifiConnect()
{
previousMillisReconnect_wifi = millis();
if (WiFi.status() != WL_CONNECTED)
{
WiFi.begin(SSID, PASS);
while (WiFi.status() != WL_CONNECTED)
{
#if DEBUG
Serial.print(".");
#endif
delay(500);
}
#if DEBUG
Serial.println("Successfully connected to WiFi!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
Serial.print("MAC: ");
Serial.println(WiFi.macAddress());
#endif
wifiClient.setCACert(root_ca_mqtt_losant); //Set the Certificate in order to establish a secure MQTT Connection
}
}
void LosantReconnect(){
if (!device.connected()){
while (!device.connected()){
device.disconnect(); //Try to fix the MQTT NOT AUTHORIZED error
device.mqttClient.disconnect(); //Try to fix the MQTT NOT AUTHORIZED error
device.connectSecure(wifiClient, LOSANT_KEY, LOSANT_SECRET);
delay(1000);
#if DEBUG
Serial.println(ESP.getFreeHeap());
Serial.print("*");
Serial.println(device.mqttClient.lastError());
Serial.println(device.mqttClient.returnCode());
#endif
}
}
}
As I comment, the code is functional, but at a certain point, Losant does not allow me to reconnect if the device disconnects from the cloud and I have to manually restart the ESP32, which is a problem for me.
Thank you very much for your attention, I look forward to your reply.