1
\$\begingroup\$

I'm sending data from an ionic app (typescript) to an ESP32chip. Data from the app uses protocol buffer format. Here's the code:

this.provisionMgrAction.setAction('stop');
let bytesOfStuff = await this.provisionMgrAction.serializeBinary();
BleClient.write(this.deviceID, serviceID, characteristicID, bytesOfStuff);

On the ESP chip side (code in C), data is received as "stop". The log (ESP_LOGI line below) prints value of inbuf as "stop" (without quotation marks).

esp_err_t custom_prov_data_handler(uint32_t session_id, const uint8_t *inbuf, ssize_t inlen,
                                          uint8_t **outbuf, ssize_t *outlen, void *priv_data)
{
    if (inbuf) {
        ESP_LOGI(TAG, "Received data: %.*s", inlen, (char *)inbuf);
        if (strcmp(inbuf, "stop") == 0) {
            ESP_LOGI(TAG, "print something");
        }
    }
}

But strcmp doesn't seem to work. I'm presuming it has something to do with the fact that when "stop" is sent over BLE from the client side app to the ESP32 chip, it comes without a null character, though I'm not sure how to confirm that. In any event, how do I make sure that strcmp equates the value of inbuf to "stop"? Do I need to add a null character to inbuf? If yes, how do I accomplish that? Or do I need to compare inbuf to "stop\0"? The length of inbuf (inlen) is printed out to be 2 more than the number of characters in the message that is transmitted to the chip over BLE (in this case, 6).

\$\endgroup\$
5
  • \$\begingroup\$ Yes, if you get 6 bytes in and there is no null character received after the letters "stop", it means that the incoming string is longer than the four character null terminated string of "stop", so it means that the strings will never be equal and won't match. But this really has nothing to do with electronics, microcontrollers or ESP32, that's just a generic C programming problem and any C resource should explain which comparison methods are available in C and how they work. \$\endgroup\$
    – Justme
    Commented Jan 14, 2022 at 7:59
  • \$\begingroup\$ What characters do you receive actually? Don't just print them as string ("%s") but as hex to reveal null and/or control characters. \$\endgroup\$ Commented Jan 14, 2022 at 8:02
  • \$\begingroup\$ @the busybee How exactly do you print const uint8_t * (const unsigned char *) in hex? Tried %x formatter, but that doesn't match the argument type const uint8_t *. \$\endgroup\$
    – coder101
    Commented Jan 14, 2022 at 8:10
  • \$\begingroup\$ To print this array, the easy way is to do what you did (your comment in the answer below) -- just hand-code a solution that works only for a six-byte receive string. Otherwise, there is a good, general solution but it's a bit of a hassle to implement: stackoverflow.com/questions/6357031/… \$\endgroup\$
    – Mr. Snrub
    Commented Jan 14, 2022 at 8:27
  • \$\begingroup\$ If you use protocol buffers to encode, use them to decode… \$\endgroup\$
    – jcaron
    Commented Jan 14, 2022 at 9:37

2 Answers 2

0
\$\begingroup\$

Yes the problem is the '\0' character that is missing.

You could use strncmp and specify the length (here it would be inlen -2 I guess, the 2 more might be checksum or something like that)

Like

if (strncmp(inbuf, "stop", inlen - 2) == 0)

That should work.

Also, be cautious if you sometime answer from ESP32. Depending on the app side you would also need a termination character (for example on Android Studio Java I needed to add '\n' because I called ReadLine function).

So based on the values extracted in hexa from the buffer you can get your info using

if (strncmp((char *)&inbuf[2], "stop", inlen - 2) == 0)
\$\endgroup\$
10
  • \$\begingroup\$ When using strncmp, your solution gives the following error: note: expected 'const char *' but argument is of type 'const uint8_t *' {aka 'const unsigned char *'} But changing it to if (strncmp((char *)inbuf, "stop", inlen -2 ) == 0) seems to resolve that error. That said, the comparison still doesn't pan out. What am I missing? \$\endgroup\$
    – coder101
    Commented Jan 14, 2022 at 7:59
  • \$\begingroup\$ Ok you could try to print char by char instead of %.*s the hexa value Something like inbuf[0], inbuf[1] ... inbuf[5] inbuf[6] so you know exactly what is in your buffer \$\endgroup\$
    – Mat
    Commented Jan 14, 2022 at 8:10
  • \$\begingroup\$ So my hex printout (ESP_LOGI(TAG, "Received data: %x, %x, %x, %x, %x, %x, %x", inbuf[0], inbuf[1], inbuf[2], inbuf[3], inbuf[4], inbuf[5], inbuf[6]); gives the following: a, 4, 73, 74, 6f, 70, 0. Not sure what the a, 4 stand for (could this be because I'm using protocol buffer to send data over BLE?), but characters 73, 74, 6f and 70 translate to "stop". \$\endgroup\$
    – coder101
    Commented Jan 14, 2022 at 8:23
  • \$\begingroup\$ Ok that's nice, they may be BLE info and some CRC you may want to look at the BLE communication if really want to understand it. Well the good news is that you now can compare but not starting from the pointer you should start 2 characters after \$\endgroup\$
    – Mat
    Commented Jan 14, 2022 at 8:27
  • \$\begingroup\$ Something like if (strncmp(&inbuf[2], "stop", inlen - 2) == 0) should work now \$\endgroup\$
    – Mat
    Commented Jan 14, 2022 at 8:28
0
\$\begingroup\$
  1. Count the amount of received characters in the payload. If they aren't 4, you can stop there because the input is obviously wrong.
  2. If there is no null termination, you don't have a C string but just a raw data array. If you don't need this to become a C string, then the fastest and easiest is memcmp(inbuf, "stop", 4);. This doesn't rely on null termination.
  3. In case you need to re-use the data later as a C string, then just do inbuf[4] = '\0' to append a null terminator manually to the 5th character. Now you could use strcmp but there's no real point of using it over memcmp when you already know the data size. memcmp is always faster than strcmp.

I can't think of any scenario where it would make sense for you to use strncmp.

\$\endgroup\$
3
  • \$\begingroup\$ Appreciate the feedback re memcmp. But there's nothing wrong with the input. The app uses protocol buffer to pack the data, which in the process of serializing the input string to binary, inserts '\n' along with the length of the input string at the beginning of the data being transmitted. Hence the two additional pieces of data at the beginning of inbuf in my code above. \$\endgroup\$
    – coder101
    Commented Jan 14, 2022 at 12:07
  • \$\begingroup\$ @coder101 When coding any form of data communication, you always need lots of error checks. You can never assume "this protocol will never be wrong". \$\endgroup\$
    – Lundin
    Commented Jan 14, 2022 at 12:54
  • \$\begingroup\$ I get it now what you were trying to say in your answer - more about error checks than the input actually being incorrect. Thanks. \$\endgroup\$
    – coder101
    Commented Jan 14, 2022 at 13:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.