Parsing Multiple Data Segments on Bluetooth Using readStringUntil

I've an App Inventor app that sends small packets of data to my ESP32 in the following format:

d12|1

Where "d12" is the data identifier, "|" is a delimiter and "1", in this case is the data. In all cases, the data being received is an integer.

This is my code:

/Bluetooth read data from phone
  if (espBT.available()) //check if data is available in the buffer
    {
      //set incoming variable to data sent from
      incoming = espBT.readStringUntil('|'); //get the button descriptor
      String button = String(incoming);
      incoming = espBT.readStringUntil('\n'); //get the associated button payload
      String butvalue = String(incoming);

      //debug
      Serial.println("button: " + button + " value: " + butvalue);

      //Parse received data
      if (button.equals(String("d10"))) { d10 = butvalue.toInt(); } //App button volume
      if (button.equals(String("d11"))) { d11 = butvalue.toInt(); } //App rotate anticlockise 90 degrees (fast)
      if (button.equals(String("d12"))) { d12 = butvalue.toInt(); } //App Drive (1)/Stop (0) 
      if (button.equals(String("d13"))) { d13 = butvalue.toInt(); } //App Calibrate motor
      if (button.equals(String("d14"))) { d14 = butvalue.toInt(); } //ESP Current Home position
      if (button.equals(String("d15"))) { d15 = butvalue.toInt(); } //ESP Cumulative motor position
      if (button.equals(String("d16"))) { d16 = butvalue.toInt(); } //App rotate clockwise 90 degrees (fast)
      if (button.equals(String("d17"))) { d17 = butvalue.toInt(); } //ESP Millis Count
      if (button.equals(String("d18"))) { d18 = butvalue.toInt(); } //ESP Temporal start Position
      if (button.equals(String("d19"))) { d19 = butvalue.toInt(); } //ESP Temporal End Poistion
      if (button.equals(String("d20"))) { d20 = butvalue.toInt(); } //App Go Home button value
      if (button.equals(String("d21"))) { d21 = butvalue.toInt(); } //App Go Home number of steps required
      if (button.equals(String("d22"))) { d22 = butvalue.toInt(); } //App Go home estimated time
      if (button.equals(String("d23"))) { d23 = butvalue.toInt(); }
      if (button.equals(String("d24"))) { d24 = butvalue.toInt(); }
      if (button.equals(String("d25"))) { d25 = butvalue.toInt(); } //App Motor Start Time
      if (button.equals(String("d26"))) { d26 = butvalue.toInt(); }
      if (button.equals(String("d27"))) { d27 = butvalue.toInt(); }
      if (button.equals(String("d28"))) { d28 = butvalue.toInt(); }
      if (button.equals(String("d29"))) { d29 = butvalue.toInt(); }
               
    }

As you can see, I expect data with identifiers from d10-d29 (not all are currently utilised).

Currently, I send one "packet" per identifier at time and this is quite sparse, time-wise.

However, If I send two discrete messages in quick succession, something goes wrong and the second message is not received. Refer to a question i've raised in the MIT App inventor forums:

Unfortunately, no help there.

I was wondering if I should just send a single packet with multiple data identifiers from the app, in which case i'd need to improve the Arduino code somewhat. I'm really looking for some guidance on how to establishing a more robust parsing protocol that could receive multiple data messages in the one "packet".

My guess is to simply stack them, eg: d10|3|d25|234554643|d18|240\n

I'm just not sure how to resolve the parsing of the final data entry where I need to identify if the next delimiter is a "|" or an \n.

Is the key to this using the .peek() function in some way?

So as it turns out, the following simple changes work:

Change my messages from the app to be in the following format:
d12|0|
d10|1|d25|1234|

Basically use a '|' as a backstop to each entry.

Change my incoming parse code to:

//set incoming variable to data sent from
      incoming = espBT.readStringUntil('|'); //get the button descriptor
      String button = String(incoming);
      incoming = espBT.readStringUntil('|'); //get the associated button payload
      String butvalue = String(incoming);

Picks up each complete message one at a time and then follows with the second on the second loop around and so on...

The terminating character '\n' seems to be removed either once i've read the last '|' in the bluetooth serial buffer or as i read the next sent command and the system does away with it at the front end of the 'd**' command.

Good that you have a solution. For future using (serial) communication, you can get ideas from Robin's Serial Input Basics - updated.

Assuming d10 .. d29 are variables, you might benefit from the use of arrays.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.