Having trouble publishing to MQTT from Argon


#1

Hi, I hope this is the right category for this question…

I’m having some trouble getting messages published to an MQTT broker from an Argon.

I’m using mesh.publish/subscribe from a Xenon, which is working fine to get the data I need.

I’m using the mesh subsribe handler function to call the MQTT client, but it refuses to connect and I’m not sure why. I have tested my MQTT broker with a simple sketch and it looks to be fine.

This is my code, I’m probably missing something obvious…!

// This #include statement was automatically added by the Particle IDE.
#include <MQTT.h>



SYSTEM_THREAD(ENABLED);

int boardLed = D7; // This is the LED that is already on your device.

//Setup MQTT

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

byte server[] = { 192,168,0,30 };
MQTT client(server, 1883, callback);

//MQTT client("192.168.0.30", 1883, callback);

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() {
    
    Serial.begin(9600);
    pinMode(boardLed, OUTPUT);


    //Use External Antenna
    selectExternalMeshAntenna();

    //Subscribe to MESH events
    Mesh.subscribe("xenon/voltage", receiver);

    //Connect to MQTT
    client.connect("sparkclient");


for( int i=0; i<3; i++) {
    digitalWrite(boardLed,HIGH);
    delay( 150 );
    digitalWrite(boardLed,LOW);

    delay( 200 );
    }

}

 
 void loop() {
     
  }


//Event listener for events from Xenon

void receiver(const char *event, const char *data)
{
    
 if (client.isConnected()) {
        //Publish to MQTT
        client.publish(event, data);
        delay(2000);
}       
 else { 
    Serial.printf("MQTT Not Connected"); 
}
 static int i = 0;
 Serial.printf( "[%d] [%s]:[%s]\n", ++i, event, (data ? data : "") );
 digitalWrite(boardLed,HIGH);
 delay( 200 );
 digitalWrite(boardLed,LOW);
 
 //Publish to the cloud.
 Particle.publish(event, data);
}



//External Mesh Antenna Code
void selectExternalMeshAntenna() {

#if (PLATFORM_ID == PLATFORM_ARGON)
	digitalWrite(ANTSW1, 1);
	digitalWrite(ANTSW2, 0);
#elif (PLATFORM_ID == PLATFORM_BORON)
	digitalWrite(ANTSW1, 0);
#else
	digitalWrite(ANTSW1, 0);
	digitalWrite(ANTSW2, 1);
#endif
}

#2

The subscribe handler is not trying to connect, it’s just checking whether a previously established connection is still active but you don’t take any counter measures if this is not the case.

BTW, you should also use PRIVATE for your events unless you really, really want everybody to see your events.


#3

loop() needs to have client.loop(); to allow MQTT to work.


#4

IIRC, that’s true for receiving evens but not necessary for sending events.


#5

Ah, yes ScruffR you’re absolutely right. The setup() is doing the connection and the handler is checking if it’s up, which it doesn’t appear to be. Should I be putting in some logic to force a reconnection to the MQTT broker inside the handler in the case that it’s disconnected?


#6

the client.connect() returns bool - you can check that you do indeed connect?


#7

This would be my choice.

You could also put a check in loop() and maybe regularly calling client.loop() as suggested by @shanevanj will prevent the connection from dropping off in the first place.

If you actually expect events from the broker - although I don’t see you subscribing to any MQTT topic - then you should definetly add that call to loop().


#8

Is this snippet of code essentially testing that bool?

 if (client.isConnected()) {
        //Publish to MQTT
        client.publish(event, data);
        delay(2000);
}       
 else { 
    Serial.printf("MQTT Not Connected"); 
}

#9

What Shane meant was that you don’t check in setup() whether your client.connect() worked at all - you just assume it did and may find out later that it either did never connect or lost the connection.
An initial check would help distinguish between the two cases.


#10

Ah, ok. Understood!


#11

And yes , do this as well :slight_smile:

I use MQTT a lot and I have a clientInit() function that does the client.connect() stuff. I call this from the check in loop above to that you can complete setup() and then on the first entry into loop() it starts the connection. (a reconnect delay is a useful trick so you dont lock up the network trying to reconnect and waste huge amounts of data - I use a 1 minute check and if it fails 3 times I then restart the device incase some external influence has affected the network connection)