In my Arduino MQTT Examples, I kept things simple by only subscribing to a single topic. One of the strengths of MQTT is that a device can subscribe (or publish) to multiple topics. The broker will sort things out. Even though my first example only showed one, it is straight forward to get the Arduino PubSubClient library to subscribe to Multiple MQTT topics. The quick answer is that you need to look at the MQTT response to find out which topic sent the payload.

tl;dr version

If you’re looking for a quick answer, here’s the magic code we’ll add to the callback() function.

void callback(char* topic, byte* payload, unsigned int length) {
if (strcmp(topic,"pir1Status")==0)
  // whatever you want for this topic
}
Keep reading for a more detailed explanation of how to Subscribe to Multiple MQTT topics with Arduino’s PubSubClient. Obviously, this code will work on Arduino boards with a TCP/IP interface and, of course, the ESP8266 based boards.

Subscribing to Multiple MQTT Topics

Subscribing to multiple MQTT topics is just a matter of repeating the subscribe code. For example, here I subscribe to topics called “red,” “green,” and “blue.” (Guess what they represent.)

boolean reconnect() {
  if (client.connect("arduinoClient")) {
    client.subscribe("pir1Status");
    client.subscribe("red");
    client.subscribe("green");
    client.subscribe("blue");
    return client.connected();
  }
  Serial.println("I think connect failed.");
  return 0;
}
Once subscribed, turn your attention to PubSubClient’s callback function. Whenever a message is received, the callback function handles it.

MQTT reply

The callback() function provides a character array called “topic.” You might be tempted to convert this into an Arduino String object. This overused object probably seems easier to use, since you could use a “==” operator to match strings. You don’t need the overhead of the String object. Instead, leave “topic” as a character array. There is a function in libc (and avr-libc) that helps, strcmp(). My guess is that “strcmp” stands for “string compare.” strcmp() takes two arguments: string1 and string2. The value it returns tells you something about how the two strings compare to each other. It’s a simple function to use but has a few things you need to know.

Issues using strcmp()

The first thing to know is that you can’t use a switch statement with strcmp(). I wish you could; it would make the code much easier to read. At least, in my eyes. Next, you should understand that strcmp() doesn’t return what most people expect. Instead ‘0’, or false, comes back when there is a match.
Note on Substrings. Since strcmp() is part of libc, there is plenty of documentation to explain how it works in detail. You should understand why it might return a negative number or something more than zero.  I’m not going to cover handling substrings here. I carefully pick my topics to avoid substring matches.
Here’s an example of callback() that could support receiving a message while subscribed to multiple topics.

void callback(char* topic, byte* payload, unsigned int length) {
  if (strcmp(topic,"pir1Status")==0){
    // whatever you want for this topic
  }

  if (strcmp(topic,"red")==0) {
    // obvioulsy state of my red LED
  }

  if (strcmp(topic,"blue")==0) {
    // this one is blue...
  }  

  if (strcmp(topic,"green")==0) {
    // i forgot, is this orange?
  }  
}
It’s a simple matter of using strcmp() to match the topic received in the PubSubClient packet.

Conclusion

No doubt, there are probably more optimized ways to handle both the subscribing and receive processing. But I like the code being straight forward and easy to read. The key to handling multiple MQTT topics is processing the packet that PubSubClient provides.
What other MQTT questions can I help answer?
Author

Fan of making things beep, blink and fly. Created AddOhms. Stream on Twitch. Video Host on element14 Presents and writing for Hackster.IO. Call sign KN6FGY.

55 Comments

  1. Thank you James,
    How would I check to see if F63F1E is in the payload?
    {“Time”:”2020-06-17T14:49:19″,”RfReceived”:{“Sync”:12570,”Low”:450,”High”:1230,”Data”:”F63F1E”,”RfKey”:”None”}}
    Thanks,
    Dennis

  2. “The callback() function provides a character array called “topic.” You might be tempted to convert this into an Arduino String object. ”

    I think you’re confusing topic with incoming payload for that topic. You already know what your incoming topic subscriptions are, so no need to do any strcmp on those. You would want to compare the payload (coming in a a char array) from your MQTT topic to see if it has an actionable value

    • Nope. I was specifically using the example where you are subscribed to multiple topics.

      You already know what your incoming topic subscriptions are

      Nope. You have to check which topic generated the callback. In this example, pir1Status, red, blue, green. Inside of the if-statement with the strcmp, you would then look at the payload to see what the actionable value is associated with the topic that generated the callback.

  3. Hello, I have a project which involves up to 50 devices
    I want to receive and store the data gathered on PC.
    Here is my setup: 1 PC and 50 esp32 devices
    I want to get the esp32 device data when the PC ask for the specific device.

    Ex: The PC publishes a topic “home/data” with message “esp32-01” which is meant for esp32-01
    The esp32-01 would response with message “XXX” to the subscribed topic “home/data” and checking the message and confirming it is for itself.
    Then when the PC receive the message sending from esp32-01 it would store it somewhere
    The repetition go for esp32-01 to esp32-50….

    How do I go about doing it ?

  4. HI, James

    I am lost as last years easter egg.

    these are my error codes, im new to this and its taken me a while to whittle down to these

    nodedht.ino: In function ‘void callback(char*, byte*, unsigned int)’:
    nodedht:73: error: expected ‘;’ before ‘)’ token
    nodedht:239: error: expected ‘}’ at end of input
    expected ‘;’ before ‘)’ token

    void callback(char* topic, byte* payload, unsigned int length) {
    Serial.print(“Message arrived on topic: “);
    Serial.print(topic);
    Serial.print(“. Message: “);
    char messageTemp;

    for (char i = 0; i < length; i++) {
    Serial.print((char)topic[i]);
    messageTemp += (char)payload[i];
    }
    Serial.println();

    // If a message is received on the topic box/relay_1, you check if the message is either on or off. Turns the relay GPIO according to the message
    if (strcmp)topic, "relay_1") == 0) {
    for (int i=0;i<length;i++) {
    char receivedChar = (char)payload[i];
    }
    if (receivedChar == '0') {
    digitalWrite(relay_1, HIGH);
    Serial.print("On");
    }
    if (receivedChar == '1')
    digitalWrite(relay_1, LOW);
    Serial.print("Off");
    }
    // If a message is received on the topic box/relay_2, you check if the message is either on or off. Turns the relay GPIO according to the message
    if (strcmp)topic, "relay_2") == 0) {
    for (int i=0;i<length;i++) {
    char receivedChar = (char)payload[i];
    }
    if (receivedChar == '0') {
    digitalWrite(relay_2, HIGH);
    Serial.print("On");
    }
    if (receivedChar == '1')
    digitalWrite(relay_2, LOW);
    Serial.print("Off");
    }
    // If a message is received on the topic box/relay_3, you check if the message is either on or off. Turns the relay GPIO according to the message
    if (strcmp)topic, "relay_3") == 0) {
    for (int i=0;i<length;i++) {
    char receivedChar = (char)payload[i];
    }
    if (receivedChar == '0') {
    digitalWrite(relay_3, HIGH);
    Serial.print("On");
    }
    if (receivedChar == '1')
    digitalWrite(relay_3, LOW);
    Serial.print("Off");
    }
    // If a message is received on the topic box/relay_3, you check if the message is either on or off. Turns the relay GPIO according to the message
    if (strcmp)topic, "relay_4") == 0) {
    for (int i=0;i<length;i++) {
    char receivedChar = (char)payload[i];
    }
    if (receivedChar == '0') {
    digitalWrite(relay_4, HIGH);
    Serial.print("On");
    }
    if (receivedChar == '1')
    digitalWrite(relay_4, LOW);
    Serial.print("Off");
    }
    }
    Serial.println();

    }

  5. Hello, dear
    I have a problem and I did not have any answer

    this part of code is working perfectly with mqtt and no have any problem

    void callback(char* topic, byte* payload, unsigned int length) {

    if (strcmp(topic,string1) ==0){
    // whatever you want for this topic
    Serial.print(“Message arrived [“);
    Serial.print(topic);
    Serial.print(“] “);
    stringTwo = “”;
    for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
    stringTwo.concat((char)payload[i]);
    }
    Serial.println();

    if (stringTwo == "connect"){
    //———————————————
    if (out1_state == 1){
    val = "out1 on";
    client.publish(sender, val.c_str(),0);
    }

    if (out1_state == 0){
    val = "out1 off";
    client.publish(sender, val.c_str(),0);
    }
    //———————————————

    if (out2_state == 1){
    val = "out2 on";
    client.publish(sender, val.c_str(),0);
    }

    if (out2_state == 0){
    val = "out2 off";
    client.publish(sender, val.c_str(),0);
    }
    //———————————————

    if (out3_state == 1){
    val = "out3 on";
    client.publish(sender, val.c_str(),0);
    }

    if (out3_state == 0){
    val = "out3 off";
    client.publish(sender, val.c_str(),0);
    }
    //———————————————

    if (out4_state == 1){
    val = "out4 on";
    client.publish(sender, val.c_str(),0);
    }

    if (out4_state == 0){
    val = "out4 off";
    client.publish(sender, val.c_str(),0);
    }
    //———————————————
    }

    but the problem is when add other if statements then then the mqtt disconnected and give this message

    Attempting MQTT connection…failed, rc=-2 try again in 5 seconds

    if (out5_state == 1){
    val = "out5 on";
    client.publish(sender, val.c_str(),0);
    }

    if (out5_state == 0){
    val = "out5 off";
    client.publish(sender, val.c_str(),0);
    }

    if (out6_state == 1){
    val = "out6 on";
    client.publish(sender, val.c_str(),0);
    }

    if (out6_state == 0){
    val = "out6 off";
    client.publish(sender, val.c_str(),0);
    }

    could you please tell me why this happen?

  6. laigeromain Reply

    Hi James,

    I learn much from your MQTT tutorials and your website is so pleasant to read, thanks for all this work.
    I have a question, I’d like to retrieve some simple digit from the payload and wonder if the callback function should be simplified without the for() loop.
    I’m trying this without success :

    void callback(char* topic, byte* payload, unsigned int length){
    if(strcmp(topic, “my_topic”)==0){
    /*
    for (int i = 0; i < length; i++) {
    my_var = (char)payload[i];
    */
    my_var = payload;
    Serial.print(my_topic);
    }
    }

    I know it is a basic programming question that involves Types (since I'm looking for digits) but I'm not able yet to deal with those arrays passed to the callback.
    Is there a way to modify the parameter inside the callback or is it "strict" since the callback has a given signature:
    https://pubsubclient.knolleary.net/api.html#callback

    Thank you for your clarification.
    Best to your website 🙂

  7. Hi,
    I want to teach in a school the MQTT to do an IoT project… Here I use the Controllino MEGA Board and followimg code:

    [arduino firstline=””]
    // (Includes lost because comment system thought it was HTML)
    #include
    #include
    #include
    #include //MQTT Bibliothek

    #define CLIENT_ID "Bua"
    //uint8_t mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };
    uint8_t ip[] = { 192, 168, 6, 66 };
    uint8_t gateway[] = { 192, 168, 6, 53 };
    uint8_t subnet[] = { 255, 255, 255, 0 };

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

    EthernetClient ethClient;
    PubSubClient client;

    void reconnect() {
    // Loop until we’re reconnected
    while (!client.connected()) {
    Serial.print("Attempting MQTT connection…");
    // Attempt to connect
    if (client.connect(CLIENT_ID)) {
    Serial.println("connected");
    // Once connected, publish an announcement…
    client.publish("outTopic","hello world");
    // … and resubscribe
    client.subscribe("inTopic");
    } else {
    Serial.print("failed, rc=");
    Serial.print(client.state());
    Serial.println(" try again in 5 seconds");
    // Wait 5 seconds before retrying
    delay(5000);
    }
    }
    }

    void setup()
    { Serial.begin(9600);
    delay(1500);
    Ethernet.begin( ip, gateway, subnet); //Ethernet.begin(mac, ip);

    Serial.println("Ethernet begin");
    client.setClient(ethClient);
    delay(1500);
    client.setServer("test.mosquitto.org",1883);
    delay(1500);
    }

    void loop()
    {
    Serial.println("loop");
    //client.connect(CLIENT_ID);
    Serial.println("client no connect?");
    client.publish("jdsr","hello world");
    client.setCallback(callback);
    Serial.println("RX TX");
    if (!client.connected()) {
    reconnect();
    }
    client.loop();
    }
    [/arduino]

    There is no work. Also, no network ping is working. Do you have an idea?
    Thanks,
    Artur

    • There is no work.

      Without any other details, I cannot help.

      no network ping is working

      Most embedded TCP/IP stacks do not support ICMP, so ping replies do not work.

    • Hi, your for have a bug.

      change this:
      for (int i=0;i>length;i++) {

      to:
      for (int i=0;i<length;i++) {

  8. Kris Jacobs Reply

    Hi James, thank you for your Arduino / ESP8266 / MQTT articles.
    I’m old hat on Arduino, but new to MQTT. This seems simple in practice, but I’m not sure how to code it:

    On an ESP8266:
    Subscribe to a topic & monitor its value
    If topic value = 1,
    do something (trigger a relay, light an LED, etc.) and write a 0 back to the topic.

    Context:
    IFTT & Adafruit.IO –> ESP8266
    I’m using an IFTT Google Assistant applet that will write a 1 to an A.IO feed/topic when I say a phrase.
    But the value stays at 1, so I figured the ESP8266 should write a 0 back to the topic after it takes action on the 1.

    Does that make sense?

    Thanks!

  9. I want to subscribe to myname/feeds/mytopic at Adafruit.com mqtt server, port 1883
    And I want to publish on my local Mosquitto mqtt server something and same port 1883.
    Using wifi to LAN
    I have tried many ways but I can not do both.

    Maybe not bossible?

    This should be interesting for some automation using voice to control things with Android + Google Asisstant + IFTTT

    Thank you

    • I think the client object can only connect to one server at a time. You might be able to create multiple objects for multiple servers. Another option is to run a script on the broker / local mosquitto server. Anytime it receives a message for the topic, it could publish it to AdafruitIO.

    • Roland Palmqvist Reply

      Hi Dag,
      Having a client connect to two brokers are a bit of an anti-pattern. Your client should connect to one broker only.
      It is the topics that should span multiple brokers (could though be renamed in transit) to serve subscribers that connect to them, not the clients. So set up your local Mosquito to connect to the Adafruit broker for the given topic and exchange messages.
      Have a look at this tutorial http://www.steves-internet-guide.com/mosquitto-bridge-configuration/
      However I’m not familiar with the Adafruit broker capability.

  10. Is it possible to both subscribe and publish to different Mqtt topics ď from an esp8288?
    The case is a garage ( or gate) opener that responds to commands, but also reports back temperature and gate open/closed state. I imagine this type of device could be possible – a controller that also reports back sensor data.

    Is there a better server/client platform to use than mqtt? ( This all connects to an openhab implementation for me )

    • This post is how to subscribe to multiple topics. To publish to multiple topics, you just change which topic you publish.

  11. Late to the party again…

    “When the student is ready, the teacher will appear.” This is EXACTLY what I needed. I was even able to modify, extend and make it work without issue. Thanks for saving me a day of pounding through the nitty-gritty of the pubsub API.

    Another trick:
    You use strcmp() to compare the returned topic value with a constant string. If you define your topics as const char*, you can use strcmp() to compare them with what is returned.

    const char* Topic1 = “cheerlights”;
    const char* Topic2 = “cheerlights/rgb/9digits”;
    …..
    if (strcmp(topic,Topic1)==0){ *do one thing* };
    if (strcmp(topic,Topic2)==0){ *do another thing* };

    I like to put all those things up at the top so I only have to correct my typos once.

    Thanks again!

  12. Hillermann Lima Reply

    Thank you verry much for your posts. You coding style is the way I like: clear and simple. I’m having a lot of fun putting your codes to run in my nodemcu.

  13. Hello,

    and what if i want that published message is not 0 or 1?

    What if i want that callback reads if the message in topic is “close” ?

    something like that: if (strcmp(topic,”pir1Status”)== “close”) {

    but this doesnt work :/

  14. Nitin Verma Reply

    Hi James,
    Hope you are doing good!!

    I have followed your tutorial for publishing single topic(Via python on raspberry Pi) and subscribe same topic on nodeMCU and it’s working fine.

    Now i want to publish multiple topic using python on raspberry pi, can you please share code to publish multiple topic using python Or can I use below mentioned code:

    import paho.mqtt.publish as publish
    import time

    print(“Sending Message ‘RedOn’ to turn on…”)

    publish.single(“ledStatus”, “RedOn”, hostname=”192.168.0.105″)

    time.sleep(1)

    print(“Sending Message ‘RedOff’ to turn on…”)

    publish.single(“ledStatus”, “RedOff”, hostname=”192.168.0.105″)

    Thanks in advance for helping me.

    Regards,
    Nitin verma

    • There’s nothing special about publishing to multiple topics. Just change the topic name in the publish() call. (There is a publish.multiple() available in Paho, but that is for sending multiple messages to the same topic.)

  15. Nick Sebring Reply

    I’m hoping you’d help me out by looking at my code and tell me where I went wrong. I’m trying to connect some Wemos Mini D1s to the mqtt broker on my raspberry pi zero w. I was able to turn on/off an led attached the wemos via an ssh connection from my laptop. Now what I would like to do is add a toggle switch to one which would publish either an 0 or 1 to tuun on/off leds attached to the Wemos that have subscribed to that topic.
    here’s the code:
    “`
    [arduino language=””]
    /*

    BABY STEPS…

    Starting with the "basic ESP8266 MQTT example", making modifications for my ongoing project as I go.

    This sketch demonstrates the capabilities of the pubsub library in combination
    with the ESP8266 board/library.

    It will reconnect to the server if the connection is lost using a blocking
    reconnect function. See the ‘mqtt_reconnect_nonblocking’ example for how to
    achieve the same result without blocking the main loop.

    My goal is to get input from a toggle switch connected to D6, Publish to topic "Charts" as output status == HIGH or LOW, then the other ESP6266s would Subsribe to "Charts", turn on/off LED accoirdingly.

    */

    #include
    #include

    int togglePin = D6;// Connect Adafruit capacitive touch toggle switch to D6
    int chartsledPin = D1;// LED indicator for Charts-up
    boolean on = false;
    int buttonState = 0;

    // Update these with values suitable for your network.
    const char* ssid = "MY SSID";
    const char* password = "MY PASSWORD";
    const char* mqtt_server = "Mosquitto_broker";

    WiFiClient espClient;
    PubSubClient client(espClient);
    long lastMsg = 0;
    char msg[50];
    int value = 0;

    void setup() {
    pinMode(D6, INPUT); // Adafruit Capacitive Touch Toggle Switch to D1
    pinMode(D1, OUTPUT);

    Serial.begin(115200);
    setup_wifi();
    client.setServer(mqtt_server, 1883);
    client.setCallback(callback);
    }

    void setup_wifi() {

    delay(10);
    // We start by connecting to a WiFi network
    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.println("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 (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
    }
    Serial.println();

    }

    void reconnect() {
    // Loop until we&#039;re reconnected
    while (!client.connected()) {
    Serial.print("Attempting MQTT connection…");
    // Attempt to connect
    if (client.connect("ESP8266Client")) {
    Serial.println("connected");
    // Once connected, publish an announcement…
    // client.publish("outTopic", "hello world"); *** I just want the LED (D1) to blink slowly until connected***
    // … and resubscribe
    client.subscribe("Charts/PS");
    client.subscribe("Chapperones/PSA");// WILL ADD THESE IN AFTER FIGURING OUT
    client.subscribe("Chapperones/PSB");// HOW TO INCLUDE BUTTON INPUT
    client.subscribe("Chapperones/PSC");//
    client.subscribe("Chapperones/PSD");//
    } else {
    Serial.print("failed, rc=");
    Serial.print(client.state());
    Serial.println(" try again in 5 seconds");
    // Wait 5 seconds before retrying
    delay(5000);
    }
    }
    }

    void loop() {

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

    int value = 0;
    client.loop();

    {
    buttonState = digitalRead(D6);
    if (buttonState == HIGH) {
    client.publish("Charts/PS", "1");
    digitalWrite(D1, HIGH);
    }

    else {
    client.publish("Charts/PS", "0");
    digitalWrite(D1, LOW);
    }
    }
    }
    [/arduino]

      • James, I am so sorry, I’m trying to add in a button press that will turn on/off leds on remote Wemos. Im toggling on/off via SSH from my laptop. It’s not 100%. I think maybe resending the publish too fast for the broker to receive, distribute the message. One Led will come on, then maybe the other, sometimes both and sometimes none at all.

        • I’m still not following ‘what you expect’ and ‘what is happening’. Now you’re saying that you have a hardware toggle button that works over ssh? I don’t understand how that’s possible. (Please read this on asking questions: http://www.catb.org/esr/faqs/smart-questions.html#beprecise)

          In your code, you are going to be blasting the broker with messages. With every iteration of loop() you are going to send either a 0 or 1. That’s a lot of messages. You need to learn how to use state-change detection for a button so you only send an event when the button’s state changes from on to off. The code in this example does that. You don’t need the counter stuff. https://www.arduino.cc/en/Tutorial/StateChangeDetection

          • Nick Sebring

            Thank you so much for your time. I see your point with the state change. Working on that. I have another issue. I can get 2 wemos to connect to the mqtt server, but when I try more than 2, the rest will not connect.
            Any suggestions? here’s the LOOP currently:

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

      • Nick Sebring Reply

        I just discovered that it goes awry when I plug in the second Wemos with the same sketch. Then it says “Client ESP8266 Client already connected, closing old connection”. Then tries reconnecting, goes into a loop of trying to reconnect.

        So in lines 32, 33 where it says espClient; I should be giving each Wemos a name?
        Line 87 is the only instance is says: “ESP8266” so I’m a bit confused. Going to change line 87 on the second Wemos to “PSA”, see what happens.

      • Nick Sebring Reply

        Thank you again for your time, patience and also directing me to the state change for my button press. I got that all sorted out. A couple of bad wires and BAD coding was tripping me up!

        Quick question: in this tutorial; I’ve read through this like 10 times. It looks like you are controlling the LEDs independently? or are they turned on/off based on results of the string comparison, meaning just one led at a time? Like a selector switch.

      • Nick Sebring Reply

        This compiles, but where, how do you digitalWrite(HIGH LOW) to turn them on/off respectively?

        [arduino firstline=””]
        void callback(char* topic, byte* payload, unsigned int length) {

        if (strcmp(topic, "Charts/PS") == 0) {
        // Charts up!
        }

        if (strcmp(topic, "Chaperone/PSA") == 0) {
        // Need a chaperone in Exam Room A
        }

        if (strcmp(topic, "Chaperone/PSB") == 0) {
        // Need a chaperone in Exam Room B
        }

        if (strcmp(topic, "Chaperone/PSC") == 0) {
        // Need a chaperone in Exam Room C
        }

        if (strcmp(topic, "Chaperone/PSD") == 0) {
        // Need a chaperone in Exam Room D
        }
        }

        [/arduino]

        • You could put your code where the comments are, like on line 3. If you’re using single character commands to turn on and off, then you would made the code something like:

          [arduino firstline=”2″]
          if (strcmp(topic, "Charts/PS") == 0) {
          // Charts up!
          for (int i=0;i<length;i++) {
          char receivedChar = (char)payload[i];
          if (receivedChar == ‘0’)
          digitalWrite(ledPin, HIGH);
          if (receivedChar == ‘1’)
          digitalWrite(ledPin, LOW);
          }
          }
          [/arduino]

          This code look as the “payload” received for a character and reacts. It’s from the original MQTT tutorial I posted. If you’re sending full strings like “ON” or “OFF” then you need another round of strcmp() on the payload variable.

          • Nick Sebring

            Thank you again for your assistance.That worked(sort of). Instead of the led just turning on and staying on, it came on for a split second. At first I didn’t think it had worked. Maybe issues with jumper wires again. But I spotted it! The led flashed. SO I added a 5 second delay after the digitalWrite. Yes! it comes on. But why is it not staying on when digitalWrite(ledPin, HIGH)? Posting the whole sketch seems a bit much.
            What parts should I post?

          • Post the entire code to something like pastebin.com. Code snippets rarely contain the problem.

          • You need brackets on your if-statements.
            [arduino firstline=””]
            if (receivedChar == ‘0’)
            Serial.println (F("PSA LED ON"));
            digitalWrite(officeaPin, HIGH);
            if (receivedChar == ‘1’)
            Serial.println (F("PSA LED OFF"));
            digitalWrite(officeaPin, LOW);
            [/arduino]

            The digitalWrite()s are executing regardless of what the payload contains. So the light might be briefly flickering on, but will also be turned off.

            Should have been
            [arduino firstline=””]
            if (receivedChar == ‘0’) {
            Serial.println (F("PSA LED ON"));
            digitalWrite(officeaPin, HIGH);
            }
            if (receivedChar == ‘1’) {
            Serial.println (F("PSA LED OFF"));
            digitalWrite(officeaPin, LOW);
            }
            [/arduino]

          • Nick Sebring

            Eureeka! They work as I intended. Thank you sooo much!
            So that just proves that an ESP8266 can Sub/Pub to several topics at the same time. Until you run out if pins. : D

            I struggled with it for some time, then I remembered you saying something about choosing the topic names carefully. PSA, PSB etc did not work but A, B, C, D did. Putting in comment tags helped keep it all straight.
            ”’
            if (strcmp(topic, “A”) == 0) {
            // Need a chaperone in Exam Room A
            for (int i = 0; i < length; i++) {
            char receivedChar = (char)payload[i];
            if (receivedChar == '0') {
            Serial.println (F("PSA LED ON"));
            digitalWrite(officeaPin, HIGH);
            }
            if (receivedChar == '1') {
            Serial.println (F("PSA LED OFF"));
            digitalWrite(officeaPin, LOW);
            }
            }
            }
            '''

  16. Great series of tutorials, helped me al lot do understand. Thank you

    • Nick Sebring Reply

      That worked! Each Client must have a name, that is specified in quotation marks on line 87.
      The lights are turning on/off consistently. Now I can drop the SSH connection and move on to the button state change as you suggested.

  17. Odilon Afonso Cenamo Reply

    Hi James. Good tutorial, thanks !

    Can I have two PubSubclient clients – onte connected to a one broker, one to another ?

    Like:
    [arduino firstline=””]
    const char* mqtt_server1 = "iot.eclipse.org";
    const char* mqtt_server2 = "odilon.local";
    #define mqtt_port 17546

    WiFiClient espClient; //this is a ESP8266 client; the connection is not aborded here

    PubSubClient MQTTclient1(espClient);
    PubSubClient MQTTclient2(espClient);

    …..
    …..

    MQTTclient1.setServer(mqtt_server1, mqtt_port);
    MQTTclient1.setCallback(callback1);

    MQTTclient2.setServer(mqtt_server2, mqtt_port);
    MQTTclient2.setCallback(callback2);
    [/arduino]
    Something like this.

    Thanks again !

    Odilon

    • I think I’ve connected to multiple brokers before (one inside my network and one public). But can’t find the code. (Maybe I haven’t.) I would imagine in addition to setCallback, you also need to add the second client to the reconnect function.

      • Odilon Afonso Cenamo Reply

        Hi James.

        Multiple brokers with a PubSubClient library are not supported. I took a look at the source, there is only one instance of the class in PubSubClient.h:

        [arduino firstline=””]
        private:
        Client* _client;
        uint8_t buffer[MQTT_MAX_PACKET_SIZE];
        uint16_t nextMsgId;
        unsigned long lastOutActivity;
        unsigned long lastInActivity;
        bool pingOutstanding;
        MQTT_CALLBACK_SIGNATURE;
        uint16_t readPacket(uint8_t*);
        boolean readByte(uint8_t * result);
        boolean readByte(uint8_t * result, uint16_t * index);
        boolean write(uint8_t header, uint8_t* buf, uint16_t length);
        uint16_t writeString(const char* string, uint8_t* buf, uint16_t pos);
        IPAddress ip;
        const char* domain;
        uint16_t port;
        Stream* stream;
        int _state;
        [/arduino]
        I’ll take a look at this library to see if I can modify it.

        Best regards !

      • Odilon Afonso Cenamo Reply

        Hi james,

        I was wrong. Yes, it is possible to connect to two different brokers simultaneously.

        However, it is also necessary to double the Ethernet client:

        [arduino firstline=””]
        Const char * mqtt_server1 = "192.168.2.111";
        Const char * mqtt_server2 = "test.mosquitto.org";
        Const int mqtt_port1 = 1883;
        Const int mqtt_port2 = 1883;

        WiFiClient espClient1, espClient2;
        PubSubClient MQTTclient1 (espClient1);
        PubSubClient MQTTclient2 (espClient2);

        I made the connection up – to the broker on my local network and to the test broker at mosquitto.org. I sent and received messages from both.

        Regards !!
        [/arduino]

      • Odilon Afonso Cenamo Reply

        The reconnect function can be parameterized:
        [arduino firstline=””]
        void reconnect(PubSubClient MQTTclient, char* cliente) {
        // Loop until we’re reconnected
        while (!MQTTclient.connected()) {
        Serial.print("Attempting MQTT connection…");
        // Attempt to connect
        if (MQTTclient.connect(cliente)) {
        [/arduino]

  18. Hi James,
    Tkx again for this tutorial, you make things simple ! In a project I’m trying to publish payload from my arduino or ESP8266 to a webpage, which updates the information. This goes about mqtt client in javascript. I’ve looked on the net but the info is scarse (or I don’t search well 🙂 Maybe you can give an example of how this could be done ?
    Thanks !

  19. faramonadrianAdrian Reply

    Hi, can you explain how to protect MQTT step by step with username and password or certificate.
    Thanx

  20. What’s the best broker software for a Windows based machine with GUI?

Write A Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.