Unable to subscribe to multiple topics in mqtt - c

I run a simple mqtt publisher c code that subscribe "Hello World".
mqtt subscriber1:
mosquitto_sub -h xx.xx.xx.xx -t "mq_test"
Consecutively i run the same mqtt publisher code in another location and subscribe with different topic to same host.
mqtt subscriber2:
mosquitto_sub -h xx.xx.xx.xx -t "mq_t"
When i starts the second publisher program, first mqtt subscription stops.
Why this issue occurs, i think it is possible to subscribe to multiple topics.
mqtt publisher c code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <MQTTClient.h>
#define ADDRESS "tcp://xx.xx.xx.xx:abcd"
#define CLIENTID "ExampleClientPub"
#define TOPIC "mq_test" //"mq_t"
#define PAYLOAD "Hello World!"
#define QOS 1
#define TIMEOUT 10000L
int main(int argc, char* argv[])
{
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
int rc = 0;
MQTTClient_create(&client, ADDRESS, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 5;
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);
}
MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
while(1){
rc = 0;
pubmsg.payload = PAYLOAD;
pubmsg.payloadlen = 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[%d] delivered\n", token,rc);
}
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
return rc;
}

You are using same code for multiple mqtt publisher only by changing topic and client id in both publisher remain same.please try out the scenario by giving different client id for the publishers.

#define CLIENTID "ExampleClientPub"
Each application/program that connects to an MQTT Broker needs their own unique clientId.
i.e. "MyClnt001", "MyClnt002", "MyClnt003", etc.

You can subscribe to multiple topics from mosquitto_sub client with multiple -t options as below:
mosquitto_sub -t topic1 -t topic2 -t topic3
Programmatically, you can achieve this by connecting once (with one clienId) and subscribing multiple times in a loop with different topics if your client library supports subscribing on the existing connection.

Related

how to send an array of integers and chars with Paho MQTT C Client

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

Paho MQTT cleaning in abortwrite for socket error in C

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);
}

MQTT over SSL with PAHO C

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!

reading sqlite database via mqtt to an mqtt broker using c

I want to read a sqlite3 db file for sending data from an embedded device over a data connection via mqtt to an mqtt broker in c language.
i m getting error "Failed to connect, return code 5"
can anyone please help me out for correcting this code
thanks in advance
#include <stdlib.h>
#include <string.h>
#include <MQTTClient.h>
#include <sqlite3.h>
#define ADDRESS "tcp:localhost:1883"
#define CLIENTID "......"
#define USERNAME "....."
#define PASSWORD "....."
#define TOPIC "..."
#define QOS 1
#define TIMEOUT 10000L
static int callback(void *NotUsed, int argc, char* argv[],char **azColName)
{
int i;
for(i = 0; i<argc; i++) {
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
}
int main() {
int rc;
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
MQTTClient_create(&client, ADDRESS, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.username = USERNAME;
conn_opts.password = PASSWORD;
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.qos = QOS;
pubmsg.retained = 0;
sqlite3 *db;
char *zErrMsg = 0;
char *sql;
const char* data = "Callback function called";
rc = sqlite3_open("db/dht.db", &db);
sql = "SELECT * from table";
rc = sqlite3_exec(db, sql, callback, (void*)data, &zErrMsg);
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: \n",
(int)(TIMEOUT/1000), TOPIC, CLIENTID);
rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
printf("Message with delivery token %d delivered\n", token);
sqlite3_close(db);
return 0 ;
}
From the Paho C doc
MQTTClient_connect()
int MQTTClient_connect(MQTTClient handle, MQTTClient_connectOptions* options)
This function attempts to connect a previously-created client (see
MQTTClient_create()) to an MQTT server using the specified options. If
you want to enable asynchronous message and status notifications, you
must call MQTTClient_setCallbacks() prior to MQTTClient_connect().
Parameters
handle A valid client handle from a successful call to MQTTClient_create().
options A pointer to a valid MQTTClient_connectOptions structure.
Returns
MQTTCLIENT_SUCCESS if the client successfully connects to the server.
An error code is returned if the client was unable to connect to the
server. Error codes greater than 0 are returned by the MQTT protocol:
1: Connection refused: Unacceptable protocol version
2: Connection refused: Identifier rejected
3: Connection refused: Server unavailable
4: Connection refused: Bad user name or password
5: Connection refused: Not authorized
6-255: Reserved for future use
A return code of 5 means "Not authorized", this implies your username/password are wrong.

Mosquitto publisher not publishing integers in C

I'm using Paho client libraries for C to write a client which publishes an integer to the mosquitto broker. When i set the payload as a string, it publishes with no problems, but when i set the payload to be an integer, the publisher crashes with the following message as shown in the image.
My client code is as follows:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "MQTTClient.h"
#define ADDRESS "tcp://localhost:1883"
#define CLIENTID "ExampleClientPub"
#define TOPIC "MQTT Examples"
#define QOS 1
#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, ch;
int i = 4;
MQTTClient_create(&client, ADDRESS, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.username = "user";
conn_opts.password = "hello";
conn_opts.keepAliveInterval = 65000;
conn_opts.cleansession = 1;
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
exit(-1);
}
pubmsg.payload = i;
pubmsg.payloadlen = sizeof(i); //strlen(PAYLOAD);
pubmsg.qos = QOS;
pubmsg.retained = 0;
MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token);
printf("Waiting for up to %d seconds for publication of %d\n"
"on topic %s for client with ClientID: %s\n",
(int)(TIMEOUT / 1000), i, TOPIC, CLIENTID);
rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
printf("Message with delivery token %d delivered\n", token);
do
{
ch = getchar();
} while (ch != 'Q' && ch != 'q');
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
return rc;
}
Can anyone please tell me what I'm doing wrong?
The type of payload is char *
typedef struct {
char * topic;
char * payload;
unsigned int length;
boolean retained;
} MQTTMessage;
That means it only accepts strings.
In case somebody comes across this post, this works for me:
Publish as:
uint32_t mmsg = (2<<31)-1;
mosquitto_publish(mosq, NULL, "topic\0", 4, &mmsg, 2, false);
Read As
LOGD("Message topic and load are %s and %lu\n ", msg->topic, *((uint32_t *) (msg->payload)));
LOGD is just a macro around fprintf(stdout, ....)
The payload field of MQTTClient_message is a char *, you need to use a pointer and to cast it properly if you want to send an integer:
pubmsg.payload = (char *)(&i);

Resources