From 3f0d91ecdbb0b5ef2e85a2a8ff596fdd2c11e853 Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Tue, 28 Oct 2025 12:33:06 +0100 Subject: [PATCH] Fixed Android BLE stack re-connection hang for RNodeInterface --- sbapp/services/sidebandservice.py | 11 +++++++ sbapp/sideband/core.py | 48 +++++++++++++------------------ 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/sbapp/services/sidebandservice.py b/sbapp/services/sidebandservice.py index 814c2b6..f76ccb6 100644 --- a/sbapp/services/sidebandservice.py +++ b/sbapp/services/sidebandservice.py @@ -229,6 +229,8 @@ class SidebandService(): self.notification_intent = None self.notification_small_icon = None + self.rnode_ble_reset_required = False + if RNS.vendor.platformutils.is_android(): self.android_service = autoclass('org.kivy.android.PythonService').mService self.app_context = self.android_service.getApplication().getApplicationContext() @@ -476,6 +478,15 @@ class SidebandService(): self.sideband.setstate("wants.settings_reload", False) self.sideband.reload_configuration() + if self.sideband.getstate("wants.rnode_ble_reset"): + self.sideband.setstate("wants.rnode_ble_reset", False) + RNS.log("RNode BLE hardware error detected, re-initializing Android BLE dispatcher", RNS.LOG_ERROR) + if hasattr(self.sideband, "interface_rnode") and self.sideband.interface_rnode != None: + self.sideband.interface_rnode.reset_ble() + RNS.log("BLE hardware reset executed", RNS.LOG_INFO) + else: + RNS.log("No RNode interface active, could not execute BLE hardware reset", RNS.LOG_ERROR) + time.sleep(sleep_time) self.sideband.cleanup() diff --git a/sbapp/sideband/core.py b/sbapp/sideband/core.py index 8fa432c..91c88f8 100644 --- a/sbapp/sideband/core.py +++ b/sbapp/sideband/core.py @@ -105,20 +105,20 @@ class PropagationNodeDetector(): self.owner_app = owner.owner_app class SidebandCore(): - CONV_P2P = 0x01 - CONV_GROUP = 0x02 - CONV_BROADCAST = 0x03 - CONV_VOICE = 0x04 + CONV_P2P = 0x01 + CONV_GROUP = 0x02 + CONV_BROADCAST = 0x03 + CONV_VOICE = 0x04 - MAX_ANNOUNCES = 24 + MAX_ANNOUNCES = 24 - SERVICE_JOB_INTERVAL = 1 - PERIODIC_JOBS_INTERVAL = 60 - PERIODIC_SYNC_RETRY = 360 - TELEMETRY_KEEP = 60*60*24*7 - TELEMETRY_INTERVAL = 60 - SERVICE_TELEMETRY_INTERVAL = 300 - TELEMETRY_CLEAN_INTERVAL = 3600 + SERVICE_JOB_INTERVAL = 1 + PERIODIC_JOBS_INTERVAL = 60 + PERIODIC_SYNC_RETRY = 360 + TELEMETRY_KEEP = 60*60*24*7 + TELEMETRY_INTERVAL = 60 + SERVICE_TELEMETRY_INTERVAL = 300 + TELEMETRY_CLEAN_INTERVAL = 3600 IF_CHANGE_ANNOUNCE_MIN_INTERVAL = 3.5 # In seconds AUTO_ANNOUNCE_RANDOM_MIN = 90 # In minutes @@ -128,6 +128,8 @@ class SidebandCore(): LOG_DEQUE_MAXLEN = 128 + ERROR_INVALID_BLE_MTU = 0x20 + aspect_filter = "lxmf.delivery" def received_announce(self, destination_hash, announced_identity, app_data, announce_packet_hash): # Add the announce to the directory announce @@ -139,7 +141,7 @@ class SidebandCore(): "q": self.reticulum.get_packet_q(announce_packet_hash)} # This reformats the new v0.5.0 announce data back to the expected format - # for Sidebands database and other handling functions. + # for Sideband's database and other handling functions. dn = LXMF.display_name_from_app_data(app_data) sc = LXMF.stamp_cost_from_app_data(app_data) app_data = b"" @@ -3580,22 +3582,12 @@ class SidebandCore(): if hasattr(self, "interface_rnode") and self.interface_rnode != None: if len(self.interface_rnode.hw_errors) > 0: - self.setpersistent("runtime.errors.rnode", self.interface_rnode.hw_errors[0]) - self.interface_rnode.hw_errors = [] + if self.interface_rnode.hw_errors[0]["error"] == self.ERROR_INVALID_BLE_MTU: + self.setstate("wants.rnode_ble_reset", True) + else: + self.setpersistent("runtime.errors.rnode", self.interface_rnode.hw_errors[0]) - # if not self.interface_rnode_adding: - # RNS.log("Hardware error on RNodeInterface, scheduling re-init", RNS.LOG_DEBUG) - # if self.interface_rnode in RNS.Transport.interfaces: - # RNS.Transport.interfaces.remove(self.interface_rnode) - # del self.interface_rnode - # self.interface_rnode = None - # self.interface_rnode_adding = True - # def job(): - # self.__add_rnodeinterface(delay=5) - # if self.config["start_announce"] == True: - # time.sleep(12) - # self.lxmf_announce(attached_interface=self.interface_rnode) - # threading.Thread(target=job, daemon=True).start() + self.interface_rnode.hw_errors = [] if (now - last_multicast_lock_check > 120): RNS.log("Checking multicast and wake locks", RNS.LOG_DEBUG)