rohitsangwan01 / win_ble

WinBle Plugin to use Bluetooth Low Energy in Flutter Windows Desktop
MIT License
35 stars 14 forks source link

discoverCharacteristics empty results #7

Open gtedone opened 2 years ago

gtedone commented 2 years ago

Often a discoverCharacteristics results in a empty array, even though the related service contains some.

My guess is a non-reentrant implementation, b/c repeating the call, the expected result will come.

This is more evident in my application, who triggers a GATT content change (here there can be due to additional issues lied to GATT caching, but I'm not so sure).

It can be possible investigate a such problem, without the need of a retry pattern as workaround?

I can explain further if necessary, with code examples/app logs, of course.

rohitsangwan01 commented 2 years ago

@gtedone can you pleas share logs and , Expecting result vs what you are getting

gtedone commented 2 years ago

I'm working on an client application which provides an OTA firmware update for a peripheral.

The peripheral normally runs in application mode, with a certain GATT server content.

flutter: {_type: response, _id: 2, result: [{00001801-0000-1000-8000-00805f9b34fb}, {00001800-0000-1000-8000-00805f9b34fb}, {0000180a-0000-1000-8000-00805f9b34fb}, {544e326b-5b72-c6b0-1c46-41c1bc448118}, {1d14d6ee-fd63-4fa1-bfa4-8f47b42119f0}]}

When the client wants to start an update, by writing to "OTA Control" [f7bf3564-fb6d-4e53-88a4-5e37e0326063] characteristic, the status of the peripheral switches to DFU mode (Device Firmware Upgrade), which causes the device to disconnect and the GATT content to change.

The first step is ok, since OTA Control is found and can be written:

flutter: {_type: response, _id: 3, result: [{uuid: {f7bf3564-fb6d-4e53-88a4-5e37e0326063}, properties: {broadcast: false, read: false, writeWithoutResponse: false, write: true, notify: false, indicate: false, authenticatedSignedWrites: false, reliableWrite: false, writableAuxiliaries: false}}]}

But once the DFU mode is triggered, the device re-connected and its services are discovered again, this is the result:

flutter: 2022-07-11T14:24:34.249571 V LogsCubit.printConsoleLog: Initializing OTA Service flutter: {_type: response, _id: 7, result: [{00001801-0000-1000-8000-00805f9b34fb}, {00001800-0000-1000-8000-00805f9b34fb}, {0000180a-0000-1000-8000-00805f9b34fb}, {544e326b-5b72-c6b0-1c46-41c1bc448118}, {1d14d6ee-fd63-4fa1-bfa4-8f47b42119f0}]} flutter: 2022-07-11T14:24:34.339573 V LogsCubit.printConsoleLog: Discovered OTA Service [1d14d6ee-fd63-4fa1-bfa4-8f47b42119f0] flutter: 2022-07-11T14:24:34.339573 D LogsCubit.printConsoleLog: Discovering OTA Characteristics... flutter: {_type: response, _id: 8, result: []} flutter: 2022-07-11T14:24:34.440570 E LogsCubit.printConsoleLog: Update fails: Exception: initOtaService fails: Exception: OTA Characteristics: empty set

While at the same time, a third-party application, i.e. nRF Connect, will got the result as in the attached picture

photo_2022-07-11_14-39-49 .

gtedone commented 2 years ago

An additional tought: my guess about possible issues with GATT caching comes from one remark from the peripheral's manufacturer (Silicon labs):

"Note that, when the target device reboots into DFU mode, the host program must perform full service and characteristic discovery again. It is not possible to store the ota_control and ota_data characteristic handles in memory and use those cached values during the second connection. This is because the target device has two GATT databases that are independent of each other: one that is used by the application in normal mode and the second that is automatically created by the stack in OTA DFU mode. While both of these GATT databases might include the Silicon labs OTA service, the characteristic handles are likely to have different values. Therefore any kind of GATT caching cannot be used."

Despite my client app behaves as recommended above, that is a rediscovery was performed again after the DFU switch, the discoverServices method works, but discoverCharacteristics fails resulting in an empty characteristics set.

And, unfortunately, even if I repeat the services and characteristics discovering some times, nothing change.

rohitsangwan01 commented 2 years ago

@gtedone can you try one thing Boot device to Dfu from NrfConnect And then Connect to the Example App of WinBle, when Device in Dfu mode , and then try if services are discovering

gtedone commented 2 years ago

Yes, after going in DFU mode using nRF Connect, the discovering works (also in my application) but, at the end of the file upload (made by writing chunks of the file to OTA Data characteristic), I have a similar issue trying to finalize the process (writing to OTA Control characteristic again): an "Unreachable" error is thrown. The strange here is that sometimes reapeating the entire process it works, but not always. A note: a similar flutter app is working on both Android and iOS platforms, I was hoping for a similar result on Windows too, using this package... :-/

rohitsangwan01 commented 2 years ago

@gtedone are you using any plugin for pushing updates to Dfu?

gtedone commented 2 years ago

No @rohitsangwan01, any other plugin: the DFU application + BLE stack is provided by Silicon Labs.

The workflow is:

  1. Advertisement > Local name: MyDevice
  2. Connect to MyDevice
  3. Discovering:
    OTA Service >
    OTA Control
  4. Write "0" to OTA Control to switch to DFU mode > [disconnection]
  5. Advertisement > Local name: changed to OTA
  6. Connect to OTA
  7. Discovering (content changed):
    OTA Service >
    OTA Control
    OTA Data
    OTA Version
    ... other characteristics ...
  8. MTU negotiation (with WinBle is fixed since a requestMtu() is not available)
  9. Write "0" to OTA Control again (to start the update)
  10. Write firmware file to OTA Data (chunked by size of max MTU)
  11. Write "3" to OTA Control to finalize the process > [disconnection]

The above is working in another Android/iOS flutter app (using flutter_ble_lib and flutter_reactive_ble) and, hopefully, I wish to get it working with WinBle too... :-)