The MQTT PubSub client callback passes the payload
parameter as a pointer to a byte array and not a pointer to a char array - this is due to the content of the publish payload being application specific. In other words, from the point of view of the protocol, the payload can be a string, a file, and image, etc. By contrast, the topic
parameter is indeed expected to be a string, hence the buffer pointer char *topic
among the function parameters.
The result is that just casting the payload
byte parameter to a const char *
and converting to a String
type will not work because the ending null character will be missing. Given the published payload:
{"action":"subscribed"}
handled by the PubSub callback:
void mqttCallback(char *topic, byte *payload, unsigned int length) { String msgTopic = String(topic); String msgPayload = (const char *) payload; //...
will result in the msgPayload
string containing garbage:
{"action":"subscribed"}d}"
Perhaps a simpler way of dealing with the payload
parameter, in case the expected content is a string, would be to create a null-terminated character array:
void mqttCallback(char *topic, byte *payload, unsigned int length) { String msgTopic = String(topic); // payload is not null terminated and casting will not work char msgPayload[length + 1]; snprintf(msgPayload, length + 1, "%s", payload); Serial.println("Message received on topic: " + String(topic) + " with payload: " + String(msgPayload)); // ...
Now String(msgPayload)
will display the string properly. Unfortunately, a lot of available examples incorrectly convert the payload
parameter resulting in small yet ever-increasing memory corruption over time which leads to stability issues with the Arduino device.
Connect an output pin to ground (ie: D3
on WeMoS mini) and plug in the USB cable to flash a new sketch. Disconnect the cable after flashing and reset the board.