BluetoothLE WriteBytes - need to send uint16_t; Appears to send uint8_t

Good evening,
I am working on an app that transmits data between an Arduino ESP32 and itself. In the Arduino, I have the following data structure:

struct bleCountsData {
    uint16_t front;
    uint16_t sides;
    uint16_t rear;
    uint16_t interior;
    uint16_t aux1;
    uint16_t aux2;
    uint8_t wifi;
    uint8_t animation;
};

In the app, I have some text boxes that hold the values of these counts (and a checkbox for the wifi). Took me forever to figure out how to remove the quotes from the list I created so they were treated as integers instead of strings, but over that hurdle now.

When I click the "save" button, I am running a procedure to get the values of all the text boxes, convert the strings to integers by suing math and adding zero to the text. I am then creating a list to mimic the data structure I am expecting in my WriteBytes transmission.

I am having the following issue - how can I ensure that the first 6 numbers in the list are 2 bytes each regardless of the value in the text field? For example, I tested where the values were 47, 89, 58, 60, 10, 69, 1, and 15 (in that order).

In my Arduino code, in the BLE callback class under the onWrite function, I wrote this to parse the data:

String value = pCharacteristic->getValue();
      Serial.println("Received Data:");
      
      // Convert the received value to a byte array
      uint8_t* byteArray = (uint8_t*) value.c_str();
      size_t length = value.length();

      // Print raw bytes
      Serial.print("Raw bytes: ");
      for (size_t i = 0; i < length; i++) {
        Serial.print(byteArray[i], DEC);
        Serial.print(" ");
      }
      Serial.println();

My output was: Raw bytes: 47 89 58 60 10 69 1 15
However, I wanted 47 0 89 0 58 0 60 0 10 0 69 0 1 15 (the last 2 are uint8_t)

I then updated the values in the app to be 270, 270, 270, 270, 270, 270 1, 15 just to see how it would handle that, and maybe it would be a 2-byte integer. No luck. My output was: Raw bytes: 14 14 14 14 14 14 1 15
I would have expected: 14 1 14 1 14 1 14 1 14 1 1 15

So that's the background. The long and short of my question is simply - is there a way to define the byte structure of the integers being sent via the BluetoothLE.WriteBytes? Or does anyone have any ideas how I could use the blocks to accomplish this? Appreciate any help :slight_smile:

Blocks below; The set ExteriorLabel.Text was only there to verify the list that was being created.

Since a byte can hold only 8 bite of data, if you insist on using the SendBytes block, you will need to split up those 16 bit integers into two bytes and send a longer list of bytes. Then you would have to reassemble pairs of bytes into 16 bit ints at the receiving end.

AI2 has math blocks to take quotient and remainder, dividing by 256, for the first part.

Or you could look for BLE blocks that send integers instead of bytes for the first few 16 bit integers.

Okay thanks. I went ahead and calculated the higher byte and sent that second. It's interesting that the plugin automatically sends the lower byte without me calculating it. The final working block looks like this:

Appreciate the guidance here!

I am surprised that worked.

The odd items needed a modulo or remainder of 256 to fit into a byte, but you rely on an accidental feature of the Send Bytes block to clip them.

That's a lurking bug in my book

:frowning: Good point haha! This is much better

1 Like

Alternatively, you could use the WriteShorts block which writes 16-bit integers. You'll have to combine the last two uint8_ts into a single uint16_t if you want to keep the structured packed in that way though.

Shorts.

Forgot about those.

While we're gilding the lily,

You don't need those + 0 operations. AI2 does text to number type conversions automatically. It's called Duck Typing.

Also, I see a block peeping out from under your blocks.
I recommend a right click Cleanup Blocks to expose lurkers.

When i create the list without doing math, it encapsulates the values in the list with double quotes. Then, when sending the bytes, those values are interpreted as strings and therefore ["50"] (for example) would be translated to

byteArray[0] = 53;  // ASCII for '5'
byteArray[1] = 48;  // ASCII for '0'
byteArray[2] = 0;   // Null terminator

instead of [50] which would be interpreted as

byteArray[0] = 50;  // Decimal value 50

Good catch on the block. I had copy/pasted and done something and I couldn't tell where that little bugger got off to!

1 Like

Thanks for the explanation about the text type leakage.

I'll have to watch out for that in the future.