mirror of
https://github.com/openglow-org/forgefirm.git
synced 2026-09-27 16:51:12 -07:00
forgetest: the fixture spaces its presses; an unattended refusal is an error; the baseline resets out of a hold
The first campaign with the bench actuator wired failed motion.button-hold-resume on the tool, not the machine: the second press was asked while the first 200 ms pulse was still on, the fixture answered 409, the runner handed the step to an operator who was not in the room, and the post pass could not jog a controller left in Hold. - fixture.py: a press waits for the last pulse to end (the fixture's pulse_ms) plus a 300 ms release, so the controller sees the edge; a 409 for a pulse in progress is waited out against button_pulsing and retried once. - runner.py: in an unattended run a fixture refusal ends the test at once as ERROR naming the refusal; the operator fallback stays for attended runs. - baseline.py: a controller in Hold or Door gets a soft reset before the return jog, position kept. - tests: the fake fixture refuses a press while one is in progress and reports button_pulsing; FakeGrbl records ^X and can land a reset in a chosen state; five new tests. - docs: ACCEPTANCE.md fixture rules, fixture/README.md tool's side. No catalog consequence: tool-side change, no covers map moves. Bench: campaign c-20260824174545-0bdc 25/25 with every action by the fixture; the hold reset proven by a dry drill.
This commit is contained in:
@@ -119,6 +119,33 @@ class BaselineTests(unittest.TestCase):
|
||||
self.assertTrue(items["position"].action.startswith("unrestorable"), items["position"].action)
|
||||
self.assertEqual(items["position"].found, [1000, 0, 0])
|
||||
|
||||
def test_a_held_controller_is_reset_before_the_return_jog(self):
|
||||
# a pause test that failed while held leaves the controller in
|
||||
# Hold, which refuses a jog: the baseline resets out of it first
|
||||
import helpers
|
||||
fc = helpers.FakeForgectrl().start()
|
||||
dev = helpers.FakeGrbl().start()
|
||||
try:
|
||||
dev.state = "Hold:0"
|
||||
dev.reset_to = "Idle"
|
||||
dev.on_command = lambda line: self._pos(0, 0, 0) if line.startswith("$J=") else None
|
||||
b = self.bl()
|
||||
cap = b.capture()
|
||||
self._pos(221, 0, 0) # 4.144 mm into the held move
|
||||
left = b.enforce("post", captured=cap)
|
||||
items = {x.item: x for x in left}
|
||||
self.assertTrue(items["position"].action.startswith("restored"), items["position"].action)
|
||||
self.assertEqual(dev.sent[0], "^X")
|
||||
jogs = [l for l in dev.sent if l.startswith("$J=")]
|
||||
self.assertEqual(len(jogs), 1)
|
||||
self.assertIn("X-4.144", jogs[0])
|
||||
self.assertTrue(any("reset out of Hold:0" in l for l in self.lines), self.lines)
|
||||
finally:
|
||||
dev.stop()
|
||||
fc.stop()
|
||||
for k in ("GRBL_HOST", "GRBL_PORT"):
|
||||
os.environ.pop(k, None)
|
||||
|
||||
def _pos_bytes(self, x, y, z, processed, total):
|
||||
with open(self.sysfs + "cnc/position", "wb") as f:
|
||||
f.write(struct.pack("<3i2I", x, y, z, processed, total))
|
||||
|
||||
Reference in New Issue
Block a user