Skip to content

Commit 6137998

Browse files
OSUpdate app: resume when wifi reconnects
1 parent ce8b36e commit 6137998

File tree

3 files changed

+33
-1
lines changed

3 files changed

+33
-1
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
0.5.1
2+
=====
3+
- OSUpdate app: pause download when wifi is lost, resume when reconnected
4+
- Fri3d Camp 2024 Badge: workaround ADC2+WiFi conflict by disconnecting WiFi to measure battery level
5+
16
0.5.0
27
=====
38
- ESP32: one build to rule them all; instead of 2 builds per supported board, there is now one single build that identifies and initializes the board at runtime!

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,9 +576,13 @@ def download_and_install(self, url, progress_callback=None, should_continue_call
576576
if self._is_network_error(e):
577577
print(f"UpdateDownloader: Network error ({e}), pausing download")
578578
self.is_paused = True
579-
self.bytes_written_so_far = result.get('bytes_written', self.bytes_written_so_far)
579+
# Only update bytes_written_so_far if we actually wrote bytes in this attempt
580+
# Otherwise preserve the existing state (important for resume failures)
581+
if result.get('bytes_written', 0) > 0:
582+
self.bytes_written_so_far = result['bytes_written']
580583
result['paused'] = True
581584
result['bytes_written'] = self.bytes_written_so_far
585+
result['total_size'] = self.total_size_expected # Preserve total size for UI
582586
else:
583587
# Non-network error
584588
result['error'] = str(e)

tests/test_osupdate.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,4 +460,27 @@ def test_download_resumes_from_saved_position(self):
460460
self.assertIn('Range', last_request['headers'])
461461
self.assertEqual(last_request['headers']['Range'], 'bytes=8192-')
462462

463+
def test_resume_failure_preserves_state(self):
464+
"""Test that resume failures preserve download state for retry."""
465+
# Simulate partial download state
466+
self.downloader.bytes_written_so_far = 245760 # 60 chunks already downloaded
467+
self.downloader.total_size_expected = 3391488
468+
469+
# Resume attempt fails immediately with EHOSTUNREACH (network not ready)
470+
self.mock_requests.set_exception(OSError(-118, "EHOSTUNREACH"))
471+
472+
result = self.downloader.download_and_install(
473+
"http://example.com/update.bin"
474+
)
475+
476+
# Should pause, not fail
477+
self.assertFalse(result['success'])
478+
self.assertTrue(result['paused'])
479+
self.assertIsNone(result['error'])
480+
481+
# Critical: Must preserve progress for next retry
482+
self.assertEqual(result['bytes_written'], 245760, "Must preserve bytes_written")
483+
self.assertEqual(result['total_size'], 3391488, "Must preserve total_size")
484+
self.assertEqual(self.downloader.bytes_written_so_far, 245760, "Must preserve internal state")
485+
463486

0 commit comments

Comments
 (0)