Files
klangkiste/box2/wifi/manager.py
T
2026-01-13 19:44:02 +00:00

116 lines
3.7 KiB
Python

"""Logical WiFi manager (mock, no OS integration)."""
from __future__ import annotations
from dataclasses import dataclass
from typing import Any
from storage.box_storage import BoxStorage
from storage.secrets_store import SecretsStore
@dataclass
class WifiProfile:
ssid: str
password: str
priority: int = 0
class WifiManager:
def __init__(self, storage: BoxStorage, secrets: SecretsStore) -> None:
self._storage = storage
self._secrets = secrets
self._profiles: list[WifiProfile] = []
self._connected_ssid: str | None = None
self._load_state()
def scan_available_networks(self) -> list[str]:
return []
def add_profile(self, ssid: str, password: str, priority: int = 0) -> None:
self._profiles = [p for p in self._profiles if p.ssid != ssid]
self._profiles.append(WifiProfile(ssid=ssid, password=password, priority=priority))
self._save_profiles()
self._auto_connect()
def remove_profile(self, ssid: str) -> None:
self._profiles = [p for p in self._profiles if p.ssid != ssid]
if self._connected_ssid == ssid:
self._connected_ssid = None
self._save_profiles()
self._save_state()
self._auto_connect()
def reset(self) -> None:
self._profiles = []
self._connected_ssid = None
self._secrets.clear_wifi_secrets()
self._save_state()
def select_best_profile(self) -> WifiProfile | None:
if not self._profiles:
return None
return sorted(self._profiles, key=lambda p: (-p.priority, p.ssid))[0]
def connect(self, profile: WifiProfile) -> None:
self._connected_ssid = profile.ssid
self._save_state()
@property
def network_status(self) -> str:
if not self._profiles:
return "NOT_CONFIGURED"
if self._connected_ssid:
return "CONNECTED"
return "DISCONNECTED"
@property
def connected_ssid(self) -> str | None:
return self._connected_ssid
@property
def profiles_count(self) -> int:
return len(self._profiles)
def _auto_connect(self) -> None:
profile = self.select_best_profile()
if profile is not None:
self.connect(profile)
def _load_state(self) -> None:
secrets = self._secrets.load_secrets()
profiles_raw = secrets.get("wifi_profiles", [])
if isinstance(profiles_raw, list):
for entry in profiles_raw:
if not isinstance(entry, dict):
continue
ssid = entry.get("ssid")
password = entry.get("password")
priority = entry.get("priority", 0)
if isinstance(ssid, str) and isinstance(password, str):
if not isinstance(priority, int):
priority = 0
self._profiles.append(
WifiProfile(ssid=ssid, password=password, priority=priority)
)
state = self._storage.load_state()
wifi_state = state.get("wifi", {}) if isinstance(state.get("wifi"), dict) else {}
connected = wifi_state.get("connected_ssid")
if isinstance(connected, str):
self._connected_ssid = connected
self._auto_connect()
def _save_profiles(self) -> None:
secrets = self._secrets.load_secrets()
secrets["wifi_profiles"] = [
{"ssid": p.ssid, "password": p.password, "priority": p.priority}
for p in self._profiles
]
self._secrets.save_secrets(secrets)
def _save_state(self) -> None:
state = self._storage.load_state()
state["wifi"] = {"connected_ssid": self._connected_ssid}
self._storage.save_state(state)