sync
This commit is contained in:
89
tool/core/cmd/put_fw.py
Normal file
89
tool/core/cmd/put_fw.py
Normal file
@@ -0,0 +1,89 @@
|
||||
import struct
|
||||
import zlib
|
||||
from pathlib import Path
|
||||
from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, DownloadColumn, TransferSpeedColumn, TimeRemainingColumn
|
||||
from core.utils import console, console_err
|
||||
from core.protocol import COMMANDS
|
||||
|
||||
class put_fw:
|
||||
def __init__(self, bus):
|
||||
self.bus = bus
|
||||
|
||||
def get(self, file_path: str):
|
||||
try:
|
||||
p = Path(file_path)
|
||||
if not p.exists() or not p.is_file():
|
||||
console_err.print(f"Fehler: Firmware-Datei existiert nicht: {file_path}")
|
||||
return None
|
||||
|
||||
file_size = p.stat().st_size
|
||||
with open(p, 'rb') as f:
|
||||
file_data = f.read()
|
||||
except Exception as e:
|
||||
console_err.print(f"Lese-Fehler: {e}")
|
||||
return None
|
||||
|
||||
# 1. Schritt: Löschvorgang mit minimalem Feedback
|
||||
with Progress(
|
||||
SpinnerColumn(),
|
||||
TextColumn("[progress.description]{task.description}"),
|
||||
BarColumn(),
|
||||
console=console,
|
||||
transient=True
|
||||
) as progress:
|
||||
erase_task = progress.add_task("Lösche Firmware Slot...", total=None)
|
||||
|
||||
payload = struct.pack('<I', file_size)
|
||||
self.bus.send_request(COMMANDS['put_fw'], payload)
|
||||
|
||||
# Warten auf ACK (Balken pulsiert ohne Byte-Anzeige)
|
||||
self.bus.receive_ack(timeout=10.0)
|
||||
progress.update(erase_task, description="✓ Slot gelöscht", completed=100, total=100)
|
||||
|
||||
# 2. Schritt: Eigentlicher Transfer mit allen Metriken (Bytes, Speed, Time)
|
||||
with Progress(
|
||||
SpinnerColumn(),
|
||||
TextColumn("[progress.description]{task.description}"),
|
||||
BarColumn(),
|
||||
DownloadColumn(),
|
||||
TransferSpeedColumn(),
|
||||
"•",
|
||||
TimeRemainingColumn(),
|
||||
console=console,
|
||||
transient=False
|
||||
) as progress:
|
||||
transfer_task = progress.add_task("Sende Firmware...", total=file_size)
|
||||
|
||||
stream_res = self.bus.send_stream(
|
||||
file_data,
|
||||
progress_callback=lambda sent, total: progress.update(transfer_task, total=total, completed=sent)
|
||||
)
|
||||
|
||||
if not stream_res:
|
||||
return None
|
||||
|
||||
remote_crc = stream_res.get('crc32')
|
||||
local_crc = zlib.crc32(file_data) & 0xFFFFFFFF
|
||||
|
||||
return {
|
||||
'success': local_crc == remote_crc,
|
||||
'source_path': file_path,
|
||||
'crc32_remote': remote_crc,
|
||||
'crc32_local': local_crc,
|
||||
'size': file_size,
|
||||
'duration': stream_res.get('duration')
|
||||
}
|
||||
|
||||
def print(self, result):
|
||||
if not result:
|
||||
return
|
||||
|
||||
if result['success']:
|
||||
console.print(f"✓ Firmware [info]{result['source_path']}[/info] erfolgreich in Slot 1 geschrieben.")
|
||||
console.print(" [warning]Achtung:[/warning] Das Image ist als 'Pending' markiert. Führe 'reboot' aus, um das Update zu installieren.")
|
||||
else:
|
||||
console_err.print(f"❌ CRC-FEHLER: Die Firmware wurde korrumpiert übertragen!")
|
||||
|
||||
console.print(f" • Größe: [info]{result['size'] / 1024:.2f} KB[/info]")
|
||||
console.print(f" • Remote CRC: [info]{result['crc32_remote']:08X}[/info]")
|
||||
console.print(f" • Local CRC: [info]{result['crc32_local']:08X}[/info]")
|
||||
Reference in New Issue
Block a user