pubsubclient icon indicating copy to clipboard operation
pubsubclient copied to clipboard

Convert/Reading payload to int, float, and String / better solution?

Open maxtox opened this issue 9 years ago • 23 comments

HI,

it would be GREAT if we could have a possibilities to "choose" what we expecting (int, float, bool, string) to get from payload. I made it like this, but i am NOT a programmer, so i need a MORE ELLEGANT way :-) !

just made for me a small sketch to check if its working to pass a string with a new topic to the Arduino, so it sends payload on a UPDATED topic.

First i converted Payload to int/float to handle it later in the code: //********** int i; for (i = 0; i<length; i++) { message_buff[i] = payload[i]; } message_buff[i] = '\0'; const char *p_payload = message_buff;

//* converting array to int and float got_double = strtod(p_payload, NULL); got_int = atoi(p_payload); got_float = atof(p_payload); if (got_int == 0 || got_int<0) { got_bool = 0; } else { got_bool = 1; } //*

after that i converted Payload (with comming topic like xxx/sdfdfdjh/lksdfkd/sdjsdhf...) to

//_convert float value to Char expected by function char temp[5]; dtostrf(rrr,4,3,temp); //rrr ist a float value //_***
for (i = 0; i<length; i++) { p_buff[i] = p[i]; } p_buff[i] = '\0'; const char p_p = p_buff; // MQTTclient.publish(p_p, CHAR); //
Maybe you can have a look into this "issue and tell us how to do it better with your library!

Thank you in Advance!

maxtox avatar Jan 03 '16 00:01 maxtox

Do you have a suggestion for what the api would look like for this? It is so trivial (and well documented with minimal google searches) to convert between different types I'm not sure it is worth increasing the library's size for some code that wouldn't be widely used.

As for your example, can you provide an example of topic/payload values you are receiving and then republishing? I don't immediately see what you're trying to achieve.

knolleary avatar Jan 03 '16 19:01 knolleary

Hi;

maxtox avatar Jan 03 '16 19:01 maxtox

I have following "problems":

  1. to send payload i have to convert int, float or bool to char: i am doing it like this
      char warn[5];
      int nn=0.00;
      dtostrf(warn,4,3,nn); 

      MQTTclient.publish(c_topic, warn);

so every time the conversion :-(

so MOST of the times you send figures over the net to MQTT, so it is pain each time to convert that :-( 2. Payload = 3.46

so now i have to convert it to a float, even it was send as a float from server I am doing it so:

int i, len;

  for (i = 0; i<length; i++) 
  {
    message_buff[i] = payload[i];
  }
  message_buff[i] = '\0';
  const char *p_payload = message_buff;

  got_double = strtod(p_payload, NULL);
  got_float = atof(p_payload);
  got_int = (int)got_float;
  if (got_int == 0 || got_int<0) {
    got_bool = 0;
  }
  else { got_bool = 1; }  
  Serial.println("BUFF");Serial.println(p_payload);
  Serial.println("FLOAT");Serial.println(got_float);
  Serial.println("INT");Serial.println(got_int);
  Serial.println("BOOL");Serial.println(got_bool);

which is a pain...

  1. if i want to "do" something with payload, f.e. compare wit o subtopic: Payload =DOino_01/Keller/Puffer_Gross/hinten/TEMP/TYPE now i want tolook if one of the subtopics is "Keller" i have to convert it again which is ok, because it is "text"

do you have better solution with your library?

P.s: SRAM does not work!!!!

maxtox avatar Jan 03 '16 19:01 maxtox

  1. that is just how you do it. You want to publish the string representation of a numeric value - so you have to create a string representation of the value and pass it to the library. But it is equally valid to publish binary data, not strings. So if the publish functions automatically converted the number 123 to the text "123" (which itself it represented as the three ASCII bytes 0x31,0x32,0x33), then it would break for scenarios where the user wanted to send the value 123 - ie the byte 0x7B.
  2. similarly, the library doesn't know anything about the payload format, so cannot decode it for you. Your code appears to try multiple formats, but most times your code would know exactly what format to decode to, which can be done in one or two lines.
  3. so I'm not clear if you mean topic or payload here. But either way, there is no conversion necessary - you can examine the bytes that are passed to you looking for any pattern you want.

knolleary avatar Jan 03 '16 20:01 knolleary

Thanks!

  1. so you mean that is wrong?

    char warn[5]; int nn=0.00; dtostrf(warn,4,3,nn); it is a float conversation? isnt it?

  2. do you have a link how to do it :-/? PLEASE

maxtox avatar Jan 03 '16 20:01 maxtox

  1. that is indeed a float to string conversion. And is almost certainly what you want.
  2. If you have published the value "3.14" then the following ought to do it.
  payload[length] = '\0';
  String s = String((char*)payload);
  float f = s.toFloat();

knolleary avatar Jan 03 '16 20:01 knolleary

cool... and for int would be ? payload[length] = '\0'; String s = String((char*)payload); int i= s.toInt();

maxtox avatar Jan 03 '16 20:01 maxtox

Yup - see https://www.arduino.cc/en/Reference/StringObject for what functions are available on String objects.

knolleary avatar Jan 03 '16 20:01 knolleary

Thank you very much @knolleary for your help! much appreciate it.

ariffinzulkifli avatar Sep 27 '16 14:09 ariffinzulkifli

I think: payload[length] = '\0'; is not safe. I think payload can go up to MQTT_MAX_PACKET_SIZE (defined = 128) in size so what if the payload is just on the boundary & we hit the next memory location?

whhsn avatar Oct 05 '16 14:10 whhsn

Dear @knolleary I would like to get the payload as an integer between [0-255] and use it to analogWrite the outPin with the payload value, would you please help me on how I can do this?

gsmartnet avatar Dec 29 '16 08:12 gsmartnet

@gsmartnet it depends how you are publishing that value. If you're publishing it as the text representation of the number, then see my comment just a few above for parsing the received data as a number - https://github.com/knolleary/pubsubclient/issues/105#issuecomment-168538000

knolleary avatar Dec 29 '16 22:12 knolleary

Anybody can help me on how to publish BOOLEAN data? I'm frustrated with type data conversion. Please help... void callback(char* topic, byte* payload, unsigned int length) { if(strcmp(topic,"/lampu/kamar1") == 0){ digitalWrite(PIN_LED, FLAG_PIN_LED); payload[length] = '\0'; String s = String((char*)payload); client.publish("/lampu/kamar1/status",FLAG_PIN_LED); FLAG_PIN_LED = !FLAG_PIN_LED; } }

MiaranaDIY avatar Jun 17 '17 16:06 MiaranaDIY

@MiaranaDIY client.publish("/lampu/kamar1/status",(FLAG_PIN_LED) ? "true" : "false"); or client.publish("/lampu/kamar1/status",(FLAG_PIN_LED) ? "1" : "0");

DjordjeMandic avatar Mar 23 '18 06:03 DjordjeMandic

ask how to parse String to char ? variable pin change to type data char.. String pin = String(); pin = client.parseInt(); Serial.print("PIN : "); Serial.println(pin);

mydhitz avatar Jun 07 '18 04:06 mydhitz

@mydhitz Your reply is not clear. Could be explain please ? thanks

clabnet avatar Jun 16 '18 17:06 clabnet

First thing I would like to know is why we have to read the payload by 1 byte at the time by using this for loop with the LENGHT as the final parameter. Why is the payload not just a string which we can just copy?

paysan18 avatar Feb 08 '19 13:02 paysan18

@paysan18 because MQTT payloads might not be Strings - the are just a set of bytes sent over the network. It is the sender/receiver who interpret those bytes into the right format for the application.

knolleary avatar Feb 08 '19 13:02 knolleary

@paysan18 because MQTT payloads might not be Strings - the are just a set of bytes sent over the network. It is the sender/receiver who interpret those bytes into the right format for the application.

Can I conver payload variable to boolean ? I ve some trouble in ioBroker MQTT adapter it show me String. I can convert it in my Scripts but thats is not a plan

boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength)

sausagerus avatar Mar 22 '19 13:03 sausagerus

how to send/publish a double value?

shadababe04 avatar Apr 29 '19 11:04 shadababe04

I solved the problem this way:

void callback(char *topic, byte *payload, unsigned int length) { char buff_p[length]; for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); buff_p[i] = (char)payload[i]; } buff_p[length] = '\0'; String msg_p = String(buff_p); val = msg_p.toFloat(); //to float val = msg_p.toInt(); // to Int }

LeandroLimaPRO avatar Jun 22 '19 05:06 LeandroLimaPRO

Hi @knolleary, Thanks for the amazing library but I disagree with you when you said "Conversion methods are unnecessary and will increase library size unnecessarily."

Conversion is obviously required every time we use the library to send or receive data. Hence, having to look for a method that works perfectly in the core language does not work very well for beginners/ intermediates.

For example, I used String library for the same and just discovered it is known to cause memory leaks and hence it malfunctions my MCU.

Apart from this, everyone has to invest a lot of time for conversion to find an easy and safe method for every MQTT application (Yes, everytime I emphasize) i.e different hard work while for example sending sensor readings, different hardwork for chat apps, different hardwork for boolean applications and so on.

So I think it would be very advantageous if the library had inbuilt functions for all type conversions.

Tejas-MD avatar Sep 25 '20 08:09 Tejas-MD

Hi @knolleary, Thanks for the amazing library but I disagree with you when you said "Conversion methods are unnecessary and will increase library size unnecessarily."

Conversion is obviously required every time we use the library to send or receive data. Hence, having to look for a method that works perfectly in the core language does not work very well for beginners/ intermediates.

For example, I used String library for the same and just discovered it is known to cause memory leaks and hence it malfunctions my MCU.

Apart from this, everyone has to invest a lot of time for conversion to find an easy and safe method for every MQTT application (Yes, everytime I emphasize) i.e different hard work while for example sending sensor readings, different hardwork for chat apps, different hardwork for boolean applications and so on.

So I think it would be very advantageous if the library had inbuilt functions for all type conversions.

I partly agree with @knolleary , leaving the library is important, but adding an abstraction layer focused on performance and memory dumping is also important when it comes to data telemetry. Therefore, it is important to have a native conversion focused on the premises of lightness.

LeandroLimaPRO avatar Feb 07 '25 19:02 LeandroLimaPRO