ui(raylib): add thread-safe property access to WifiManagerWrapper (#35162)

* Add thread-safe property access to WifiManagerWrapper

* cleanup

* type-safe manager, always specify default

* import

---------

Co-authored-by: Cameron Clough <cameronjclough@gmail.com>
pull/35145/head^2
Dean Lee 2 weeks ago committed by GitHub
parent dde9c703f3
commit 908ea36126
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 27
      system/ui/lib/wifi_manager.py

@ -1,10 +1,12 @@
import asyncio import asyncio
import concurrent.futures
import threading import threading
import time import time
import uuid import uuid
from collections.abc import Callable from collections.abc import Callable
from dataclasses import dataclass from dataclasses import dataclass
from enum import IntEnum from enum import IntEnum
from typing import TypeVar
from dbus_next.aio import MessageBus from dbus_next.aio import MessageBus
from dbus_next import BusType, Variant, Message from dbus_next import BusType, Variant, Message
@ -12,6 +14,8 @@ from dbus_next.errors import DBusError
from dbus_next.constants import MessageType from dbus_next.constants import MessageType
from openpilot.common.swaglog import cloudlog from openpilot.common.swaglog import cloudlog
T = TypeVar("T")
# NetworkManager constants # NetworkManager constants
NM = "org.freedesktop.NetworkManager" NM = "org.freedesktop.NetworkManager"
NM_PATH = '/org/freedesktop/NetworkManager' NM_PATH = '/org/freedesktop/NetworkManager'
@ -437,11 +441,11 @@ class WifiManagerWrapper:
@property @property
def networks(self) -> list[NetworkInfo]: def networks(self) -> list[NetworkInfo]:
"""Get the current list of networks.""" """Get the current list of networks."""
return self._manager.networks if self._manager else [] return self._run_coroutine_sync(lambda manager: manager.networks.copy(), default=[])
def is_saved(self, ssid: str) -> bool: def is_saved(self, ssid: str) -> bool:
"""Check if a network is saved.""" """Check if a network is saved."""
return self._manager.is_saved(ssid) if self._manager else False return self._run_coroutine_sync(lambda manager: manager.is_saved(ssid), default=False)
def connect(self): def connect(self):
"""Connect to DBus and start Wi-Fi scanning.""" """Connect to DBus and start Wi-Fi scanning."""
@ -479,3 +483,22 @@ class WifiManagerWrapper:
cloudlog.error("WifiManager thread is not running") cloudlog.error("WifiManager thread is not running")
return return
asyncio.run_coroutine_threadsafe(coro, self._loop) asyncio.run_coroutine_threadsafe(coro, self._loop)
def _run_coroutine_sync(self, func: Callable[[WifiManager], T], default: T) -> T:
"""Run a function synchronously in the async thread."""
if not self._running or not self._loop or not self._manager:
return default
future = concurrent.futures.Future[T]()
def wrapper(manager: WifiManager) -> None:
try:
future.set_result(func(manager))
except Exception as e:
future.set_exception(e)
try:
self._loop.call_soon_threadsafe(wrapper, self._manager)
return future.result(timeout=1.0)
except Exception as e:
cloudlog.error(f"WifiManagerWrapper property access failed: {e}")
return default

Loading…
Cancel
Save