OSUpdate app: resume when wifi reconnects

This commit is contained in:
Thomas Farstrike
2025-11-24 18:20:06 +01:00
parent ce8b36e3a8
commit 61379985e9
3 changed files with 33 additions and 1 deletions
+5
View File
@@ -1,3 +1,8 @@
0.5.1
=====
- OSUpdate app: pause download when wifi is lost, resume when reconnected
- Fri3d Camp 2024 Badge: workaround ADC2+WiFi conflict by disconnecting WiFi to measure battery level
0.5.0
=====
- 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!
@@ -576,9 +576,13 @@ class UpdateDownloader:
if self._is_network_error(e):
print(f"UpdateDownloader: Network error ({e}), pausing download")
self.is_paused = True
self.bytes_written_so_far = result.get('bytes_written', self.bytes_written_so_far)
# Only update bytes_written_so_far if we actually wrote bytes in this attempt
# Otherwise preserve the existing state (important for resume failures)
if result.get('bytes_written', 0) > 0:
self.bytes_written_so_far = result['bytes_written']
result['paused'] = True
result['bytes_written'] = self.bytes_written_so_far
result['total_size'] = self.total_size_expected # Preserve total size for UI
else:
# Non-network error
result['error'] = str(e)
+23
View File
@@ -460,4 +460,27 @@ class TestUpdateDownloader(unittest.TestCase):
self.assertIn('Range', last_request['headers'])
self.assertEqual(last_request['headers']['Range'], 'bytes=8192-')
def test_resume_failure_preserves_state(self):
"""Test that resume failures preserve download state for retry."""
# Simulate partial download state
self.downloader.bytes_written_so_far = 245760 # 60 chunks already downloaded
self.downloader.total_size_expected = 3391488
# Resume attempt fails immediately with EHOSTUNREACH (network not ready)
self.mock_requests.set_exception(OSError(-118, "EHOSTUNREACH"))
result = self.downloader.download_and_install(
"http://example.com/update.bin"
)
# Should pause, not fail
self.assertFalse(result['success'])
self.assertTrue(result['paused'])
self.assertIsNone(result['error'])
# Critical: Must preserve progress for next retry
self.assertEqual(result['bytes_written'], 245760, "Must preserve bytes_written")
self.assertEqual(result['total_size'], 3391488, "Must preserve total_size")
self.assertEqual(self.downloader.bytes_written_so_far, 245760, "Must preserve internal state")