[SOLVED] Simple actuation program using MQTT API not working

Hi. I am new to ubidots and am trying to write a simple actuator program. I have an Intel Edison board, and I am programming using Eclipse IDE. I am using Paho MQTT library and APIs. So far I have been able to connect to the dashboard and can publish data. Now I want to simulate actuation, where if my data reaches 50, a buzzer = 1 event should be sent to my device.

In my dashboard, I have created 2 variables. dummy which stores the published data and buzzer. I have created an event that when dummy = 50, buzzer = 1. This is also reflecting in the dashboard. But the notification is not received by my program.

In my code, I have registered callback, subscribed to variable and also implemented the callback function. Yet my callback is not being invoked.

code snippet:

#define MESSAGE_TOPIC "/v1.6/devices/dummy_db"
#define TOPIC "/v1.6/devices/dummy_db/#"

main()
{

MQTTClient_setCallbacks(client, NULL,
			&connection_lost, &message_arrived, &delivery_complete);

data.username = const_cast<char *>(ubidots_username);
data.password = NULL;

rc = MQTTClient_connect(client, &data);
if (rc != MQTTCLIENT_SUCCESS) {
	std::cerr << "Failed to connect MQTT client, exiting :" << rc <<std::endl;
	exit(rc);
}

rc = MQTTClient_subscribe(client, const_cast<char *>(TOPIC), MQTT_DEFAULT_QOS);
if (rc != MQTTCLIENT_SUCCESS) {
	std::cerr << "Failed to subscribe, exiting :" << rc <<std::endl;
	exit(rc);
}

for(;;)
{
       //publish dummy data
       int rc = MQTTClient_publish(client, const_cast<char *>(MESSAGE_TOPIC), message_size,
				const_cast<char *>(payload), MQTT_DEFAULT_QOS, retained, &dt);
}

}
int message_arrived(void * context, char * topic, int topic_len, MQTTClient_message * message)
{
	int i;
	char* payloadptr;
	printf("inside function message arrived\n");
	printf("Message arrived\n");
	printf("topic: %s\n", topic);
	printf("message : ");
	payloadptr = (char *)message->payload;
	for(i=0; i<(int)message->payloadlen; i++)
	{
	    putchar(*payloadptr++);
	}
	putchar('\n');
	MQTTClient_freeMessage(&message);
	MQTTClient_free(topic);

	return true;
}

I am stuck and cannot progress forward. Can anyone help with the settings required in ubidots dashboard and the sequence of APIs to be followed in Paho MQTT in eclipse IDE to enable actuation?

Any example or documentation will be helpful.

2 days… 18 views… yet no response. I hope Ubidots has an active community !

@rahul2901 i have never used eclipse IDE to program an Edison.

But i read your code and i think that the problem is on your topic and connection:

  1. In data.username: Put your token
  2. You forgot to put the server and port

Do you have a link of that library that you are using? Because i cannot found that functions that you are using.
Best regards,
Metavix

Hi @rahul2901,

Here’s a few useful links:

Maybe @juanda95 or @woakas can check your code?

Hi @rahul2901,

I can’t compile your code, I have several errors, I’m using https://github.com/eclipse/paho.mqtt.c library, have you reviewed the examples of the Paho library?

What libraries are using to compile this code? and compiler?

(You can find the examples in github)

Gustavo.

Thanks for the response. I am using MQTT with C++ on Eclipse IDE. I have include Paho MQTT library (paho-mqtt3c).

@woakes - You are getting compilation error because I had not completely copied my code. Below is my code, which is publishing a dummy data every second to the cloud. In the ubidots dashboard I have created a variable called dummy. Then a rule that when dummy = 50, a variable buzzer is set to 1. I have subscribed to the variable buzzer and implemented a callback to print the received message,

Please include paho-mqtt3c in c/c++ build->settings->IoT cross G++ linker->Libraries

#include "mraa.hpp"
extern "C" {
#include "MQTTClient.h"
}

#include "stdlib.h"

#include <iostream>

MQTTClient client;

#define MESSAGE_TOPIC "/v1.6/devices/dummy_db"
#define TOPIC "/v1.6/devices/dummy_db/+/buzzer"

#define HOST_PROTO "tcp://"
#define HOST_SUFFIX "things.ubidots.com:"
#define HOST_PORT "1883"

#define DUMMY_MAX_VALUE 100
#define MQTT_DEFAULT_QOS 0
#define QOS 1
const char * ubidots_username = "TOKENMK4TOKENAFc3";
const char * ubidots_password = "";

void delivery_complete(void * context, MQTTClient_deliveryToken dt)
{
	printf("Publishing of message with token %d confirmed\n", dt);
}

void connection_lost(void * context, char* cause)
{
	printf("Connection lost\n");
	exit(MQTTCLIENT_DISCONNECTED);
}

int message_arrived(void * context, char * topic, int topic_len, MQTTClient_message * message)
{
	int i;
	char* payloadptr;
	printf("inside function message arrived\n");
	printf("Message arrived\n");
	printf("topic: %s\n", topic);
	printf("message : ");
	payloadptr = (char *)message->payload;
	for(i=0; i<(int)message->payloadlen; i++)
	{
	    putchar(*payloadptr++);
	}
	putchar('\n');
	MQTTClient_freeMessage(&message);
	MQTTClient_free(topic);

	return true;
}

int main()
{
	char host[256];
	char clientID[256];

	mraa::Platform platform = mraa::getPlatformType();
	snprintf(host, sizeof host, "%s%s%s", HOST_PROTO ,HOST_SUFFIX, HOST_PORT);
	snprintf(clientID, sizeof clientID, "%s", ubidots_username);
	int rc = 0;
	rc = MQTTClient_create(&client, const_cast<char *>(host), const_cast<char *>(clientID),
			MQTTCLIENT_PERSISTENCE_NONE, NULL);
	if (rc != MQTTCLIENT_SUCCESS) {
		std::cerr << "Failed to create MQTT client, exiting : " << rc << std::endl;
		exit(rc);
	}
	MQTTClient_setCallbacks(client, NULL,
			&connection_lost, &message_arrived, &delivery_complete);

	MQTTClient_connectOptions data = MQTTClient_connectOptions_initializer;
	data.username = const_cast<char *>(ubidots_username);
	data.password = NULL;
	rc = MQTTClient_connect(client, &data);
	if (rc != MQTTCLIENT_SUCCESS) {
		std::cerr << "Failed to connect MQTT client, exiting :" << rc <<std::endl;
		exit(rc);
	}
	rc = MQTTClient_subscribe(client, const_cast<char *>(TOPIC), MQTT_DEFAULT_QOS);
	if (rc != MQTTCLIENT_SUCCESS) {
		std::cerr << "Failed to subscribe, exiting :" << rc <<std::endl;
		exit(rc);
	}
	unsigned short dummyData = 1;
	for (;;) {
		char payload[80];
		sprintf(payload, "{ \"dummy\": \"%d\" }", dummyData);
		int message_size = strlen(payload);

		int retained = 0;
		MQTTClient_deliveryToken dt;
		int rc = MQTTClient_publish(client, const_cast<char *>(MESSAGE_TOPIC), message_size,
				const_cast<char *>(payload), MQTT_DEFAULT_QOS, retained, &dt);
		if (rc == MQTTCLIENT_SUCCESS) {
			printf("Waiting for message with token %d to be published...\n", dt);
			rc = MQTTClient_waitForCompletion(client, dt, 1000);
			if (rc == MQTTCLIENT_SUCCESS) {
				printf("Message with token %d published\n", dt);
			} else {
				std::cerr << "Failed to publish message with token " << dt << std::endl;
			}
		} else {
			std::cerr << "Failed to publish message with token " << dt << std::endl;
		}
		if (dummyData == DUMMY_MAX_VALUE) {
			dummyData = 1;
		} else {
			dummyData++;
		}
		sleep(1);
	}
	printf("Stopping\n");

	int timeout = 100;
	MQTTClient_disconnect(client, timeout);
	MQTTClient_destroy(&client);
	return mraa::SUCCESS;
}

@woakas - Were you able to compile my code? @juanda95 can you also look into the issue?

I am kind of stuck here and any help or next steps will be very helpful.

@rahul2901 Thank you for give us the code i will working on that code to give you an answer as soon as possible.

Best regards,
Metavix

@Metavix - Thank you for jumping in. Good news is that I was able to solve the issue and I am able to receive actuation messages successfully. :smile:

The issue was with the TOKEN (variable) to which I was subscribing to for receiving actuation.

#define TOPIC “/v1.6/devices/dummy_db/+/buzzer”
was changed to
#define TOPIC “/v1.6/devices/dummy_db/buzzer”

I am changing the topic to [SOLVED]

1 Like

@rahul2901 Great!

1 Like