fix(urovo): status() falls back to ESC !S — firmware stops answering ESC !? after &CALIBRATE,A,R

After &CALIBRATE,A,R this printer answered model() but not the one-byte <ESC>!?
status, for minutes, so wait_ready/recover/do_print all reported 'no response'
and refused to print a printer that was in fact Ready. The extended <ESC>!S is
still answered: STX + 4 bytes + ETX CRLF, first byte 0x40+code, which maps
one-to-one onto STATUS_TEXT (0x48 = ribbon latched, 0x40 = Ready). Seen live:
!? silent, !S -> 02 40 40 40 40 03 0D 0A.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
type-two 2026-09-04 11:19:17 +10:00
parent 3a741079d6
commit 88f18d98a1

View File

@ -147,11 +147,28 @@ class Urovo(object):
# ---- status ----------------------------------------------------------
def status(self, wait=0.8):
"""Real-time status: <ESC>!? -> one byte. 0x00 = Ready."""
"""Real-time status. 0x00 = Ready.
Asks the one-byte <ESC>!? first. After &CALIBRATE,A,R this firmware stops answering
that form entirely -- the printer sat "no response" for minutes while model() kept
working over the same pipe -- and every caller that gates on status() (wait_ready,
recover, do_print) then refuses to print a printer that is in fact fine. So fall back to
the extended <ESC>!S, which it does keep answering: STX + 4 status bytes + ETX CR LF,
first byte 0x40 + code. That offset maps one-to-one onto STATUS_TEXT (0x41 head open,
0x48 ribbon latched, 0x40 ready), so the fallback returns the same codes as the primary.
Seen live: <ESC>!? silent, <ESC>!S -> 02 40 40 40 40 03 0D 0A = Ready."""
self.flush_in()
self.write(b'\x1b!?')
r = self.read(wait)
return r[-1] if r else None
if r:
return r[-1]
self.flush_in()
self.write(b'\x1b!S')
r = self.read(wait)
i = r.find(b'\x02') if r else -1
if i >= 0 and len(r) > i + 1:
return (r[i + 1] - 0x40) & 0xFF
return None
def model(self):
self.flush_in()