mirror of
https://github.com/openglow-org/forgefirm.git
synced 2026-09-27 08:41:13 -07:00
forgetest: the air-assist offset calibration runs before the heater tools
A queue runs the catalog in registration order among tests with the same prerequisites, and cooling.aa-offset-calibrate followed cooling.flow-verify. A flow-verify trial heats the tube water (a no-flow trial by 17 C on the bench) and the warm slug circulates past the coolant sensors for minutes afterward; the calibration's stationary gate passed 44 s after the trial on image 20260902144848 and the edges read the wave as disagreement. The calibration is registered first now, with the reason beside it, and tests/test_cooling_order.py holds the order. Catalog consequence: the cooling.* implementation hashes move (the suite file changed).
This commit is contained in:
@@ -20,61 +20,9 @@ _COOL_COVERS = [("forgectrl", "src/cool.*"), ("forgectrl", "src/coolfmt.*"), ("f
|
||||
("kernel-module-glowforge", "src/pic*")]
|
||||
|
||||
|
||||
@test("cooling.flow-verify", title="Coolant flow check separates flow from no-flow",
|
||||
subsystem="cooling", kind="auto", est_min=4,
|
||||
covers=_COOL_COVERS, requires=["kernel.latch-locked-idle"],
|
||||
steps=["Coolant loop normal (pump on); the machine idle. The controller is suspended by "
|
||||
"forgectrl for the duration (about 3 minutes)."],
|
||||
description="forgectrl's flow-verify diagnostic: one heater window with the pump on and "
|
||||
"one with it commanded off, judged against the configured threshold. PASS = "
|
||||
"the threshold separates the two readings with the margins forgectrl reports; "
|
||||
"a thin margin is recorded as a warning.")
|
||||
def flow_verify(ctx):
|
||||
fc = ctx.forgectrl
|
||||
ev = ctx.evidence
|
||||
st, body = fc.get("/diag/status")
|
||||
ctx.check(st == 200 and isinstance(body, dict), "GET /diag/status -> %s", st)
|
||||
ctx.check(not body.get("running"), "a diagnostic is already running (%s)", body.get("tool"))
|
||||
st, body = fc.post("/diag/flow-verify")
|
||||
ctx.log("POST /diag/flow-verify -> %s %s", st, body if isinstance(body, dict) else "")
|
||||
ctx.check(st == 202 and isinstance(body, dict) and body.get("started") is True,
|
||||
"could not start flow-verify (%s %s)", st, body)
|
||||
last_phase = None
|
||||
result = None
|
||||
t0 = time.time()
|
||||
try:
|
||||
while time.time() - t0 < 900:
|
||||
ctx.checkpoint()
|
||||
st, d = fc.get("/diag/status")
|
||||
if st == 200 and isinstance(d, dict):
|
||||
if d.get("phase") != last_phase:
|
||||
last_phase = d.get("phase")
|
||||
ctx.log("phase: %s (down %.1f C, up %.1f C)", last_phase, d.get("down_c", 0), d.get("up_c", 0))
|
||||
if not d.get("running") and d.get("result") is not None:
|
||||
result = d.get("result")
|
||||
for line in d.get("log", [])[-12:]:
|
||||
ctx.log(" diag: %s", line)
|
||||
break
|
||||
time.sleep(2)
|
||||
except BaseException:
|
||||
fc.post("/diag/abort")
|
||||
raise
|
||||
ctx.check(result is not None, "flow-verify did not finish within 15 minutes")
|
||||
ev["result"] = result
|
||||
ctx.check("error" not in result, "flow-verify error: %s", result.get("error"))
|
||||
ctx.log("verdict: pass=%s threshold=%s flow_rise=%s noflow_rise=%s margins %s/%s thin=%s",
|
||||
result.get("pass"), result.get("threshold"), result.get("flow_rise"),
|
||||
result.get("noflow_rise"), result.get("margin_flow"), result.get("margin_noflow"),
|
||||
result.get("thin_margin"))
|
||||
ctx.check(result.get("pass") is True, "the threshold does not separate flow from no-flow: %s", result)
|
||||
if result.get("thin_margin"):
|
||||
ctx.log("WARNING: thin margin - run flow-calibrate")
|
||||
ctx.check(fc.wait_idle(120, abort=ctx.aborted), "machine did not return to idle after the diagnostic")
|
||||
|
||||
|
||||
AA_CAL_TIMEOUT_S = 540 # the tool's 420 s settle limit plus its six edges
|
||||
|
||||
|
||||
# Registered before the heater tools: a queue runs the catalog in this
|
||||
# order, and a heater trial leaves a warm slug circulating past the
|
||||
# coolant sensors for minutes, which the tool's edges read as disagreement.
|
||||
@test("cooling.aa-offset-calibrate", title="The air-assist ground shift on the coolant readings measures cleanly",
|
||||
subsystem="cooling", kind="auto", est_min=6,
|
||||
covers=_COOL_COVERS, requires=["kernel.latch-locked-idle"],
|
||||
@@ -137,6 +85,61 @@ IDLE_REF_TIMEOUT_S = 180 # a previous test's cooldown + spin-down
|
||||
COOLDOWN_TIMEOUT_S = 240 # the engine's smoke phase + idle drop + spin-down
|
||||
|
||||
|
||||
@test("cooling.flow-verify", title="Coolant flow check separates flow from no-flow",
|
||||
subsystem="cooling", kind="auto", est_min=4,
|
||||
covers=_COOL_COVERS, requires=["kernel.latch-locked-idle"],
|
||||
steps=["Coolant loop normal (pump on); the machine idle. The controller is suspended by "
|
||||
"forgectrl for the duration (about 3 minutes)."],
|
||||
description="forgectrl's flow-verify diagnostic: one heater window with the pump on and "
|
||||
"one with it commanded off, judged against the configured threshold. PASS = "
|
||||
"the threshold separates the two readings with the margins forgectrl reports; "
|
||||
"a thin margin is recorded as a warning.")
|
||||
def flow_verify(ctx):
|
||||
fc = ctx.forgectrl
|
||||
ev = ctx.evidence
|
||||
st, body = fc.get("/diag/status")
|
||||
ctx.check(st == 200 and isinstance(body, dict), "GET /diag/status -> %s", st)
|
||||
ctx.check(not body.get("running"), "a diagnostic is already running (%s)", body.get("tool"))
|
||||
st, body = fc.post("/diag/flow-verify")
|
||||
ctx.log("POST /diag/flow-verify -> %s %s", st, body if isinstance(body, dict) else "")
|
||||
ctx.check(st == 202 and isinstance(body, dict) and body.get("started") is True,
|
||||
"could not start flow-verify (%s %s)", st, body)
|
||||
last_phase = None
|
||||
result = None
|
||||
t0 = time.time()
|
||||
try:
|
||||
while time.time() - t0 < 900:
|
||||
ctx.checkpoint()
|
||||
st, d = fc.get("/diag/status")
|
||||
if st == 200 and isinstance(d, dict):
|
||||
if d.get("phase") != last_phase:
|
||||
last_phase = d.get("phase")
|
||||
ctx.log("phase: %s (down %.1f C, up %.1f C)", last_phase, d.get("down_c", 0), d.get("up_c", 0))
|
||||
if not d.get("running") and d.get("result") is not None:
|
||||
result = d.get("result")
|
||||
for line in d.get("log", [])[-12:]:
|
||||
ctx.log(" diag: %s", line)
|
||||
break
|
||||
time.sleep(2)
|
||||
except BaseException:
|
||||
fc.post("/diag/abort")
|
||||
raise
|
||||
ctx.check(result is not None, "flow-verify did not finish within 15 minutes")
|
||||
ev["result"] = result
|
||||
ctx.check("error" not in result, "flow-verify error: %s", result.get("error"))
|
||||
ctx.log("verdict: pass=%s threshold=%s flow_rise=%s noflow_rise=%s margins %s/%s thin=%s",
|
||||
result.get("pass"), result.get("threshold"), result.get("flow_rise"),
|
||||
result.get("noflow_rise"), result.get("margin_flow"), result.get("margin_noflow"),
|
||||
result.get("thin_margin"))
|
||||
ctx.check(result.get("pass") is True, "the threshold does not separate flow from no-flow: %s", result)
|
||||
if result.get("thin_margin"):
|
||||
ctx.log("WARNING: thin margin - run flow-calibrate")
|
||||
ctx.check(fc.wait_idle(120, abort=ctx.aborted), "machine did not return to idle after the diagnostic")
|
||||
|
||||
|
||||
AA_CAL_TIMEOUT_S = 540 # the tool's 420 s settle limit plus its six edges
|
||||
|
||||
|
||||
def _duties():
|
||||
return {k: hw.sysfs_int(k) for k in IDLE_DUTY}
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
"""cooling.aa-offset-calibrate is registered before the heater tools, so
|
||||
a queue runs it first: a heater trial leaves a warm slug circulating past
|
||||
the coolant sensors for minutes, and the tool's edges read it as
|
||||
disagreement."""
|
||||
import unittest
|
||||
|
||||
from forgetest import catalog
|
||||
|
||||
|
||||
class CoolingOrderTests(unittest.TestCase):
|
||||
def test_aa_offset_precedes_flow_verify(self):
|
||||
reg = catalog.load_suite()
|
||||
tests = catalog.all_tests(reg)
|
||||
order = catalog.order_by_requires(tests, [t.id for t in tests])
|
||||
self.assertLess(order.index("cooling.aa-offset-calibrate"), order.index("cooling.flow-verify"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user