import sys
import serial
import struct
import time

from PySide6.QtCore import QObject, Signal

START_OF_TEMPS = bytes((0xFF, 0xFF))
N_SENSORS = 12
TEMP_QUANT = 0.0625  # °C/quant


class Temperatures(QObject):
    temperaturesUpdated = Signal(list)

    _temps: list[float]

    def __init__(self, uart_path: str):
        super().__init__(parent=None)
        self.dev = serial.Serial(uart_path, 115200)
        self._temps = [0.0] * N_SENSORS

    def run(self):
        while True:
            time.sleep(0.01)
            self.dev.read_until(START_OF_TEMPS)
            data = self.dev.read(N_SENSORS * 2)
            temps = struct.unpack(f">{N_SENSORS}h", data)
            err = False
            for i, t in enumerate(temps):
                if (t & 0x0F) != 0:
                    print(
                        f"WARN: temperature had a non-zero least-significant nibble: {t:04x}",
                        file=sys.stderr,
                    )
                    err = True
                else:
                    self._temps[i] = (t >> 4) * TEMP_QUANT
            # Only emit the signal if there's no error, so we cause a timeout if
            # there were errors.
            if not err:
                self.temperaturesUpdated.emit(self._temps)
