3

I am trying to convert byte* value to int here is how I have it.

void mqttCallback(char* topic, byte* payload, unsigned int length) {

  String topicStr = topic;
  int* payload_value;
  int updates_cal;

    payload_value = (int*)payload;
    //updates_cal = *payload_value;


    Serial.print((int)payload_value);


  delay(1);

  Serial.println();
  Serial.println("-----------------------");

}

I am getting MQTT payload as Integer value. Which I want to receive in my NodeMCU (ESP8266).

Is there any way to do this?

Thank you!

user3201500
  • 225
  • 1
  • 6
  • 15

3 Answers3

2

Judging by the comments, you are actually receiving your integer data as text, as a sequence of ASCII characters. This is what you send yourself using mosquitto_pub. The buffer is apparently not zero-terminated.

If these characters represent an integer value, then the way to retrieve it as an integer value would be

char buffer[128];

// Make sure here that `length` is smaller than the above buffer size. 
// Otherwise, you'd need a bigger buffer

// Form a C-string from the payload
memcpy(buffer, payload, length);
buffer[length] = '\0';

// Convert it to integer
char *end = nullptr;
long value = strtol(buffer, &end, 10);

// Check for conversion errors
if (end == buffer || errno == ERANGE)
  ; // Conversion error occurred
else
  Sterial.println(value);

Another approach, which avoids using a separate large[ish] buffer just for the purposes of zero-termination, would be

// Build a `scanf` format string that will read no more than `length`
// characters without relying on zero-termination of the payload
char format[16];
snprintf(format, sizeof format, "%%%ud", length);

// Convert the payload
int payload_value = 0;
if (sscanf((const char *) payload, format, &payload_value) == 1)
  Serial.println(payload_value);
else
  ; // Conversion error occurred

However, this approach is less protected from integer overflow than the previous one.


Note that most of the above "jumping through the hoops" is dedicated to adding a zero-terminator to the input buffer. If instead you opt for ensuring zero-termination on the sender's side, then it would all reduce to a simple

// Convert C-string to integer
char *end = nullptr;
long value = strtol((const char *) payload, &end, 10);

// Check for conversion errors
if (end == buffer || errno == ERANGE)
  ; // Conversion error occurred
else
  Sterial.println(value);

No extra buffers required.

1

Don't know if you found an answer yet, but I had the exact same issue and eventually came up with this:

   payload[length] = '\0'; // Add a NULL to the end of the char* to make it a string.
   int aNumber = atoi((char *)payload);

Pretty simple in the end!

0

byte* means "pointer to byte(s). It is usually used to point to a byte buffer, and usually will also have a length value so you know how many bytes are in the buffer. It looks like your function does have a length value.

If you're certain that the data in the payload parameter is a single int, and the length is correct for an int (2 bytes on Arduino I believe) then you should be able to cast the pointer to int* type and then fetch the value from the buffer:

void mqttCallback(char* topic, byte* payload, unsigned int length) {
  String topicStr = topic;
  int payload_value;
  int updates_cal;

  if (length >= 2) {
    //Cast payload to an int pointer and fetch the value
    intValue = *((int*)payload); 
  }
}
Duncan C
  • 5,752
  • 3
  • 19
  • 30