[WebBluetooth]: Writing GATT characteristic results in an internal error
Reported by
devel...@gmail.com,
Aug 7 2016
|
|||
Issue description
Chrome Version : 54.0.2822.0
OS Version: OS X 10.11.6
UserAgentString: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2822.0 Safari/537.36
When writing a characteristic value of a GATT service an internal error occurs.
The data has been written to the device (the data ended up being transmitted to the device) but the Promise chain breaks because of the mentioned internal error (No Characteristics with specified UUID found in Service)
Code that writes the characteristic (TS):
private transmitDataPromise(characteristicUUID : string, checkDirtyAction, getBytesAction, successAction) {
return this.m_service.getCharacteristic(characteristicUUID)
.then((characteristic) => {
if(checkDirtyAction()) {
var data: Uint8Array = getBytesAction();
return characteristic.writeValue(data);
}
return new Promise((resolve, reject) => { reject(); });
})
.then(() => {
successAction();
})
.catch((ex) => { console.error(ex, "Error writing characteristic value!"); });
}
[...SNIP...]
Promise.all([
this.transmitDataPromise(
Protocol.STEER_CHARACTERISTIC_UUID,
() => {
return l_steering != this.m_lastSentSteering;
},
() => {
var angle = (l_steering * 90) / 100;
var steeringData = new Uint8Array(1);
steeringData[0] = Math.floor(angle);
console.log("Sending steering (" + l_steering + "%)");
return steeringData;
},
() => {
this.m_lastSentSteering = l_steering;
console.log("Sent steering (" + l_steering + "%)");
}),
[...SNIP...]
See the attached log files (Chrome log and Mac BT log)
If you need any additional information about the environment please let me know.
,
Aug 7 2016
Thanks for filing this bug Michael. Jerome can you have a look please?
,
Aug 7 2016
For info, here are the interesting logs I get from PacketLogger.pklg: ... Info: **** [IOBluetoothHostControllerUSBTransport][BulkOutWriteCompleteAction] -- removed Bulk Out Write Timer 0xffffff8025205cc0 **** Rcvd Error Response - Attribute Not Found, Handle: 0x0017 Sent LE Create Connection Cancel
,
Aug 9 2016
Hello develmil, Do you reproduce this problem all the time? What device do you use? I wish to reproduce this bug. Thanks.
,
Aug 9 2016
Also, can you give scan you device with the Apple application "Bluetooth Explorer" and tell me what are the properties of your characteristic? Thanks,
,
Aug 9 2016
I think they are using a Parrot Mini Drone. It seems to me that it's a problem with the device. The "No Characteristic Found" error is showing up because the device disconnected so we remove all it's services, characteristics, and descriptors. That said, we could be using the API in a way that causes the disconnection. I think Francois has a parrot drone.
,
Aug 9 2016
I believe Michael is using a custom piece of hardware: https://www.hackster.io/22864/bluetooth-remote-controllable-lego-cars-9b59a9 The characteristic having an issue is https://github.com/devmil/remotelego/blob/master/embedded/RedBearDuo/LegoControl/BLECommunication.hpp#L48 for info
,
Aug 9 2016
Yes that is correct! It is a custom hardware. There might be an issue with the characteristic implementation but the Android App and the WebApp on Chrome for Android work. I will do the characteristic scan when I'm back home and post them here.
,
Aug 9 2016
Hmm then yeah then problem is probably with how we use the CoreBluetooth API.
,
Aug 9 2016
I did connect to the device using the Bluetooth Explorer. I didn't find a way to export this information so I made a screenshot.
,
Aug 9 2016
And as a side note if this isn't clear: it doesn't matter what characteristic I try to write to. They all behave the same. The Steering characteristic I took as an example is only representative
,
Aug 9 2016
Thanks for the screen shot! That's perfect! I suspected you had a characteristic with Write and WriteWithoutResponse. I will try to get a characteristic like that on a device. It might work better if you change your characteristic to be Write or WriteWithResponse (but even if it works for you better that way, it is definitely a valid bug). Thanks
,
Aug 9 2016
Can you let us know if changing to either Write or WriteWithoutResponse works better for you? Not both at the same time.
,
Aug 9 2016
Ok, I did some tests: When the characteristics have read/write the same error occurs and breaks the Promise chain. When the characteristics have read/write without response then the error also occurs but the Promise chain gets completed. The result is a slight delay but a much better behavior then with variant 1 (read/write). I have attached the screenshots of the configurations I tested and the chrome log of the "write without response" try.
,
Aug 10 2016
Hello develmil, I see that you use RedBear DUO and BLE Nano for you project. With which board do you have the problem? Where is the code for this board? Did you try to use something else than chrome to communicate with your board? Do you have the same problem when your attribute is in "write"? I don't know very well RedBear. But I have a BLE Mini. Could I use your code on that board? Thanks,
,
Aug 10 2016
Hi, The DUO is used for the communication with the app. You can find the code here: https://github.com/devmil/remotelego/tree/master/embedded/RedBearDuo/LegoControl You can try if it works on the Mini but as RedBear used different APIs for many of there boards I fear that this won't work out of the box. I used Chrome for Android and a native Android app to communicate with the device and they both worked. In the evening I will do some tests with an older Raspberry Pi variant of the car control software and see if this problem is reproducible in that setting.
,
Aug 10 2016
If you can make a little code to reproduce it on a BLE Mini, that would be great! But maybe I should confirm I can find it somewhere in my house, before you send too much time on the code...
,
Aug 10 2016
Intermediate find: Chrome on Android also throws exceptions. I didn't see them because a) they don't break the Promise chain b) I hadn't a version published that logs the errors So summary so far on my environment: Chrome on Mac breaks the Promise chain on Read/Write characteristics. Having "Read/Wrinte without response" characteristics doesn't break the Promise chain but throws exceptions. On Android exceptions are thrown (the exact same exceptions) but they don't break the Promise chain. Next: I will try to get a reproduction of the problem using a BLE Mini (as far as I understand the BLE Mini isn't meant to be programmed directly for but it provides kind of a bridge to an UART connected device) as I also have one lying around. I will also do some experiments with other BLE devices (directly accessing the BLE Nano for example) to get a better environment parameter narrowing.
,
Aug 10 2016
What exceptions are you seeing?
,
Aug 10 2016
I have attached the JavaScript log from the Android Chrome version. One containing the communication with a model configured with read/write characteristics and containing the communication with a model configured with read/write without response characteristics.
,
Aug 10 2016
I'm on a hot track and I think the problem has something to do with the way I use the API. I will do some more tests with some variants tomorrow and post my findings here.
,
Aug 10 2016
fwiw: You are not supposed to be calling Promise.all([char.writeValue(), char.writeValue()]). If you do this the second promise should reject with "In progress", but for some reason you are not getting this error...
,
Aug 11 2016
For info, I've just tested this sample code on Mac and it works great: ... let reset = new Uint8Array([1]); Promise.all([ heartRateControlPointCharacteristic.writeValue(reset), heartRateControlPointCharacteristic.writeValue(reset) ]); I do get the "GATT operation already in progress" error.
,
Aug 11 2016
It looks like the root issue is the fact that "this.m_service.getCharacteristic(characteristicUUID)" returns "DOMException: No Characteristics with specified UUID found in Service." Michael, may you give a try to https://googlechrome.github.io/samples/web-bluetooth/characteristic-properties.html?service=40480f29-7bad-4ea5-8bf8-499405c9b324&characteristic=7baf8dca-2bfc-47fb-af29-042fccc180eb This will simply read Steer characteristic properties from a nearby BLE device that advertises 40480f29-7bad-4ea5-8bf8-499405c9b324 Service UUID. I'd like to see if we also get the same error.
,
Aug 11 2016
Hi, a short update. there was more than one problem involved this is why my narrowing took so long and that caused some misleading tracks: For clarification 1) Characteristic not found This is 100% no bug in Chrome. This has been caused by the WebApp implementation as it tried to get Characteristics that are optional. As the log didn't state the UUID that is missing I mistakenly mixed this log entry with the behavior the app showed (no / delayed characteristic write with a broken Promise chain) 2) Broken Promise chain The Bluetooth implementation on the device had an issue. (The write method I have implemented returned the number of bytes written but the integer was expected to represent a boolean value so basically I always returned false) So I think the Mac implementation behaves (in contrast to the Android implementation) correctly by throwing an exception upon a error code returned by the device. You can see this in the packet logger file I initially posted. So again no bug in the Mac implementation. If anything then an issue in the Android implementation. I fixed the BT implementation on the device, replaced the Promise.all with chaining the Promises one after the other and fixed the frequent requests for unavailable characteristics and I can see the following behavior: a) the Promise chain isn't broken any more b) there is a big delay between writing the data and the data arriving at the device c) the chrome log still contains thrown exceptions (see attached files) I will continue to do some tests. I tried a BLE Nano and implemented an empty BT service with speed, steer and blink characteristics (set to read/write) and tested the application with it. It basically behaves the same way the DUO behaves (laggy, exceptions, no broken Promise chain). I will now try to reproduce this behavior using a small and simple test application.
,
Aug 11 2016
Is this on macOS? > there is a big delay between writing the data and the data arriving at the device Is this a consequence of having to wait for previous values to be written or is a single write operation taking longer now? To speed things up you could use Write Without Response. > the chrome log still contains thrown exceptions The logs only show DOMException :) Could you print the name and message of the exception as well?
,
Aug 11 2016
Also, could you link to your source code so we can tell what "LegoCar.js (249)" refers to?
,
Aug 11 2016
Yes, this is MacOS. You are right. I switched back to WriteWithoutResponse and the delay got much better. Not as good as on Android though. To be sure to have the log matching the source code I logged another round. You can find the source code for these logs here: https://github.com/devmil/remotelego_app/tree/Chrome_BLE_bug_reference_1/src I have no idea how to get more information about the errors in the logs because I don't get any exception object in the Promise catch. The log entry basically only states that the catch entry has been called without any argument and without any effect on the Promise chain. Maybe this is something completely different and independent of the Bluetooth API. This is why I want to create a small sample app. I also attached the log of the Android Chrome running the app containing the same Promise catch calls. The DOMExceptions you have seen in the other logs were GATT Exceptions stating that there is another GATT operation going on, they are OK and were triggered by a too frequent update call. As far as I see this the only remaining "issue" is the mysterious catch call that doesn't have any effect and even may relate to some different problem (Promise related?)
,
Aug 11 2016
You are talking about "undefined "Error writing characteristic value! " right? That catch is getting executed with no arguments because you rejected the promise earlier with no arguments[1]:
if (checkDirtyAction()) {
//...
}
return new Promise((resolve, reject) => { reject(); });
Also fwiw: you could replace that with "return Promise.reject()";
[1] https://github.com/devmil/remotelego_app/blob/687dd1d06d71ad3a46ab8d72a650efe458006562/src/app/shared/LegoCar.ts#L228
,
Aug 11 2016
Ok... This is embarrassing :) thanks for the hint. So no issue left.
,
Aug 11 2016
Great! Feel free to open another bug if you run into any issues. |
|||
►
Sign in to add a comment |
|||
Comment 1 by fbeaufort@chromium.org
, Aug 7 2016Status: Available (was: Unconfirmed)