1

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!

  • If you want to convert a byte * to int, then you already have it, assuming that int is large enough to store an address on your platform. But what would be the point of this? Your payload_value is an address. – AnT May 1 '19 at 13:08
  • @AnT I just want integer (without pointer). How can I Serial.print it? – user3201500 May 1 '19 at 13:10
  • What specific integer do you want? Taken from where? – AnT May 1 '19 at 13:21
  • @AnT the integer is published by MQTT as a message. – user3201500 May 1 '19 at 13:25
  • The description of the format of MQQT message suggest that the second part of my answer (as well as Duncan C's) answer is the proper way to do it. – AnT May 1 '19 at 13:28
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.

| improve this answer | |
  • Comments are not for extended discussion; this conversation has been moved to chat. – Majenko May 1 '19 at 16:04
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); 
  }
}
| improve this answer | |
  • I tried this, but there is some error. Its resetting my NodeMCU. Exception number is 9 is througing. – user3201500 May 1 '19 at 13:17
0

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!

| improve this answer | |
  • Keep in mind that payload[length] is not part of the memory dedicated to the payload variable. The last item in the memory space of an array always is length-1. Your approach may work most of the time, but you could potentialy overwrite other variables located at that place in memory. – Steve2955 Apr 9 at 17:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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