Hi, I'm trying to create a method to reconnect my Arduino OPTA to the AWS MQTT broker when it loses connection, without blocking the main thread.**
Following the official guide: https://docs.arduino.cc/tutorials/opta/getting-started-with-aws-iot-core/, and opening the file:
File > Examples > Arduino Cloud Provider Examples > AWSIoT > AWS_IoT_Opta -> AWS_IoT_Opta_wifi > AWS_IoT_Opta_wifi.ino, I see that the connectMqtt() function:
void connectMQTT()
{
Serial.print("Attempting to MQTT broker: ");
Serial.print(broker);
Serial.print(":");
Serial.print(port);
Serial.println();
int status;
while ((status = mqttClient.connect(broker, port)) == 0) {
// failed, retry
Serial.println(status);
delay(1000);
}
Serial.println();
Serial.println("You're connected to the MQTT broker");
Serial.println();
// subscribe to a topic with QoS 1
constexpr char incomingTopic[] { "arduino/incoming" };
constexpr int incomingQoS { 1 };
Serial.print("Subscribing to topic: ");
Serial.print(incomingTopic);
Serial.print(" with QoS ");
Serial.println(incomingQoS);
mqttClient.subscribe(incomingTopic, incomingQoS);
}
has a potentially infinite while loop. I tried to do it this way:
#include <ArduinoECCX08.h>
#include <ArduinoMqttClient.h>
#include <Arduino_ConnectionHandler.h>
#include <ArduinoBearSSL.h>
#include <Arduino_JSON.h>
#include <NTPClient.h>
#include <mbed_mktime.h>
#include <WiFi.h>
#include <WiFiUdp.h>
#include "network_manager.h"
const char broker[] { SECRET_BROKER };
const unsigned port { SECRET_PORT };
const char* certificate { SECRET_CERTIFICATE };
const char ssid[] { SECRET_SSID };
const char pass[] { SECRET_PASS };
const char deviceId[] = { SECRET_DEVICE_ID };
// MQTT Topics definition
const String PROGRAMS_RESPONSE_TOPIC = String(SECRET_DEVICE_ID) + "/programs/response";
const String PROGRAMS_UPDATE_TOPIC = String(SECRET_DEVICE_ID) + "/programs/update";
const String PROGRAMS_INIT_TOPIC = String(SECRET_DEVICE_ID) + "/programs/init";
const String STATUS_TOPIC = String(SECRET_DEVICE_ID) + "/status";
const String EXECUTION_REPORT_TOPIC = String(SECRET_DEVICE_ID) + "/execution/report";
const String EXECUTION_COMMAND_TOPIC = String(SECRET_DEVICE_ID) + "/execution/command";
void setup() {
Serial.begin(115200);
initializeNetwork();
}
void loop() {
const auto conStatus = conMan.check();
if (conStatus != NetworkConnectionState::CONNECTED) {
initMessageSent = false;
return;
}
if (!mqttClient.connected()) {
connectMQTT();
return;
}
}
#include <ArduinoECCX08.h>
#include <Arduino_JSON.h>
#include "data_types.h"
#include "program_manager.h"
#include "ntp.h"
WiFiConnectionHandler conMan(SECRET_SSID, SECRET_PASS);
WiFiClient tcpClient;
BearSSLClient sslClient(tcpClient);
MqttClient mqttClient(sslClient);
unsigned long lastAttempt = 0;
const unsigned long RECONNECT_INTERVAL = 10000;
void initializeNetwork() {
conMan.addCallback(NetworkConnectionEvent::CONNECTED, onNetworkConnect);
conMan.addCallback(NetworkConnectionEvent::DISCONNECTED, onNetworkDisconnect);
conMan.addCallback(NetworkConnectionEvent::ERROR, onNetworkError);
if (!ECCX08.begin()) {
Serial.println("No ECCX08 present!");
while (1);
}
ArduinoBearSSL.onGetTime(getTime);
sslClient.setEccSlot(0, certificate);
mqttClient.onMessage(onMessageReceived);
timeClient.begin();
}
void connectMQTT() {
static unsigned long lastAttemptTime = 0;
if (mqttClient.connected()) {
Serial.println("mqtt not connected");
return;
}
unsigned long now = millis();
if (now - lastAttemptTime < 5000) {
Serial.println("a");
return;
}
lastAttemptTime = now;
Serial.print("Attempting to connect to MQTT broker: ");
Serial.print(broker);
Serial.print(":");
Serial.println(port);
int status = mqttClient.connect(broker, port);
if (status == 0) {
Serial.println("Connected to MQTT broker");
mqttClient.subscribe(PROGRAMS_UPDATE_TOPIC, 1);
mqttClient.subscribe(EXECUTION_COMMAND_TOPIC, 1);
initMessageSent = false;
} else {
Serial.print("MQTT connection failed, status: ");
Serial.println(status);
}
}
void onNetworkConnect() {
Serial.println(">>>> CONNECTED to network");
printWifiStatus();
setNtpTime();
connectMQTT();
}
void onNetworkDisconnect() {
Serial.println(">>>> DISCONNECTED from network");
initMessageSent = false;
}
void onNetworkError() {
Serial.println(">>>> NETWORK ERROR");
initMessageSent = false;
}
But at the start of my Opta, I get these prints:
14:47:04.641 -> Attempting to connect to MQTT broker: xxxxxx
14:47:05.799 -> MQTT connection failed, status: 1
If I add Serial.println(mqttClient.connected()); inside the loop, it always prints 1. Why does that happen? How can I fix it? How can I make the reconnection cycle non-blocking?