From e6c01db3173530566851b489d96edecbfe5d92f6 Mon Sep 17 00:00:00 2001 From: torlando-tech Date: Tue, 11 Nov 2025 15:00:11 -0500 Subject: [PATCH] fix(ble): Filter invalid RSSI sentinel values and add scanner debug logging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prevent invalid RSSI values (-127, -128, 0) from causing connection issues by filtering them at three stages: scanner detection, discovery handler, and peer scoring. These sentinel values indicate Bleak cache/state issues rather than actual signal strength. Add comprehensive debug logging to scanner lifecycle for troubleshooting: - Callback invocations with device details - Scanner start/stop/duration events - Filtering stages (UUID matching, RSSI thresholds) - Device discovery counts Logging uses INFO level (via "EXTRA" fallback) for visibility without requiring DEBUG log level configuration. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/RNS/Interfaces/BLEInterface.py | 10 ++++++++++ src/RNS/Interfaces/linux_bluetooth_driver.py | 20 ++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/RNS/Interfaces/BLEInterface.py b/src/RNS/Interfaces/BLEInterface.py index 55cce61..3e11822 100644 --- a/src/RNS/Interfaces/BLEInterface.py +++ b/src/RNS/Interfaces/BLEInterface.py @@ -695,6 +695,11 @@ class BLEInterface(Interface): RNS.log(f"{self} device {device.name if device.name else device.address} does not advertise Reticulum service UUID, skipping", RNS.LOG_EXTREME) return + # Validate RSSI - skip devices with invalid/sentinel values + if device.rssi in (-127, -128, 0): + RNS.log(f"{self} skipping {device.name or device.address} ({device.address}): invalid sentinel RSSI {device.rssi} dBm", RNS.LOG_DEBUG) + return + # Update or create discovered peer entry if device.address not in self.discovered_peers: self.discovered_peers[device.address] = DiscoveredPeer( @@ -1037,6 +1042,11 @@ class BLEInterface(Interface): """ score = 0.0 + # Validate RSSI - reject peers with invalid/sentinel values + if peer.rssi is None or peer.rssi in (-127, -128, 0): + RNS.log(f"{self} peer {peer.address} has invalid RSSI {peer.rssi}, returning minimum score", RNS.LOG_DEBUG) + return 0.0 + # Signal strength component (0-100 points) # RSSI typically ranges from -30 (excellent) to -100 (poor) # Convert to 0-100 scale diff --git a/src/RNS/Interfaces/linux_bluetooth_driver.py b/src/RNS/Interfaces/linux_bluetooth_driver.py index aaef028..5f43bd8 100644 --- a/src/RNS/Interfaces/linux_bluetooth_driver.py +++ b/src/RNS/Interfaces/linux_bluetooth_driver.py @@ -591,6 +591,7 @@ class LinuxBluetoothDriver(BLEDriverInterface): def detection_callback(device, advertisement_data): """Called for each discovered device.""" + self._log(f"🔍 CALLBACK INVOKED: {device.address} ({device.name or 'Unknown'}) RSSI={advertisement_data.rssi} UUIDs={advertisement_data.service_uuids}", "EXTRA") discovered_devices.append((device, advertisement_data)) # Scan duration based on power mode @@ -601,14 +602,20 @@ class LinuxBluetoothDriver(BLEDriverInterface): else: # balanced scan_time = 1.0 + self._log(f"🔍 Starting BleakScanner (power_mode={self.power_mode}, scan_time={scan_time}s, service_uuid={self.service_uuid})", "EXTRA") scanner = BleakScanner(detection_callback=detection_callback) try: + self._log("🔍 Calling scanner.start()", "EXTRA") await scanner.start() + self._log(f"🔍 Scanner started, sleeping for {scan_time}s", "EXTRA") await asyncio.sleep(scan_time) + self._log("🔍 Calling scanner.stop()", "EXTRA") await scanner.stop() + self._log(f"🔍 Scanner stopped. Total devices discovered: {len(discovered_devices)}", "EXTRA") except Exception as e: error_msg = str(e) + self._log(f"🔍 Scanner exception: {error_msg}", "ERROR") # Check for adapter power issues if "No powered Bluetooth adapters" in error_msg or "Not Powered" in error_msg: @@ -620,13 +627,24 @@ class LinuxBluetoothDriver(BLEDriverInterface): raise # Process discovered devices + self._log(f"🔍 Processing {len(discovered_devices)} discovered devices", "EXTRA") for device, adv_data in discovered_devices: # Check if device advertises our service UUID if self.service_uuid and self.service_uuid.lower() in [uuid.lower() for uuid in adv_data.service_uuids]: + self._log(f"✓ {device.address} has service UUID {self.service_uuid}", "EXTRA") + # Check RSSI threshold if adv_data.rssi < self.min_rssi: + self._log(f"✗ {device.address}: RSSI {adv_data.rssi} below threshold {self.min_rssi}", "EXTRA") continue + # Check for invalid/sentinel RSSI values (-127, -128 indicate no signal/error) + if adv_data.rssi in (-127, -128, 0): + self._log(f"✗ {device.address}: invalid sentinel RSSI {adv_data.rssi} dBm", "DEBUG") + continue + + self._log(f"✓ {device.address} passed all filters, notifying callback", "EXTRA") + # Create BLEDevice and notify callback ble_device = BLEDevice( address=device.address, @@ -641,6 +659,8 @@ class LinuxBluetoothDriver(BLEDriverInterface): self.on_device_discovered(ble_device) except Exception as e: self._log(f"Error in device discovered callback: {e}", "ERROR") + else: + self._log(f"✗ {device.address} ({device.name or 'Unknown'}): service UUID mismatch (has {adv_data.service_uuids}, want {self.service_uuid})", "EXTRA") # ======================================================================== # Advertising (Peripheral Mode)