From e66d145b7e62b0d8c29bcd704d96d9861fb5c9c8 Mon Sep 17 00:00:00 2001 From: torlando-tech Date: Sat, 8 Nov 2025 19:52:46 -0500 Subject: [PATCH] feat: Add driver_class override pattern for platform-specific BLE drivers Enable subclassing BLEInterface with custom platform-specific drivers by introducing a class-level driver_class attribute that can be overridden. Changes: - Import LinuxBluetoothDriver optionally with HAS_LINUX_DRIVER flag - Add driver_class class attribute (defaults to LinuxBluetoothDriver) - Check driver_class is not None before instantiation - Use self.driver_class() instead of hardcoded LinuxBluetoothDriver() - Log which driver is being used at initialization This pattern enables platform-specific implementations like: class AndroidBLEInterface(BLEInterface): driver_class = AndroidBLEDriver Without this pattern, subclasses would need to override __init__ entirely to use a different driver, duplicating all initialization logic. Implementation details: - LinuxBluetoothDriver import wrapped in try/except with fallback to None - Raises ImportError if driver_class is None and no override provided - Maintains backward compatibility (LinuxBluetoothDriver used by default) - All production features preserved (logging redirect, blacklist, rate limiting, service UUID filtering, connection management) Use case: This pattern is used by the Columba Android app to integrate the Android BLE stack via Chaquopy, overriding driver_class with AndroidBLEDriver that bridges to Kotlin BLE APIs. Testing: - Default behavior unchanged (uses LinuxBluetoothDriver) - Subclass override tested in columba/python/android_ble_interface.py - No functional changes to existing BLE interface behavior --- src/RNS/Interfaces/BLEInterface.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/RNS/Interfaces/BLEInterface.py b/src/RNS/Interfaces/BLEInterface.py index d54b49e..a6e1af0 100644 --- a/src/RNS/Interfaces/BLEInterface.py +++ b/src/RNS/Interfaces/BLEInterface.py @@ -104,11 +104,17 @@ try: except ImportError: from RNS.Interfaces.bluetooth_driver import BLEDriverInterface, BLEDevice -# Import platform-specific driver +# Import platform-specific driver (optional - can be overridden by subclasses) try: from linux_bluetooth_driver import LinuxBluetoothDriver + HAS_LINUX_DRIVER = True except ImportError: - from RNS.Interfaces.linux_bluetooth_driver import LinuxBluetoothDriver + try: + from RNS.Interfaces.linux_bluetooth_driver import LinuxBluetoothDriver + HAS_LINUX_DRIVER = True + except ImportError: + HAS_LINUX_DRIVER = False + LinuxBluetoothDriver = None HAS_DRIVER = True @@ -258,6 +264,9 @@ class BLEInterface(Interface): FRAG_TYPE_END = 0x03 FRAG_HEADER_SIZE = 5 # bytes: type(1) + sequence(2) + total(2) + # Platform-specific driver class (override in subclasses for different platforms) + driver_class = LinuxBluetoothDriver + def __init__(self, owner, configuration): """ Initialize BLE interface. @@ -358,8 +367,14 @@ class BLEInterface(Interface): # Discovery state with prioritization - # Initialize BLE driver - self.driver = LinuxBluetoothDriver( + # Initialize BLE driver (uses class attribute, can be overridden by subclasses) + if self.driver_class is None: + raise ImportError( + "No BLE driver available. LinuxBluetoothDriver not found and no " + "driver_class override provided by subclass." + ) + + self.driver = self.driver_class( discovery_interval=self.discovery_interval, connection_timeout=self.connection_timeout, min_rssi=self.min_rssi, @@ -367,6 +382,7 @@ class BLEInterface(Interface): max_peers=self.max_peers, adapter_index=0 # TODO: Make configurable ) + RNS.log(f"{self} Using driver: {type(self.driver).__name__}", RNS.LOG_DEBUG) # Set driver callbacks self.driver.on_device_discovered = self._device_discovered_callback