How do you parse a byte array with C++?

I'm using the PubSubClient library for linking my Wemos D1 Mini Pro to a MQTT server.

When the Wemos subscribes to a topic, it must specify a callback function which would normally contain instructions on what to do when data is received on the topic.

https://pubsubclient.knolleary.net/api.html#callback

void setup(){
  // other setup code, including code to setup the client
  client.setCallback(callback);
}

void callback(const char[] topic, byte* payload, unsigned int length){
 // do something with the topic and payload, like turn on relays or whatever
}

Everywhere I've read states that byte or byte arrays aren't really a thing with C++, so I'm confused why it's used in this library. I also don't know how I would proceed to parse the payload when it arrives.

I plan on sending the payload in the form of something like "02:0" to the "relay" topic.

02 would be relay #2 and 0 would be to turn it off.

Any help on how 02:0 can be parsed if it's being sent as a byte array?

byte is a type alias created by Arduino intended to make programming more beginner friendly. From Arduino/Arduino.h at 1.8.4 · arduino/Arduino · GitHub

typedef uint8_t byte;

The Arduino.h include is automatically added to every .ino file when you compile with the Arduino IDE.

As for how to parse a byte array, just like you would any other array. There's no magic to it.

A byte is nothing more than an another name for unsigned char; no idea where your comment about C++ and bytes came from. If needed you can cast.

No idea about MQTT, but what I would do is try something like

void callback(const char[] topic, byte* payload, unsigned int length)
{
  Serial.println("Received: ");
  for(int cnt=0;cnt<length; cnt++)
  {
    Serial.print(payload[cnt], HEX);
    Serial.print("  ");
  }
  Serial.println();
  Serial.println("===");
}

This will print the hex values for whatever you receive; see e.g. asciitable.com. For your example you will see at least

30  32  3A  30

It’s important to check if there is anything else after that like 0D and / or 0A (carriage return and / or linefeed).

Let’s say that your received (note that leading zeroes are omitted by serial.print)

30  32  3A  30  A  D

You can copy the bytes to a character array; you might be able to work on the payload variable directly, not sure.

// character array with space for 6 characters and terminating nul character
// make sure it's big enough to hold the longest message
char data[7];
// clear the data
memset(data, 0, sizeof(data));
// copy payload to data
memcpy(data, payload, length);

You now have a so-called C string (nul terminated character array) and can process that. Below a small function to strip carriage returns and/or linefeeds

/*
  trim CR and LF from end of text
  In: pointer to text to trim
  Returns: pointer to (trimmed) text

  Note:
  this modifies the original text
*/
char *trim(char *txt)
{
  while (txt[strlen(txt) - 1] == '\r' ||
         txt[strlen(txt) - 1] == '\n')
  {
    txt[strlen(txt) - 1] = '\0';
  }
  return txt;
}

You can call this after the memcpy and use e.g. strtok() or strchr() to split the received text on the colon.

If you can work directly on the payload and there is a carriage return or linefeed, you can replace them by a nul terminator and directly use strtok() or strchr() on the payload. You might have to use a cast (not sure).

As said, no experience with MQTT so not sure which way one should go.

The parse example in Serial Input Basics may help to illustrate the use of strtok() etc.

...R