import serial, struct
import numpy as np
import cv2

# ---- ANPASSEN ----
PORT = "COM6"          # nativer USB-Port des S3 (zickenfrei). CH343/COM5 streamt nicht zuverlaessig.
BAUD = 921600
FULLSCREEN = False     # True = Vollbild fuer den Beamer
FIXED_SCALE = False    # JETZT zum Testen: False = Auto-Kontrast (Hand/Gesicht sichtbar).
                       # FUER DEN VERSUCH mit heissen Staeben: auf True stellen (faire feste Skala)!
TMIN_C, TMAX_C = 20, 120   # Skala bei FIXED_SCALE (Grad C)
FLIP_H, FLIP_V = False, False   # Bild spiegeln, falls Sensor verdreht montiert
SMOOTH = 0.5           # 0..1: Flacker-Glaettung (0 = aus, hoch = ruhiger/traeger)
# ------------------

W, H = 32, 24
FRAME_BYTES = W * H * 4
ser = serial.Serial(PORT, BAUD, timeout=2)
acc = None

def read_frame():
    while True:                         # auf Startmarker 0x5A 0xA5 synchronisieren
        b = ser.read(1)
        if not b: return None
        if b == b'\x5A' and ser.read(1) == b'\xA5':
            break
    data = ser.read(FRAME_BYTES)
    if len(data) != FRAME_BYTES: return None
    vals = struct.unpack('<' + 'f' * (W * H), data)
    return np.array(vals, dtype=np.float32).reshape(H, W)

win = "Waermebild"
cv2.namedWindow(win, cv2.WINDOW_NORMAL)
if FULLSCREEN:
    cv2.setWindowProperty(win, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)

while True:
    f = read_frame()
    if f is None:
        continue
    if FLIP_H: f = np.fliplr(f)
    if FLIP_V: f = np.flipud(f)

    acc = f if acc is None else SMOOTH * acc + (1 - SMOOTH) * f   # Glaettung

    if FIXED_SCALE:
        lo, hi = TMIN_C, TMAX_C
    else:
        lo, hi = acc.min(), acc.max()                 # Auto: maximaler Kontrast
    norm = np.clip((acc - lo) / (hi - lo + 1e-6), 0, 1)
    img8 = (norm * 255).astype(np.uint8)

    big = cv2.resize(img8, (1024, 768), interpolation=cv2.INTER_CUBIC)
    color = cv2.applyColorMap(big, cv2.COLORMAP_INFERNO)   # COLORMAP_JET = klassisch bunt

    cv2.putText(color, f"min {acc.min():.1f}C   max {acc.max():.1f}C",
                (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 255, 255), 2)
    cv2.imshow(win, color)
    if cv2.waitKey(1) & 0xFF == ord('q'):   # 'q' beendet
        break

ser.close()
cv2.destroyAllWindows()
