ESP8266 does not connect to AWS IoT MQTT broker

Hello, my ESP8266 cannot connect to AWS IoT MQTT broker via PubSubClient.

  • PubSubClient returns status -2.
  • My AWS IoT logs are empty.
  • ESP8266 connects to WiFi.
  • I can ping my AWS IoT endpoint from my PC.
  • I can connect using same credentials from my ESP32 via MQTTClient.
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char *ssid = "myinternetname";
const char *password = "mpass";

const char *awsEndpoint = "xxxxxxxxxxxxxxx-ats.iot.us-east-2.amazonaws.com";

// xxxxxxxxxx-certificate.pem.crt
const char *certificate_pem_crt =

    "-----BEGIN CERTIFICATE-----\n"
    "MIIDWTCCAkGgAwIBAgIUJ1gT+uvYaUrsqYAuKDGCCY+exfEwDQYJKoZIhvcNAQEL\n"
    "-----END CERTIFICATE-----\n";

// xxxxxxxxxx-private.pem.key
const char *private_pem_key =

    "-----BEGIN RSA PRIVATE KEY-----\n"
    "MIIEpAIBAAKCAQEA3mf0dUwoQY47sL1DL9yKlwoafBpRwgXLqo6bb+ZFKyqmSmU0\n"
    "-----END RSA PRIVATE KEY-----\n";

const char *rootCA =
    "-----BEGIN CERTIFICATE-----\n"
    "MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB\n"
    "-----END CERTIFICATE-----\n";

BearSSL::X509List CERT_CA(rootCA);
BearSSL::X509List CERT_CRT(certificate_pem_crt);
BearSSL::PrivateKey CERT_PRIVATE(private_pem_key);

WiFiClientSecure wiFiClient;
void msgReceived(char *topic, byte *payload, unsigned int len);
PubSubClient pubSubClient(awsEndpoint, 8883, msgReceived, wiFiClient);

void connectToMQTT();

void setup()
{
    Serial.begin(9600);
    delay(50);
    Serial.println();
    Serial.println("ESP8266 AWS IoT Example");
    Serial.printf("SDK version: %s\n", ESP.getSdkVersion());

    Serial.print("Connecting to ");
    Serial.print(ssid);
    WiFi.begin(ssid, password);
    WiFi.waitForConnectResult();
    Serial.print(", WiFi connected, IP address: ");
    Serial.println(WiFi.localIP());

    wiFiClient.setTrustAnchors(&CERT_CA);
    wiFiClient.setClientRSACert(&CERT_CRT, &CERT_PRIVATE);
}

unsigned long lastPublish;
int msgCount;

void loop()
{
    connectToMQTT();

    if (millis() - lastPublish > 10000)
    {
        String msg = String("Hello from ESP8266: ") + ++msgCount;
        boolean rc = pubSubClient.publish("outTopic", msg.c_str());
        Serial.print("Published, rc=");
        Serial.print((rc ? "OK: " : "FAILED: "));
        Serial.println(msg);
        lastPublish = millis();
    }
}

void msgReceived(char *topic, byte *payload, unsigned int length)
{
    Serial.print("Message received on ");
    Serial.print(topic);
    Serial.println();
}

void connectToMQTT()
{
    if (!pubSubClient.connected())
    {
        Serial.print("PubSubClient connecting to: ");
        Serial.print(awsEndpoint);
        while (!pubSubClient.connected())
        {
            Serial.print(".");
            pubSubClient.connect("ESPthingXXXX");
            delay(1000);
        }
        Serial.println(" connected");
        pubSubClient.subscribe("inTopic");
    }
    pubSubClient.loop();
}

I noticed in the connectToMqtt() function that the function does not check for a valid WiFi connection before trying the MQTT connect thingy. If WiFi is not connected then MQTT will not connect.

here is how I do the thing.


void MQTTkeepalive( void *pvParameters )
{
  sema_MQTT_KeepAlive   = xSemaphoreCreateBinary();
  xSemaphoreGive( sema_MQTT_KeepAlive ); // found keep alive can mess with a publish, stop keep alive during publish
  MQTTclient.setKeepAlive( 90 ); // setting keep alive to 90 seconds makes for a very reliable connection, must be set before the 1st connection is made.
  TickType_t xLastWakeTime = xTaskGetTickCount();
  const TickType_t xFrequency = 250; //delay for ms
  for (;;)
  {
    //check for a is-connected and if the WiFi 'thinks' its connected, found checking on both is more realible than just a single check
    if ( (wifiClient.connected()) && (WiFi.status() == WL_CONNECTED) )
    {
      xSemaphoreTake( sema_MQTT_KeepAlive, portMAX_DELAY ); // whiles MQTTlient.loop() is running no other mqtt operations should be in process
      MQTTclient.loop();
      xSemaphoreGive( sema_MQTT_KeepAlive );
    }
    else {
      log_i( "MQTT keep alive found MQTT status % s WiFi status % s", String(wifiClient.connected()), String(WiFi.status()) );
      if ( !(wifiClient.connected()) || !(WiFi.status() == WL_CONNECTED) )
      {
        connectToWiFi();
      }
      connectToMQTT();
    }
    //log_i( " high watermark % d",  uxTaskGetStackHighWaterMark( NULL ) );
    xLastWakeTime = xTaskGetTickCount();
    vTaskDelayUntil( &xLastWakeTime, xFrequency );
  }

Notice I check for a WiFi connection before running client.loop().

Hi, I presume the code you provided was taken not from ESP8266 board's code? Actually, I do use the same logic you provided in my ESP32 code and it does connect to my broker. But FreeRTOS is not available in ESP8266.

I added a check if WiFi is connected before connecting to MQTT.

PS: I did check if WiFi is connected before connecting to MQTT and it actually is.

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>

const char *ssid = "myssid";
const char *password = "mypass";

#include <MQTTClient.h>

const char *awsEndpoint = "xxxxxxxxxxxxxxx-ats.iot.us-east-2.amazonaws.com";

// xxxxxxxxxx-certificate.pem.crt
const char *certificate_pem_crt =

    "-----BEGIN CERTIFICATE-----\n"
    "MIIDWTCCAkGgAwIBAgIUJ1gT+uvYaUrsqYAuKDGCCY+exfEwDQYJKoZIhvcNAQEL\n"
    "-----END CERTIFICATE-----\n";

// xxxxxxxxxx-private.pem.key
const char *private_pem_key =

    "-----BEGIN RSA PRIVATE KEY-----\n"
    "MIIEpAIBAAKCAQEA3mf0dUwoQY47sL1DL9yKlwoafBpRwgXLqo6bb+ZFKyqmSmU0\n"
    "-----END RSA PRIVATE KEY-----\n";

/* root CA can be downloaded in:
  https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem
*/
const char *rootCA =
    "-----BEGIN CERTIFICATE-----\n"
    "MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB\n"
    "-----END CERTIFICATE-----\n";

BearSSL::X509List CERT_CA(rootCA);
BearSSL::X509List CERT_CRT(certificate_pem_crt);
BearSSL::PrivateKey CERT_PRIVATE(private_pem_key);

WiFiClientSecure wiFiClient;
void msgReceived(char *topic, byte *payload, unsigned int len);
PubSubClient pubSubClient(awsEndpoint, 8883, msgReceived, wiFiClient);

void connectToMQTT();
void connectToWiFi();

void setup()
{
    Serial.begin(9600);
    delay(50);
    Serial.println();
    Serial.println("ESP8266 AWS IoT Example");
    Serial.printf("SDK version: %s\n", ESP.getSdkVersion());

    connectToWiFi();
}

unsigned long lastPublish;
int msgCount;

void loop()
{
    connectToMQTT();

    if (millis() - lastPublish > 10000)
    {
        String msg = String("Hello from ESP8266: ") + ++msgCount;
        boolean rc = pubSubClient.publish("outTopic", msg.c_str());
        Serial.print("Published, rc=");
        Serial.print((rc ? "OK: " : "FAILED: "));
        Serial.println(msg);
        lastPublish = millis();
    }
}

void msgReceived(char *topic, byte *payload, unsigned int length)
{
    Serial.print("Message received on ");
    Serial.print(topic);
    Serial.println();
}

void connectToWiFi()
{
    Serial.print("Connecting to ");
    Serial.print(ssid);

    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    WiFi.waitForConnectResult();
    Serial.println("Connecting to WiFi...");

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

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

    wiFiClient.setTrustAnchors(&CERT_CA);
    wiFiClient.setClientRSACert(&CERT_CRT, &CERT_PRIVATE);
}

void connectToMQTT()
{
    if (WiFi.status() != WL_CONNECTED)
    {
        connectToWiFi();
    }

    if (!pubSubClient.connected())
    {
        Serial.print("PubSubClient connecting to: ");
        Serial.print(awsEndpoint);
        while (!pubSubClient.connected())
        {
            Serial.print(".");
            pubSubClient.connect("ESPthingXXXX");
            delay(1000);
        }
        Serial.println(" connected");
        pubSubClient.subscribe("inTopic");
    }
    pubSubClient.loop();
}

This code

void connectToMQTT()
{
    if (WiFi.status() != WL_CONNECTED)
    {
        connectToWiFi();
    }

    if (!pubSubClient.connected())
    {
        Serial.print("PubSubClient connecting to: ");
        Serial.print(awsEndpoint);
        while (!pubSubClient.connected())
        {
            Serial.print(".");
            pubSubClient.connect("ESPthingXXXX");
            delay(1000);
        }
        Serial.println(" connected");
        pubSubClient.subscribe("inTopic");
    }
    pubSubClient.loop();
}

assumes a WiFi connection has been made. Even though the code checks for WiFi, the rest of the code assumes a valid WiFI connection has been made.

freeRTOS stuff removed

if ( (wifiClient.connected()) && (WiFi.status() == WL_CONNECTED) )
    {
      MQTTclient.loop();
    }

No assumption that WiFi is connected.

Have you used a 3rd party app, like MQTT.fx to connect to AWS and confirm the AWS thingies are correct? I found that using a 3rd party app to make sure my AWS security stuff is correct is much easier to do.

For testing purposes, I am using the same thingname, certificates and etc. from my ESP32 which successfully connects (it's off now). This ESP8266 does not connect with the same stuff.

Tried adding below connectToMQTT and under loop, still nothing. The result in logs:

Connecting to MyWiFiNameConnecting to WiFi...
, WiFi connected, IP address: 192.168.1.216
MQTT keep alive found MQTT status 0 WiFi status 3

Connecting to MyWiFiNameConnecting to WiFi...
, WiFi connected, IP address: 192.168.1.216
PubSubClient connecting to: xxxxxxxxxxx-ats.iot.us-east-2.amazonaws.com............................................
void loop()
{
    if ((wiFiClient.connected()) && (WiFi.status() == WL_CONNECTED))
    {
        pubSubClient.loop();
    }
    else
    {
        Serial.print("MQTT keep alive found MQTT status ");
        Serial.print(String(wiFiClient.connected()));
        Serial.print(" WiFi status ");
        Serial.print(String(WiFi.status()));
        Serial.print("\n\n");

        if (!(wiFiClient.connected()) || !(WiFi.status() == WL_CONNECTED))
        {
            connectToWiFi();
        }

        connectToMQTT();
    }

One thing i notice Is that the way we pass certificates and key in esp32 code is different than the way we do it for 8266 . I am facing the same problem with 8266z can someone help

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.