MediaTek-Labs / Arduino-Add-On-for-LinkIt-SDK

Arduino board support package for LinkIt 7697
https://docs.labs.mediatek.com/resource/linkit7697-arduino/en
34 stars 33 forks source link

BLE Characteristic not handling write request? #86

Closed weixiongmei closed 6 years ago

weixiongmei commented 6 years ago

Reproduce Steps

Error & Expected Results

After fixing the notification for Android, the Linkit 7697 BLE Characteristic has no response to the write request, the code from the SimplePeripheral sample below switchCharacteristic.isWritten() never returns true...

if (switchCharacteristic.isWritten()) { const char value = switchCharacteristic.getValue(); switch (value) { case 1: digitalWrite(LED_BUILTIN, HIGH); break; case 0: digitalWrite(LED_BUILTIN, LOW); break; default: Serial.println("Unknown value written"); break; } }

Environment

nRF Connect tool on Android

weixiongmei commented 6 years ago

solution found, the characteristic must set value at least once, otherwise it will not going to handles read & write request like 0.10.12 or older BSP....

pablosun commented 6 years ago

Hi, can you describe the Android API used to write the BLE characteristic? I've tested the SimplePeripheral with Android nRF Connect and iOS LightBlue app, both apps can 1st read/ 1st write the switchCharacteristic characteristic without problem.

Note that if you are using the "Buffer" characteristic, the default value of the buffer is indeed set to a 0-length buffer, so you'll have to initialize the buffer content before starting the BLE service.

weixiongmei commented 6 years ago
                bluetoothle.write((e) => {
                    document.body.children[0].innerHTML += "[" + e.name + "] Value:" + bluetoothle.bytesToString(bluetoothle.encodedStringToBytes(e.value)) + "\r\n";
                }, (e) => {
                        document.body.children[0].innerHTML += "Write " + e.message + "\r\n";
                    }, { address: e.address, service: "19B10010-E8F2-537E-4F6C-D104768A1214", characteristic: "19B10011-E8F2-537E-4F6C-D104768A1214", type: "Response", value: bluetoothle.bytesToEncodedString(bluetoothle.stringToBytes("Hello Weixiong")) });

this is the code i used, it's not native Android code, it's the code of the framework call "Apache Cordova". But it also happens in the nRF Connect tool, but seems like happens randomly with the SimplePeripheral sample, but set the value once 100% fixs the problem, it never happens on 0.10.12 or older.

pablosun commented 6 years ago

Thanks for the reply, can you describe the steps using nRF connect? I've tried to reproduce it 10 times but fails to reproduce it - maybe the issue is triggered by specific read/write steps.

Here's my reproduce steps, maybe there are some differences from your steps.

  1. Connect to "BLE LED" device
  2. Tap Unknown Service 19b10010-xxxxx
  3. Tap the "Read" (a downward arrow). The app shows Value:(0x)00-00-00-00
  4. Tap the "Write" (a upward arrow), choose UINT 32 from the dropdown list, and set 1 as the new value.
  5. Tap "Send"
  6. The on-board LED lights up as expected
weixiongmei commented 6 years ago

i did the same thing as you, maybe my environment problem, could you try write&read to LBLECharacteristicBuffer on 0.10.12 & 0.10.13 without setting the value? If it works with 0.10.12 but not 0.10.13, then there may be something changed...

weixiongmei commented 6 years ago

Hi pablosun, There is one more issue with the notification, when using the LBLECharacteristicBuffer, if i set a 247 bytes array as the value, i can read it manualy from the Android side with no problem, but when i set a byte array which above 20 bytes, then the notification is not going to received on the the Android side(sometimes it can receives 6 bytes or never receive anything), but try to read it from the Android side manualy still has no problem, seems like the notification is limited to a size? Thank you~~~

pablosun commented 6 years ago

Hi @weixiongmei,

I see. the problem here is the LBLECharacteristicBuffer. Indeed we've changed the default values of LBLECharacteristicBuffer.

From a design point of view we think the behavior in 0.10.13 is more common (objects should not be initialized with a large value). Therefore, please change the implementation of your Arduino sketch and call setValueBuffer when initializing the LBLE peripheral.

For the 2nd issue: Yes, it seems there are limitations in the Android BLE stack. In my experiment:

Therefore, it might be safer to break the data into smaller pieces before pushing to Android devices. (and you may want to use GATT Indication since it allows APP to send ACK).

weixiongmei commented 6 years ago

Hi, thanks!!!

Does the current BSP support to check the BLE tx buffer is full or not? it is helpful when transmitting a bunch of data...

pablosun commented 6 years ago

Hi, unfortunately currently there are no specific APIs to query the txBuffer directly.

The notifyAll and indicateAll return value needs to have a new implementation to report successful/fail state of each connection. (It currently returns # of connections instead of # of succeeded notify/indicate requests

This way, the user can choose to re-send the notification/indication when there are errors returned from the notifyAll or requestAll methods.