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
This commit is contained in:
torlando-tech 2025-11-08 19:52:46 -05:00
commit e66d145b7e

View file

@ -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