From 77debfab8b2dbb03fe32ac1363ff920dfc6da03a Mon Sep 17 00:00:00 2001 From: torlando-tech Date: Tue, 4 Nov 2025 00:09:11 -0500 Subject: [PATCH] fix(ble): Harden peripheral identity characteristic handling This commit addresses a timeout issue where a central device would fail to read the identity characteristic from the peripheral. The root cause is suspected to be a race condition in the underlying BlueZ/D-Bus stack, where the `read_callback` for the characteristic was not firing reliably, causing the central's read request to hang and time out. To make this process more robust and less dependent on timing, the GATT server implementation has been hardened: 1. The identity characteristic is now initialized with a 16-byte placeholder value. This ensures the D-Bus object is created with the correct data length from the start. 2. When the asynchronous RNS identity becomes available, the server now proactively pushes the identity to the characteristic using `set_value()`. This no longer relies exclusively on the fragile `read_callback` mechanism. Additionally, error logging within the driver has been improved to include the exception type, aiding future diagnostics. --- src/RNS/Interfaces/linux_bluetooth_driver.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/RNS/Interfaces/linux_bluetooth_driver.py b/src/RNS/Interfaces/linux_bluetooth_driver.py index 9121d6b..03982f8 100644 --- a/src/RNS/Interfaces/linux_bluetooth_driver.py +++ b/src/RNS/Interfaces/linux_bluetooth_driver.py @@ -1017,7 +1017,7 @@ class LinuxBluetoothDriver(BLEDriverInterface): result = future.result(timeout=5.0) return bytes(result) except Exception as e: - self._log(f"Error reading characteristic {char_uuid} from {address}: {e}", "ERROR") + self._log(f"Error reading characteristic {char_uuid} from {address}: {type(e).__name__}: {e}", "ERROR") raise def write_characteristic(self, address: str, char_uuid: str, data: bytes): @@ -1203,10 +1203,10 @@ class BluezeroGATTServer: self.adapter_index = adapter_index self.agent_capability = agent_capability - # State - self.running = False + # bluezero objects self.peripheral_obj = None self.tx_characteristic = None + self.identity_characteristic = None # Identity self.identity_bytes: Optional[bytes] = None @@ -1233,6 +1233,10 @@ class BluezeroGATTServer: raise ValueError("Identity must be 16 bytes") self.identity_bytes = identity_bytes + # Proactively update the characteristic value if it already exists + if self.identity_characteristic: + self.identity_characteristic.set_value(list(self.identity_bytes)) + self._log(f"Identity set: {identity_bytes.hex()}") def start(self, device_name: str): @@ -1368,16 +1372,16 @@ class BluezeroGATTServer: self._log(f"Added TX characteristic: {self.tx_char_uuid}", "DEBUG") # Add Identity characteristic (centrals read our identity) - identity_value = list(self.identity_bytes) if self.identity_bytes else [] self.peripheral_obj.add_characteristic( srv_id=1, chr_id=3, uuid=self.identity_char_uuid, - value=identity_value, + value=[0]*16, # Initialize with 16-byte placeholder notifying=False, flags=['read'], read_callback=self._handle_read_identity ) + self.identity_characteristic = self.peripheral_obj.characteristics[-1] self._log(f"Added Identity characteristic: {self.identity_char_uuid}", "DEBUG") # Save TX characteristic reference