forgetest: the setup burns need two witnesses and record the beam sensor

setup.focus and setup.floor follow forgectrl: a burn counts on the tube
current and the kernel's LASER_ON samples, and its result records the
beam sensor's rise and beam_sensor_seen, never requiring a rise (a head
may give no output from the sensor). The check reads that both are
recorded and logs them; the descriptions name the two witnesses.

Proof: the setup host tests (74) and the manifest tests pass, two of
them new: a burn whose sensor gave no output passes, and a result that
does not record the sensor fails, each with the settings put back.

Acceptance: these are the tests.
This commit is contained in:
ScottW514
2026-10-12 16:15:24 -04:00
parent ecbfe64cef
commit 748d28686d
2 changed files with 27 additions and 7 deletions
+10 -6
View File
@@ -81,13 +81,16 @@ def preview_ok(ctx, wid):
def emission_ok(ctx, last): def emission_ok(ctx, last):
"""The three witnesses of the burn, from the wizard's result.""" """The two witnesses of the burn, from the wizard's result. The head's
beam sensor is recorded, never required: the result reports its rise
and whether it read as the beam seen."""
e = (last.get("result") or {}).get("emission") or {} e = (last.get("result") or {}).get("emission") or {}
ctx.evidence["emission"] = e ctx.evidence["emission"] = e
ctx.check(e.get("hv_max", 0) > 30, "the tube current never rose (%s)", e.get("hv_max")) ctx.check(e.get("hv_max", 0) > 30, "the tube current never rose (%s)", e.get("hv_max"))
ctx.check(e.get("laser_on_samples", 0) > 0, "the kernel never sampled LASER_ON") ctx.check(e.get("laser_on_samples", 0) > 0, "the kernel never sampled LASER_ON")
ctx.check(e.get("thermopile_delta", 0) >= 100, "the thermopile did not see the beam (%s)", ctx.check(isinstance(e.get("thermopile_delta"), int) and isinstance(e.get("beam_sensor_seen"), bool),
e.get("thermopile_delta")) "the result does not record the beam sensor: %s", e)
ctx.log("the beam sensor rose %s (seen: %s)", e.get("thermopile_delta"), e.get("beam_sensor_seen"))
def thickness_answer(ctx): def thickness_answer(ctx):
@@ -219,8 +222,9 @@ def focus_window_ok(ctx, r, before):
"head and its tail returns there. With its preview and program served by GET " "head and its tail returns there. With its preview and program served by GET "
"/wiz/sheet.svg and /wiz/sheet.gcode and every Z the program commands inside the " "/wiz/sheet.svg and /wiz/sheet.gcode and every Z the program commands inside the "
"reach /status reports, it burns twelve lines after the press, from the top of " "reach /status reports, it burns twelve lines after the press, from the top of "
"the window to the bottom, seen by the three witnesses (the tube current, the " "the window to the bottom, seen by the two witnesses (the tube current and the "
"kernel's LASER_ON samples, the thermopile rise). The pick is line 11. The " "kernel's LASER_ON samples), with the beam sensor's rise recorded and not "
"required. The pick is line 11. The "
"result carries its keys; the ladder ran in the window the machine held, which " "result carries its keys; the ladder ran in the window the machine held, which "
"the burn leaves as found (it writes the edge alone, the one its result " "the burn leaves as found (it writes the edge alone, the one its result "
"reports); every ladder height lies in the reach; the program served afterward " "reports); every ladder height lies in the reach; the program served afterward "
@@ -273,7 +277,7 @@ def focus(ctx):
"its preview and program served and every Z the program commands inside the " "its preview and program served and every Z the program commands inside the "
"reach /status reports, it burns twelve rungs from 2 to 24 percent density at " "reach /status reports, it burns twelve rungs from 2 to 24 percent density at "
"the focal point on the scrap's surface, the floor and the curve off for the " "the focal point on the scrap's surface, the floor and the curve off for the "
"job, after the press, seen by the three witnesses. The pick is 8, so the floor " "job, after the press, seen by the two witnesses. The pick is 8, so the floor "
"written is 10 (two above it) and the setting reads it; the result carries its " "written is 10 (two above it) and the setting reads it; the result carries its "
"keys; the record carries laser.floor at version 1. laser_floor_density is " "keys; the record carries laser.floor at version 1. laser_floor_density is "
"restored at the end.") "restored at the end.")
+17 -1
View File
@@ -22,7 +22,8 @@ from forgetest.runner import Context, Failed, Run # noqa: E402
from forgetest.suite import setup_burns, setup_dark # noqa: E402 from forgetest.suite import setup_burns, setup_dark # noqa: E402
LIVE = ["laser.focus", "laser.floor"] LIVE = ["laser.focus", "laser.floor"]
EMISSION = {"hv_max": 610, "laser_on_samples": 900, "thermopile_delta": 600, "lit_s": 30.0} EMISSION = {"hv_max": 610, "laser_on_samples": 900, "thermopile_delta": 600, "beam_sensor_seen": True,
"lit_s": 30.0}
SPM = 2.922 # the lens screw, half-steps per mm ($102) SPM = 2.922 # the lens screw, half-steps per mm ($102)
EDGE_DEFAULT = 3.35 # the edge's height while the setting is unset (lens.h) EDGE_DEFAULT = 3.35 # the edge's height while the setting is unset (lens.h)
@@ -368,6 +369,21 @@ class BurnRunTests(unittest.TestCase):
self.assertIn("the tube current never rose", str(cm.exception)) self.assertIn("the tube current never rose", str(cm.exception))
self.assert_found() self.assert_found()
def test_a_burn_with_a_silent_beam_sensor_passes(self):
# A head whose beam sensor gives no output: the tube current and
# LASER_ON saw the beam, so the burn counts.
self.daemon.patch["laser.floor"] = {"emission": dict(EMISSION, thermopile_delta=0,
beam_sensor_seen=False)}
self.run_test("setup.floor")
self.assert_found()
def test_a_burn_that_does_not_record_the_beam_sensor_fails(self):
self.daemon.patch["laser.floor"] = {"emission": {"hv_max": 610, "laser_on_samples": 900}}
with self.assertRaises(Failed) as cm:
self.run_test("setup.floor")
self.assertIn("the result does not record the beam sensor", str(cm.exception))
self.assert_found()
def test_a_focus_burn_that_writes_the_window_fails(self): def test_a_focus_burn_that_writes_the_window_fails(self):
# The focus burn writes the edge alone: the window is the Lens # The focus burn writes the edge alone: the window is the Lens
# travel check's. A burn that moves it fails, and it goes back. # travel check's. A burn that moves it fails, and it goes back.