Skip to content

Commit

Permalink
Some changes for lost bluetooth connection / hci_uart stack restart
Browse files Browse the repository at this point in the history
  • Loading branch information
Marvo2011 committed Oct 3, 2023
1 parent 60bdde9 commit 1383b29
Showing 1 changed file with 85 additions and 45 deletions.
130 changes: 85 additions & 45 deletions etc/dbus-serialbattery/bms/lltjbd_ble.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import os
import threading
import sys
import re
from asyncio import CancelledError
from time import sleep
from typing import Union, Optional
Expand Down Expand Up @@ -43,6 +44,21 @@ def __init__(self, port: Optional[str], baud: Optional[int], address: str):
self.response_queue: Optional[asyncio.Queue] = None
self.ready_event: Optional[asyncio.Event] = None

self.hci_uart_ok = True
if not os.path.isfile("/tmp/dbus-blebattery-hciattach"):
execfile = open("/tmp/dbus-blebattery-hciattach", "w")
execpath = os.popen('ps -ww | grep hciattach | grep -v grep').read()
execpath = re.search("/usr/bin/hciattach.+", execpath)
execfile.write(execpath.group())
execfile.close()
else:
execpath = os.popen('ps -ww | grep hciattach | grep -v grep').read()
if not execpath:
execfile = open("/tmp/dbus-blebattery-hciattach", "r")
os.system(execfile.readline())
execfile.close()


logger.info("Init of LltJbd_Ble at " + address)

def connection_name(self) -> str:
Expand All @@ -64,10 +80,14 @@ async def bt_main_loop(self):
exception_type, exception_object, exception_traceback = sys.exc_info()
file = exception_traceback.tb_frame.f_code.co_filename
line = exception_traceback.tb_lineno
logger.error(
f"BleakScanner(): Exception occurred: {repr(exception_object)} of type {exception_type} "
f"in {file} line #{line}"
)
if "Bluetooth adapters" in repr(exception_object):
self.reset_hci_uart()
else:
logger.error(
f"BleakScanner(): Exception occurred: {repr(exception_object)} of type {exception_type} "
f"in {file} line #{line}"
)

self.device = None
await asyncio.sleep(0.5)
# allow the bluetooth connection to recover
Expand Down Expand Up @@ -131,20 +151,21 @@ def background_loop(self):
asyncio.run(self.bt_main_loop())

async def async_test_connection(self):
self.ready_event = asyncio.Event()
if not self.bt_thread.is_alive():
self.bt_thread.start()

def shutdown_ble_atexit(thread):
self.run = False
thread.join()

atexit.register(shutdown_ble_atexit, self.bt_thread)
try:
return await asyncio.wait_for(self.ready_event.wait(), timeout=5)
except asyncio.TimeoutError:
logger.error(">>> ERROR: Unable to connect with BLE device")
return False
if self.hci_uart_ok:
self.ready_event = asyncio.Event()
if not self.bt_thread.is_alive():
self.bt_thread.start()

def shutdown_ble_atexit(thread):
self.run = False
thread.join()

atexit.register(shutdown_ble_atexit, self.bt_thread)
try:
return await asyncio.wait_for(self.ready_event.wait(), timeout=5)
except asyncio.TimeoutError:
logger.error(">>> ERROR: Unable to connect with BLE device")
return False

def test_connection(self):
# call a function that will connect to the battery, send a command and retrieve the result.
Expand Down Expand Up @@ -201,33 +222,34 @@ def rx_callback(future: asyncio.Future, data: bytearray, sender, rx: bytearray):
return result

async def async_read_serial_data_llt(self, command):
try:
bt_task = asyncio.run_coroutine_threadsafe(
self.send_command(command), self.bt_loop
)
result = await asyncio.wait_for(asyncio.wrap_future(bt_task), 20)
return result
except asyncio.TimeoutError:
logger.error(">>> ERROR: No reply - returning")
return False
except BleakDBusError:
exception_type, exception_object, exception_traceback = sys.exc_info()
file = exception_traceback.tb_frame.f_code.co_filename
line = exception_traceback.tb_lineno
logger.error(
f"BleakDBusError: {repr(exception_object)} of type {exception_type} in {file} line #{line}"
)
self.reset_bluetooth()
return False
except Exception:
exception_type, exception_object, exception_traceback = sys.exc_info()
file = exception_traceback.tb_frame.f_code.co_filename
line = exception_traceback.tb_lineno
logger.error(
f"Exception occurred: {repr(exception_object)} of type {exception_type} in {file} line #{line}"
)
self.reset_bluetooth()
return False
if self.hci_uart_ok:
try:
bt_task = asyncio.run_coroutine_threadsafe(
self.send_command(command), self.bt_loop
)
result = await asyncio.wait_for(asyncio.wrap_future(bt_task), 20)
return result
except asyncio.TimeoutError:
logger.error(">>> ERROR: No reply - returning")
return False
except BleakDBusError:
exception_type, exception_object, exception_traceback = sys.exc_info()
file = exception_traceback.tb_frame.f_code.co_filename
line = exception_traceback.tb_lineno
logger.error(
f"BleakDBusError: {repr(exception_object)} of type {exception_type} in {file} line #{line}"
)
self.reset_bluetooth()
return False
except Exception:
exception_type, exception_object, exception_traceback = sys.exc_info()
file = exception_traceback.tb_frame.f_code.co_filename
line = exception_traceback.tb_lineno
logger.error(
f"Exception occurred: {repr(exception_object)} of type {exception_type} in {file} line #{line}"
)
self.reset_bluetooth()
return False

def read_serial_data_llt(self, command):
if not self.bt_loop:
Expand Down Expand Up @@ -268,6 +290,24 @@ def reset_bluetooth(self):
sleep(5)
sys.exit(1)

def reset_hci_uart(self):
logger.error("Reset of hci_uart stack... Reconnecting to: " + self.address)
self.run = False
os.system("pkill -f 'hciattach'")
sleep(0.5)
os.system("rmmod hci_uart")
os.system("rmmod btbcm")
os.system("modprobe hci_uart")
os.system("modprobe btbcm")
sys.exit(1)
# execfile = open("/tmp/dbus-blebattery-hciattach", "r")
# sleep(5)
# os.system(execfile.readline())
# os.system(execfile.readline())
# execfile.close()
# sleep(0.5)
# os.system("bluetoothctl connect " + self.address)
# self.run = True

if __name__ == "__main__":
bat = LltJbd_Ble("Foo", -1, sys.argv[1])
Expand Down

0 comments on commit 1383b29

Please sign in to comment.