ESP32 lwmqtt_network_failed_connect

Hello,

I’m retooling into the ESP32 and I’m having difficulty establishing a connection. I created a device in the dashboard, copied its device ID, my access key, and secret into the esp32.ino sourced from here:

I’m receiving this error:
LWMQTT_NETWORK_FAILED_CONNECT = -3
according to this code:

and Return Code 0.

I’ve confirmed it is getting an IP and I can see it on my network.

I’m using the Node32S board in ArduinoIDE to do the programming, and this is the board:

Any help pushing through this would be greatly appreciated.

Hey @Wayne_Hughes,

LWMQTT_NETWORK_FAILED_CONNECT = -3 is usually associated with having something incorrect in the MQTT credentials.

Can you confirm that the access key, access secret, and device ID that you copied over were pasted correctly? Using something like a web based MQTT client may also help troubleshoot this issue (by using your device’s credentials to connect to the Losant broker).

If you try using #include <WiFiClient.h> instead of #include <WiFiClientSecure.h>, and then using WiFiClient wifiClient; instead of WiFiClientSecure wifiClient;, and device.connect(...) instead of device.connectSecure(...), do you get the same error? This is using the unsecure (non-TLS) connection to the Losant broker rather than the TLS connection.

In the meantime, I will test on an ESP32 I have handy, and will update you with what I find.

Thank you,
Heath

Thanks, Heath. I’m very certain my device creds match. I triple checked those and use the simulator to establish a connection. I have no idea what fields to map to the device creds and keys in the website you listed. :frowning:

I tried the changes you listed, but now it doesn’t like the WiFi keyword (even though it’s listed as one in my library). Perhaps I missed something? I get “‘WiFi’ was not declared in this scope.”

Here’s my code with sensitive info removed:

/**
 * Example that connects an ESP32 based board to the Losant
 * IoT platform. This example reports state to Losant whenever a button is
 * pressed. It also listens for the "toggle" command to turn the LED on and off.
 *
 * This example assumes the following connections:
 * Button connected to pin 14.
 * LED connected to pin 12.
 *
 * Copyright (c) 2021 Losant. All rights reserved.
 * http://losant.com
 */

#include <WiFiClient.h>
#include <Losant.h>

// WiFi credentials.
const char* WIFI_SSID = "my-ssid";
const char* WIFI_PASS = "my-password";

// Losant credentials.
const char* LOSANT_DEVICE_ID = "my-device-id"; 
const char* LOSANT_ACCESS_KEY = "my-access-key";
const char* LOSANT_ACCESS_SECRET = "my-access-secret";

const int BUTTON_PIN = 14;
const int LED_PIN = 12;

bool ledState = false;

// initiate the the wifi client
WiFiClient wifiClient;

LosantDevice device(LOSANT_DEVICE_ID);

void toggle() {
  Serial.println("Toggling LED.");
  ledState = !ledState;
  digitalWrite(LED_PIN, ledState ? HIGH : LOW);
}

// Called whenever the device receives a command from the Losant platform.
void handleCommand(LosantCommand *command) {
  Serial.print("Command received: ");
  Serial.println(command->name);

  // Optional command payload. May not be present on all commands.
  // JsonObject payload = *command->payload;

  // Perform action specific to the command received.
  if(strcmp(command->name, "toggle") == 0) {
    toggle();
    /**
    * In Losant, including a payload along with your
    * command is optional. This is an example of how
    * to parse a JSON payload from Losant and print
    * the value of a key called "temperature".
    */
    // int temperature = payload["temperature"];
    // Serial.println(temperature);
  }
}

void connect() {

  // Connect to Wifi.
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(WIFI_SSID);

  WiFi.begin(WIFI_SSID, WIFI_PASS);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }  

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // Connect to Losant.
  Serial.println();
  Serial.print("Connecting to Losant...");

  device.connect(wifiClient, LOSANT_ACCESS_KEY, LOSANT_ACCESS_SECRET);

  while(!device.connected()) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("Connected!");
}

void setup() {
  Serial.begin(115200);
  while(!Serial) { }
  pinMode(BUTTON_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);

  // Register the command handler to be called when a command is received
  // from the Losant platform.
  device.onCommand(&handleCommand);

  connect();
}

void buttonPressed() {
  Serial.println("Button Pressed!");

  // Losant uses a JSON protocol. Construct the simple state object.
  // { "button" : true }
  StaticJsonDocument<200> jsonBuffer;
  JsonObject root = jsonBuffer.to<JsonObject>();
  root["button"] = true;

  // Send the state to Losant.
  device.sendState(root);
}

int buttonState = 0;

void loop() {

  bool toReconnect = false;

  if(WiFi.status() != WL_CONNECTED) {
    Serial.println("Disconnected from WiFi");
    toReconnect = true;
  }

  if(!device.connected()) {
    Serial.println("Disconnected from Losant");
    toReconnect = true;
  }

  if(toReconnect) {
    connect();
  }

  device.loop();

  int currentRead = digitalRead(BUTTON_PIN);

  if(currentRead != buttonState) {
    buttonState = currentRead;
    if(buttonState) {
      buttonPressed();
    }
  }

  delay(100);
}

I’m getting the same error on several different ESP32’s I have. The library is also not working on an Arduino Nano IoT 33.

Switching to the insecure version works for both.

Hey @Justin_Decker - can you post the insecure version you are using, please? I’m not having success with the above listed steps. Thanks.

Edit - got lucky and tried WiFi.h instead of WiFiClient.h. Now the client connects successfully over http.

Changed the library back to WiFiClientSecure.h and it is failing to connect. Seems there’s a problem in the library? Are you able to validate that, @Heath ?

@Heath - Can we get a status update on what the problem may be, please? It’s been a week with no comms.

@Wayne_Hughes,

I am working on getting a fix for you now. Since the WifiClientSecure is not a library that Losant has any involvement with, I can’t be sure if something changed with it. I am, though, going to do some digging and some testing today. I will follow up with you shortly, hopefully with good news.

Heath

@Wayne_Hughes & @Justin_Decker,

I did some digging this morning and have found a potential solution. Here’s the updated code:

/**
 * Example that connects an ESP32 based board to the Losant
 * IoT platform. This example reports state to Losant whenever a button is
 * pressed. It also listens for the "toggle" command to turn the LED on and off.
 *
 * This example assumes the following connections:
 * Button connected to pin 14.
 * LED connected to pin 12.
 *
 * Copyright (c) 2021 Losant. All rights reserved.
 * http://losant.com
 */

#include <WiFiClientSecure.h>
#include <Losant.h>

// WiFi credentials.
const char* WIFI_SSID = "";
const char* WIFI_PASS = "";

// Losant credentials.
const char* LOSANT_DEVICE_ID = "";
const char* LOSANT_ACCESS_KEY = "";
const char* LOSANT_ACCESS_SECRET = "";

const int BUTTON_PIN = 14;
const int LED_PIN = 12;

bool ledState = false;

const char* rootCABuff = \
"-----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-----\n";

// initiate the the wifi client
WiFiClientSecure wifiClient;

LosantDevice device(LOSANT_DEVICE_ID);

void toggle() {
  Serial.println("Toggling LED.");
  ledState = !ledState;
  digitalWrite(LED_PIN, ledState ? HIGH : LOW);
}

// Called whenever the device receives a command from the Losant platform.
void handleCommand(LosantCommand *command) {
  Serial.print("Command received: ");
  Serial.println(command->name);

  // Optional command payload. May not be present on all commands.
  // JsonObject payload = *command->payload;

  // Perform action specific to the command received.
  if(strcmp(command->name, "toggle") == 0) {
    toggle();
    /**
    * In Losant, including a payload along with your
    * command is optional. This is an example of how
    * to parse a JSON payload from Losant and print
    * the value of a key called "temperature".
    */
    // int temperature = payload["temperature"];
    // Serial.println(temperature);
  }
}

void connect() {

  // Connect to Wifi.
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(WIFI_SSID);

//  wifiClient.setInsecure();

  WiFi.begin(WIFI_SSID, WIFI_PASS);
  wifiClient.setCACert(rootCABuff);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }  

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // Connect to Losant.
  Serial.println();
  Serial.print("Connecting to Losant...");

  device.connectSecure(wifiClient, LOSANT_ACCESS_KEY, LOSANT_ACCESS_SECRET);

  while(!device.connected()) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("Connected!");
}

void setup() {
  Serial.begin(115200);
  while(!Serial) { }
  pinMode(BUTTON_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);

  // Register the command handler to be called when a command is received
  // from the Losant platform.
  device.onCommand(&handleCommand);

  connect();
}

void buttonPressed() {
  Serial.println("Button Pressed!");

  // Losant uses a JSON protocol. Construct the simple state object.
  // { "button" : true }
  StaticJsonDocument<200> jsonBuffer;
  JsonObject root = jsonBuffer.to<JsonObject>();
  root["button"] = true;

  // Send the state to Losant.
  device.sendState(root);
}

int buttonState = 0;

void loop() {

  bool toReconnect = false;

  if(WiFi.status() != WL_CONNECTED) {
    Serial.println("Disconnected from WiFi");
    toReconnect = true;
  }

  if(!device.connected()) {
    Serial.println("Disconnected from Losant");
    toReconnect = true;
  }

  if(toReconnect) {
    connect();
  }

  device.loop();

  int currentRead = digitalRead(BUTTON_PIN);

  if(currentRead != buttonState) {
    buttonState = currentRead;
    if(buttonState) {
      buttonPressed();
    }
  }

  delay(100);
}

What I was able to find is that prior to 2019, the root CA that Losant’s certificate chained down to came on the ESP32 by default. In 2019, some changes were made and that was no longer the case. Now, to use a secure connection to Losant, you either need to set the root CA on the device, or not verify the certificate coming from the server (not really that secure).

I will be updating the official example in our code today so that this does not happen again in the future.

Please let me know if this works for you, or if you run into any other roadblocks.

Thank you,
Heath

Hi @Heath,

This works in a standalone scenario, but it’s giving me trouble in my other sketches. I had actually started to use the cert from the ESP8266 sketches, but was unsuccessful in that endeavor. Thank you so much for sorting this and providing working code!