@@ -33,11 +33,12 @@ def __init__(self):
3333 self .current_state = UpdateState .IDLE
3434 self .connectivity_manager = None # Will be initialized in onStart
3535
36+ # This function gets called from both the main thread as the update_with_lvgl() thread
3637 def set_state (self , new_state ):
3738 """Change app state and update UI accordingly."""
3839 print (f"OSUpdate: state change { self .current_state } -> { new_state } " )
3940 self .current_state = new_state
40- self ._update_ui_for_state ()
41+ self .update_ui_threadsafe_if_foreground ( self . _update_ui_for_state ) # Since called from both threads, be threadsafe
4142
4243 def onCreate (self ):
4344 self .main_screen = lv .obj ()
@@ -78,19 +79,6 @@ def onCreate(self):
7879 self .status_label .align_to (self .force_update , lv .ALIGN .OUT_BOTTOM_LEFT , 0 , mpos .ui .pct_of_display_height (5 ))
7980 self .setContentView (self .main_screen )
8081
81- def onStart (self , screen ):
82- # Get connectivity manager instance
83- self .connectivity_manager = ConnectivityManager .get ()
84-
85- # Check if online and either start update check or wait for network
86- if self .connectivity_manager .is_online ():
87- self .set_state (UpdateState .CHECKING_UPDATE )
88- print ("OSUpdate: Online, checking for updates..." )
89- self .show_update_info ()
90- else :
91- self .set_state (UpdateState .WAITING_WIFI )
92- print ("OSUpdate: Offline, waiting for network..." )
93-
9482 def _update_ui_for_state (self ):
9583 """Update UI elements based on current state."""
9684 if self .current_state == UpdateState .WAITING_WIFI :
@@ -112,10 +100,11 @@ def _update_ui_for_state(self):
112100 def onResume (self , screen ):
113101 """Register for connectivity callbacks when app resumes."""
114102 super ().onResume (screen )
115- if self .connectivity_manager :
116- self .connectivity_manager .register_callback (self .network_changed )
117- # Check current state
118- self .network_changed (self .connectivity_manager .is_online ())
103+ # Get connectivity manager instance
104+ self .connectivity_manager = ConnectivityManager .get ()
105+ self .connectivity_manager .register_callback (self .network_changed )
106+ # Start, based on network state:
107+ self .network_changed (self .connectivity_manager .is_online ())
119108
120109 def onPause (self , screen ):
121110 """Unregister connectivity callbacks when app pauses."""
@@ -138,17 +127,13 @@ def network_changed(self, online):
138127 pass
139128 elif self .current_state == UpdateState .CHECKING_UPDATE :
140129 # Was checking for updates when network dropped
141- self .update_ui_threadsafe_if_foreground (
142- self .set_state , UpdateState .WAITING_WIFI
143- )
130+ self .set_state (UpdateState .WAITING_WIFI )
144131 else :
145132 # Went online
146- if self .current_state == UpdateState .WAITING_WIFI :
133+ if self .current_state == UpdateState .IDLE or self . current_state == UpdateState . WAITING_WIFI :
147134 # Was waiting for network, now can check for updates
148- self .update_ui_threadsafe_if_foreground (
149- self .set_state , UpdateState .CHECKING_UPDATE
150- )
151- self .show_update_info ()
135+ self .set_state (UpdateState .CHECKING_UPDATE )
136+ self .schedule_show_update_info ()
152137 elif self .current_state == UpdateState .DOWNLOAD_PAUSED :
153138 # Download was paused, will auto-resume in download thread
154139 pass
@@ -191,8 +176,12 @@ def _get_user_friendly_error(self, error):
191176 else :
192177 return f"An error occurred:\n { str (error )} \n \n Please try again."
193178
194- def show_update_info (self ):
195- self .status_label .set_text ("Checking for OS updates..." )
179+ # Show update info with a delay, to ensure ordering of multiple lv.async_call()
180+ def schedule_show_update_info (self ):
181+ timer = lv .timer_create (self .show_update_info , 150 , None )
182+ timer .set_repeat_count (1 )
183+
184+ def show_update_info (self , timer = None ):
196185 hwid = mpos .info .get_hardware_id ()
197186
198187 try :
@@ -212,6 +201,7 @@ def show_update_info(self):
212201 self .set_state (UpdateState .ERROR )
213202 self .status_label .set_text (self ._get_user_friendly_error (e ))
214203 except Exception as e :
204+ print (f"show_update_info got exception: { e } " )
215205 # Unexpected error
216206 self .set_state (UpdateState .ERROR )
217207 self .status_label .set_text (self ._get_user_friendly_error (e ))
@@ -220,9 +210,7 @@ def handle_update_info(self, version, download_url, changelog):
220210 self .download_update_url = download_url
221211
222212 # Use UpdateChecker to determine if update is available
223- is_newer = self .update_checker .is_update_available (
224- version , mpos .info .CURRENT_OS_VERSION
225- )
213+ is_newer = self .update_checker .is_update_available (version , mpos .info .CURRENT_OS_VERSION )
226214
227215 if is_newer :
228216 label = "New"
@@ -270,7 +258,7 @@ def check_again_click(self):
270258 print ("OSUpdate: Check Again button clicked" )
271259 self .check_again_button .add_flag (lv .obj .FLAG .HIDDEN )
272260 self .set_state (UpdateState .CHECKING_UPDATE )
273- self .show_update_info ()
261+ self .schedule_show_update_info ()
274262
275263 def progress_callback (self , percent ):
276264 print (f"OTA Update: { percent :.1f} %" )
@@ -296,12 +284,9 @@ def update_with_lvgl(self, url):
296284
297285 if result ['success' ]:
298286 # Update succeeded - set boot partition and restart
299- self .update_ui_threadsafe_if_foreground (
300- self .status_label .set_text ,
301- "Update finished! Restarting..."
302- )
287+ self .update_ui_threadsafe_if_foreground (self .status_label .set_text ,"Update finished! Restarting..." )
303288 # Small delay to show the message
304- time .sleep_ms (500 )
289+ time .sleep_ms (2000 )
305290 self .update_downloader .set_boot_partition_and_restart ()
306291 return
307292
@@ -312,9 +297,7 @@ def update_with_lvgl(self, url):
312297 percent = (bytes_written / total_size * 100 ) if total_size > 0 else 0
313298
314299 print (f"OSUpdate: Download paused at { percent :.1f} % ({ bytes_written } /{ total_size } bytes)" )
315- self .update_ui_threadsafe_if_foreground (
316- self .set_state , UpdateState .DOWNLOAD_PAUSED
317- )
300+ self .set_state (UpdateState .DOWNLOAD_PAUSED )
318301
319302 # Wait for wifi to return
320303 # ConnectivityManager will notify us via callback when network returns
@@ -326,9 +309,7 @@ def update_with_lvgl(self, url):
326309 while elapsed < max_wait and self .has_foreground ():
327310 if self .connectivity_manager .is_online ():
328311 print ("OSUpdate: Network reconnected, resuming download" )
329- self .update_ui_threadsafe_if_foreground (
330- self .set_state , UpdateState .DOWNLOADING
331- )
312+ self .set_state (UpdateState .DOWNLOADING )
332313 break # Exit wait loop and retry download
333314
334315 time .sleep (check_interval )
@@ -338,12 +319,8 @@ def update_with_lvgl(self, url):
338319 # Timeout waiting for network
339320 msg = f"Network timeout during download.\n { bytes_written } /{ total_size } bytes written.\n Press 'Update OS' to retry."
340321 self .update_ui_threadsafe_if_foreground (self .status_label .set_text , msg )
341- self .update_ui_threadsafe_if_foreground (
342- self .install_button .remove_state , lv .STATE .DISABLED
343- )
344- self .update_ui_threadsafe_if_foreground (
345- self .set_state , UpdateState .ERROR
346- )
322+ self .update_ui_threadsafe_if_foreground (self .install_button .remove_state , lv .STATE .DISABLED )
323+ self .set_state (UpdateState .ERROR )
347324 return
348325
349326 # If we're here, network is back - continue to next iteration to resume
@@ -366,26 +343,16 @@ def update_with_lvgl(self, url):
366343 progress_info += "\n \n Press 'Update OS' to resume."
367344 msg = friendly_msg + progress_info
368345
369- self .update_ui_threadsafe_if_foreground (
370- self .set_state , UpdateState .ERROR
371- )
346+ self .set_state (UpdateState .ERROR )
372347 self .update_ui_threadsafe_if_foreground (self .status_label .set_text , msg )
373- self .update_ui_threadsafe_if_foreground (
374- self .install_button .remove_state , lv .STATE .DISABLED
375- ) # allow retry
348+ self .update_ui_threadsafe_if_foreground (self .install_button .remove_state , lv .STATE .DISABLED ) # allow retry
376349 return
377350
378351 except Exception as e :
379352 msg = self ._get_user_friendly_error (e ) + "\n \n Press 'Update OS' to retry."
380- self .update_ui_threadsafe_if_foreground (
381- self .set_state , UpdateState .ERROR
382- )
383- self .update_ui_threadsafe_if_foreground (
384- self .status_label .set_text , msg
385- )
386- self .update_ui_threadsafe_if_foreground (
387- self .install_button .remove_state , lv .STATE .DISABLED
388- ) # allow retry
353+ self .set_state (UpdateState .ERROR )
354+ self .update_ui_threadsafe_if_foreground (self .status_label .set_text , msg )
355+ self .update_ui_threadsafe_if_foreground (self .install_button .remove_state , lv .STATE .DISABLED ) # allow retry
389356
390357# Business Logic Classes:
391358
0 commit comments