Problems with MQTT and Ubidots

Hello guys,

I´m trying to use the MQTT function for Ubidots. The project in the WebIDE compiles and I can flash the Photon. As soon as it starts up it starts blinking red (SOS). Have you had the same problem ?

Here is my test code:

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

// This #include statement was automatically added by the Particle IDE.
#include "UbidotsMQTT.h"



#define TOKEN "XXXXX"  // Add here your Ubidots TOKEN
#define VARIABLE_IDENTIFIER_ONE "humidity" // Add a variable identifier, it must be in lowercase
#define VARIABLE_IDENTIFIER_TWO "temperature" // Add a variable identifier, it must be in lowercase
#define DATA_SOURCE_NAME "My_beautiful_device"

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

Ubidots client(TOKEN, callback);

void callback(char* topic, byte* payload, unsigned int length) {
    char p[length + 1];
    memcpy(p, payload, length);
    p[length] = NULL;
    String message(p);
    Serial.write(payload, length);
    Serial.println(topic);
}

void setup() {
    Serial.begin(115200);
    while (client.connect());
    client.setDataSourceLabel(DATA_SOURCE_NAME);
}

void loop() {
    int value_one = 22;
    int value_two = 33;
    client.add(VARIABLE_IDENTIFIER_ONE, value_one);
    client.add(VARIABLE_IDENTIFIER_TWO, value_two);
    client.sendValues();
}

maybe try another site like things speak …I’ve had good experience with it.I know when I am running MQTT my indicator light on the particle shuts off completely but is still working…

Here is some Working MQTT Code …

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

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


byte server[] = {10,0,0,2 };MQTT client(server, 1883, callback);

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

    if (message.equals("RED"))
        RGB.color(255, 0, 0);
    else if (message.equals("GREEN"))
        RGB.color(0, 255, 0);
    else if (message.equals("BLUE"))
        RGB.color(0, 0, 255);
    else
        RGB.color(255, 255, 255);
    delay(1000);
}
//**********
const int AlarmPinIn = D1;//LowPressure
const int AlarmPinIn1 = D2;//High Pressure
const int AlarmPinIn2 = D3;//Flame Fail
const int AlarmPinIn3 = D4;//CO2 Alarm

int buttonState = 0;
int buttonState1 = 0;
int buttonState2 = 0;
int buttonState3 = 0;
int buttonState4 = 0;
int buttonState5 = 0;
int buttonState6 = 0;

int sensorValue = 0;
int outputValue = 0;
int sensorValue1 = 0;
int outputValue1 = 0;
int sensorValue2 = 0;
int outputValue2 = 0;
int sensorValue3 = 0;
int outputValue3 = 0;
int sensorValue4 = 0;
int outputValue4 = 0;
int sensorValue5 = 0;
int outputValue5 = 0;
int sensorValue6 = 0;
int outputValue6 = 0;
int sensorValue7 = 0;
int outputValue7 = 0;
int sensorValue8 = 0;
int outputValue8 = 0;
int sensorValue9 = 0;
int outputValue9 = 0;
int sensorValue10 = 0;
int outputValue10 = 0;

#define DHTPIN 0     // what pin we're connected to

#define DHTTYPE DHT11		// DHT 11 


DHT dht(DHTPIN, DHTTYPE);

void setup() {
	Serial.begin(9600); 
	Serial.println("DHT11 test!");

	dht.begin();
//*******************	
	RGB.control(true);

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

    // publish/subscribe
    if (client.isConnected()) {
        client.publish("outTopic/message","hello world");
        client.subscribe("inTopic/message");
    }
//*********************
 pinMode(AlarmPinIn, INPUT);
 pinMode(AlarmPinIn1, INPUT);
 pinMode(AlarmPinIn2, INPUT);
 pinMode(AlarmPinIn3, INPUT);
 
//********************
}

void loop() {
    
    char message[56];
    
     if (client.isConnected())
        client.loop();
// Wait a few seconds between measurements.
	delay(2000);

// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a 
// very slow sensor)
	float h = dht.getHumidity();
// Read temperature as Celsius
	float t = dht.getTempCelcius();
// Read temperature as Farenheit
	float f = dht.getTempFarenheit();
  
// Check if any reads failed and exit early (to try again).
	if (isnan(h) || isnan(t) || isnan(f)) {
		Serial.println("Failed to read from DHT sensor!");
		return;
	}
//*********************


// Compute heat index
// Must send in temp in Fahrenheit!
	float hi = dht.getHeatIndex();
	float dp = dht.getDewPoint();
	float k = dht.getTempKelvin();

	Serial.print("Humid: "); 
	Serial.print(h);
	Serial.print("% - ");
	Serial.print("Temp: "); 
	Serial.print(t);
	Serial.print("*C ");
//	Serial.print(f);
//	Serial.print("*F ");
//	Serial.print(k);
//	Serial.print("*K - ");
//	Serial.print("DewP: ");
//	Serial.print(dp);
//	Serial.print("*C - ");
//	Serial.print("HeatI: ");
//	Serial.print(hi);
//	Serial.println("*C");
//	Serial.println(Time.timeStr());
	
	sensorValue4 =(t);
	sprintf(message, "%d",sensorValue4);
//	Particle.publish("Temperature", message, PRIVATE);
	client.publish("mymosquitto/arduino/temp", message);
	sensorValue5 =(h);
	sprintf(message, "%d",sensorValue5);
//	Particle.publish("Humidity", message ,PRIVATE);
	client.publish("mymosquitto/arduino/humid", message);
	
  int buttonState = digitalRead(AlarmPinIn);
  sensorValue = buttonState;
  sprintf(message,"%d",sensorValue);
  client.publish("mymosquitto/arduino/BoilerLowPressure",message);
//  Particle.publish("BoilerLowWater", message, PRIVATE);
  delay(100);

  
  int buttonState1 = digitalRead(AlarmPinIn1);
  sensorValue1 = buttonState1;
  sprintf(message,"%d",sensorValue1);
  Particle.publish("BoilerHighPress", message, PRIVATE);
  client.publish("mymosquitto/arduino/BoilerHighPress",message);
  delay(100); 

  
  int buttonState2 = digitalRead(AlarmPinIn2);
  sensorValue3 = buttonState2;
  sprintf(message,"%d",sensorValue3);
  Particle.publish("BoilerFlameFail", message, PRIVATE);
 
  int buttonState5 = digitalRead(AlarmPinIn2);
  sensorValue4 = buttonState2;
  sprintf(message,"%d",sensorValue4);
  client.publish("mymosquitto/arduino/BoilerFlameFail",message);
  delay(100);

  
  int buttonState3 = digitalRead(AlarmPinIn3);
  sensorValue5 = buttonState3;
  sprintf(message,"%d",sensorValue5);
  Particle.publish("CO2Alarm", message, PRIVATE);
  
  int buttonState6 = digitalRead(AlarmPinIn3);
  sensorValue6 = buttonState3;
  sprintf(message,"%d",sensorValue6);
  client.publish("mymosquitto/arduino/CO2Alarm",message);

  delay(100);

//******************************//

int buttonState7 = digitalRead(AlarmPinIn);
  sensorValue7 = buttonState7;
  sprintf(message,"%d",sensorValue7);
if (sensorValue ==LOW) {
    client.publish("mymosquitto/Alarm/BoilerLowPressure", "Boiler 188 Low Water");
    Particle.publish("BoilerLowWater", message, PRIVATE);
    delay(10000);
}

int buttonState8 = digitalRead(AlarmPinIn1);
  sensorValue8 = buttonState8;
  sprintf(message,"%d",sensorValue8);
if (sensorValue == LOW) {
    client.publish("mymosquitto/Alarm/BoilerHighPress", "Boiler 188 High Pressure");
    delay(10000);
}

int buttonState9 = digitalRead(AlarmPinIn2);
 if (sensorValue == LOW) {
    client.publish("mymosquitto/Alarm/BoilerFlameFail","Boiler 188 Flame Fail");
    delay(10000);
}


int buttonState10 = digitalRead(AlarmPinIn3);
  sensorValue = buttonState10;
if (sensorValue == LOW) {
    client.publish("mymosquitto/particle/CO2Alarm", "Boiler 188 CO2 Alarm");
    delay(10000);
    Particle.publish("CO2Alarm", message, PRIVATE);
}

//******************************//

Serial.println(Time.timeStr());
        
//******************************//

}

Try these minor alterations

void callback(char* topic, byte* payload, unsigned int length) {
    char p[length + 1];
    memcpy(p, payload, length);
    p[length] = '\0';
    Serial.write(p, length);
    Serial.println(topic);
}

And I’ds low down loop() a bit or at least not push data every millisecond to Ubidots :wink:

BTW, with SOS faults the number of blinks between the SOS patterns is important info for troubleshooting.


@jade7272, when posting code, wrap it in a set of these for better formatting

 ```cpp
 // your code here
I have corrected that for you. And for further hints on the subject have a look here
  https://community.particle.io/t/forum-tips-and-tricks/3999

Thanks …

Welcome!
For your code I’d see some potential in the use of arrays instead of these lists of variables that basically do a lot of the same stuff.

Ok …Definitely will look it that …Still newbie …lol

Hello guys and thank you for very quick reply !

I tried both tweaks but I´m still getting red flashing light (10 times)…

Can it be a problem with the MQTT lib version ? If I try to use version 0.4.8 (the newest) I get the following errors when I compile:

/workspace/lib/MQTT/src/MQTT/…/MQTT.h:85:7: error: redefinition of 'class MQTT’
class MQTT {
^
/workspace/lib/MQTT/src/MQTT.h:85:7: error: previous definition of 'class MQTT’
class MQTT {
^

But I can use version 0.4.4 but then get the following error using the tweak from ScruffR

workspace//src/mqtt_test.cpp:26:27: error: invalid conversion from ‘char*’ to ‘const uint8_t* {aka const unsigned char*}’ [-fpermissive]

                       ^

…/wiring/inc/spark_wiring_print.h:67:20: error: initializing argument 1 of ‘virtual size_t Print::write(const uint8_t*, size_t)’ [-fpermissive]
virtual size_t write(const uint8_t *buffer, size_t size);

Hello @rdavidsson @jade7272 @ScruffR , my name is José García and I’m an Ubidots Engineer, first than all my apologizes for the issues that you are experiencing, the MQTT library for particle is outdated and I’m working right now for making it work properly and I hope to launch next week the fixed version.

Meanwhile, please use this code as example, it should work for publish and subscribe to Ubidots, simply replace your device and variable labels:

    /****************************************
     * Include Libraries
     ****************************************/

    #include "MQTT/MQTT.h"

    /****************************************
     * Define Constants
     ****************************************/

    #define TOKEN "...."  // Add here your Ubidots TOKEN

    /****************************************
     * Auxiliar Functions
     ****************************************/

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

    void callback(char* topic, byte* payload, unsigned int length) {
        char p[length + 1];
        memcpy(p, payload, length);
        p[length] = NULL;
        String message(p);
        Serial.write(payload, length);
        Serial.println(topic);
    }


    /****************************************
     * Instances
     ****************************************/

    MQTT client = MQTT("things.ubidots.com", 1883, callback, 512);
    String clientName = "";

    /****************************************
     * Main Functions
     ****************************************/

    void setup() {
        Serial.begin(115200);
        clientName = System.deviceID();
        client.connect(clientName, TOKEN, NULL);
        if(client.isConnected()){
            client.subscribe("/v1.6/devices/my-device/my-variable/lv");
        }
    }

    void loop() {
        if(!client.isConnected()){
            Serial.println("attemping to connect");
        }
        while(!client.isConnected()){
            client.connect(clientName, TOKEN, NULL);
            Serial.print(".");
            delay(500);
        }
        Serial.println("connected");
        client.publish("/v1.6/devices/test-m", "{\"test-var\":1}"); // Publish to device 'test-m' and variable 'test-var'
        client.subscribe("/v1.6/devices/my-device/my-variable/lv"); // Subscribe to 'my-variable' at 'my-device' device
        client.loop();
        delay(1000);
    }

Please do not forget to include the MQTT library for particle in your app. Hope it works for you, I’ll update you as soon as I finish the testing for the new version of the library.

Let me know any question that you have.

The last error can easily be fixed with a type cast

Serial.write((uint8_t*)p, length);

The other errors might be due to some recent hick-ups with 0.6.1.
Can you try 0.6.2-rc.1 or 0.6.0?

But after looking at the MQTT library it seems the contributor has failed to guard the lib against multiple inclusion.
So just try to remove the MQTT include from your main project file.

This was already reported to the owner begining of March

@jotathebest, can you clarify a few things in this code please?

  • What’s the use of this line that comes up in so many samples I see, but often is rather superfluous: String message(p);? message is created but never used.
  • Why do we copy payload to p but fail to use p?
  • Why do we see a forward declaration of callback() immediately prior the actual implementation?
  • Please limit the use of String to the absolute minimum as heap fragmentation might impair the stability of embedded systems like this.
  • Have a safeguard against multi inclusion.

With professional libraries like yours we’d like to see best practices even in the most simple of samples.

Thanks :+1:

Hello @ScruffR, I’m very sorry to disturb you, the example was a fast wrapper to help to rdavidsson as soon as possible that I made based on the official example of the library for MQTT of hirotakaster which is one of the most popular libraries that I found at Particle’s online IDE (3235 of included times in apps), maybe I should check it better before to post it here, my mistake. Keeping the last in mind, I explain some things about:

  • The callback is a function that is necessary to be declared, “Why do we see a forward declaration of callback() immediately prior the actual implementation?” You are right, it should see only one declaration, what I wanted to show is that the programmer must declare it and to setup the routine to run the logic inside it, the callback must have three parameters: topic that is the topic that you are subscribed, payload that is the answer directly from the broker and lenght that is the size of the payload char array, these parameters are returned directly from the library and that’s why you call the constructor with the callback function. If you don’t need to subscribe to any topic anyway you have to declare it in this way:

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

  • What’s the use of this line that comes up in so many samples I see, but often is rather superfluous String message§; - message is created but never used?”, "Why do we copy payload to p but fail to use p?"
    As I said previously, the programmer is the one who should use the payload in the way that he believes convenient for his app, and yes, as you say, “Please limit the use of String to the absolute minimum as heap fragmentation might impair the stability of embedded systems like this” this should be avoided and the original maker did his example using it, my error to make a fast example was to let as it was but maybe the suggestion should go for him too, anyway, I attach maybe a better callback implementation:
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  Serial.println("payload:");
  for (int i=0;i<length;i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

So keeping in mind your suggestions please tell me if this would a proper example for you:

    /****************************************
     * Include Libraries
     ****************************************/

    #include "MQTT/MQTT.h"

    /****************************************
     * Define Constants
     ****************************************/
    #ifndef TOKEN
    #define TOKEN "...."  // Add here your Ubidots TOKEN
    #endif

    /****************************************
     * Auxiliar Functions
     ****************************************/

    void callback(char* topic, byte* payload, unsigned int length) {
        Serial.print("Message arrived [");
        Serial.print(topic);
        Serial.print("] ");
        Serial.println("payload obtained from server:");
        for (int i=0;i<length;i++) {
            Serial.print((char)payload[i]); // prints the answer of the broker for debug purpose
        }
        // Some stuff to make with the payload obtained
            // ......
       //
        Serial.println();
    }


    /****************************************
     * Instances
     ****************************************/

    MQTT client = MQTT("things.ubidots.com", 1883, callback, 512);
    String clientName = "";

    /****************************************
     * Main Functions
     ****************************************/

    void setup() {
        Serial.begin(115200);
        clientName = System.deviceID();
        client.connect(clientName, TOKEN, NULL);
        if(client.isConnected()){
            client.subscribe("/v1.6/devices/my-device/my-variable/lv");
        }
    }

    void loop() {
        if(!client.isConnected()){
            Serial.println("attemping to connect");
        }
        while(!client.isConnected()){
            client.connect(clientName, TOKEN, NULL);
            Serial.print(".");
            delay(5000);
        }
        Serial.println("connected");
        client.publish("/v1.6/devices/test-m", "{\"test-var\":1}"); // Publish to device 'test-m' and variable 'test-var'
        client.subscribe("/v1.6/devices/my-device/my-variable/lv"); // Subscribe to 'my-variable' at 'my-device' device
        client.loop();
        delay(1000);
    }

Apologies for the delay and the issues, I have been working hard this week to have as soon as possible this library wrapper ready for all Ubidots users.

2 Likes

Nice, thanks alot ! :wink: can you send me an Email when it´s ready: rdavidsson@gmail.com

@jotathebest, thanks for the update on that and I had the impression that you may be working together with hirotakaster when you mentioned this

I have already filed an issue on his repo about safe guarding too.
I have also filed another one about the sample code.

About that, there isn't anything wrong with using the multi byte overload of Serial.write(), so I would write the callbacl like this

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.printlnf("Message arrived [%s] payload:", topic);
  Serial.write((uint8_t*)payload, length);
  Serial.println();
}

Hello,

I’ve released a new version for the Ubidots HTTP and MQTT libraries, I’ve tested them and it seems to work properly, I’ll thankful a lot you if you can test them and to let me know any issues or improvements.

Regards.

4 Likes