Need help parsing String down byte or bytes?

Im having a major issue of breaking up a string of data "03D88039E8987A21489A376EF603000000C0060000CF060D3B00000000009C1B"
I need it broken up
03 (D8)8039E8987A 21 48 9A37 6EF603 000000 C006 0000 CF06 0D3B00 000000 00 9C1B
all I’m able to do is break it up 1 byte at a time and read that.
Last two: 1B

Voltage is: 6

Current is: 06

This is Sequence: (D8) What I need here is D88039E8987A
Need more examples on how to parsing a String,
Any ides or help would be greatly appreciated. Thank You

Since you don’t have any embedded structure in that source string, you need to count the bytes and inject seperators where needed and extract bytes wanted based on the current position.

But only you know the origin and hence structure of your source data stream, so not a lot for us to help you with.

2 Likes

To expand a little on what @ScruffR said, it's not possible to give you specific advise without knowing what structure (if any) is inherent in your string. For instance, the string you show is 64 characters long. Is it always 64 characters long? You also said you wanted it broken into these parts:

03 (D8)8039E8987A 21 48 9A37 6EF603 000000 C006 0000 CF06 0D3B00 000000 00 9C1B

That's 14 substrings of length 2, 12, 2, 2, 4, 6, 6, 4, 4, 4, 6, 6, 2, and 4 respectively. Are each of those substrings always exactly that length? If so, parsing it would be quite easy, if not, it could be quite difficult depending on what constant features are present. Do you have any control over the structure of this string, or is it fixed?

Yes the string is a fixed 64 characters long, The 03 D88039E8987A 21 82 9A37 1CBD07 000000 C106 0000 CB06 B65800 000000 00 9396
is broken up as the following, there in lest to most significant digits
03 - Message type
D88039E8987A - Device ID
21 - Device type
82 - Sequence number
9A37 - Firmware checksum
1CBD07 R>L watt hours, Actually 07BD1C = 507,164 decimal
000000 L>R watt hours
C106 - Voltage for this it 06C1 = 1729
0000 - Temp
CB06 - Current
B65800 - Amp hours R>L
000000 - Amp hours L>R
00 - Filler
9396 - CRC

Then I’ll be taking the data and int values and doing calculations on my end. Thanks for all the help.

So, the best thing may be to lock onto the 03 grab the next 62 chars and verify the CRC. If the crc verifies, then we can parse the string.

I just ran into some code from the Webduino project that can help so that if the 03/CRC is not correct, you don’t have to throw the 62 chars away, but scan them for another 03.

Do you have a way to check the CRC?

There are multiple C functions for parsing strings. Here is one example of how you could do it using snprintf.

char input[] = "03D88039E8987A21489A376EF603000000C0060000CF060D3B00000000009C1B";
char parsedArray[14][13];
const int len[] = {2,12,2,2,4,6,6,4,4,4,6,6,2,4}; // the length of each of the pieces
int offset; // used to create offsets into the input string to the beginning of each piece

enum pieces {messageType,deviceID,deviceType,sequenceNumber,checksum,wattHoursR_L,wattHoursL_R,voltage,temp,current,ampHoursR_L,ampHoursL_R,filler,crc};

void setup() {
    Serial.begin();
    delay(3000);
    
    for (int i=0; i<14; i++) {
        snprintf(parsedArray[i], len[i] + 1, "%s", input + offset); // len[i] + 1, the plus 1 is to allow space for the terminating zero
        offset += len[i];
    }
    
    // Access the individual strings using the names in the enum
    Serial.printlnf("voltage is: %s", parsedArray[voltage]);
    Serial.printlnf("current is: %s", parsedArray[current]);
}

If your input is a String object, rather than a char array, you could use the toCharArray() function to convert it.

1 Like

Thank You, That helps a great deal.