diff --git a/picopy/wifi.py b/picopy/wifi.py index 5b062a4..2d2812b 100644 --- a/picopy/wifi.py +++ b/picopy/wifi.py @@ -5,7 +5,7 @@ import threading import time from picopy.config import ( - NM_AP_CON, NM_CLIENT_CON, WIFI_BOOT_WAIT, + NM_AP_CON, NM_CLIENT_CON, load_cfg, log ) @@ -81,6 +81,17 @@ def stop_ap(): nm('con', 'down', NM_AP_CON) +def _takeover_wifi_autoconnect(): + """Deaktiviert Autoconnect aller Fremd-WLAN-Profile, damit NM beim Boot PiCopy-WiFi bevorzugt.""" + r = nm('-t', '-f', 'NAME,TYPE', 'con', 'show') + for line in r.stdout.splitlines(): + parts = line.split(':', 1) + if len(parts) == 2 and parts[1] == '802-11-wireless' and parts[0] not in (NM_CLIENT_CON, NM_AP_CON): + nm('con', 'mod', parts[0], 'connection.autoconnect', 'no') + log.info(f'Autoconnect für Fremdprofil deaktiviert: {parts[0]}') + nm('con', 'mod', NM_CLIENT_CON, 'connection.autoconnect', 'yes') + + def connect_client_wifi(ssid, password): log.info(f'Verbinde mit WiFi: {ssid}') nm('con', 'delete', NM_CLIENT_CON) @@ -98,6 +109,7 @@ def connect_client_wifi(ssid, password): ok = r.returncode == 0 if ok: log.info(f'Verbunden mit {ssid}') + _takeover_wifi_autoconnect() else: log.error(f'WiFi-Verbindung fehlgeschlagen: {r.stderr.strip()}') return ok @@ -139,19 +151,49 @@ def update_wifi_state(): wifi_state.update(mode='disconnected', ssid='', ip='') +def _wait_for_nm(max_wait: int = 30) -> None: + """Wartet bis NetworkManager bereit ist, statt eine feste Zeit zu schlafen.""" + for i in range(max_wait): + r = nm('general', 'status') + if r.returncode == 0: + if i > 0: + log.info(f'NetworkManager bereit nach {i}s') + return + time.sleep(1) + log.warning('NetworkManager nach 30s noch nicht bereit') + + def wifi_monitor(): - log.info(f'WiFi-Monitor: warte {WIFI_BOOT_WAIT}s auf Verbindung...') - time.sleep(WIFI_BOOT_WAIT) + log.info('WiFi-Monitor: warte auf NetworkManager...') + _wait_for_nm() + + first_run = True while True: try: update_wifi_state() with wifi_lock: mode = wifi_state['mode'] + current_conn = wifi_state.get('ssid', '') + + cfg = load_cfg() + picopy_ssid = cfg.get('wifi_ssid', '') + + # Beim ersten Durchlauf: falls ein Fremdprofil (Imager) verbunden ist + # und PiCopy eine eigene SSID kennt → zu PiCopy-WiFi wechseln + if first_run and mode == 'client' and current_conn != NM_CLIENT_CON and picopy_ssid: + log.info(f'Fremdprofil aktiv ({current_conn}), wechsle zu PiCopy-WiFi ({picopy_ssid})...') + connected = connect_client_wifi(picopy_ssid, cfg.get('wifi_password', '')) + if connected: + time.sleep(5) + update_wifi_state() + with wifi_lock: + mode = wifi_state['mode'] + + first_run = False if mode == 'disconnected': - cfg = load_cfg() - ssid = cfg.get('wifi_ssid', '') + ssid = picopy_ssid pw = cfg.get('wifi_password', '') connected = False @@ -163,7 +205,7 @@ def wifi_monitor(): if not connected: ap_ssid = cfg.get('ap_ssid', 'PiCopy') - ap_pw = cfg.get('ap_password', 'PiCopy,') + ap_pw = cfg.get('ap_password', 'PiCopy123') if start_ap(ap_ssid, ap_pw): time.sleep(3) with wifi_lock: