OpenBluetoothToolbox / SimpleBLE

SimpleBLE - the all-in-one Bluetooth library for MacOS, iOS, Windows, Linux and Android.
https://www.simpleble.org
Other
655 stars 110 forks source link

Can't read data from BLE on windows 10 , need Devices::Bluetooth::BluetoothCacheMode::Cached #226

Closed jefferyfang closed 1 year ago

jefferyfang commented 1 year ago

gatt_characteristic.ReadValueAsync(Devices::Bluetooth::BluetoothCacheMode::Uncached), Can't read right data,return buffer is what you have wroten.

use Devices::Bluetooth::BluetoothCacheMode::Cached, it works fine.

diff --git a/simpleble/src/backends/windows/PeripheralBase.cpp b/simpleble/src/backends/windows/PeripheralBase.cpp index 0edb984..d7574fa 100644 --- a/simpleble/src/backends/windows/PeripheralBase.cpp +++ b/simpleble/src/backends/windows/PeripheralBase.cpp @@ -172,7 +172,7 @@ ByteArray PeripheralBase::read(BluetoothUUID const& service, BluetoothUUID const }

 // Read the value.
kdewald commented 1 year ago

Hey @jefferyfang, thanks for reaching out.

Using the Cached version of the call doesn't actually communicate with the device, it uses whatever internal value has been stored. Can you please describe a bit more what the actual problem seems to be?

jefferyfang commented 1 year ago

Hey @jefferyfang, thanks for reaching out.

Using the Cached version of the call doesn't actually communicate with the device, it uses whatever internal value has been stored. Can you please describe a bit more what the actual problem seems to be?

Hi, kdewald

 thanks for your help.

my C++ demo :

adapter.set_callback_on_scan_found(callback_on_scan_found);

void callback_on_scan_found(SimpleBLE::Peripheral device) { std::string command_string= "{\"cmd\" : 0}"; // json command std::string response; SimpleBLE::BluetoothUUID service; SimpleBLE::BluetoothUUID characteristic;
//find the right service, and characteristic; find_device_service(device, service, characteristic);

device.write_request(service, characteristic, command_string); response = device.read(service, characteristic);

//the device reply actually is : { "cmd": 1, "code":200} //but the response above is : { "cmd" : 0}, what you have wroten to the device,the response is wrong data

//I changed the PeripheralBase::read(BluetoothUUID const& service, BluetoothUUID const& characteristic) //use Devices::Bluetooth::BluetoothCacheMode::Cached // sometimes the response is right { "cmd": 1, "code":200}, but sometimes the response is still wrong { "cmd" : 0}. }

I truly appreciate your timely help.

jefferyfang commented 1 year ago

Hey @jefferyfang, thanks for reaching out.

Using the Cached version of the call doesn't actually communicate with the device, it uses whatever internal value has been stored. Can you please describe a bit more what the actual problem seems to be?

Additional information:

response = device.read(service, characteristic);

1, Using Devices::Bluetooth::BluetoothCacheMode::Uncached, the read function return the wrong data immediately: return what you have wroten to the device: { "cmd" : 0}

2, Using Devices::Bluetooth::BluetoothCacheMode::Cached, if the BLE device hasn't send any data, the read function return the wrong data immediately: return what you have wroten to the device: { "cmd" : 0}

if the BLE device has send reply data, it works fine.

kdewald commented 1 year ago

Ok, I think I better understand what's going on.

I think that you're dealing with a race condition where the characteristic has not yet been updated by the time you're trying to read it. The correct way to handle these situations is by using indications or notifications, as those will guarantee that the change on the peripheral side propagates back to the host.

One way you can probably test this assumption is by adding a delay between the write and the subsequent read (of at least a few connection intervals), but the best path forward would be to use an update mechanism such as notifications or indications.