I would like to convert a byte *payload
to a String
, because I want to compare the content of payload
to another String
.
void mqttCallbackHandler(char *topic, byte *payload, unsigned int length) {
String payloadstr = ???
...
}
Arduino Stack Exchange is a question and answer site for developers of open-source hardware and software that is compatible with Arduino. It only takes a minute to sign up.
Sign up to join this communityDepending on what is setting the message on the topic, payload
may, or may not be, a NULL-terminated string. This is why they provide the length
parameter.
You could consider comparing the data with memcmp()
which is like strcmp()
but doesn't look for a NULL termination - instead it takes a length parameter. This is good if you may have NULL bytes in your payload.
An alternative is strncmp()
which both looks for a NULL termination and also limits the length using a length
parameter. Better for payloads you know are strings, but you aren't sure if they have NULL termination or not.
Here is a callback (for PubSubClient on ESP8266) I have in one of my projects which uses strncmp()
:
void callback(char *topic, byte *payload, unsigned int length) {
if (!strcmp(topic, SUBTOPIC)) {
if (!strncmp((char *)payload, "on", length)) {
digitalWrite(POWERPIN, HIGH);
powerState = true;
client.publish(PUBTOPIC, "on", true);
} else if (!strncmp((char *)payload, "off", length)) {
digitalWrite(POWERPIN, LOW);
powerState = false;
client.publish(PUBTOPIC, "off", true);
}
}
}
Simply casting your payload to (char *)
is enough for the functions to take it as a string, and the length
parameter will prevent looking past the end of the payload if there is no NULL termination.
It's not perfect - a single byte payload of o
will falsely match the first on
, but if that is a critical problem I am sure you can find a way to work around it by checking what length
equals.
This is an old post but probably somebody can use this info:
void mqtt_callback(char* topic, byte* payload, unsigned int length) {
String topicStr = topic;
String recv_payload = String(( char *) payload);
Serial.println( "mqtt_callback - message arrived - topic [" + topicStr +
"] payload [" + recv_payload + "]" );
}
Consider simply using the returned pointer.
Payload is a pointer of type byte. You can compare each byte in a string to the byte the pointer is pointing at. Then increment the pointer to the next byte and repeat the process. You don't need to allocate more memory for new string.
If a type string is necessary. For example, if you were using a complex library method which requires a string to be passed to it, you could copy what the returned pointer is pointing at byte by byte into a locally defined string.
For comparing a byte array to a String object, you could convert the byte array to another String object, but this involves dynamically allocating memory for a whole copy of the string. This is memory unfriendly, and preferably avoided on small microcontrollers.
The cheapest way to achieve what you want is to compare them as character arrays :
if (strcmp((char *) payload, theReferenceString.c_str()) == 0) {
// the strings are equal
}
strcmp()
is a standard C function that does the byte by byte
comparison, exactly as suggested by st2000.
Marco's answer worked for me, but worked better with:
payload[length] = 0;
String recv_payload = String(( char *) payload);
Therefore, the full code would be:
void mqtt_callback(char* topic, byte* payload, unsigned int length) {
String topicStr = topic;
payload[length] = 0;
String recv_payload = String(( char *) payload);
Serial.println( "mqtt_callback - message arrived - topic [" + topicStr +
"] payload [" + recv_payload + "]" );
}