Convert/Reading payload to int, float, and String / better solution?
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!
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.
Hi;
I have following "problems":
- 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...
- 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!!!!
- 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.
- 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.
- 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.
Thanks!
-
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?
-
do you have a link how to do it :-/? PLEASE
- that is indeed a float to string conversion. And is almost certainly what you want.
- 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();
cool... and for int would be ? payload[length] = '\0'; String s = String((char*)payload); int i= s.toInt();
Yup - see https://www.arduino.cc/en/Reference/StringObject for what functions are available on String objects.
Thank you very much @knolleary for your help! much appreciate it.
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?
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 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
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 client.publish("/lampu/kamar1/status",(FLAG_PIN_LED) ? "true" : "false"); or client.publish("/lampu/kamar1/status",(FLAG_PIN_LED) ? "1" : "0");
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 Your reply is not clear. Could be explain please ? thanks
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 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.
@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)
how to send/publish a double value?
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 }
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.
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.