Home > Back-end >  explode a char array
explode a char array

Time:07-24

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.

  • Related