mirror of
https://github.com/openglow-org/forgefirm.git
synced 2026-09-29 01:21:16 -07:00
forgetest: a resume is proven by leaving the hold, and status polling no longer eats [MSG:] lines
Bench (image 20260817124714): motion.button-hold-resume FAILED on a machine that did exactly the right thing. The operator paused about 7 s into an 8 s move, so the resume had a fraction of a second of travel left; the job was already Idle by the next poll and the test - which insisted on catching the Run state - called it "the second press did not resume the job". Its own evidence contradicted the verdict: the kernel counters read 2133 = 40.000 mm, the whole move, and the position check two lines below would have passed. Catching the state a command moves INTO is a race whenever the remaining work is short. What proves the press was acted on is the job LEAVING the hold, so that is what the test waits for now (wait_left_state), with the state it left into required to be Run or Idle - not Alarm or Door - and the existing "landed on its target" check still doing the real work. laser.pause-resume-lid-cancel had the same shape and gets the same treatment. Second defect, visible in the same record as "message seen: False": the driver DOES report "button pressed - job paused", but Grbl.status_report() began by discarding the read buffer and then kept only what followed the report, so every asynchronous [MSG:] line that landed during a poll was thrown away. It now consumes status reports only - stale ones included, which is what that discard was for - and leaves everything else for drain(). Tests that assert on what the controller said open their window with an explicit drain() before the prompt, so the text they judge is the text from the action.
This commit is contained in:
@@ -228,7 +228,8 @@ class Grbl:
|
||||
pass
|
||||
self.sock = None
|
||||
|
||||
def drain(self):
|
||||
def _recv(self):
|
||||
"""Pull whatever is waiting into the buffer; never blocks long."""
|
||||
self.sock.settimeout(0.05)
|
||||
try:
|
||||
while True:
|
||||
@@ -238,6 +239,22 @@ class Grbl:
|
||||
self.buf += d
|
||||
except (socket.timeout, OSError):
|
||||
pass
|
||||
|
||||
def _take_report(self):
|
||||
"""Remove every complete <...> report from the buffer and return the
|
||||
last one, keeping the text around them. Status reports are the only
|
||||
thing consumed here: the driver's [MSG:] lines stay for drain()."""
|
||||
last = None
|
||||
while True:
|
||||
i = self.buf.find(b"<")
|
||||
j = self.buf.find(b">", i + 1) if i >= 0 else -1
|
||||
if i < 0 or j <= i:
|
||||
return last
|
||||
last = self.buf[i + 1:j].decode("utf-8", "replace")
|
||||
self.buf = self.buf[:i] + self.buf[j + 1:]
|
||||
|
||||
def drain(self):
|
||||
self._recv()
|
||||
out, self.buf = self.buf, b""
|
||||
return out.decode("utf-8", "replace")
|
||||
|
||||
@@ -279,8 +296,12 @@ class Grbl:
|
||||
"""One '?' report, parsed: {'state': 'Idle', 'MPos': (x,y,z), ...}.
|
||||
The '?' is re-sent every 0.5 s until a report arrives: a soft
|
||||
reset (^X) flushes the controller's read buffer and eats a '?'
|
||||
that lands in it."""
|
||||
self.drain()
|
||||
that lands in it. Reports already buffered are stale and dropped -
|
||||
but only the reports: anything else the controller said is left in
|
||||
the buffer, so a test that polls for a state does not lose the
|
||||
[MSG:] line that explains it."""
|
||||
self._recv()
|
||||
self._take_report() # stale: predates this '?'
|
||||
self.send_raw(b"?")
|
||||
deadline = time.time() + self.timeout
|
||||
resend = time.time() + 0.5
|
||||
@@ -295,11 +316,8 @@ class Grbl:
|
||||
if time.time() >= resend:
|
||||
self.send_raw(b"?")
|
||||
resend = time.time() + 0.5
|
||||
i = self.buf.find(b"<")
|
||||
j = self.buf.find(b">", i + 1) if i >= 0 else -1
|
||||
if i >= 0 and j > i:
|
||||
rep = self.buf[i + 1:j].decode("utf-8", "replace")
|
||||
self.buf = self.buf[j + 1:]
|
||||
rep = self._take_report()
|
||||
if rep is not None:
|
||||
return parse_report(rep)
|
||||
raise HwError("no status report from grbl")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user