I have 2 microcontrollers that do communicate to each other through encrypted radiofrequencies.
The unencrypted data obeys to following pattern : recipient^send^rollingcode^message^checksum
example : BAL^HUB^123^dark=456^2549230589
which means HUB sent a message to BAL, with rolling code 123, saying dark=456
, where crc32 checksum equals 2549230589
I want BAL to explode that whole data packet.
void rxProcess() {
char tmp[RX_MSG_MAX_LENGTH] = "BAL^HUB^123^dark=456^2549230589";
char *strTokIndex = strtok(tmp, "^");
// to
char to[32] = {0};
strcpy(to, strTokIndex); // BAL
serialPrintln(to);
// from
strTokIndex = strtok(NULL, "^");
char from[32] = {0};
strcpy(from, strTokIndex); // HUB
serialPrintln(from);
// rc
strTokIndex = strtok(NULL, "^");
uint32_t rc = atol(strTokIndex); // 123
serialPrintln(rc);
// msg
strTokIndex = strtok(NULL, "^");
char msg[RX_MSG_MAX_LENGTH] = {0};
strcpy(msg, strTokIndex); // dark=456
serialPrintln(msg);
// checksum
strTokIndex = strtok(NULL, "^");
uint32_t checksum = atol(strTokIndex); // 2549230589
serialPrintln(checksum);
// verify checksum to ensure no packet corruption (todo : optimize)
//...
}
I'm printing stuff to my serial monitor here and there with serialPrintln()
in order to debug, and here is what it shows :
00:40:51.874 -> BAL^HUB^123^dark=456^2549230589
00:40:51.874 -> BAL
00:40:51.874 -> HUB
00:40:51.874 -> 123
00:40:51.874 -> dark=456
00:40:51.874 -> 2147483647
it prints the checksum as 2147483647
(2^31 - 1 ?) while it received 2549230589
I must be wrong in the way I explode and parse my char array.
TL;DR : how do I explode a char array like BAL^HUB^123^dark=456^2549230589
with the delimiter being ^
CodePudding user response:
The atoi() function converts the initial portion of the string pointed to by nptr to int. The behavior is the same as strtol(nptr, NULL, 10); except that atoi() does not detect errors. The atol() and atoll() functions behave the same as atoi(), except that they convert the initial portion of the string to their return type of long or long long.
The strtol() function returns the result of the conversion, unless the value would underflow or overflow. If an underflow occurs, strtol() returns LONG_MIN. If an overflow occurs, strtol() returns LONG_MAX. In both cases, errno is set to ERANGE. Precisely the same holds for strtoll() (with LLONG_MIN and LLONG_MAX instead of LONG_MIN and LONG_MAX).
2147483647
is larger than LONG_MAX
so LONG_MAX
is returned. There is no provision for reading an unsigned long. Using atoll
will use at least 64bits and then you truncate the result to unsigned long (32bit). You can use that as workaround for parsing unsigned long. But that's even slower than atol
. There is also strtoul
which might be more appropriate.
Personally I would change the source to send the checksum as uint32_t
, 4 raw bytes. Converting it to string and back is just waste of CPU power.
CodePudding user response:
quickfixed it with atoll()
instead of atol()
works with strtoul(strTokIndex, NULL, 0)
as well.