# core/commands/check.py from core.connection import BuzzerError def _split_parent_and_name(path: str) -> tuple[str, str]: normalized = path.rstrip("/") if not normalized or normalized == "/": raise BuzzerError("Für CHECK wird ein Dateipfad benötigt.") idx = normalized.rfind("/") if idx <= 0: return "/", normalized parent = normalized[:idx] name = normalized[idx + 1:] if not name: raise BuzzerError("Ungültiger Dateipfad für CHECK.") return parent, name def _lookup_file_size_bytes(conn, path: str) -> int | None: parent, filename = _split_parent_and_name(path) lines = conn.list_directory(parent) for line in lines: parts = line.split(",", 2) if len(parts) != 3: continue entry_type, entry_size, entry_name = parts if entry_type == "F" and entry_name == filename: try: return int(entry_size) except ValueError: return None return None def _estimate_crc_timeout_seconds(conn, size_bytes: int | None) -> float: min_timeout = float(getattr(conn, "crc_timeout_min_seconds", 2.0)) ms_per_100kb = float(getattr(conn, "crc_timeout_ms_per_100kb", 1.5)) base = max(float(conn.timeout), min_timeout) if size_bytes is None or size_bytes <= 0: return base blocks_100kb = size_bytes / (100.0 * 1024.0) extra = blocks_100kb * (ms_per_100kb / 1000.0) return base + extra def execute(conn, path: str) -> dict: """Holt die CRC32 nur über Audiodaten und passt Timeout für große Dateien an.""" size_bytes = _lookup_file_size_bytes(conn, path) timeout = _estimate_crc_timeout_seconds(conn, size_bytes) crc32 = conn.check_file_crc(path, timeout=timeout) return { "crc32": crc32, "size_bytes": size_bytes, }