Difficulties parsing with "list from csv row"

(apologies if this is in wrong forum section, happy to be redirected if need be, as long as I don;t have to enter it all again!)

I have an Arduino (a teensy 4.1) communicating over bluetooth classic with my AI2 app. The teensy is fitted with up to five DS18B20 thermometers and runs a sketch that sends a compound CSV text string containing the temperatures over bluetooth, every 2 seconds.

Here are the sketch code pieces for transmitting the string:

#include <Streaming.h>
#define bt Serial7                    // Bluetooth on TX7/RX7 

bt << "#" << _FLOAT(DT0_degrees,2) << ","
		  << _FLOAT(DT1_degrees,2) << ","    
		  << _FLOAT(DT2_degrees,2) << ","    
		  << _FLOAT(DT3_degrees,2) << ","    
		  << _FLOAT(DT4_degrees,2) << '\n';   

My AI2 mobile App is reading the text string but I'm having trouble parsing the string using "list from csv row".

Using the "Serial Bluetooth Terminal" on my mobile shows the CSV strings are being sent correctly

A reading of -99.00 means that thermometer is not connected yet. Each string is preceded by a hash character (#).

The longest string (no thermometers connected) would be #,-99.00,-99.00,-99.00,-99.00,-99.00
for a total length of 1 + (5 x 7) + 1 = 37 characters including the \n line feed.

The shortest string (all thermometers active) would be
#,00.00,00.00,00.00,00.00,00.00
for a length of 1 + (5 x 6) + 1 = 32 characters.

In testing I noticed that reception of the whole string by bluetoothClient is inconsistent. Sometimes it receives a few bytes, sometimes 1 byte, but most times it receives the whole string correctly. To handle this I added the extra test to redirect any dud strings into dummyString (also ensures the Serial buffer is emptied)

If BytesAvailableToReceive > 30
load into textString (& lbl_String)
else
load into dummyString

But when I run the App using AI Companion I get this runtime error:

If build and load the App onto my mobile I get this similar error:

Here are my parsing blocks:

  1. How can I avoid these bugs ?

In addition my attempts to parse and display the individual temperatures on the App screen is not working as shown in this screenshot:

Note the display does show lbl_byteCount, lbl_String values (yellow arrangement) showing current textString and byte count to help in debugging.

  1. How can I get the parsing to work so values appear on screen?

In case they are important, here are the blocks for whole App:

A couple of other minor Q's if I may:

  1. Is it possible to strip the \n character of end of textString before displaying in lbl_String (so it doesn't wap on the App screen)?

  2. why does my tick counter trigger every 10ms even though the setting in TimerInterval for Clock1 is set at 500ms?

Many TIA

Be sure to use println() at the end of each message to send from the sending device, to signal end of message.

Only use print() in the middle of a message.

Be sure not to println() in the middle of a message, or you will break it into two short messages and mess up the item count after you split the message in AI2.

Do not rely on timing for this, which is unreliable.

In the AI2 Designer, set the Delimiter attribute of the BlueTooth Client component to 10 to recognize the End of Line character.
BlueToothClient1_Properties
Also, return data is not immediately available after sending a request,
you have to start a Clock Timer repeating and watch for its arrival in the Clock Timer event. The repeat rate of the Clock Timer should be faster than the transmission rate in the sending device, to not flood the AI2 buffers.

In your Clock Timer, you should check

  Is the BlueTooth Client still Connected?
  Is Bytes Available > 0?
     IF Bytes Available > 0 THEN
       set message var  to BT.ReceiveText(-1) 

This takes advantage of a special case in the ReceiveText block:

ReceiveText(numberOfBytes)
Receive text from the connected Bluetooth device. If numberOfBytes is less than 0, read until a delimiter byte value is received.

If you are sending multiple data values per message separated by | or comma, have your message split into a local or global variable for inspection before trying to select list items from it. Test if (length of list(split list result) >= expected list length) before doing any select list item operations, to avoid taking a long walk on a short pier. This bulletproofing is necessary in case your sending device sneaks in some commentary messages with the data values.

Some people send temperature and humidity in separate messages with distinctive prefixes like "t:" (for temperature) and "h:" (for humidity).
(That's YAML format.)

The AI2 Charts component can recognize these and graph them. See Bluetooth Client Polling Rate - #12 by ABG

To receive YAML format messages, test if the incoming message contains ':' . If true, split it at ':' into a list variable, and find the prefix in item 1 and the value in item 2.

...

thanks ABG, I must remember to set that DelimiterByte to 10 !! That plus use of -1 length fixed my transmission reliability. Re your other points: my code already addressed them all in my original program.

My only remaining issue is the parsing using "list from csv row". whcih causes the runtime errors shown above, and the temperature readings never appear in the labels lbl_DT0, lbl_DT1 ... etc

The CSV string is only loaded into the global list_Celsius when the string length is > 30 and < 38. So I can't see what might be causing the runtime error "Attempt to get item number 1 from a list of length 0"?

It would be easier to correct your blocks if you posted an .aia export.

attached as requested ...

(just noticed I left some blocks disabled, I should have enabled them before attaching.)

Pathrider2_F.aia (75.5 KB)