Arduino Nano 33 IoT connection to MQTT broker and subscribing to topics

Hi,

I want to use an Arduino Nano 33 IoT to constantly get the status of a Shelly device using MQTT and the MQTT broker HiveMQ or another free easy to use broker.
The Shelly device Shelly 1 is already setup in HiveMQ and I can subscribe to the topic and get the status in the HiveMQ broker.

I am not good at programming and I am looking for a similar arduino code that I can adapt according to my needs and learn from it. Unfortunately I have not found anything for the Nano 33 IoT so far.

Basically the following is needed:

  • Establish WiFI connection
  • Connect to MQTT broker and MQTT client
  • Subscibe to topic
  • Evaluate the device status {"connected":false} and {"connected":true} and display any change in subscribed topics in the serial monitor
  • Send an alarm message to a mail adress in case of {"connected":false}

Can anyone help me out with this?

Thanks, Daniel

I find that the pubsubclient library works well. It includes examples.

1 Like

Welcome to the forum

Take a look at the examples from the ArduinoMqttClient library. They work with the Nano 33 IOT

1 Like

Never used that library. But, perhaps it's a better one for beginners as the examples include establishing a WiFi connections. Note, to the best of my knowledge, HiveMQ requires a secure connection and using a TSL Certificate.

1 Like

Nor had I until now, but the examples work "straight out of the box" for the Nano 33 IOT which gives you a good starting point

Nice.
The next challenge may then be establishing a secure connection and supplying the TSL Certificate. I've only done that with ESP32, it's likely similar with Nano 33 IOT although perhaps not identical.

Judging from the original post, @piotrowski is looking for a copy / paste solution which may not exist.

What does supplying the TSL Certificate involve when using an ESP32 ?

Check out the WiFiClientSecure example. Looks like there's some differences in the details between ESP Core v2.x and v3.x.

Hello,
Thanks for your answers so far :slight_smile:

I can get the example "WiFiSimpleReceive" running, WIFI connects but it does not connect to the HiveMQ broker address:

WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);

const char broker[] = "a766053533df41398ab1a5b7589d257d.s1.eu.hivemq.cloud"; // "test.mosquitto.org";
int        port     = 8884; // 1883
const char topic[]  = "shelly1g3-5432046e856c/status"; //"arduino/simple";

I want to use a cloud MQTT broker because I can't have an MQTT broker running on a server that is online all the time. If HiveMQ cloud is not working for this, do you know if there are other cloud brokers that will do for my project?

Or is it just the wrong attempt to solve this little problem?

Thanks, Daniel

Does the connection work if you use a different broker such as test.mosquitto.org ?

Yes it does. Serial monitor messages below:

Attempting to connect to WPA SSID: TobiiGuest
You're connected to the network

Attempting to connect to the MQTT broker: test.mosquitto.org
You're connected to the MQTT broker!

Subscribing to topic: arduino/simple

Waiting for messages on topic: arduino/simple

The problem may well be that pointed out by @gfvalvo earlier in the topic

Hi,

I asked chatGPT :rofl: and it wrote the following code which actually works! (scary stuff...)
It connects and when I unplug my shelly device, the message "....connected: false" appears in the serial monitor.
Now I will try to solve the next step with the email alert...

#include <WiFiNINA.h>
#include <PubSubClient.h>

// Replace these with your network credentials
const char* ssid = "mydata";
const char* password = "mydata";

// HiveMQ Cloud configuration
const char* mqtt_server = "mydata";
const int mqtt_port = 8883; // Use 8883 for SSL/TLS
const char* mqtt_user = "mydata";
const char* mqtt_password = "mydata";

// MQTT topics
const char* publish_topic = "shelly1g3-5432046e856c";
const char* subscribe_topic = "#"; //"shelly1g3-5432046e856c/status"; // use "#"; to get all messages

// WiFi and MQTT client objects
WiFiSSLClient espClient;
PubSubClient client(espClient);

void setup_wifi() {
  delay(10);
  Serial.begin(9600);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

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

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

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (unsigned int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ArduinoNano33IoTClient", mqtt_user, mqtt_password)) {
      Serial.println("connected");
      client.subscribe(subscribe_topic);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

void setup() {
  setup_wifi();
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  // Publish a message every 10 seconds
  static unsigned long lastMsg = 0;
  unsigned long now = millis();
  if (now - lastMsg > 10000) {
    lastMsg = now;
    String msg = "Hello from Arduino Nano 33 IoT";
    Serial.print("Publish message: ");
    Serial.println(msg);
    client.publish(publish_topic, msg.c_str());
  }
}

BR, Daniel

Have you confirmed that the published message actually appears in your HiveMQ topic dashboard?

That is odd because the sketch does not have any code to print that message

Yes, I changed the publish message to "ArduinoNano33IOT/messageFromArduino" and subscribed to that topic in HiveMQ → it appears every few seconds :wink:

It's a message created by the Shelly device and because I subscribed to the topic "#" all messages from this client are received. At least that's how I understand it...

I also found the code to send the Mail and it works. I will try to combine the codes tomorrow and see if I can get it to work using an IF condition...

Looks like both you and chatGPT got lucky that WiFi boards supported by WiFiNINA come preloaded with SSL Certificates and apply them even if you don't know enough to do it yourself: WiFiNINA API

I am still on this and I am stuck again. Now it's about the "sendEmail();" function.
If I put the "sendEmail();" in the void setup() block, it send me the email once (this is to test iw it works). So far it works and I receive the Mail.

As soon as I put it into the IF statement, the mail does not get sent. Why?? See the code below:

// Message arrived [shelly1g3-5432046e856c/status/ws] {"connected":false}

#include <WiFiNINA.h>
#include <PubSubClient.h>
#include <EMailSender.h>

// Replace these with your network credentials
const char* ssid = "xxxxxx";
const char* password = "xxxxx";

// Mail configuration
char eMailUser[] = "xxxxxxxxxxxxxxxxxxxxxx"; // account must have correct settings (see video)
char eMailPass[] = "xxxxxxxxxxxxxxxx "; // has to be an app password (see video)
char eMailRecipient[] = "xxxxxxxxxxxxxxxxxxxxxxxxxx";  // if you want to send an email  
char phoneRecipient[] = "1234567890@txt.att.net";    // if you want to send an text (formatted for at&t)
//1234567890@vtext.com (formatted for verizon)
//1234567890@tmomail.net (formatted for tmobile)
const String TEXT = "The Shelly device is offline"; // main body text of the email
const char SUBJ[] = "SCL FI Monitor Alarm"; // subject of the email

// HiveMQ Cloud configuration
const char* mqtt_server = "a766053533df41398ab1a5b7589d257d.s1.eu.hivemq.cloud";
const int mqtt_port = 8883; // Use 8883 for SSL/TLS
const char* mqtt_user = "xxxxxxxxxxxxxxxxxxx";
const char* mqtt_password = "xxxxxxxxxxxxxxxxx";

// MQTT topics
const char* publish_topic = "ArduinoNano33IOT/messageFromArduino";
const char* subscribe_topic = "shelly1g3-5432046e856c/online"; //"shelly1g3-5432046e856c/status"; // use "#"; to get all messages

bool sendEmailFlag = false;

// WiFi and MQTT client objects
WiFiSSLClient espClient;
PubSubClient client(espClient);


void setup_wifi() {
  delay(10);
  Serial.begin(9600);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

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

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


void sendEmail(){
    // sends an email or text depending on which recipient you choose
    char senderName[] = "SENDER"; // the name it will display who the email is from

    // the actual stuff that sends the email:
    EMailSender emailSend(eMailUser, eMailPass, eMailUser, senderName);
    EMailSender::EMailMessage msg;
    EMailSender::Response resp;
    Serial.println("Sending email...");
    msg.subject = SUBJ;
    msg.message = TEXT;
    resp = emailSend.send(eMailRecipient, msg); // change eMailRecipient to phoneRecipient to send a text instead

    // all of this just prints the info
    Serial.println("Sending status: ");
    Serial.print(resp.status);
    Serial.println(resp.code);
    Serial.println(resp.desc);
    Serial.println("");
    Serial.print("FROM: ");
    Serial.println(eMailUser);
    Serial.print("TO: ");
    Serial.println(eMailRecipient);
    Serial.print("SUBJECT: ");
    Serial.println(SUBJ);
    Serial.print("DATA:");
    Serial.println(TEXT);
    Serial.println("");
}




void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic); // die message "Message arrived [shellyplusht-c049ef871e5c/status/ws] {"connected":false}" kommt aus diesem topic
   Serial.print("] ");
  for (unsigned int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  // Extract text for alarm Mail in case of "Message arrived [shellyplusht-c049ef871e5c/online] false"
  //
  String message;
  for (unsigned int i = 0; i < length; i++) {
    message += (char)payload[i];
 }
 //Serial.println(message);
    if (message == "false") { // {"connected":false}  geht nicht
Serial.println("Alarm Alarm Alarm "); // for testing!
sendEmailFlag = true; // Set the flag to send the email in the main loop
//sendEmail(); does not work inside callback loop

// sendEmailFlag = true; // Set the flag to send the email in the main loop
  }
  //
  //
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ArduinoNano33IoTClient", mqtt_user, mqtt_password)) {
      Serial.println("connected");
      client.subscribe(subscribe_topic);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

void setup() {
  setup_wifi();
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);
  //sendEmail(); // just to test if it works and it worked
  
}

void loop() {
  
   if (!client.connected()) {
    reconnect();
  }
    client.loop();
/*
    if (sendEmailFlag) {
    sendEmail();
    sendEmailFlag = false; // Reset the flag after sending the email
  }
  */
 //delay(5000);

/*
  // Publish a message every 10 seconds
  static unsigned long lastMsg = 0;
  unsigned long now = millis();
  if (now - lastMsg > 10000) {
    lastMsg = now;
    String msg = "Hello from Arduino Nano 33 IoT";
    //Serial.print("Publish message: ");
    //Serial.println(msg);
    //client.publish(publish_topic, msg.c_str());
  }
*/
 


}