0

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.

A problem has caused the program to stop working correctly

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?

halfer
  • 19,824
  • 17
  • 99
  • 186
bhai 410
  • 1
  • 5

3 Answers3

1

The type of payload is char *

typedef struct {
    char * topic;
    char * payload;
    unsigned int length;
    boolean retained;
} MQTTMessage;

That means it only accepts strings.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
deamentiaemundi
  • 5,502
  • 2
  • 12
  • 20
  • @bhai410 only if you change everything else that makes use of it, too. That includes the server. Without even looking at the relevant code: that would be a large haul! – deamentiaemundi Sep 01 '16 at 20:54
  • but according to the mosquitto.h file, struct mosquitto_message{ int mid; char *topic; void *payload; int payloadlen; int qos; bool retain; }; The type is just a pointer – bhai 410 Sep 01 '16 at 21:01
  • @bhai410 To be exact: a pointer to an array of `char`. If it has a `\0` at the end it is a compliant C-string, too. You can't put an `int` in there without changing it into an array of `char`. The simplest way to do so is to `sprintf()` it into a proper C-string. I don't know if teh serevr relies on it to be a proper C-string, so you can try to feed the four (prob., better: measure) bytes of the `int` as a `char` array. – deamentiaemundi Sep 01 '16 at 21:07
  • Argh! My bad, I overlooked the fact that you seem to have a different header from the header I found on the net. Sorry for that. But it is `void *` so it still wants a pointer. Give it one. Should do. – deamentiaemundi Sep 01 '16 at 21:24
  • @bhai410 please drop a note if you have read it, so I can delete my wrong answer. – deamentiaemundi Sep 01 '16 at 21:39
  • can you please write a snippet to show me what you mean? it will be of great help – bhai 410 Sep 01 '16 at 21:47
  • 1
    @bhai410 I still haven't read the full code, so I cannot say how the server side receives the payload , so please take it with a slightly larger grain of salt. You can try to give it the pointer to the `int` (e.g.: `&i`) and see what it does (Doc just says "must be a valid memory location"). But be aware that the receiveing end does not know that you send an `int`! – deamentiaemundi Sep 01 '16 at 22:06
  • @bhai410 OK, now that I had glimpsed over the sources (just followed the path of `payload`) and the protocol (MQTT3) you can feed it what you want (MQTT3: "The content and format of the data is application specific"), getting the semantic is due to the user. So send the four bytes of the `int` and rebuild the integer at the receiving end. Sending strings (UTF8 acc. to MQTT3) would be the simplest. – deamentiaemundi Sep 01 '16 at 22:36
  • Thanks a lot for your help. I assigned the address of the int to the payload (pubmsg.payload = &i) as you mentioned and now it does not crash and delivers the message. But how to rebuild the integer at the broker? – bhai 410 Sep 01 '16 at 22:42
  • @bhai410 do you actually get the four bytes `0x00, 0x00, 0x01, 0x00` for the number `4`? (the order might differ) – deamentiaemundi Sep 01 '16 at 22:58
  • currently i'm just checking with the publisher client and server (no subscriber). I am using printf in the server to see the results. The question is, since i am assigning the address of the integer to the payload in the publisher client (pubmsg.payload = &i), how do i know that the mosquitto server has received the integer value (which in my case is 4)? – bhai 410 Sep 01 '16 at 23:15
  • @bhai410 Play around with this `#include int main(int argc, char **argv){int i = atoi(argv[1]);union{int k;char c[4];}u;u.k=i;printf("%x %x %x %x\n",u.c[3],u.c[2],u.c[1],u.c[0]);u.c[3]=0,u.c[2]=0,u.c[1]=0,u.c[0]=5; printf("%d\n",u.k);return 0;}` – deamentiaemundi Sep 01 '16 at 23:29
0

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, ....)

Makketronix
  • 1,389
  • 1
  • 11
  • 31
0

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);
jeremf
  • 652
  • 5
  • 8