Thread saftey when processing incoming BLE data from OnCharacteristicChanged

I want to process BLE data received by OnCharacteristicChanged.

I assume it's necessary to keep runtime of the OnCharactericChanged callback function low?
Thus, processing of the received byte array should be carried out in a separate class/function.

How do i hand over the Byte Array to a separate class/function in a thread safe way?

  • Some depends on how quickly the sensor sends data.  Every few seconds shouldn't really an issue, but many times a second could be.

    On some devices, like the thingy52, how often the data is sent is configurable.  On others, like a HRM, it's reasonable as it is.

    How often is onCharacteriscChanged being called with your sensor?  What all are you doing when you get new data?

    Remember CIQ all runs in a single thread in an app. The delegate runs in the same thread as the view.

  • The sensor sends a stream of 90-120 bytes (length varies) once a second. I add this from the input Byte Array, received by OnCharacteristicChanged, to a second buffer Byte Array, which is declared as public var in the DeviceManager class. In the View class is parse this buffer, process the data from it, then slice the buffer.

    Analysis shows that slicing always sets the buffer to zero. I was suprised first, but your note that Monkey C runs single threaded explains this, thus the slice is always a clear, because while parsing the buffer there is no data added in parallel.

    So my design should be "thread safe" and a buffer overrun is not necessary to handle, because can never happen?

  • added: runtime of the data encoding loop is around 10ms, according to profiler.

  • added: onCharacteristicChanged is called 4-5 times per second, because the sensor chunks it's data in 20 bytes blocks, forced by Garmin's BLE MTU maxsize of 20.

  • added: why i am asking: the app is a simple datafield and working. But if the datafield is active, i get repeatedly drops of BLE and ANT+ connections. The drops 100% disappear after i switch off the BLE phone connection on the Garmin device (Edge1030 / Egde1030plus), while the datafield still remains active and perfectly working (no data loss, verified by checksums).

    My assumption is that the drops may be caused by BLE data overload. Thus, i'm looking for ways to make my datafield app more efficient.

  • If instead of sending data 4-5 times a second, does it work if you only send data every second?

  • i can't modify the chunking, because it's managed by the MTU of BLE stack.

  • Sounds to me you're overdriving the Garmin in general, and ANT and BLE both are impacted. Maybe your sensor simply isn't compatible in a DF.  Can you run the same code in your own device app?

  • What do you mean with own device app?

    If i run the datafield (same code) on a.Vivoactive4 watch, there are no disconnects. But the watch serves less sensors...