2

I'm trying to convert the string that I receive from the Websocket to uint8_t that I can copy to the data bytes of CAN protocol frame. I'm using an ESP32 chip and programming it on an Arduino IDE. The string that it receives from the websocket is "0322F12155555555".

#include <WiFi.h>
#include <SPIFFS.h>
#include <ESPAsyncWebServer.h>
#include <WebSocketsServer.h>
#include <esp32_can.h>
#include <SPI.h>
#include <string.h>

uint8_t payload1;
char payload2[100];
...
AsyncWebServer server(80);
WebSocketsServer webSocket = WebSocketsServer(1337);
...
// Callback: receiving any WebSocket message
void onWebSocketEvent(uint8_t client_num,
                      WStype_t type,
                      uint8_t * payload,
                      size_t length) {
...
      Serial.printf("[%u] Received text: %s\n", client_num, payload);
      strcpy(payload2, (const char*)payload);
      payload1 = (uint8_t)(payload2);
...

Error:

error: cast from 'char*' to 'uint8_t {aka unsigned char}' loses precision [-fpermissive]
       payload1 = (uint8_t)(payload2);
                                    ^

I'm segmenting the data into an array later, but I'm not confident that my cast is correct. Can someone please help with this? Thanks

-- Keith

3
  • It should be uint8_t * not uint8_t.
    – Majenko
    Sep 11 '20 at 18:44
  • @Majenko, I have to finally segment the data and copy it into an array that accepts uint8_t. How do I do that? Sep 11 '20 at 18:48
  • I think it sounds like you need to do a lot more than just casting. You need to interpret the content of the string.
    – Majenko
    Sep 11 '20 at 19:02
2

You can't just cast a string to a numeric type - C just doesn't work that way. What you're actually casting is the address in memory that the string resides at.

Instead you need to take the content of the string and interpret it.

For instance, you might take each pair of characters and combine them into a HEX value in a string that you then interpret as a number. That could be done a number of ways.

For example:

char temp[3]; // Temporary space for the conversion string
// Copy two characters into the temporary string
temp[0] = payload[0];
temp[1] = payload[1];
// and terminate the string properly
temp[2] = 0;
// Convert the string using base 16
uint8_t val = strtol(temp, NULL, 16);

In your example string you have 16 characters, which would be 8 bytes of data. So you could put it in a loop:

char temp[3]; // Temporary space for the conversion string
uint8_t vals[8]; // Array to store your values

// Iterate over the values
for (int i = 0; i < 8; i++) {
    // Copy two characters into the temporary string
    temp[0] = payload[i * 2];
    temp[1] = payload[i * 2 + 1];
    // and terminate the string properly
    temp[2] = 0;
    // Convert the string using base 16
    vals[i] = strtol(temp, NULL, 16);
}

Of course there are "lighter" ways of doing it that don't involve an intermediate string or the strtol() function. For example I often use this little function:

uint8_t h2d(char hex) {
    if(hex > 0x39) hex -= 7; // adjust for hex letters upper or lower case
    return(hex & 0xf);
}

That takes a single character and converts it from hex to decimal. So you can combine that with bit shifting and OR to create a byte from two characters:

val = h2d(payload[0]) << 4 | h2d(payload[1]);

In your loop that would look like:

for (int i = 0; i < 8; i++) {
    // Convert the string using base 16
    vals[i] = h2d(payload[i * 2]) << 4 | h2d(payload[i * 2 + 1]);
}

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.