I am new to MQTT. my final project is to send an array that contains a UNIX-based timestamp and its timezone code and a few integer values.
following Paho MQTT C Client - MQTT Client Library Encyclopedia, I come up with its code snippet:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "MQTTClient.h"
#define ADDRESS "tcp://localhost:1883"
#define CLIENTID "ExampleClientPub"
#define TOPIC "testTopic"
#define PAYLOAD "220"
#define QOS 0
#define TIMEOUT 10000L
int main(int argc, char* argv[])
{
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
int rc;
MQTTClient_create(&client, ADDRESS, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
exit(-1);
}
int arr [3] = {1, 2, 3};
pubmsg.payload = arr; // PAYLOAD;
pubmsg.payloadlen = strlen(PAYLOAD);
pubmsg.qos = QOS;
pubmsg.retained = 0;
// while(1){
MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token);
// }
printf("Waiting for up to %d seconds for publication of %s\n"
"on topic %s for client with ClientID: %s\n",
(int)(TIMEOUT/1000), PAYLOAD, TOPIC, CLIENTID);
rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
printf("Message with delivery token %d delivered\n", token);
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
return rc;
}
I changed its payload with an array (for example with only int values). but when I publish the msg, I get an undefined character on the subscriber side:
testClient1#localhost> sub -t testTopic -s
"
can someone please tell me how can I send that array?
strlen(payload) won't work because arr is not a null terminated string.
The payload size should be sizeof arr / sizeof int (assuming it might change in length later)
But even after that you WILL get what looks like garbage out of the mosquitto_sub command because by default to treats all payloads as strings and you haven't sent a string, you've sent 3 int values that do not map to printable characters.
You need to look at the OUTPUT FORMAT section of the mosquitto_sub man page here
I have been trying to send some information using MQTT from an embedded device(RFID reader). This device pushes the data very frequently(~25-30 data for every second). When I start the process in the device, it runs without any issues for ~9-10 hours. Then the process gets killed and when checked the logs, it says
cleaning in abortwrite for socket 5
Failed to connect, return code -1
cleaning in abortwrite for socket 4
Failed to connect, return code -1
Is this problem MQTT or any memory related?Can someone help me out with this?
Please find the below code I have used
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTClient.h"
int main()
{
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
int rc;
MQTTClient_create(&client, "tcp://mqtt1.mindlogic.com:1883", "ExampleClientPub",
MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
pubmsg.payload = buf;
pubmsg.payloadlen = (int)strlen(buf);
// pubmsg.payloadlen = sizeof *antenna_id;
pubmsg.qos = 1;
pubmsg.retained = 0;
MQTTClient_publishMessage(client, "mqtt-ex", &pubmsg, &token);
printf("Waiting for up to %d seconds for publication of %s\n""on topic %s for client with ClientID: %s\n",(int)(10000L/1000), "Hello World!", "MQTT-Examples", "ExampleClientPub");
rc = MQTTClient_waitForCompletion(client, token, 10000L);
printf("Message with delivery token %d delivered\n", token);
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
}
I'm trying to figure out how paho works with SSL.
I've tested a simple pub (without SSL) using mosquitto as broker (with default mosquitto.conf) and all works well. Now I've modified the code below (using the ADDRESS define instead of ADDRESSTEST) for testing SSL. I've used the certified provided by the section "test" of paho.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <MQTTClient.h>
#define ADDRESS "ssl://localhost:18885"
#define ADDRESSTEST "tcp://localhost:1883"
#define CLIENTID "ExampleClientPub"
#define TOPIC "MQTTExamples"
#define PAYLOAD "Hello World!"
#define QOS 1
#define TIMEOUT 10000L
int main() {
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_SSLOptions ssl_opts = MQTTClient_SSLOptions_initializer;;
MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
int rc;
MQTTClient_create(&client, ADDRESS, CLIENTID,
MQTTCLIENT_PERSISTENCE_DEFAULT, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
conn_opts.ssl = &ssl_opts;
conn_opts.ssl->trustStore = "../../validpath/test-root-ca.crt";
conn_opts.ssl->keyStore = "../../validpath/client.pem";
conn_opts.serverURIcount = 0;
conn_opts.serverURIs = NULL;
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
pubmsg.payload = PAYLOAD;
pubmsg.payloadlen = (int)strlen(PAYLOAD);
pubmsg.qos = QOS;
pubmsg.retained = 0;
MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token);
printf("Waiting for up to %d seconds for publication of %s\n"
"on topic %s for client with ClientID: %s\n",
(int)(TIMEOUT/1000), PAYLOAD, TOPIC, CLIENTID);
rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
printf("Message with delivery token %d delivered\n", token);
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
return 0;
}
The problem is that when i run the software with this configuration, the MQTTClient_connect return me the code MQTTCLIENT_WRONG_MQTT_VERSION. Mosquitto runs in localhost and I've modified the mosquitto.conf in this way:
# server authentication - no client authentication
listener 18885
cafile validpath/all-ca.crt
certfile validpath/server.crt
keyfile validpath/server.key
require_certificate false
#tls_version tlsv1
This problem occurs when you compile with -lpaho-mqtt3c, instead of -lpaho-mqtt3cs (that enable SSL). Now it works properly!
I want to connect mqtt subscriber c client to cloudamqp but don't know how to authenticate with C program? Are there any other C language clients with working example. I am using linux.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTClient.h"
#define ADDRESS "tcp://buck.rmq.cloudamqp.com:1883"
#define CLIENTID "ExampleClientSub"
#define PAYLOAD "Hello World!"
#define QOS 1
#define TIMEOUT 10000L
#define USERNAME "sakhdjs"
#define PASSWORD "B7JnaMNF2evJmWpT_WZn"
char TOPIC[12];
volatile MQTTClient_deliveryToken deliveredtoken;
void delivered(void *context, MQTTClient_deliveryToken dt)
{
printf("Message with token value %d delivery confirmed\n", dt);
deliveredtoken = dt;
}
int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
int i;
char* payloadptr;
printf("Message arrived\n");
printf(" topic: %s\n", topicName);
printf(" message: ");
payloadptr = message->payload;
for(i=0; i<message->payloadlen; i++)
{
putchar(*payloadptr++);
}
putchar('\n');
MQTTClient_freeMessage(&message);
MQTTClient_free(topicName);
return 1;
}
void connlost(void *context, char *cause)
{
printf("\nConnection lost\n");
printf(" cause: %s\n", cause);
}
int main(int argc, char* argv[])
{
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
int rc;
int ch;
printf("Enter toic name to subscribe ");
scanf("%s", TOPIC);
//printf("Enter host adderss with format like tcp://localhost:1883 ");
// scanf("%s", ADDRESS);
MQTTClient_create(&client, ADDRESS, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE,NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered);
if ((rc = MQTTClient_connect(client, &conn_opts ,USERNAME,PASSWORD)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
"Press Q<Enter> to quit\n\n", TOPIC, CLIENTID, QOS);
MQTTClient_subscribe(client, TOPIC, QOS);
do
{
ch = getchar();
} while(ch!='Q' && ch != 'q');
MQTTClient_unsubscribe(client, TOPIC);
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
return rc;
}
How to connect using paho mqtt subscriber and also publish? Are there any other C language clients for this purpose? Or any other way in C language with code?
You set the username and password fields in the MQTTClient_connectOptions structure before you pass it to the MQTTClient_connect() function.
MQTTClient_create(&client, ADDRESS, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE,NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
conn_opts.username = USERNAME
conn_opts.password = PASSWORD
I am trying to send a specific message type using the MQTT protocol. I am using the paho.mqtt.c library, and my broker is RabbitMQ 3.6.12, running Erlang 20.0. I am working on a virtual machine running CentOS 6.9.
I first tried doing it by creating a struct for my specific message type, then before asking this question, I also tried using JSON to create my specific message type. I installed cJSON (from here).
Here is my whole code using cJSON :
pubframe.c :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTClient.h"
#include "../tools.c"
#include <cjson/cJSON.h>
#define ADDRESS "tcp://localhost:1883"
#define CLIENTID "MY_PUB"
#define TOPIC "MQTT/Test"
int main(int argc, char* argv[])
{
frame1 test = {42,"test"};
cJSON* frm = NULL;
frm = cJSON_CreateObject();
cJSON_AddNumberToObject(frm,"entier",test.E);
cJSON_AddStringToObject(frm,"string",test.S);
print_frame1(frm);
int i = cJSON_GetArraySize(frm);
printf("number of items in frame : %d\n",i);
cJSON* entier = NULL;
entier = cJSON_GetObjectItem(frm,"entier");
char* pt = cJSON_Print(entier);
printf("entier : %s\n",pt);
cJSON* str = NULL;
str = cJSON_GetObjectItem(frm,"string");
char* st = cJSON_Print(str);
printf("string : %s\n",st);
printf("size of message : %d\n",sizeof(cJSON));
MQTTClient publisher;
MQTTClient_connectOptions connexion = MQTTClient_connectOptions_initializer;
MQTTClient_message msg = msg_creation(frm,sizeof(cJSON),0,0);
MQTTClient_deliveryToken token;
int rc;
MQTTClient_create(&publisher, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
connexion.cleansession = 1;
MQTTClient_setCallbacks(publisher, NULL, connlost, frame_json_arrvd, NULL);
if ((rc = MQTTClient_connect(publisher,&connexion)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
}
MQTTClient_publishMessage(publisher, TOPIC,&msg,NULL);
printf("Message sent!\n");
cJSON_Delete(frm);
MQTTClient_disconnect(publisher,10000);
MQTTClient_destroy(&publisher);
return rc;
}
subframe.c :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTClient.h"
#include "../tools.c"
#include <cjson/cJSON.h>
#define ADDRESS "tcp://localhost:1883"
#define CLIENTID "ClientID"
#define TOPIC "MQTT/Test"
#define QOS 0
#define TIMEOUT 10000L
int main(int argc, char* argv[])
{
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
int rc;
int ch;
MQTTClient_create(&client, ADDRESS, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
MQTTClient_setCallbacks(client, NULL, connlost, frame_json_arrvd, NULL);
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
"Press Q<Enter> to quit\n\n", TOPIC, CLIENTID, QOS);
MQTTClient_subscribe(client, TOPIC, QOS);
do
{
ch = getchar();
} while(ch!='Q' && ch != 'q');
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
return rc;
}
tools.c :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <cjson/cJSON.h>
#include "MQTTClient.h"
int compteur;
// message frames
typedef struct frame1
{
int E;
char* S;
} frame1;
void print_frame1bis(frame1* F)
{
printf(" %s\n",F->S);
printf(" %d\n",F->E);
}
void print_frame1(cJSON* frame1)
{
char * str = cJSON_Print(frame1);
printf("%s\n",str);
}
int frame_json_arrvd(void* context, char* topicName, int topicLen, MQTTClient_message* msg)
{
cJSON* payload_ptr = NULL;
printf("size of message : %d\n",sizeof(msg->payload));
int j = cJSON_GetArraySize(msg->payload);
printf("ok\n");
printf("number of items in frame : %d\n",j);
payload_ptr = cJSON_CreateObject();
payload_ptr = msg->payload;
int i = cJSON_GetArraySize(payload_ptr);
printf("number of items in frame : %d\n",i);
print_frame1(payload_ptr);
cJSON_Delete(payload_ptr);
MQTTClient_freeMessage(&msg);
MQTTClient_free(topicName);
return 1;
}
// in case connexion is lost
void connlost(void *context, char *cause)
{
printf("\nConnection lost\n");
printf(" cause: %s\n", cause);
}
// create message
MQTTClient_message msg_creation(void* payload, int length, int qos, int retained)
{
MQTTClient_message pubmsg = MQTTClient_message_initializer;
pubmsg.payload = payload;
pubmsg.payloadlen = length;
pubmsg.qos = qos;
pubmsg.retained = retained;
return pubmsg;
}
The outpus from the subscriber is
Subscribing to topic MQTT/Test
for client ClientID using QoS0
Press Q<Enter> to quit
size of message : 8
Segmentation fault (core dumped)
So it seems the message is not correctly received as the subscriber crashes as soon as it tries to get the number of items.
This is what I get when I run gdb, not sure if it helps.
Program terminated with signal 11, Segmentation fault.
#0 0x00007f4e49a8b63e in cJSON_GetArraySize () from /usr/lib64/libcjson.so.1
(gdb) bt
#0 0x00007f4e49a8b63e in cJSON_GetArraySize () from /usr/lib64/libcjson.so.1
#1 0x00000000004010c9 in frame_json_arrvd (context=0x0,
topicName=0x7f4e440009e4 "MQTT/Test", topicLen=0, msg=0x7f4e44000bb4)
at ../tools.c:110
#2 0x00007f4e49c962a5 in MQTTClient_run (n=<value optimized out>)
at src/MQTTClient.c:604
#3 0x000000378b807aa1 in start_thread (arg=0x7f4e49a83700) at pthread_create.c:301
#4 0x000000378b4e8bcd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:115
The output from the publisher is
{
"entier": 42,
"string": "test"
}
number of items in frame : 2
entier : 42
string : "test"
size of message : 64
Message sent!
So it looks like the message is correctly created.
I just looked into cJSON recently, so I will keep investigating in case I am using it wrong, but any help would be appreciated.
I tried to narrow it down as suggested in the comments, but I don't see what I can do, seeing as it crashes as soon as it tries to access to the payload of the message.
Please keep in mind I am only a student with no more than a year of experience in computer science. Also, english is not my native language, I hope I am explaining myself clearly enough.
Problem solved (kinda)
I just send the whole message frame as a string and parse it in the msgarrvd function :
pubframe.c :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTClient.h"
#include "../tools.c"
#include <cjson/cJSON.h>
#define ADDRESS "tcp://localhost:1883"
#define CLIENTID "MY_PUB"
#define TOPIC "MQTT/Test"
volatile MQTTClient_deliveryToken deliveredtoken;
void delivered(void *context, MQTTClient_deliveryToken dt)
{
printf("Message with token value %d delivery confirmed\n", dt);
deliveredtoken = dt;
}
int main(int argc, char* argv[])
{
char* test = "{\"string\" : \"whatever\", \"entier\" : 42}";
MQTTClient publisher;
MQTTClient_connectOptions connexion = MQTTClient_connectOptions_initializer;
MQTTClient_message msg = msg_creation(test,strlen(test),0,0);
int rc;
MQTTClient_create(&publisher, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
connexion.cleansession = 1;
MQTTClient_setCallbacks(publisher, NULL, connlost, frame_test_arrvd, NULL);
if ((rc = MQTTClient_connect(publisher,&connexion)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
}
MQTTClient_publishMessage(publisher, TOPIC,&msg,&token);
printf("Message sent!\n");
cJSON_Delete(frm);
MQTTClient_disconnect(publisher,10000);
MQTTClient_destroy(&publisher);
return rc;
}
tools.c :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <cjson/cJSON.h>
#include "MQTTClient.h"
// message frames
void print_frame1(cJSON* frame1)
{
char * str = cJSON_Print(frame1);
printf("%s\n",str);
}
int frame_test_arrvd(void* context, char* topicName, int topicLen, MQTTClient_message* msg)
{
printf("message original : %s\n",msg->payload);
cJSON* payload_ptr = cJSON_Parse(msg->payload);
print_frame1(payload_ptr);
int i = cJSON_GetArraySize(payload_ptr);
printf("number of items in frame : %d\n",i);
cJSON* entier = NULL;
entier = cJSON_GetObjectItem(payload_ptr,"entier");
char* pt = cJSON_Print(entier);
printf("entier : %s\n",pt);
cJSON* str = NULL;
str = cJSON_GetObjectItem(payload_ptr,"string");
char* st = cJSON_Print(str);
printf("string : %s\n",st);
cJSON_Delete(payload_ptr);
MQTTClient_freeMessage(&msg);
MQTTClient_free(topicName);
return 1;
}
// in case connexion is lost
void connlost(void *context, char *cause)
{
printf("\nConnection lost\n");
printf(" cause: %s\n", cause);
}
// create message
MQTTClient_message msg_creation(void* payload, int length, int qos, int retained)
{
MQTTClient_message pubmsg = MQTTClient_message_initializer;
pubmsg.payload = payload;
pubmsg.payloadlen = length;
pubmsg.qos = qos;
pubmsg.retained = retained;
return pubmsg;
}
subframe.c :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTClient.h"
#include "../tools.c"
#include <cjson/cJSON.h>
#define ADDRESS "tcp://localhost:1883"
#define CLIENTID "ClientID"
#define TOPIC "MQTT/Test"
#define QOS 0
#define TIMEOUT 10000L
int main(int argc, char* argv[])
{
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
int rc;
int ch;
MQTTClient_create(&client, ADDRESS, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
MQTTClient_setCallbacks(client, NULL, connlost, frame_test_arrvd, NULL);
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
"Press Q<Enter> to quit\n\n", TOPIC, CLIENTID, QOS);
MQTTClient_subscribe(client, TOPIC, QOS);
do
{
ch = getchar();
} while(ch!='Q' && ch != 'q');
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
return rc;
}
It is not ideal as I still would like to create specific types of message, and I haven't found out what was causing the segmentation fault, but it works perfectly this way.
UPDATE
I found a way to create specific types of message and still send them as string to parse them in the msgarrvd function, I just created a function cJSON_ToString to convert a cJSON* object to a string, so that I can create a cJOSN from any struct I want and then convert it to a string to send it.