|
3 | 3 | from esp32 import Partition |
4 | 4 | import urequests |
5 | 5 |
|
6 | | -import lvgl as lv |
7 | | -from esp32 import Partition |
8 | | -import urequests |
9 | | -import hashlib |
10 | | -import machine |
11 | 6 |
|
12 | 7 | subwindow.clean() |
13 | 8 | canary = lv.obj(subwindow) |
|
20 | 15 | current |
21 | 16 | current.get_next_update() |
22 | 17 |
|
23 | | - |
24 | | -# Assuming subwindow is defined elsewhere |
25 | | -# subwindow.clean() |
26 | | - |
27 | | -# Initialize LVGL display |
| 18 | +# Initialize LVGL display (assuming setup is done) |
28 | 19 | label = lv.label(subwindow) |
29 | 20 | label.set_text("OTA Update: 0.00%") |
30 | | -label.align(lv.ALIGN.CENTER, 0, 0) |
31 | | -progress_bar = lv.bar(lv.screen_active()) |
| 21 | +label.align(lv.ALIGN.CENTER, 0, -30) |
| 22 | +progress_bar = lv.bar(subwindow) |
32 | 23 | progress_bar.set_size(200, 20) |
33 | | -progress_bar.align(lv.ALIGN.BOTTOM_MID, 0, -20) |
| 24 | +progress_bar.align(lv.ALIGN.BOTTOM_MID, 0, -50) |
34 | 25 | progress_bar.set_range(0, 100) |
35 | 26 | progress_bar.set_value(0, lv.ANIM.OFF) |
36 | 27 |
|
37 | 28 | # Custom OTA update with LVGL progress |
38 | | -def update_with_lvgl(url, expected_sha256=None): |
| 29 | +def update_with_lvgl(url): |
39 | 30 | def progress_callback(percent): |
40 | 31 | print(f"OTA Update: {percent:.1f}%") |
41 | | - label.set_text(f"OTA Update: {percent:.2f}%") |
| 32 | + label.set_text(f"OTA Update: {percent:.2f}%") # Cloud upload symbol |
42 | 33 | progress_bar.set_value(int(percent), lv.ANIM.ON) |
43 | | - lv.task_handler() # Ensure LVGL updates the display |
44 | | - |
45 | | - # Free memory before starting |
46 | | - import gc |
47 | | - gc.collect() |
48 | | - |
49 | | - # Get partition information |
50 | 34 | current = Partition(Partition.RUNNING) |
51 | 35 | next_partition = current.get_next_update() |
52 | | - print("Current partition:", current.info()) |
53 | | - print("Next partition:", next_partition.info()) |
54 | | - |
55 | | - # Validate partition size |
56 | | - partition_size = next_partition.ioctl(4, 0) * 4096 # Total sectors * sector size |
57 | 36 | response = urequests.get(url, stream=True) |
58 | 37 | total_size = int(response.headers.get('Content-Length', 0)) |
59 | | - if total_size > partition_size: |
60 | | - print(f"Error: Firmware size {total_size} exceeds partition size {partition_size}") |
61 | | - response.close() |
62 | | - return |
63 | | - print(f"Starting OTA update of size: {total_size}") |
64 | | - |
65 | | - # Initialize SHA256 hash |
66 | | - sha256 = hashlib.sha256() if expected_sha256 else None |
67 | | - |
68 | 38 | bytes_written = 0 |
69 | 39 | chunk_size = 4096 |
70 | 40 | i = 0 |
71 | | - while True: |
| 41 | + print(f"Starting OTA update of size: {total_size}") |
| 42 | + while canary.is_valid(): |
72 | 43 | chunk = response.raw.read(chunk_size) |
73 | 44 | if not chunk: |
| 45 | + print("No chunk, breaking...") |
74 | 46 | break |
75 | | - print(f"Writing chunk {i}, size: {len(chunk)} bytes") |
76 | | - # Pad the chunk if it's smaller than 4096 bytes |
77 | 47 | if len(chunk) < chunk_size: |
78 | 48 | print(f"Padding chunk {i} from {len(chunk)} to {chunk_size} bytes") |
79 | 49 | chunk = chunk + b'\xFF' * (chunk_size - len(chunk)) |
80 | | - # Update hash |
81 | | - if sha256: |
82 | | - sha256.update(chunk) |
83 | | - try: |
84 | | - next_partition.writeblocks(i, chunk) |
85 | | - except OSError as e: |
86 | | - print(f"Error writing chunk {i}: {e}") |
87 | | - response.close() |
88 | | - return |
| 50 | + print(f"Writing chunk {i}") |
| 51 | + next_partition.writeblocks(i, chunk) |
89 | 52 | bytes_written += len(chunk) |
90 | 53 | i += 1 |
91 | 54 | if total_size: |
92 | 55 | progress_callback(bytes_written / total_size * 100) |
93 | | - |
94 | 56 | response.close() |
95 | | - print(f"OTA update complete, wrote {bytes_written} bytes") |
96 | | - |
97 | | - # Verify checksum if provided |
98 | | - if sha256 and expected_sha256: |
99 | | - computed_sha256 = sha256.hexdigest() |
100 | | - if computed_sha256 != expected_sha256: |
101 | | - print(f"Checksum mismatch: expected {expected_sha256}, got {computed_sha256}") |
102 | | - return |
103 | | - print("Checksum verified successfully") |
104 | | - |
105 | | - # Set the boot partition |
106 | | - try: |
107 | | - next_partition.set_boot() |
108 | | - print("Boot partition set to:", next_partition.info()) |
109 | | - print("Current boot partition:", Partition(Partition.BOOT).info()) |
110 | | - except OSError as e: |
111 | | - print(f"Error setting boot partition: {e}") |
112 | | - return |
113 | | - |
114 | | - # Mark the new partition as valid to prevent rollback |
115 | | - try: |
116 | | - Partition.mark_app_valid_cancel_rollback() |
117 | | - print("Marked new partition as valid") |
118 | | - except OSError as e: |
119 | | - print(f"Error marking partition as valid: {e}") |
120 | | - return |
121 | | - |
122 | | - # Reboot |
123 | | - print("Rebooting to new firmware...") |
| 57 | + next_partition.set_boot() |
| 58 | + import machine |
124 | 59 | machine.reset() |
125 | 60 |
|
126 | | -# Example usage |
127 | | -# Replace with your firmware URL and SHA256 checksum (if available) |
128 | | -update_with_lvgl("http://demo.lnpiggy.com:2121/ESP32_GENERIC_S3-SPIRAM_OCT_micropython.bin", expected_sha256="c167de508c354724e97857ed4bd5c5608f383302399a506d2a16d6ee0cab08ce") |
129 | | -lvgl_micropy_ESP32_GENERIC_S3-SPIRAM_OCT-16.bin |
130 | | - |
131 | 61 | # Start OTA update |
132 | | -#update_with_lvgl("http://demo.lnpiggy.com:2121/latest.bin") |
| 62 | +update_with_lvgl("http://demo.lnpiggy.com:2121/ESP32_GENERIC_S3-SPIRAM_OCT_micropython.bin") |
0 commit comments