diff --git a/backend/Pipfile b/backend/Pipfile index d8546f3d..32b9b99d 100644 --- a/backend/Pipfile +++ b/backend/Pipfile @@ -8,6 +8,7 @@ websockets = "*" requests = "*" pinecil = "*" typing_extensions = "*" +rich = "*" [dev-packages] black = "*" diff --git a/backend/bluetooth_check.py b/backend/bluetooth_check.py new file mode 100644 index 00000000..2db49697 --- /dev/null +++ b/backend/bluetooth_check.py @@ -0,0 +1,65 @@ +import subprocess + + +def run_command(command: str) -> tuple[bool, str]: + try: + result = subprocess.run( + command, + shell=True, + check=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + ) + return True, result.stdout.strip() + except subprocess.CalledProcessError as e: + return False, e.stderr.strip() + + +class ServiceCheck: + def __init__(self, name: str, command: str, recommend: str = ""): + self.command = command + self.name = name + self.recommend = recommend + self.success = False + + def run(self) -> bool: + self.success, _ = run_command(self.command) + return self.success + + +def run_checks() -> tuple[bool, list[str]]: + checks = [ + ServiceCheck("BlueZ", "bluetoothd -v", recommend="Install BlueZ"), + ServiceCheck( + "bluetooth.service active", + "systemctl status bluetooth.service", + recommend="Install/Start bluetooth.service", + ), + ServiceCheck( + "D-Bus configuration file for Bluetooth", + "test -f /etc/dbus-1/system.d/bluetooth.conf || test -f /usr/share/dbus-1/system.d/bluetooth.conf || test -f /var/lib/dbus-1/system.d/bluetooth.conf", + recommend="Install D-Bus configuration file for Bluetooth", + ), + ] + all_passed = all([c.run() for c in checks]) + return all_passed, [ + f"{c.name} check failed. {c.recommend}" for c in checks if not c.success + ] + + +def main(): + all_passed, errors = run_checks() + if not all_passed: + print("Bluetooth check failed:") + print("\n".join(errors)) + return + success, output = run_command("journalctl -u bluetooth.service -n 10") + if success: + print("Last 10 lines of bluetooth.service logs:\n" + output) + else: + print("Failed to retrieve bluetooth.service logs.") + + +if __name__ == "__main__": + main() diff --git a/backend/main.py b/backend/main.py index bb02f854..a65be3d5 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1,10 +1,13 @@ import asyncio import os +import sys from pinecil_monitor import PinecilMonitor, PinecilFinder from ws_server import CommandProcessor, WebSocketHandler from version_checker import VersionChecker import logging from io_utils import parse_cmd_args, get_resource_path +from bluetooth_check import run_checks as run_bluetooth_checks +from rich.logging import RichHandler LOG_LEVEL = os.environ.get("LOG_LEVEL", "INFO").upper() timestamp_format = "%H:%M:%S" @@ -12,6 +15,7 @@ level=LOG_LEVEL, format="%(asctime)s.%(msecs)03d::%(levelname)s::%(message)s", datefmt=timestamp_format, + handlers=[RichHandler(rich_tracebacks=True)], ) DEFAULT_HOST = "0.0.0.0" @@ -22,7 +26,13 @@ async def main(stop_event=asyncio.Event()): host, port = parse_cmd_args(DEFAULT_HOST, DEFAULT_PORT) if not host or not port: return - + if sys.platform == "linux": + bt_ok, bt_errors = run_bluetooth_checks() + if not bt_ok: + logging.warning( + "Bluetooth check failed. Application may not work as expected." + ) + logging.warning("\n" + "\n".join(bt_errors)) pinesam_url = "https://api.github.com/repos/builder555/PineSAM/releases/latest" ironos_url = "https://api.github.com/repos/Ralim/IronOS/releases/latest" app_version_manager = VersionChecker( diff --git a/docs/img/full_settings.png b/docs/img/full_settings.png index da7fb77c..6f52a180 100644 Binary files a/docs/img/full_settings.png and b/docs/img/full_settings.png differ diff --git a/version.txt b/version.txt index ccbccc3d..b1b25a5f 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -2.2.0 +2.2.2