#!/home/sam/dev/perso/flsun/klippy-env/bin/python
"""Suit une impression via le socket API de klippy et emet une ligne par
evenement notable : changement d'etat, palier de progression (10 %), fin.
Se termine quand l'impression est finie (complete / error / cancelled).
"""
import json
import socket
import sys
import time

UDS = "/tmp/klippy_uds"
PAS = 10           # palier de progression, en %
PERIODE = 30       # secondes entre deux interrogations


def query():
    s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    s.settimeout(10)
    s.connect(UDS)
    s.sendall(json.dumps({"id": 1, "method": "objects/query", "params": {"objects": {
        "print_stats": None, "virtual_sdcard": None, "extruder": None,
        "heater_bed": None, "gcode_move": None}}}).encode() + b"\x03")
    buf = b""
    while b"\x03" not in buf:
        buf += s.recv(65536)
    s.close()
    return json.loads(buf.split(b"\x03")[0])["result"]["status"]


def main():
    dernier_etat = None
    dernier_palier = -1
    vu_printing = False
    while True:
        try:
            st = query()
        except OSError as e:
            print("[watch] klippy injoignable : %s" % e, flush=True)
            time.sleep(PERIODE)
            continue
        ps, sd = st["print_stats"], st["virtual_sdcard"]
        etat = ps["state"]
        prog = int(sd.get("progress", 0) * 100)
        z = st["gcode_move"]["gcode_position"][2]
        off = st["gcode_move"]["homing_origin"][2]
        temps = "buse %.0f/%.0f plateau %.0f/%.0f" % (
            st["extruder"]["temperature"], st["extruder"]["target"],
            st["heater_bed"]["temperature"], st["heater_bed"]["target"])
        if etat != dernier_etat:
            print("[print] etat: %s  fichier: %s  (%s)" % (etat, ps.get("filename"), temps), flush=True)
            dernier_etat = etat
        if etat == "printing":
            vu_printing = True
            palier = prog // PAS
            if palier != dernier_palier:
                print("[print] %d %%  Z=%.2f  offset=%+.2f  duree=%dmin  %s" % (
                    prog, z, off, ps["print_duration"] // 60, temps), flush=True)
                dernier_palier = palier
        if etat in ("complete", "error", "cancelled") or (vu_printing and etat == "standby"):
            print("[print] TERMINE (%s) apres %d min, offset Z final %+.2f" % (
                etat, ps["print_duration"] // 60, off), flush=True)
            return 0
        time.sleep(PERIODE)


if __name__ == "__main__":
    sys.exit(main())
