Particle Electron MQTT example

Hi,

Is there available a very easy example of how to use Particle Electron to a MQTT server and receive messages.

I tried something like this:

#include "MQTT.h"

SYSTEM_MODE(MANUAL); /*do not autoconnect to particle cloud*/
String APN = "my_APN";
STARTUP(cellular_credentials_set(APN, "", "", NULL));

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

/**
 * if want to use IP address,
 * byte server[] = { XXX,XXX,XXX,XXX };
 * MQTT client(server, 1883, callback);
 * want to use domain name,
 * exp) iot.eclipse.org is Eclipse Open MQTT Broker: https://iot.eclipse.org/getting-started
 * MQTT client("iot.eclipse.org", 1883, callback);
 **/
 
MQTT client("broker.mqttdashboard.com", 8000, callback);

// recieve message
void callback(char* topic, byte* payload, unsigned int length) {
    char p[length + 1];
    memcpy(p, payload, length);
    p[length] = NULL;

    if (!strcmp(p, "RED"))
        RGB.color(255, 0, 0);
    else if (!strcmp(p, "GREEN"))
        RGB.color(0, 255, 0);
    else if (!strcmp(p, "BLUE"))
        RGB.color(0, 0, 255);
    else
        RGB.color(255, 255, 255);
    delay(1000);
}


void setup() {
    RGB.control(true);

    Cellular.on();
    Cellular.connect();
    
    while(!Cellular.ready());
        //waitFor(Cellular.ready());
        Serial.println("Connected to cellular network. ...");

    // connect to the server
    client.connect("sparkclient");

    // publish/subscribe
    if (client.isConnected()) {
        client.publish("1outTopic/message","hello world from 1");
        client.subscribe("1inTopic/message");
    }
}

void loop() {
    if (client.isConnected())
        client.loop();
}

Did I miss something or why aren’t I receiving any MQTT messages?

Also the LED just shuts itself off after 10 seconds of blinking different colors

This turns off the LED for system use and makes it available to app use.

Try this change:

void callback(char* topic, byte* payload, unsigned int length) {
    char p[length + 1];
    memcpy(p, payload, length);
    p[length] = NULL;

    Serial.printlnf("Received:"%s, p);

    if (!strcmp(p, "RED"))
        RGB.color(255, 0, 0);
    else if (!strcmp(p, "GREEN"))
        RGB.color(0, 255, 0);
    else if (!strcmp(p, "BLUE"))
        RGB.color(0, 0, 255);
    else
        RGB.color(255, 255, 255);
    delay(1000);
}

void setup() {
    Serial.begin();
    RGB.control(true);

//...
// publish/subscribe
    if (client.isConnected()) {
        client.publish("1outTopic/message","hello world from 1");
        client.subscribe("1outTopic/message");
    }

void loop() {
    if (client.isConnected())
        client.loop();

     delay(2000);
     client.publish("1outTopic/message","RED");
     delay(2000);
     client.publish("1outTopic/message","GREEN");
     delay(2000);
     client.publish("1outTopic/message","BLUE");

}


this should show you connect message and then change the LED colours

Thanks for the suggestions. But I see the main problem is in connecting the electron to MQTT over cellular. I have edited my code and updated in in the post, have a look.
But it still seems that maybe it’s a connection issue and it doesn’t establish a session?

I would like to send MQTT messages from the public broker to the Electron and change the LED based on that.

If you search the forum, there are lots of discussion around electron and MQTT … some of these may help?

The public broker you are using does not have a client interface - you will need to provide that with an MQTT client (on your PC perhaps) to publish to the same subscription topic in your code - hence my example did that in the loop.

I would still set the SYSTEM_MODE to automatic while debugging - it makes no difference at this stage - let the DeviceOS get connected then check if your MQTT session connects - hint the client.connect function returns a result based on connection status...

1 Like

Thanks for mentioning this
Indeed, that was the issue probably. I switched to test.mosquitto.org and it is working nicely!

Now I'm able to received the MQTT messages and the LED changes.
But as you seem to know way better than me, let me ask you few very basic things more, not necessarily related to the problem but to my code.

    while(!Cellular.ready());
        //waitFor(Cellular.ready());
        Serial.println("Connected to cellular network. ...");

Is this decent enough to check for cellular connection and retry if there are issues?

if (!strcmp(p, "RED"))
        Serial.println("RED")
        RGB.color(255, 0, 0);
    else if (!strcmp(p, "GREEN"))
        RGB.color(0, 255, 0);
    else if (!strcmp(p, "BLUE"))
        RGB.color(0, 0, 255);
    else
        RGB.color(255, 255, 255);
    delay(1000);

If I try to add Serial.println("RED") to the if statement I will get following error:

'else' without a previous 'if'

Should be Serial.println("RED"); :slight_smile:

@Kepete, you need to add block definers { } if using more than one line within the body of a statement (eg if()…). Otherwise, the first line is used and the following line is treated as being outside the body.

if (!strcmp(p, "RED")) {
        Serial.println("RED");
        RGB.color(255, 0, 0);
    }
    else if (!strcmp(p, "GREEN"))
        RGB.color(0, 255, 0);
    else if (!strcmp(p, "BLUE"))
        RGB.color(0, 0, 255);
    else
        RGB.color(255, 255, 255);
    delay(1000);

And as @shanevanj pointed out, don’t forget your semicolon at the end of a statement.

Makes totally sense :man_facepalming:
thanks :slight_smile:

1 Like

I'd not do it this way.
Also, the commented waitFor() line uses wrong syntax.

waitFor() would be used like this

  if (waitFor(Cellular.ready, 300000)) {
    Serial.println("Connected to cellular network. ...");
    client.connect();
    ...
  }
  else {
    Serial.println("Connection still not established after 5 minutes");
  }

Or more in line of what your code suggests you intended

  waitUntil(Cellular.ready);

Also, while loop() checks whether your client still is connected, you have no countermeasure in case that's not true anymore. You may want to consider a reconnect in such case.

1 Like