Fix small bug with services set via --device-config

before:
```
  File "/home/alanrosenthal/code/fitbit/bumble/bumble/gatt.py", line 572, in __str__
    f'Descriptor(handle=0x{self.handle:04X}, '
  File "/home/alanrosenthal/code/fitbit/bumble/bumble/att.py", line 756, in read_value
    self.permissions & self.READ_REQUIRES_ENCRYPTION
TypeError: unsupported operand type(s) for &: 'str' and 'int'
```
This commit is contained in:
Alan Rosenthal
2023-03-14 18:16:46 -04:00
parent e77723a5f9
commit c34c5fdf17
3 changed files with 51 additions and 3 deletions

View File

@@ -23,11 +23,12 @@
# Imports # Imports
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
from __future__ import annotations from __future__ import annotations
import functools
import struct import struct
from pyee import EventEmitter from pyee import EventEmitter
from typing import Dict, Type, TYPE_CHECKING from typing import Dict, Type, TYPE_CHECKING
from bumble.core import UUID, name_or_number from bumble.core import UUID, name_or_number, get_dict_key_by_value
from bumble.hci import HCI_Object, key_with_value from bumble.hci import HCI_Object, key_with_value
from bumble.colors import color from bumble.colors import color
@@ -725,11 +726,33 @@ class Attribute(EventEmitter):
READ_REQUIRES_AUTHORIZATION = 0x40 READ_REQUIRES_AUTHORIZATION = 0x40
WRITE_REQUIRES_AUTHORIZATION = 0x80 WRITE_REQUIRES_AUTHORIZATION = 0x80
PERMISSION_NAMES = {
READABLE: 'READABLE',
WRITEABLE: 'WRITEABLE',
READ_REQUIRES_ENCRYPTION: 'READ_REQUIRES_ENCRYPTION',
WRITE_REQUIRES_ENCRYPTION: 'WRITE_REQUIRES_ENCRYPTION',
READ_REQUIRES_AUTHENTICATION: 'READ_REQUIRES_AUTHENTICATION',
WRITE_REQUIRES_AUTHENTICATION: 'WRITE_REQUIRES_AUTHENTICATION',
READ_REQUIRES_AUTHORIZATION: 'READ_REQUIRES_AUTHORIZATION',
WRITE_REQUIRES_AUTHORIZATION: 'WRITE_REQUIRES_AUTHORIZATION',
}
@staticmethod
def string_to_permissions(permissions_str: str):
return functools.reduce(
lambda x, y: x | get_dict_key_by_value(Attribute.PERMISSION_NAMES, y),
permissions_str.split(","),
0,
)
def __init__(self, attribute_type, permissions, value=b''): def __init__(self, attribute_type, permissions, value=b''):
EventEmitter.__init__(self) EventEmitter.__init__(self)
self.handle = 0 self.handle = 0
self.end_group_handle = 0 self.end_group_handle = 0
self.permissions = permissions if isinstance(permissions, str):
self.permissions = self.string_to_permissions(permissions)
else:
self.permissions = permissions
# Convert the type to a UUID object if it isn't already # Convert the type to a UUID object if it isn't already
if isinstance(attribute_type, str): if isinstance(attribute_type, str):

View File

@@ -999,7 +999,7 @@ class Device(CompositeEventEmitter):
new_characteristic = Characteristic( new_characteristic = Characteristic(
uuid=characteristic["uuid"], uuid=characteristic["uuid"],
properties=characteristic["properties"], properties=characteristic["properties"],
permissions=int(characteristic["permissions"], 0), permissions=characteristic["permissions"],
descriptors=descriptors, descriptors=descriptors,
) )
characteristics.append(new_characteristic) characteristics.append(new_characteristic)

View File

@@ -37,10 +37,12 @@ from bumble.gatt import (
Service, Service,
Characteristic, Characteristic,
CharacteristicValue, CharacteristicValue,
Descriptor,
) )
from bumble.transport import AsyncPipeSink from bumble.transport import AsyncPipeSink
from bumble.core import UUID from bumble.core import UUID
from bumble.att import ( from bumble.att import (
Attribute,
ATT_EXCHANGE_MTU_REQUEST, ATT_EXCHANGE_MTU_REQUEST,
ATT_ATTRIBUTE_NOT_FOUND_ERROR, ATT_ATTRIBUTE_NOT_FOUND_ERROR,
ATT_PDU, ATT_PDU,
@@ -861,6 +863,29 @@ async def async_main():
await test_mtu_exchange() await test_mtu_exchange()
# -----------------------------------------------------------------------------
def test_attribute_string_to_permissions():
assert Attribute.string_to_permissions('READABLE') == 1
assert Attribute.string_to_permissions('WRITEABLE') == 2
assert Attribute.string_to_permissions('READABLE,WRITEABLE') == 3
# -----------------------------------------------------------------------------
def test_charracteristic_permissions():
characteristic = Characteristic(
'FDB159DB-036C-49E3-B3DB-6325AC750806',
Characteristic.READ | Characteristic.WRITE | Characteristic.NOTIFY,
'READABLE,WRITEABLE',
)
assert characteristic.permissions == 3
# -----------------------------------------------------------------------------
def test_descriptor_permissions():
descriptor = Descriptor('2902', 'READABLE,WRITEABLE')
assert descriptor.permissions == 3
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
if __name__ == '__main__': if __name__ == '__main__':
logging.basicConfig(level=os.environ.get('BUMBLE_LOGLEVEL', 'INFO').upper()) logging.basicConfig(level=os.environ.get('BUMBLE_LOGLEVEL', 'INFO').upper())