safety commit

This commit is contained in:
2026-07-06 20:16:51 +02:00
parent 02e51717e8
commit 28ae97fa45
8 changed files with 806 additions and 34 deletions

View File

@@ -43,7 +43,7 @@ STATUS_RE = re.compile(
r"htop=(?P<htop>\S+)\s+"
r"hblk=(?P<hblk>\S+)\s+"
r"ssr=(?P<ssr>on|off)\s+"
r"fan=(?P<fan>\S+)\s+"
r"fan=(?P<fan>\d+/255\(\d+%\)(?:\([^)]+\))?(?:\s+TEST)?)\s+"
r"cutoff=(?P<cutoff_active>\S+)\s+"
r"failsafe=(?P<failsafe>\S+)\s+"
r"mode=(?P<mode>.+?)\s+sensors=\[(?P<sensors>.*)\]"
@@ -55,6 +55,10 @@ AUTOTUNE_MODE_RE = re.compile(
r"autotune/(?P<phase>[\w-]+) (?P<elapsed>\d+)s (?P<cycles>\d+/\d+)cyc pre>=(?P<pre>\d+)C"
)
STEPRESP_MODE_RE = re.compile(
r"stepresp/(?P<phase>[\w-]+) (?P<elapsed>\d+)s step (?P<step>\d+/\d+) heat=(?P<heat>\d+)%"
)
def format_mode_line(mode: str) -> str:
match = AUTOTUNE_MODE_RE.match(mode)
@@ -64,6 +68,13 @@ def format_mode_line(mode: str) -> str:
f"Autotune {d['phase']}: {d['elapsed']}s elapsed, "
f"{d['cycles']} cycles, preheat avg >= {d['pre']} C"
)
match = STEPRESP_MODE_RE.match(mode)
if match:
d = match.groupdict()
return (
f"Step response {d['phase']}: {d['elapsed']}s, "
f"step {d['step']}, heater {d['heat']}%"
)
return f"Mode: {mode}"
@@ -141,7 +152,7 @@ def apply_status(state: DryerState, data: dict) -> None:
fan_raw = data["fan"]
state.fan = fan_raw
state.fan_note = ""
if fan_raw.endswith("(off)") or fan_raw.endswith("(cooldown)") or " TEST" in fan_raw:
if fan_raw.endswith("(off)") or fan_raw.endswith("(cooldown)") or fan_raw.endswith("(cmd-off)") or " TEST" in fan_raw:
state.fan_note = fan_raw[fan_raw.find("(") :] if "(" in fan_raw else ""
state.cutoff_active = data["cutoff_active"]
state.failsafe = data["failsafe"]
@@ -409,7 +420,7 @@ def _draw_dashboard(stdscr, state: DryerState) -> None:
stdscr,
help_y,
1,
"0 idle | t target | p presets | f fan | l log | a autotune | : cmd | q quit",
"0 idle | t target | p presets | f fan | l log | a autotune | r stepresp | : cmd | q quit",
curses.A_DIM,
)
stdscr.refresh()
@@ -491,6 +502,21 @@ def _curses_main(stdscr, ser, log_dir: Path, auto_log_on: bool) -> int:
if value is not None:
cmd = "autotune" if value == "" else f"autotune {value}"
worker.send(cmd)
elif key == ord("r"):
temp = _prompt(stdscr, "Stepresp temp °C (Enter = 45)")
if temp is None:
continue
heater = _prompt(stdscr, "Heater % (Enter = 35)")
if heater is None:
continue
if temp == "" and heater == "":
worker.send("stepresp")
elif heater == "":
worker.send(f"stepresp {temp}")
elif temp == "":
worker.send(f"stepresp 45 {heater}")
else:
worker.send(f"stepresp {temp} {heater}")
elif key == ord(":"):
value = _prompt(stdscr, "Command")
if value is not None and value != "":