MKR WiFi 1010 stuck checking MQTT Connection

Board: MKR WiFi 1010
IDE: Arduino IDE
OS: Mac

I'm running this example from Arduino Cloud Provider Examples, AWS IoT WiFi.

/*
  AWS IoT WiFi

  This sketch securely connects to an AWS IoT using MQTT over WiFi.
  It uses a private key stored in the ATECC508A and a public
  certificate for SSL/TLS authetication.

  It publishes a message every 5 seconds to arduino/outgoing
  topic and subscribes to messages on the arduino/incoming
  topic.

  The circuit:
  - Arduino MKR WiFi 1010 or MKR1000

  The following tutorial on Arduino Project Hub can be used
  to setup your AWS account and the MKR board:

  https://create.arduino.cc/projecthub/132016/securely-connecting-an-arduino-mkr-wifi-1010-to-aws-iot-core-a9f365

  This example code is in the public domain.
*/

#include <ArduinoBearSSL.h>
#include <ArduinoECCX08.h>
#include <ArduinoMqttClient.h>
#include <WiFiNINA.h> // change to #include <WiFi101.h> for MKR1000

#include "arduino_secrets.h"

/////// Enter your sensitive data in arduino_secrets.h
const char ssid[]        = SECRET_SSID;
const char pass[]        = SECRET_PASS;
const char broker[]      = SECRET_BROKER;
const char* certificate  = SECRET_CERTIFICATE;

BearSSLClient sslClient; // Used for SSL/TLS connection, integrates with ECC508
MqttClient    mqttClient(sslClient);

unsigned long lastMillis = 0;

void setup() {
  Serial.begin(115200);
  while (!Serial);

  if (!ECCX08.begin()) {
    Serial.println("No ECCX08 present!");
    while (1);
  }

  // Set a callback to get the current time
  // used to validate the servers certificate
  ArduinoBearSSL.onGetTime(getTime);

  // Set the ECCX08 slot to use for the private key
  // and the accompanying public certificate for it
  sslClient.setEccSlot(0, certificate);

  // Optional, set the client id used for MQTT,
  // each device that is connected to the broker
  // must have a unique client id. The MQTTClient will generate
  // a client id for you based on the millis() value if not set
  //
  // mqttClient.setId("clientId");

  // Set the message callback, this function is
  // called when the MQTTClient receives a message
  mqttClient.onMessage(onMessageReceived);
}

void loop() {
  if (WiFi.status() != WL_CONNECTED) {
    connectWiFi();
  }

  Serial.println("Checking for MQTT connection...");
  if (!mqttClient.connected()) {
    // MQTT client is disconnected, connect
    Serial.println("Not connected to MQTT broker");
    connectMQTT();
  }

  // poll for new MQTT messages and send keep alives
  mqttClient.poll();

  // publish a message roughly every 5 seconds.
  if (millis() - lastMillis > 5000) {
    lastMillis = millis();

    publishMessage();
  }
}

unsigned long getTime() {
  // get the current time from the WiFi module
  return WiFi.getTime();
}

void connectWiFi() {
  Serial.print("Attempting to connect to SSID: ");
  Serial.print(ssid);
  Serial.print(" ");

  while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
    // failed, retry
    Serial.print(".");
    delay(5000);
  }
  Serial.println();

  Serial.println("You're connected to the network");
  Serial.println();
}

void connectMQTT() {
  Serial.print("Attempting to MQTT broker: ");
  Serial.print(broker);
  Serial.println(" ");

  while (!mqttClient.connect(broker, 8883)) {
    // failed, retry
    Serial.print(".");
    delay(5000);
  }
  Serial.println();

  Serial.println("You're connected to the MQTT broker");
  Serial.println();

  // subscribe to a topic
  mqttClient.subscribe("arduino/incoming");
}

void publishMessage() {
  Serial.println("Publishing message");

  // send message, the Print interface can be used to set the message contents
  mqttClient.beginMessage("arduino/outgoing");
  mqttClient.print("hello ");
  mqttClient.print(millis());
  mqttClient.endMessage();
}

void onMessageReceived(int messageSize) {
  // we received a message, print out the topic and contents
  Serial.print("Received a message with topic '");
  Serial.print(mqttClient.messageTopic());
  Serial.print("', length ");
  Serial.print(messageSize);
  Serial.println(" bytes:");

  // use the Stream interface to print the contents
  while (mqttClient.available()) {
    Serial.print((char)mqttClient.read());
  }
  Serial.println();

  Serial.println();
}

The output is as follows:

Attempting to connect to SSID: ***** 
You're connected to the network

Checking for MQTT connection...

And it just gets stuck there. It's not even to the connection part. What could be the issue?

According to the code it is connected. In order to be sure add another print before the .poll saying polling or similar.

But it never prints "Attempting to MQTT broker:" or "You're connected to the MQTT broker". And the broker never receives any messages.

Do you know if .poll returns?
When I created my MQTT project, I never had a poll, so I don't know if it blocks or not, but I am suspicious. An easy way to tell is to debug each side of the call.

I added this:

Serial.println("Polling MQTT...");
mqttClient.poll();
Serial.println("Done polling MQTT");

Neither of these print. It gets stuck before this. At mqttClient.connected()

Sorry, I can't help further. I don't have that board in my boards file. What I would do is look at the code for the connected member of the mqtt library.

connected is just

uint8_t MqttClient::connected()
{
  return clientConnected() && _connected;
}

which first calls

uint8_t MqttClient::clientConnected()
{
  return _client->connected();
}

So given that you have

you could first try -- with println around everything to see where things get stuck

Serial.println("sslClient is connected?");
Serial.println(sslClient.connected());
Serial.println("did it work?");

To compare, you can try an unencrypted connection, using a plain WiFiClient, to a public test server like test.mosquitto.org on port 1883.

You might also try to connect at the end of setup and see if that says something or does something that helps.

Finally, AWS IoT uses mutual TLS (mTLS), which requires a key pair for the client. That's the mutual part: the client verifies the server and vice versa. While there is some mention of the private key in some code comments, there isn't one in the code; only the public key certificate. The text of the SECRET_CERTIFICATE likely starts with -----BEGIN CERTIFICATE-----. Do you have anything with a -----BEGIN RSA PRIVATE KEY-----? When you generate the key pair in the AWS Console, you download both at the same time.

Fixed with the following lines:

WiFiClient    wifiClient;            // Used for the TCP socket connection
BearSSLClient sslClient(wifiClient); // Used for SSL/TLS connection, integrates with ECC508
MqttClient    mqttClient(sslClient);

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