82 lines
3.0 KiB
Python
82 lines
3.0 KiB
Python
import os
|
|
import zlib
|
|
import glob
|
|
import time
|
|
import sys
|
|
from core.connection import BuzzerError
|
|
|
|
def get_file_crc32(filepath: str) -> int:
|
|
"""Berechnet die IEEE CRC32-Prüfsumme einer Datei in Chunks."""
|
|
crc = 0
|
|
with open(filepath, 'rb') as f:
|
|
while chunk := f.read(4096):
|
|
crc = zlib.crc32(chunk, crc)
|
|
return crc & 0xFFFFFFFF
|
|
|
|
def execute(conn, sources: list, target: str):
|
|
# 1. Globbing auflösen
|
|
resolved_files = [f for src in sources for f in glob.glob(src) if os.path.isfile(f)]
|
|
|
|
if not resolved_files:
|
|
print("Keine gültigen Dateien gefunden.")
|
|
return
|
|
|
|
total_size_all = sum(os.path.getsize(f) for f in resolved_files)
|
|
sent_all = 0
|
|
start_time_all = time.monotonic()
|
|
is_target_dir = target.endswith('/')
|
|
|
|
for filepath in resolved_files:
|
|
filename = os.path.basename(filepath)
|
|
filesize = os.path.getsize(filepath)
|
|
crc32 = get_file_crc32(filepath)
|
|
dest_path = f"{target}{filename}" if is_target_dir else target
|
|
|
|
print(f"Sende 📄 {filename} ({filesize/1024:.1f} KB) -> {dest_path}")
|
|
|
|
start_time_file = time.monotonic()
|
|
sent_file = 0
|
|
|
|
def progress_handler(chunk_len):
|
|
nonlocal sent_file, sent_all
|
|
sent_file += chunk_len
|
|
sent_all += chunk_len
|
|
|
|
elapsed = time.monotonic() - start_time_file
|
|
speed = (sent_file / 1024) / elapsed if elapsed > 0 else 0
|
|
|
|
# Prozentberechnungen
|
|
perc_file = (sent_file / filesize) * 100
|
|
perc_all = (sent_all / total_size_all) * 100
|
|
|
|
# ETA (Basierend auf Gesamtgeschwindigkeit)
|
|
elapsed_all = time.monotonic() - start_time_all
|
|
avg_speed_all = sent_all / elapsed_all if elapsed_all > 0 else 0
|
|
eta_sec = (total_size_all - sent_all) / avg_speed_all if avg_speed_all > 0 else 0
|
|
eta_str = f"{int(eta_sec // 60):02d}:{int(eta_sec % 60):02d}"
|
|
|
|
# Ausgabezeile (\r überschreibt die aktuelle Zeile)
|
|
sys.stdout.write(
|
|
f"\r \033[90mProg: {perc_file:3.0f}% | Gesamt: {perc_all:3.0f}% | "
|
|
f"{speed:6.1f} KB/s | ETA: {eta_str}\033[0m"
|
|
)
|
|
sys.stdout.flush()
|
|
|
|
try:
|
|
cmd = f"put {dest_path};{filesize};{crc32}\n"
|
|
conn.serial.write(cmd.encode('utf-8'))
|
|
conn.serial.flush()
|
|
|
|
# Binärtransfer mit unserem Handler
|
|
conn.send_binary(filepath, progress_callback=progress_handler)
|
|
|
|
# Zeile nach Erfolg abschließen
|
|
print(f"\r \033[32mFertig: {filename} übertragen. \033[0m")
|
|
except Exception as e:
|
|
print(f"\n ❌ \033[31mFehler: {e}\033[0m")
|
|
|
|
total_duration = time.monotonic() - start_time_all
|
|
total_kb = total_size_all / 1024
|
|
avg_speed = total_kb / total_duration if total_duration > 0 else 0
|
|
|
|
print(f"\nÜbertragung abgeschlossen: {total_kb:.1f} KB in {total_duration:.1f}s ({avg_speed:.1f} KB/s)") |