Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong handling of property 'name' for BLE devices #570

Open
Z80sp opened this issue Dec 10, 2021 · 3 comments
Open

Wrong handling of property 'name' for BLE devices #570

Z80sp opened this issue Dec 10, 2021 · 3 comments

Comments

@Z80sp
Copy link

Z80sp commented Dec 10, 2021

Hi team,

I currently get troubles interacting with a BLE device from which advertisement data is dynamic.
It runs a scenario where the AD structure LOCAL NAME (AD_TYPE 0x09) needs to update regularly its raw binary content.

Here are the 2 issues encountered:

  1. Web BLE API assumes LOCAL_NAME to be a NULL terminated string whereas the BLE specifications clearly don't.
    An AD structure looks like this : (1)[LENGTH] + (LENGTH)[ (N)[AD_TYPE] + (LENGTH-N)[AD_DATA] ]
    For an AD structure of type LOCAL_NAME containing 4 bytes : (1)[0x05] (5)[ (1)[0x09] + (4)[0x00 0x01 0x02 0x03] ]
    ==> Final byte sequence is : (6)[ 0x05 0x09 0x00 0x01 0x02 0x03 ]

    But in such case Web BLE API returns a 0 byte long name (empty string) instead of 4 bytes long string
    "\x00\x01\x02\x03".
    Whatever bytes are non ASCII nor displayable, the AD length byte is the only reliable data telling how long the local
    name is, and since it's allowed to pass raw binary data here, null byte should not be interpreted as an 'end of string'.

  2. BluetoothDevice.name always contains the same value while the device dynamically updates advertised data.
    Even using watchAdvertisements() and event 'advertisementreceived', property 'name' remains the same. It seems
    the value is retrieved at pairing stage, but is never updated anymore after.

Case 1) is trivial to experiment : just introduce a null byte in LOCAL_NAME AD structure of any advertising BLE device...
Case 2) is easily reproduced running this demo page while advertisement gets updated:
https://googlechrome.github.io/samples/web-bluetooth/watch-advertisements.html

Thanks for reading.

Best Regards,

Phil

@Z80sp Z80sp changed the title Wrong handling of property 'name' of Bluetooth devices Wrong handling of property 'name' for Bluetooth devices Dec 10, 2021
@Z80sp Z80sp changed the title Wrong handling of property 'name' for Bluetooth devices Wrong handling of property 'name' for BLE devices Dec 10, 2021
@reillyeon
Copy link
Contributor

There are some implementation issues which make passing strings that are not valid UTF-8. I'd like to better understand the use case for device names containing unprintable characters. Why isn't this information in fields designed for binary data like manufacturerData or serviceData?

Not updating BluetoothDevice.name when a new advertisement is received is tracked by Chromium issue 1133489 however the name field of the BluetoothAdvertisingEvent should include the name from that particular advertisement packet.

@Emill
Copy link

Emill commented Dec 11, 2021

Actually the NUL character is fully valid in UTF-8, although not a printable one.

The Bluetooth standard says the following:

The Bluetooth Device Name can be up to 248 bytes (see [Vol 2] Part C, Section 4.3.5). It shall be encoded according to UTF-8 (therefore the name entered on the UI level may be restricted to as few as 62 characters if codepoints outside the range U+0000 to U+007F are used).

It here explicitly lists U+0000 (and all other non-printable characters) as codepoints.

This is most likely an implementation bug where NUL-terminated C strings are used somewhere in the pipeline and not a WebBluetooth specification issue.

@Z80sp
Copy link
Author

Z80sp commented Dec 15, 2021

Hi,
Thanks all for your reply.

@reillyeon :
I understand fully your point as from a workstation dev perspective, cleaner and well organized is better even if consuming more (memory, energy...). Unfortunately BLE is tight to uControlled world where both few bytes and mAh count (no 32kb buffers and power plugs there). In my situation the BLE spot needs :

  1. to be visible from a wide range of handsets (including those still featuring only the BLE stack in v4). Thus, it's important to keep away from extended advertisements and stick on using basic ones only, allowing 31 bytes of data max.

  2. to avoid dealing with several connections (and even a single one) when it is not necessary to do. For tiny environmental and not critical information broadcasting, better to do it through the advertisement than via a full connection and data exchange workflow handling. This makes the device less sensitive to DOS attacks (most of BLE modules cannot manage more than a few simultaneous connections), and let it keep the only connection available for maintenance procedures.

Given the constrains below, we get only a 31 bytes (minus IDs and payload bytes) in which to carry an information changing from time to time. It's quite tight and using raw binary values gives a chance to pack data even a bit more, allowing the full range of values to be used whereas b64 or any other kind of encoding won't allow that.
Also, putting custom data in other extra AD "fields" reduces the space left to place such an information.
For example, putting user data in 'serviceData', will consume 4 extra bytes:
(1)[8BIT_PAYLOAD_LENGTH] + (1)[0x16] + (2)[16BIT_UUID]

Anyway I sacrified 4 bytes just to try, adding an AD block of type SERVICE_DATA (0x16):
[0x09 0x16 0x1C 0x2A] + [0x00 0x01 0x02 0x03 0x04 0x05]
It works, but I miss my 4 bytes.

@Emill :
I agree also your point, but isn't this statement just about how should be the local name in its general definition? When explained within the context of advertisement data structures (AD type COMPLETE_LOCAL_NAME) it is not told we should place UTF8 so it's a bit confusing. Anyway, I agree since we are talking about the same object, its format should remain exactly the same wherever this object stands.
Any Idea, where in implementation you suspect the null terminated char rule to apply? Once again when I run mobile application 'nRF Connect', it handles correctly retrieval for both dynamic content and pure random binary content (both in AD blocks COMPLETE_LOCAL_NAME and SERVICE_DATA) and I believe the app just makes use of the underlying BLE stack implementation.

Thanks,

Phil

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants