2

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 = ???
  ...
}

5 Answers 5

7

Depending 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.

1
  • strncmp is good for internal comparison, what if I want to send the data to a rest API?
    – dvdmn
    Apr 29, 2022 at 22:44
3

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 + "]" );
}
1
  • Thanks for answering the actual question. But how does the String constructor know where the end of the char array is ?
    – tavis
    Jul 1, 2021 at 4:51
2

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.

2

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.

2
  • what if the payload string is not terminated with zero?
    – Juraj
    Aug 5, 2018 at 8:45
  • 1
    @Juraj: then memcmp(). Aug 5, 2018 at 8:56
0

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 + "]" );
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.