1111
1212class OSUpdate (Activity ):
1313
14+ keep_running = True
15+
16+ # Widgets:
1417 install_button = None
1518 main_screen = None
16- keep_running = True
19+ progress_label = None
20+ progress_bar = None
1721
1822 def onCreate (self ):
1923 self .main_screen = lv .obj ()
@@ -88,43 +92,51 @@ def handle_update_info(self, version, download_url, changelog):
8892
8993 def install_button_click (self , download_url ):
9094 print (f"install_button_click for url { download_url } " )
95+ self .install_button .add_state (lv .STATE .DISABLED ) # button will be enabled if there is an update available
96+ self .status_label .set_text ("Update in progress.\n Navigate away to cancel." )
97+ self .progress_label = lv .label (self .main_screen )
98+ self .progress_label .set_text ("OS Update: 0.00%" )
99+ self .progress_label .align (lv .ALIGN .CENTER , 0 , 0 )
100+ self .progress_bar = lv .bar (self .main_screen )
101+ self .progress_bar .set_size (200 , 20 )
102+ self .progress_bar .align (lv .ALIGN .BOTTOM_MID , 0 , - 50 )
103+ self .progress_bar .set_range (0 , 100 )
104+ self .progress_bar .set_value (0 , lv .ANIM .OFF )
91105 try :
92106 _thread .stack_size (mpos .apps .good_stack_size ())
93107 _thread .start_new_thread (self .update_with_lvgl , (download_url ,))
94108 except Exception as e :
95109 print ("Could not start update_with_lvgl thread: " , e )
96110
111+ def progress_callback (self , percent ):
112+ print (f"OTA Update: { percent :.1f} %" )
113+ lv .async_call (lambda l : self .progress_label .set_text (f"OTA Update: { percent :.2f} %" ), None )
114+ lv .async_call (lambda l : self .progress_bar .set_value (int (percent ), lv .ANIM .ON ), None )
115+ time .sleep_ms (100 )
116+
97117 # Custom OTA update with LVGL progress
98118 def update_with_lvgl (self , url ):
99- self .install_button .add_flag (lv .obj .FLAG .HIDDEN ) # or change to cancel button?
100- self .status_label .set_text ("Update in progress.\n Navigate away to cancel." )
101- import ota .update
102- import ota .status
103- ota .status .status ()
104- from esp32 import Partition
105- current_partition = Partition (Partition .RUNNING )
106- print (f"Current partition: { current_partition } " )
107- next_partition = current_partition .get_next_update ()
108- print (f"Next partition: { next_partition } " )
109- label = lv .label (self .main_screen )
110- label .set_text ("OS Update: 0.00%" )
111- label .align (lv .ALIGN .CENTER , 0 , - 30 )
112- progress_bar = lv .bar (self .main_screen )
113- progress_bar .set_size (200 , 20 )
114- progress_bar .align (lv .ALIGN .BOTTOM_MID , 0 , - 50 )
115- progress_bar .set_range (0 , 100 )
116- progress_bar .set_value (0 , lv .ANIM .OFF )
117- def progress_callback (percent ):
118- print (f"OTA Update: { percent :.1f} %" )
119- label .set_text (f"OTA Update: { percent :.2f} %" )
120- progress_bar .set_value (int (percent ), lv .ANIM .ON )
121- current = Partition (Partition .RUNNING )
122- next_partition = current .get_next_update ()
119+ simulate = False
120+ try :
121+ from esp32 import Partition
122+ #current_partition = Partition(Partition.RUNNING)
123+ #print(f"Current partition: {current_partition}")
124+ #next_partition = current_partition.get_next_update()
125+ #print(f"Next partition: {next_partition}")
126+ current = Partition (Partition .RUNNING )
127+ next_partition = current .get_next_update ()
128+ #import ota.update
129+ #import ota.status
130+ #ota.status.status()
131+ except Exception as e :
132+ print ("Warning: could not import esp32.Partition, simulating update..." )
133+ simulate = True
123134 response = requests .get (url , stream = True )
124135 total_size = int (response .headers .get ('Content-Length' , 0 ))
125136 bytes_written = 0
126137 chunk_size = 4096
127138 i = 0
139+ total_size = round_up_to_multiple (total_size , chunk_size )
128140 print (f"Starting OTA update of size: { total_size } " )
129141 while self .keep_running : # stop if the user navigates away
130142 time .sleep_ms (100 ) # don't hog the CPU
@@ -135,21 +147,26 @@ def progress_callback(percent):
135147 if len (chunk ) < chunk_size :
136148 print (f"Padding chunk { i } from { len (chunk )} to { chunk_size } bytes" )
137149 chunk = chunk + b'\xFF ' * (chunk_size - len (chunk ))
138- print (f"Writing chunk { i } " )
139- next_partition .writeblocks (i , chunk )
150+ print (f"Writing chunk { i } with length { len (chunk )} " )
151+ if not simulate :
152+ next_partition .writeblocks (i , chunk )
140153 bytes_written += len (chunk )
141154 i += 1
142155 if total_size :
143- progress_callback (bytes_written / total_size * 100 )
156+ self . progress_callback (bytes_written / total_size * 100 )
144157 response .close ()
145- if bytes_written >= total_size : # if the update was completely installed
158+ if bytes_written >= total_size and not simulate : # if the update was completely installed
146159 next_partition .set_boot ()
147160 import machine
148161 machine .reset ()
149-
162+ # In case it didn't reset:
163+ lv .async_call (lambda l : self .status_label .set_text ("Update finished! Please restart." ), None )
150164
151165# Non-class functions:
152166
167+ def round_up_to_multiple (n , multiple ):
168+ return ((n + multiple - 1 ) // multiple ) * multiple
169+
153170def compare_versions (ver1 : str , ver2 : str ) -> bool :
154171 """Compare two version numbers (e.g., '1.2.3' vs '4.5.6').
155172 Returns True if ver1 is greater than ver2, False otherwise."""
0 commit comments