Disconnections from Losant (MQTT NOT AUTHORIZED = 5 // MQTT_CONNECTION_DENIED = -10)

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.

Hello again. I have finally found the error. The error came from working with Gateways and Peripherals and I think it is something very important to take into account, especially at the level of code and at the level of examples in the Github (since there is only uploaded example of a Standalone device).

Basically, to report peripheral device states, we have to use the function

device.setId(perifericalId);

and then send the corresponding data.

The problem comes when the WiFi connection drops. The device has the peripheral’s ID set as the last ID, so when it tries to reconnect to Losant the MQTT connection is rejected (because a peripheral can never connect to Losant).

To solve this, in the Losant reconnect function, I have added an

device.setId(GATEWAY_ID);

before
device.connectSecure(wifiClient, LOSANT_KEY, LOSANT_SECRET);

so that the reconnection is made with the gateway ID (and not with the last peripheral that used the setId() function).

I think it is important to clarify this (or upload an example that references Gateway+Peripherals in Github) to clarify this possible doubt, since I had a hard time debugging what the heck was going on.

Thanks anyway, best regards.

Thanks for the info. I’ll make a note to at least document in the repo how to handle peripherals in the Losant MQTT Arduino library. Our other clients support gateway/peripheral relationships; I’ll also check with the engineering team about if that’s something we can add to this library.