Skip to content

Commit 73cba70

Browse files
WiFi app: delegate to WiFiService where possible
1 parent 59bbcfb commit 73cba70

File tree

2 files changed

+203
-144
lines changed

2 files changed

+203
-144
lines changed

internal_filesystem/builtin/apps/com.micropythonos.wifi/assets/wifi.py

Lines changed: 90 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,28 @@
1-
import os
21
import time
32
import lvgl as lv
43
import _thread
54

65
from mpos.apps import Activity, Intent
76
from mpos.ui.keyboard import MposKeyboard
87

9-
import mpos.config
8+
import mpos.apps
109
from mpos.net.wifi_service import WifiService
1110

11+
1212
class WiFi(Activity):
13+
"""
14+
WiFi settings app for MicroPythonOS.
15+
16+
This is a pure UI layer - all WiFi operations are delegated to WifiService.
17+
"""
1318

14-
prefs = None
15-
saved_access_points={}
1619
last_tried_ssid = ""
1720
last_tried_result = ""
18-
have_network = True
19-
try:
20-
import network
21-
except Exception as e:
22-
have_network = False
2321

2422
scan_button_scan_text = "Rescan"
2523
scan_button_scanning_text = "Scanning..."
2624

27-
scanned_ssids=[]
25+
scanned_ssids = []
2826
busy_scanning = False
2927
busy_connecting = False
3028
error_timer = None
@@ -39,25 +37,25 @@ def onCreate(self):
3937
print("wifi.py onCreate")
4038
main_screen = lv.obj()
4139
main_screen.set_style_pad_all(15, 0)
42-
self.aplist=lv.list(main_screen)
43-
self.aplist.set_size(lv.pct(100),lv.pct(75))
44-
self.aplist.align(lv.ALIGN.TOP_MID,0,0)
45-
self.error_label=lv.label(main_screen)
40+
self.aplist = lv.list(main_screen)
41+
self.aplist.set_size(lv.pct(100), lv.pct(75))
42+
self.aplist.align(lv.ALIGN.TOP_MID, 0, 0)
43+
self.error_label = lv.label(main_screen)
4644
self.error_label.set_text("THIS IS ERROR TEXT THAT WILL BE SET LATER")
47-
self.error_label.align_to(self.aplist, lv.ALIGN.OUT_BOTTOM_MID,0,0)
45+
self.error_label.align_to(self.aplist, lv.ALIGN.OUT_BOTTOM_MID, 0, 0)
4846
self.error_label.add_flag(lv.obj.FLAG.HIDDEN)
49-
self.add_network_button=lv.button(main_screen)
50-
self.add_network_button.set_size(lv.SIZE_CONTENT,lv.pct(15))
51-
self.add_network_button.align(lv.ALIGN.BOTTOM_LEFT,0,0)
52-
self.add_network_button.add_event_cb(self.add_network_callback,lv.EVENT.CLICKED,None)
53-
self.add_network_button_label=lv.label(self.add_network_button)
47+
self.add_network_button = lv.button(main_screen)
48+
self.add_network_button.set_size(lv.SIZE_CONTENT, lv.pct(15))
49+
self.add_network_button.align(lv.ALIGN.BOTTOM_LEFT, 0, 0)
50+
self.add_network_button.add_event_cb(self.add_network_callback, lv.EVENT.CLICKED, None)
51+
self.add_network_button_label = lv.label(self.add_network_button)
5452
self.add_network_button_label.set_text("Add network")
5553
self.add_network_button_label.center()
56-
self.scan_button=lv.button(main_screen)
57-
self.scan_button.set_size(lv.SIZE_CONTENT,lv.pct(15))
58-
self.scan_button.align(lv.ALIGN.BOTTOM_RIGHT,0,0)
59-
self.scan_button.add_event_cb(self.scan_cb,lv.EVENT.CLICKED,None)
60-
self.scan_button_label=lv.label(self.scan_button)
54+
self.scan_button = lv.button(main_screen)
55+
self.scan_button.set_size(lv.SIZE_CONTENT, lv.pct(15))
56+
self.scan_button.align(lv.ALIGN.BOTTOM_RIGHT, 0, 0)
57+
self.scan_button.add_event_cb(self.scan_cb, lv.EVENT.CLICKED, None)
58+
self.scan_button_label = lv.label(self.scan_button)
6159
self.scan_button_label.set_text(self.scan_button_scan_text)
6260
self.scan_button_label.center()
6361
self.setContentView(main_screen)
@@ -66,11 +64,9 @@ def onResume(self, screen):
6664
print("wifi.py onResume")
6765
super().onResume(screen)
6866

69-
if not self.prefs:
70-
self.prefs = mpos.config.SharedPreferences("com.micropythonos.system.wifiservice")
67+
# Ensure WifiService has loaded saved networks
68+
WifiService.get_saved_networks()
7169

72-
self.saved_access_points = self.prefs.get_dict("access_points")
73-
print(f"loaded access points from preferences: {self.saved_access_points}")
7470
if len(self.scanned_ssids) == 0:
7571
if WifiService.wifi_busy == False:
7672
WifiService.wifi_busy = True
@@ -83,34 +79,24 @@ def show_error(self, message):
8379
print(f"show_error: Displaying error: {message}")
8480
self.update_ui_threadsafe_if_foreground(self.error_label.set_text, message)
8581
self.update_ui_threadsafe_if_foreground(self.error_label.remove_flag, lv.obj.FLAG.HIDDEN)
86-
self.error_timer = lv.timer_create(self.hide_error,5000,None)
82+
self.error_timer = lv.timer_create(self.hide_error, 5000, None)
8783
self.error_timer.set_repeat_count(1)
8884

8985
def hide_error(self, timer):
90-
self.update_ui_threadsafe_if_foreground(self.error_label.add_flag,lv.obj.FLAG.HIDDEN)
86+
self.update_ui_threadsafe_if_foreground(self.error_label.add_flag, lv.obj.FLAG.HIDDEN)
9187

9288
def scan_networks_thread(self):
9389
print("scan_networks: Scanning for Wi-Fi networks")
94-
if self.have_network:
95-
wlan=network.WLAN(network.STA_IF)
96-
if not wlan.isconnected(): # restart WiFi hardware in case it's in a bad state
97-
wlan.active(False)
98-
wlan.active(True)
9990
try:
100-
if self.have_network:
101-
networks = wlan.scan()
102-
self.scanned_ssids = list(set(n[0].decode() for n in networks))
103-
else:
104-
time.sleep(1)
105-
self.scanned_ssids = ["Home WiFi", "Pretty Fly for a Wi Fi", "Winternet is coming", "The Promised LAN"]
91+
self.scanned_ssids = WifiService.scan_networks()
10692
print(f"scan_networks: Found networks: {self.scanned_ssids}")
10793
except Exception as e:
10894
print(f"scan_networks: Scan failed: {e}")
10995
self.show_error("Wi-Fi scan failed")
11096
# scan done:
11197
self.busy_scanning = False
11298
WifiService.wifi_busy = False
113-
self.update_ui_threadsafe_if_foreground(self.scan_button_label.set_text,self.scan_button_scan_text)
99+
self.update_ui_threadsafe_if_foreground(self.scan_button_label.set_text, self.scan_button_scan_text)
114100
self.update_ui_threadsafe_if_foreground(self.scan_button.remove_state, lv.STATE.DISABLED)
115101
self.update_ui_threadsafe_if_foreground(self.refresh_list)
116102

@@ -126,28 +112,35 @@ def start_scan_networks(self):
126112

127113
def refresh_list(self):
128114
print("refresh_list: Clearing current list")
129-
self.aplist.clean() # this causes an issue with lost taps if an ssid is clicked that has been removed
115+
self.aplist.clean() # this causes an issue with lost taps if an ssid is clicked that has been removed
130116
print("refresh_list: Populating list with scanned networks")
131-
for ssid in set(self.scanned_ssids + list(ssid for ssid in self.saved_access_points)):
117+
118+
# Combine scanned SSIDs with saved networks
119+
saved_networks = WifiService.get_saved_networks()
120+
all_ssids = set(self.scanned_ssids + saved_networks)
121+
122+
for ssid in all_ssids:
132123
if len(ssid) < 1 or len(ssid) > 32:
133124
print(f"Skipping too short or long SSID: {ssid}")
134125
continue
135126
print(f"refresh_list: Adding SSID: {ssid}")
136-
button=self.aplist.add_button(None,ssid)
137-
button.add_event_cb(lambda e, s=ssid: self.select_ssid_cb(s),lv.EVENT.CLICKED,None)
127+
button = self.aplist.add_button(None, ssid)
128+
button.add_event_cb(lambda e, s=ssid: self.select_ssid_cb(s), lv.EVENT.CLICKED, None)
129+
130+
# Determine status
138131
status = ""
139-
if self.have_network:
140-
wlan=network.WLAN(network.STA_IF)
141-
if wlan.isconnected() and wlan.config('essid')==ssid:
142-
status="connected"
143-
if status != "connected":
144-
if self.last_tried_ssid == ssid: # implies not connected because not wlan.isconnected()
145-
status = self.last_tried_result
146-
elif ssid in self.saved_access_points:
147-
status="saved"
148-
label=lv.label(button)
132+
current_ssid = WifiService.get_current_ssid()
133+
if current_ssid == ssid:
134+
status = "connected"
135+
elif self.last_tried_ssid == ssid:
136+
# Show last connection attempt result
137+
status = self.last_tried_result
138+
elif ssid in saved_networks:
139+
status = "saved"
140+
141+
label = lv.label(button)
149142
label.set_text(status)
150-
label.align(lv.ALIGN.RIGHT_MID,0,0)
143+
label.align(lv.ALIGN.RIGHT_MID, 0, 0)
151144

152145
def add_network_callback(self, event):
153146
print(f"add_network_callback clicked")
@@ -159,36 +152,28 @@ def scan_cb(self, event):
159152
print("scan_cb: Scan button clicked, refreshing list")
160153
self.start_scan_networks()
161154

162-
def select_ssid_cb(self,ssid):
155+
def select_ssid_cb(self, ssid):
163156
print(f"select_ssid_cb: SSID selected: {ssid}")
164157
intent = Intent(activity_class=EditNetwork)
165158
intent.putExtra("selected_ssid", ssid)
166-
intent.putExtra("known_password", self.findSavedPassword(ssid))
159+
intent.putExtra("known_password", WifiService.get_network_password(ssid))
167160
self.startActivityForResult(intent, self.edit_network_result_callback)
168-
161+
169162
def edit_network_result_callback(self, result):
170163
print(f"EditNetwork finished, result: {result}")
171164
if result.get("result_code") is True:
172165
data = result.get("data")
173166
if data:
174167
ssid = data.get("ssid")
175-
editor = self.prefs.edit()
176168
forget = data.get("forget")
177169
if forget:
178-
try:
179-
del self.saved_access_points[ssid]
180-
editor.put_dict("access_points", self.saved_access_points)
181-
editor.commit()
182-
self.refresh_list()
183-
except Exception as e:
184-
print(f"WARNING: could not forget access point, maybe it wasn't remembered in the first place: {e}")
185-
else: # save or update
170+
WifiService.forget_network(ssid)
171+
self.refresh_list()
172+
else:
173+
# Save or update the network
186174
password = data.get("password")
187175
hidden = data.get("hidden")
188-
self.setPassword(ssid, password, hidden)
189-
editor.put_dict("access_points", self.saved_access_points)
190-
editor.commit()
191-
print(f"access points: {self.saved_access_points}")
176+
WifiService.save_network(ssid, password, hidden)
192177
self.start_attempt_connecting(ssid, password)
193178

194179
def start_attempt_connecting(self, ssid, password):
@@ -200,73 +185,47 @@ def start_attempt_connecting(self, ssid, password):
200185
else:
201186
self.busy_connecting = True
202187
_thread.stack_size(mpos.apps.good_stack_size())
203-
_thread.start_new_thread(self.attempt_connecting_thread, (ssid,password))
188+
_thread.start_new_thread(self.attempt_connecting_thread, (ssid, password))
204189

205190
def attempt_connecting_thread(self, ssid, password):
206-
print(f"attempt_connecting_thread: Attempting to connect to SSID '{ssid}' with password '{password}'")
207-
result="connected"
191+
print(f"attempt_connecting_thread: Attempting to connect to SSID '{ssid}'")
192+
result = "connected"
208193
try:
209-
if self.have_network:
210-
wlan=network.WLAN(network.STA_IF)
211-
wlan.disconnect()
212-
wlan.connect(ssid,password)
213-
for i in range(10):
214-
if wlan.isconnected():
215-
print(f"attempt_connecting: Connected to {ssid} after {i+1} seconds")
216-
break
217-
print(f"attempt_connecting: Waiting for connection, attempt {i+1}/10")
218-
time.sleep(1)
219-
if not wlan.isconnected():
220-
result="timeout"
194+
if WifiService.attempt_connecting(ssid, password):
195+
result = "connected"
221196
else:
222-
print("Warning: not trying to connect because not self.have_network, just waiting a bit...")
223-
time.sleep(5)
197+
result = "timeout"
224198
except Exception as e:
225199
print(f"attempt_connecting: Connection error: {e}")
226-
result=f"{e}"
227-
self.show_error("Connecting to {ssid} failed!")
200+
result = f"{e}"
201+
self.show_error(f"Connecting to {ssid} failed!")
202+
228203
print(f"Connecting to {ssid} got result: {result}")
229204
self.last_tried_ssid = ssid
230205
self.last_tried_result = result
231-
# also do a time sync, otherwise some apps (Nostr Wallet Connect) won't work:
232-
if self.have_network and wlan.isconnected():
233-
mpos.time.sync_time()
234-
self.busy_connecting=False
206+
207+
# Note: Time sync is handled by WifiService.attempt_connecting()
208+
209+
self.busy_connecting = False
235210
self.update_ui_threadsafe_if_foreground(self.scan_button_label.set_text, self.scan_button_scan_text)
236211
self.update_ui_threadsafe_if_foreground(self.scan_button.remove_state, lv.STATE.DISABLED)
237212
self.update_ui_threadsafe_if_foreground(self.refresh_list)
238213

239-
def findSavedPassword(self, ssid):
240-
ap = self.saved_access_points.get(ssid)
241-
if ap:
242-
return ap.get("password")
243-
return None
244-
245-
def setPassword(self, ssid, password, hidden=False):
246-
ap = self.saved_access_points.get(ssid)
247-
if ap:
248-
ap["password"] = password
249-
if hidden is True:
250-
ap["hidden"] = True
251-
return
252-
# if not found, then add it:
253-
self.saved_access_points[ssid] = { "password": password, "hidden": hidden }
254-
255214

256215
class EditNetwork(Activity):
257216

258217
selected_ssid = None
259218

260219
# Widgets:
261220
ssid_ta = None
262-
password_ta=None
221+
password_ta = None
263222
hidden_cb = None
264-
keyboard=None
265-
connect_button=None
266-
cancel_button=None
223+
keyboard = None
224+
connect_button = None
225+
cancel_button = None
267226

268227
def onCreate(self):
269-
password_page=lv.obj()
228+
password_page = lv.obj()
270229
password_page.set_style_pad_all(0, lv.PART.MAIN)
271230
password_page.set_flex_flow(lv.FLEX_FLOW.COLUMN)
272231
self.selected_ssid = self.getIntent().extras.get("selected_ssid")
@@ -275,31 +234,31 @@ def onCreate(self):
275234
# SSID:
276235
if self.selected_ssid is None:
277236
print("No ssid selected, the user should fill it out.")
278-
label=lv.label(password_page)
237+
label = lv.label(password_page)
279238
label.set_text(f"Network name:")
280-
self.ssid_ta=lv.textarea(password_page)
239+
self.ssid_ta = lv.textarea(password_page)
281240
self.ssid_ta.set_width(lv.pct(90))
282241
self.ssid_ta.set_style_margin_left(5, lv.PART.MAIN)
283242
self.ssid_ta.set_one_line(True)
284243
self.ssid_ta.set_placeholder_text("Enter the SSID")
285-
self.keyboard=MposKeyboard(password_page)
244+
self.keyboard = MposKeyboard(password_page)
286245
self.keyboard.set_textarea(self.ssid_ta)
287246
self.keyboard.add_flag(lv.obj.FLAG.HIDDEN)
288-
247+
289248
# Password:
290-
label=lv.label(password_page)
249+
label = lv.label(password_page)
291250
if self.selected_ssid is None:
292251
label.set_text("Password:")
293252
else:
294253
label.set_text(f"Password for '{self.selected_ssid}':")
295-
self.password_ta=lv.textarea(password_page)
254+
self.password_ta = lv.textarea(password_page)
296255
self.password_ta.set_width(lv.pct(90))
297256
self.password_ta.set_style_margin_left(5, lv.PART.MAIN)
298257
self.password_ta.set_one_line(True)
299258
if known_password:
300259
self.password_ta.set_text(known_password)
301260
self.password_ta.set_placeholder_text("Password")
302-
self.keyboard=MposKeyboard(password_page)
261+
self.keyboard = MposKeyboard(password_page)
303262
self.keyboard.set_textarea(self.password_ta)
304263
self.keyboard.add_flag(lv.obj.FLAG.HIDDEN)
305264

@@ -316,24 +275,24 @@ def onCreate(self):
316275
buttons.set_style_border_width(0, lv.PART.MAIN)
317276
# Delete button
318277
if self.selected_ssid:
319-
self.forget_button=lv.button(buttons)
278+
self.forget_button = lv.button(buttons)
320279
self.forget_button.align(lv.ALIGN.LEFT_MID, 0, 0)
321280
self.forget_button.add_event_cb(self.forget_cb, lv.EVENT.CLICKED, None)
322-
label=lv.label(self.forget_button)
281+
label = lv.label(self.forget_button)
323282
label.set_text("Forget")
324283
label.center()
325284
# Close button
326-
self.cancel_button=lv.button(buttons)
285+
self.cancel_button = lv.button(buttons)
327286
self.cancel_button.center()
328287
self.cancel_button.add_event_cb(lambda *args: self.finish(), lv.EVENT.CLICKED, None)
329-
label=lv.label(self.cancel_button)
288+
label = lv.label(self.cancel_button)
330289
label.set_text("Close")
331290
label.center()
332291
# Connect button
333292
self.connect_button = lv.button(buttons)
334293
self.connect_button.align(lv.ALIGN.RIGHT_MID, 0, 0)
335-
self.connect_button.add_event_cb(self.connect_cb,lv.EVENT.CLICKED,None)
336-
label=lv.label(self.connect_button)
294+
self.connect_button.add_event_cb(self.connect_cb, lv.EVENT.CLICKED, None)
295+
label = lv.label(self.connect_button)
337296
label.set_text("Connect")
338297
label.center()
339298

0 commit comments

Comments
 (0)