From b36ff9dcb97f1086966093cf51f779a309e56959 Mon Sep 17 00:00:00 2001 From: Thomas Farstrike Date: Wed, 25 Mar 2026 15:45:48 +0100 Subject: [PATCH] WifiService: disable hotspot when connecting to access point --- CHANGELOG.md | 2 +- .../lib/mpos/net/wifi_service.py | 8 +- tests/test_graphical_hotspot_then_station.py | 82 ++++++++++++++++++- 3 files changed, 86 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ffb9945..5bcea4e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ Frameworks: - Websocket library: renamed to uaiowebsocket to avoid conflicts OS: -- ESP32 boards: bundle WebREPL (disabled by default, password protected, can be enabled in Settings) +- ESP32 boards: bundle WebREPL (not started by default) to offer remote MicroPython shell over the network, accessible through webbrowser - New board support: LilyGo T-Display-S3 (physical and emulated by QEMU) - New board support: LilyGo T-Watch S3 Plus - New board support: M5Stack Fire diff --git a/internal_filesystem/lib/mpos/net/wifi_service.py b/internal_filesystem/lib/mpos/net/wifi_service.py index 21206e50..8cbf1fa0 100644 --- a/internal_filesystem/lib/mpos/net/wifi_service.py +++ b/internal_filesystem/lib/mpos/net/wifi_service.py @@ -257,6 +257,10 @@ class WifiService: time_mod = time_module if time_module else time + if WifiService.is_hotspot_enabled(network_module=network_module): + WifiService._needs_hotspot_restore = False + WifiService.disable_hotspot(network_module=network_module) + # Desktop mode - simulate successful connection if WifiService._is_desktop_mode(network_module): print("WifiService: Desktop mode, simulating connection...") @@ -268,10 +272,6 @@ class WifiService: net = WifiService._get_network_module(network_module) try: - if WifiService.is_hotspot_enabled(network_module=network_module): - WifiService._needs_hotspot_restore = True - WifiService.disable_hotspot(network_module=network_module) - wlan = WifiService._get_sta_wlan(net) wlan.connect(ssid, password) diff --git a/tests/test_graphical_hotspot_then_station.py b/tests/test_graphical_hotspot_then_station.py index 4fa421c4..c5360512 100644 --- a/tests/test_graphical_hotspot_then_station.py +++ b/tests/test_graphical_hotspot_then_station.py @@ -10,14 +10,56 @@ Usage: """ import unittest +import time import lvgl as lv import mpos.ui -from mpos import AppManager, WifiService, wait_for_render, click_button, print_screen_labels +from mpos import ( + AppManager, + WifiService, + wait_for_render, + click_button, + print_screen_labels, + get_widget_coords, + simulate_click, +) class TestGraphicalHotspotThenStation(unittest.TestCase): """Test hotspot start flow via the hotspot settings app.""" + def _find_first_list_item(self, screen): + def find_list(node): + try: + if node.__class__.__name__ == "list": + return node + except Exception: + pass + try: + if hasattr(node, "add_button") and hasattr(node, "get_child_count"): + return node + except Exception: + pass + try: + child_count = node.get_child_count() + except Exception: + child_count = 0 + for i in range(child_count): + child = node.get_child(i) + found = find_list(child) + if found: + return found + return None + + wifi_list = find_list(screen) + if wifi_list is None: + return None + try: + if wifi_list.get_child_count() < 1: + return None + return wifi_list.get_child(0) + except Exception: + return None + def tearDown(self): """Clean up after each test method.""" try: @@ -64,6 +106,44 @@ class TestGraphicalHotspotThenStation(unittest.TestCase): "Hotspot should be enabled after pressing Start", ) + result = AppManager.start_app("com.micropythonos.settings.wifi") + self.assertTrue(result, "Failed to start WiFi settings app") + wait_for_render(iterations=20) + + screen = lv.screen_active() + print("\nWiFi screen labels (before scan wait):") + print_screen_labels(screen) + + print("\nWaiting 10 seconds for WiFi scan to finish...") + time.sleep(10) + wait_for_render(iterations=20) + + screen = lv.screen_active() + print("\nWiFi screen labels (after scan wait):") + print_screen_labels(screen) + + first_item = self._find_first_list_item(screen) + self.assertIsNotNone(first_item, "Could not find first WiFi access point") + + coords = get_widget_coords(first_item) + if coords: + print(f"Clicking first WiFi access point at ({coords['center_x']}, {coords['center_y']})") + first_item.send_event(lv.EVENT.CLICKED, None) + else: + first_item.send_event(lv.EVENT.CLICKED, None) + wait_for_render(iterations=40) + + self.assertTrue( + click_button("Connect"), + "Could not find Connect button in WiFi edit screen", + ) + wait_for_render(iterations=40) + + self.assertFalse( + WifiService.is_hotspot_enabled(), + "Hotspot should be disabled after connecting to a WiFi access point", + ) + print("\n=== Hotspot start-flow test completed ===")