-
Notifications
You must be signed in to change notification settings - Fork 330
Description
- 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:
bleak/bleak/backends/service.py
Lines 107 to 117 in d7e9558
| 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:
The suggested fix would be to:
- 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.
- Implement new functions
get_services_by_uuid(),get_characteristics_by_uuid(), and so on to return Lists ofBleakGattService,BleakGattCharacteristic, ... - 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])