diff --git a/bumble/gatt.py b/bumble/gatt.py index 902fa075..90867cd7 100644 --- a/bumble/gatt.py +++ b/bumble/gatt.py @@ -320,6 +320,12 @@ class CharacteristicAdapter: def __getattr__(self, name): return getattr(self.wrapped_characteristic, name) + def __setattr__(self, name, value): + if name in {'wrapped_characteristic', 'read_value', 'write_value', 'subscribe'}: + super().__setattr__(name, value) + else: + setattr(self.wrapped_characteristic, name, value) + def read_encoded_value(self, connection): return self.encode_value(self.wrapped_characteristic.read_value(connection)) @@ -343,6 +349,10 @@ class CharacteristicAdapter: None if subscriber is None else lambda value: subscriber(self.decode_value(value)) ) + def __str__(self): + wrapped = str(self.wrapped_characteristic) + return f'{self.__class__.__name__}({wrapped})' + # ----------------------------------------------------------------------------- class DelegatedCharacteristicAdapter(CharacteristicAdapter): diff --git a/bumble/gatt_server.py b/bumble/gatt_server.py index 3afcecc4..8297f11a 100644 --- a/bumble/gatt_server.py +++ b/bumble/gatt_server.py @@ -545,13 +545,13 @@ class Server(EventEmitter): value = attribute.read_value(connection) if request.value_offset > len(value): response = ATT_Error_Response( - request_opcode_in_error = request.op_code, + request_opcode_in_error = request.op_code, attribute_handle_in_error = request.attribute_handle, error_code = ATT_INVALID_OFFSET_ERROR ) elif len(value) <= mtu - 1: response = ATT_Error_Response( - request_opcode_in_error = request.op_code, + request_opcode_in_error = request.op_code, attribute_handle_in_error = request.attribute_handle, error_code = ATT_ATTRIBUTE_NOT_LONG_ERROR ) diff --git a/bumble/hci.py b/bumble/hci.py index bbac8430..9858c04d 100644 --- a/bumble/hci.py +++ b/bumble/hci.py @@ -3276,6 +3276,9 @@ class HCI_Event(HCI_Packet): parameters = b'' if self.parameters is None else self.parameters return bytes([HCI_EVENT_PACKET, self.event_code, len(parameters)]) + parameters + def __bytes__(self): + return self.to_bytes() + def __str__(self): result = color(self.name, 'magenta') if fields := getattr(self, 'fields', None): diff --git a/tests/self_test.py b/tests/self_test.py index a1d2ddda..cf1befff 100644 --- a/tests/self_test.py +++ b/tests/self_test.py @@ -163,6 +163,44 @@ async def test_self_gatt(): assert(result == c1.value) +# ----------------------------------------------------------------------------- +@pytest.mark.asyncio +async def test_self_gatt_long_read(): + # Create two devices, each with a controller, attached to the same link + two_devices = TwoDevices() + + # Add some GATT characteristics to device 1 + characteristics = [ + Characteristic( + f'3A143AD7-D4A7-436B-97D6-5B62C315{i:04X}', + Characteristic.READ, + Characteristic.READABLE, + bytes([x & 255 for x in range(i)]) + ) + for i in range(0, 513) + ] + + service = Service('8140E247-04F0-42C1-BC34-534C344DAFCA', characteristics) + two_devices.devices[1].add_service(service) + + # Start + await two_devices.devices[0].power_on() + await two_devices.devices[1].power_on() + + # Connect the two devices + connection = await two_devices.devices[0].connect(two_devices.devices[1].random_address) + peer = Peer(connection) + + result = await peer.discover_service(service.uuid) + assert(len(result) == 1) + found_service = result[0] + found_characteristics = await found_service.discover_characteristics() + assert(len(found_characteristics) == 513) + for (i, characteristic) in enumerate(found_characteristics): + value = await characteristic.read_value() + assert(value == characteristics[i].value) + + # ----------------------------------------------------------------------------- async def _test_self_smp_with_configs(pairing_config1, pairing_config2): # Create two devices, each with a controller, attached to the same link @@ -274,7 +312,7 @@ async def test_self_smp(io_cap, sc, mitm, key_dist): pairing_config2.delegate.peer_delegate = pairing_config1.delegate await _test_self_smp_with_configs(pairing_config1, pairing_config2) - + # ----------------------------------------------------------------------------- @@ -323,6 +361,7 @@ async def test_self_smp_wrong_pin(): async def run_test_self(): await test_self_connection() await test_self_gatt() + await test_self_gatt_long_read() await test_self_smp() await test_self_smp_reject() await test_self_smp_wrong_pin()