Converting uint8_t byte data to a string (ESP-NOW)

Thread Starter

zazas321

Joined Nov 29, 2015
936
Hello. I am using ESP-NOW to communicate wireleslly between remote ESP32 nodes. I have found this library :
https://github.com/yoursunny/WifiEspNow/blob/master/src/WifiEspNow.cpp


In order to send data:
Code:
      char msg[60];
      int len = snprintf(msg, sizeof(msg), "2");
      WifiEspNow.send(PEER, reinterpret_cast<const uint8_t*>(msg),len);

and receiving data:
void printReceivedMessage(const uint8_t mac[6], const uint8_t* buf, size_t count, void* cbarg) {
Serial.printf("Message from %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
for (int i = 0; i < count; ++i) {
Serial.print(static_cast<char>(buf));
}

digitalWrite(ONBOARD_LED,HIGH);
Serial.println();
}



I have a few questions:

1. Is it possible to simplify the sending data function ? I dont really understand the way he is suggesting to cast the message data.

2. Lets say I send a string to one ESP32 device:
Code:
      char msg[60];
      int len = snprintf(msg, sizeof(msg), "hello");
      WifiEspNow.send(PEER, reinterpret_cast<const uint8_t*>(msg),len);
and my reciver ESP32 device will collect the data that I have sent byte by byte. :
Code:
void printReceivedMessage(const uint8_t mac[6], const uint8_t* buf, size_t count, void* cbarg) {
  Serial.printf("Message from %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  for (int i = 0; i < count; ++i) {
    Serial.print(static_cast<char>(buf[i]));
  }

  digitalWrite(ONBOARD_LED,HIGH);
  Serial.println();
}
After I receive a full message, I would like to convert the data into a string.
What would be the correct way to convert data that is stored in uint8_t* buf into a char array?
I have tried the using strcat function as following:

I have declared my char array as following:
char string_var[10];

Code:
void printReceivedMessage(const uint8_t mac[6], const uint8_t* buf, size_t count, void* cbarg) {
  Serial.printf("Message from %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  for (int i = 0; i < count; ++i) {
    Serial.print(static_cast<char>(buf[i]));
    strcat(string_var, (char*)buf[i]);
  }
  Serial.print("string_var=");
  Serial.println(string_var);

  digitalWrite(ONBOARD_LED,HIGH);
  Serial.println();
}
But when receiving any message, the device restarts (meditation error, exception was unhandled)


1603109122571.png
 

bogosort

Joined Sep 24, 2011
696
After I receive a full message, I would like to convert the data into a string.
What would be the correct way to convert data that is stored in uint8_t* buf into a char array?
It seems to me that buf is already a char array. It looks like buf is a pointer to an array of unsigned 8-bit integers, which is practically equivalent to an array of unsigned char.

The only thing preventing you from treating buf as a string is that it probably isn't null-terminated. One way to handle this is to create another array of uint8_t that's at least one byte larger than buff. Then, do something like
C:
    size_t bufflen = sizeof(buff);
    memcpy( str, buff, bufflen );
    str[bufflen] = '\0'; // 'str' is now a string
 

Thread Starter

zazas321

Joined Nov 29, 2015
936
It seems to me that buf is already a char array. It looks like buf is a pointer to an array of unsigned 8-bit integers, which is practically equivalent to an array of unsigned char.

The only thing preventing you from treating buf as a string is that it probably isn't null-terminated. One way to handle this is to create another array of uint8_t that's at least one byte larger than buff. Then, do something like
C:
    size_t bufflen = sizeof(buff);
    memcpy( str, buff, bufflen );
    str[bufflen] = '\0'; // 'str' is now a string

Thanks for replying. I have implemented your function and everything seems to work fine except one strange thing. On my master side, I am sending:
Code:
WifiEspNow.send(device_mac[1], reinterpret_cast<const uint8_t*>("reset"),5);
So Im just sending a string "reset" converted to uint8_t


my receiving side:
Code:
void printReceivedMessage(const uint8_t mac[6], const uint8_t* buf, size_t count, void* cbarg) {
  char string_var[100];
  Serial.printf("Message from %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  for (int i = 0; i < count; ++i) {
    Serial.println(static_cast<char>(buf[i]));
  }

    size_t bufflen = sizeof(buf);
    memcpy( string_var, buf, bufflen );
    string_var[bufflen] = '\0'; // 'str' is now a string
    Serial.print("string_var=");
    Serial.println(string_var)
}
As you can see from the function above, I have initialized string_var as 100 characters to make sure its larger than everything im going to send.

However, Im not fully understanding why is it cutting off the last letter? Instead of receiving "reset",I am receiving "rese"

1603167976348.png
 

Thread Starter

zazas321

Joined Nov 29, 2015
936
Adding +1 to the size_t bufflen seems to fix the issue:
Code:
size_t bufflen = sizeof(buf)+1;
However what I am not able to understand now, why it was not cutting off the last letter when i was sending a string "ok". I was receiving a full string and not "o"
 

bogosort

Joined Sep 24, 2011
696
However, Im not fully understanding why is it cutting off the last letter? Instead of receiving "reset",I am receiving "rese"
That snippet of code was a suggestion for how to attack the problem, not something to be copy-pasted into production code. The main idea was that 'buf' is already a character array; it's up to you to integrate that idea in a robust way in your code.

I know it's easy to rely on the copy-paste method of troubleshooting code, especially if you feel like you're banging your head against a problem. But it's rarely an effective method. For one thing, it might solve that particular problem but introduce other, more subtle issues. Every line of code should be mentally integrated and vetted for correctness, and copy-pasting has a strong tendency to short-circuit that process. Even the simple act of re-factoring the code snippet can go a long way to making sure you understand it.

Case in point: one of the arguments to your printReceivedMessage function is 'count', whose value almost certainly is the number of characters in 'buf'. Does replacing 'bufflen' with 'count' in the memcpy and null-termination fix the problem? I'm betting it does.
 

bogosort

Joined Sep 24, 2011
696
Adding +1 to the size_t bufflen seems to fix the issue:
Code:
size_t bufflen = sizeof(buf)+1;
However what I am not able to understand now, why it was not cutting off the last letter when i was sending a string "ok". I was receiving a full string and not "o"
The usual first step in resolving these weird, apparently inexplicable issues is with printf breadcrumbs. Print the size of 'buff' and compare it what you expect.
 
Top