Ctrl K
ComunidadGuías…

ft8_all_log.py

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
"""
ft8_all_log.py - dziennik wszystkiego, co bylo odebrane i nadane w FT8/FT4,
w formacie pliku ALL.TXT z WSJT-X (jedna linia na komunikat):

    251027_183015    14.074 Rx FT8    -12  0.3 1500 K1ABC W9XYZ RR73
    251027_183030    14.074 Tx FT8      0  0.0 1500 W9XYZ K1ABC 73

Osobny plik dla kazdego operatora (wedlug id konta): odebrane dekody trafiaja
do kazdego zalogowanego z otwarta zakladka FT8 i do posiadacza radia, nadane -
do tego, kto nadaje (patrz webapp.py). Pliki w DATA/all_txt/. Rozmiar pilnowany
rotacja: po przekroczeniu MAX_BYTES biezacy plik staje sie kopia ".old" (poprzednia
kopia jest kasowana), czyli na operatora najwyzej ~2 x MAX_BYTES.
"""
import re
import time
from pathlib import Path

MAX_BYTES = 5_000_000


class Ft8AllLog:
    def __init__(self, data_dir: Path):
        self.dir = Path(data_dir) / "all_txt"

    def path_for(self, uid) -> Path:
        safe = re.sub(r"[^A-Za-z0-9_-]", "_", str(uid)) or "unknown"
        return self.dir / f"ALL_{safe}.TXT"

    def old_path_for(self, uid) -> Path:
        return self.path_for(uid).with_suffix(".old.TXT")

    def write(self, uid, rx: bool, dial_hz: float, mode: str, snr: int, dt: float,
              freq_hz: int, message: str, time_str: str = "", epoch: float | None = None):
        """time_str: HHMMSS okna (z dekodera); epoch: kiedy (do daty, albo
        do czasu gdy brak time_str)."""
        if not uid:
            return
        try:
            t = time.gmtime(epoch if epoch is not None else time.time())
            hhmmss = time_str if (time_str and len(time_str) == 6) else time.strftime("%H%M%S", t)
            line = (f"{time.strftime('%y%m%d', t)}_{hhmmss}"
                    f"{(dial_hz or 0) / 1e6:11.3f} {'Rx' if rx else 'Tx'} {mode:<4}"
                    f"{int(snr):6d}{float(dt):5.1f}{int(freq_hz):5d} {message}\n")
            self.dir.mkdir(parents=True, exist_ok=True)
            p = self.path_for(uid)
            if p.exists() and p.stat().st_size > MAX_BYTES:
                p.replace(self.old_path_for(uid))
            with open(p, "a", encoding="utf-8") as f:
                f.write(line)
        except Exception as e:
            # Dziennik nigdy nie moze przerwac odbioru/nadawania.
            print(f"[all.txt] blad zapisu: {e}", flush=True)

    def read(self, uid) -> bytes:
        """Starsza kopia (jesli jest) + biezacy plik, chronologicznie."""
        out = b""
        for p in (self.old_path_for(uid), self.path_for(uid)):
            if p.exists():
                out += p.read_bytes()
        return out