import os import time import sys def _estimate_fw_timeout_seconds(conn, total_size: int) -> float: base = float(getattr(conn, "timeout", 5.0)) erase_budget = 8.0 stream_and_write_budget = total_size / (25.0 * 1024.0) return max(base, erase_budget + stream_and_write_budget) def execute(conn, source: str): if not os.path.isfile(source): raise FileNotFoundError(f"Firmware-Datei nicht gefunden: {source}") with open(source, "rb") as f: data = f.read() total_size = len(data) if total_size == 0: raise ValueError("Firmware-Datei ist leer.") print(f"Sende 🧩 Firmware ({total_size / 1024:.1f} KB) -> secondary slot") fw_timeout = _estimate_fw_timeout_seconds(conn, total_size) print(f" Timeout fw_put: {fw_timeout:.1f}s") print(" Phase 1/3: Lösche secondary slot und initialisiere Flash...") start_time = time.monotonic() last_ui_update = start_time transfer_started = False def progress_handler(chunk_len, sent_file, total_file): nonlocal last_ui_update, transfer_started if not transfer_started: transfer_started = True print(" Phase 2/3: Übertrage Firmware...") now = time.monotonic() if now - last_ui_update < 0.2 and sent_file < total_file: return last_ui_update = now elapsed = now - start_time speed = (sent_file / 1024.0) / elapsed if elapsed > 0 else 0.0 perc = (sent_file / total_file) * 100.0 if total_file > 0 else 100.0 eta_sec = ((total_file - sent_file) / (sent_file / elapsed)) if sent_file > 0 and elapsed > 0 else 0.0 eta_str = f"{int(eta_sec // 60):02d}:{int(eta_sec % 60):02d}" sys.stdout.write( f"\r \033[90mProg: {perc:3.0f}% | {speed:6.1f} KB/s | ETA: {eta_str}\033[0m" ) sys.stdout.flush() crc32 = conn.fw_put_data(data, timeout=fw_timeout, progress_callback=progress_handler) print("\n Phase 3/3: Finalisiere und warte auf Geräte-ACK...") print(f"\r \033[32mFertig: Firmware übertragen (CRC32: 0x{crc32:08x}).{' ' * 16}\033[0m") print("ℹ️ Nächste Schritte: reboot -> testen -> confirm")