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

Multiple services/characteristics with the same UUID should not be an error #362

Closed
AGlass0fMilk opened this issue Nov 19, 2020 · 2 comments
Assignees
Labels
Backend: BlueZ Issues and PRs relating to the BlueZ backend Backend: Core Bluetooth Issues and PRs relating to the Core Bluetooth backend Backend: pythonnet Issues or PRs relating to the .NET/pythonnet backend bug Something isn't working

Comments

@AGlass0fMilk
Copy link

AGlass0fMilk commented Nov 19, 2020

  • bleak version: 0.9.1
  • Python version: 3.9.0
  • Operating System: Ubuntu 20.04
  • BlueZ version (bluetoothctl -v) in case of Linux: 5.53

Description

There is no universal requirement in the BT specification that a GATT Server cannot have multiple instances of the same service in its profile, or multiple instances of the same characteristic in a service. This restriction may be specified by a GATT Service specification, but it is not the default nature of GATT services.

Currently, bleak stores services in the client object inside a dictionary using the UUID as the key. This innately disallows multiple services with the same UUID. In fact, it raises an exception here:

def add_service(self, service: BleakGATTService):
"""Add a :py:class:`~BleakGATTService` to the service collection.
Should not be used by end user, but rather by `bleak` itself.
"""
if service.uuid not in self.__services:
self.__services[service.uuid] = service
else:
raise BleakError(
"This service is already present in this BleakGATTServiceCollection!"
)

I am implementing a DFU Service for Mbed OS and I was planning to use bleak as the platform for a desktop-based update tool. Through our discussion of the DFU Service specification, we want to allow multiple DFU Services to exist on the GATT Server so that different embedded devices within the same product may be updated over BLE.

This limitation of bleak will make it impossible to support multiple DFU services on the same GATT server. Another example of a service (one that is BT SIG specified, in fact) that allows multiple instances in this way is the common Battery Service:

ble-battery-svc

The suggested fix would be to:

  1. Change from storing any attributes (services/characteristics/descriptors, etc) in a map using their UUID as a key. The key should be the handle of the attribute.
  2. Implement new functions get_services_by_uuid(), get_characteristics_by_uuid(), and so on to return Lists of BleakGattService, BleakGattCharacteristic, ...
  3. Deprecate the get_service(), get_descriptor(), etc functions and in the mean time have them return the first occurrence of a service/descriptor by UUID (ie: return `get_services_by_uuid(uuid)[0])
@AGlass0fMilk AGlass0fMilk changed the title Multiple services with the same UUID should not be an error Multiple services/characteristics with the same UUID should not be an error Nov 19, 2020
@hbldh
Copy link
Owner

hbldh commented Nov 20, 2020

Characteristics and descriptors already use handles, but for services I was not sure I could get handles in a good fashion in all OS backends, so I let that remain as uuids. I assumed that no one would ever want to split characteristics over two different services with the same uuid...

I haven’t got time to fix this in the foreseeable future, but feel free to have a go by yourselves! It does seem to be an error in implementation since it apparently says that it should be allowed in some spec.

@hbldh hbldh self-assigned this Nov 20, 2020
@hbldh hbldh added Backend: pythonnet Issues or PRs relating to the .NET/pythonnet backend Backend: BlueZ Issues and PRs relating to the BlueZ backend Backend: Core Bluetooth Issues and PRs relating to the Core Bluetooth backend bug Something isn't working labels Nov 20, 2020
@AGlass0fMilk
Copy link
Author

Characteristics and descriptors already use handles, but for services I was not sure I could get handles in a good fashion in all OS backends, so I let that remain as uuids. I assumed that no one would ever want to split characteristics over two different services with the same uuid...

I haven’t got time to fix this in the foreseeable future, but feel free to have a go by yourselves! It does seem to be an error in implementation since it apparently says that it should be allowed in some spec.

I'll take a look into fixing this as I develop my DFU tooling. Hopefully the service handles are available on all OS's... I do not have a Mac to test with but I can test on Ubuntu 20.04 and Windows 10.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Backend: BlueZ Issues and PRs relating to the BlueZ backend Backend: Core Bluetooth Issues and PRs relating to the Core Bluetooth backend Backend: pythonnet Issues or PRs relating to the .NET/pythonnet backend bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants