106 lines
3.4 KiB
Python
106 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Printer diagnostic v2 — tests print area width, character spacing,
|
|
and direct USB device access on Epson TM-T88V.
|
|
"""
|
|
import subprocess, sys, time, glob
|
|
|
|
PRINTER = "receipt"
|
|
|
|
ESC = b'\x1b'
|
|
GS = b'\x1d'
|
|
|
|
INIT = ESC + b'\x40'
|
|
FONT_A = ESC + b'\x4d\x00'
|
|
FONT_B = ESC + b'\x4d\x01'
|
|
SIZE_NORM = GS + b'\x21\x00' # GS ! 0 — 1x1 character size
|
|
SP_ZERO = ESC + b'\x20\x00' # ESC SP 0 — zero right-side char spacing
|
|
# GS L nL nH — set left margin to 0
|
|
MARGIN_L = GS + b'\x4c\x00\x00'
|
|
# GS W nL nH — set print area width
|
|
# 576 dots = full 80mm printable width (203dpi): 576 = 0x0240 -> nL=0x40 nH=0x02
|
|
WIDTH_576 = GS + b'\x57\x40\x02'
|
|
# 512 dots — conservative full width
|
|
WIDTH_512 = GS + b'\x57\x00\x02'
|
|
# 480 dots (what 42 chars x ~11.4 dots rounds to)
|
|
WIDTH_480 = GS + b'\x57\xe0\x01'
|
|
|
|
CUT = GS + b'\x56\x00'
|
|
|
|
RULER_42 = "123456789|123456789|123456789|123456789|12"
|
|
RULER_56 = "123456789|123456789|123456789|123456789|123456789|123456"
|
|
|
|
def send_lpr(data: bytes):
|
|
r = subprocess.run(["lpr", "-P", PRINTER, "-o", "raw"],
|
|
input=data, capture_output=True)
|
|
if r.returncode != 0:
|
|
print(" lpr error:", r.stderr.decode().strip(), file=sys.stderr)
|
|
return False
|
|
return True
|
|
|
|
def send_usb(data: bytes):
|
|
"""Try writing directly to the USB device, bypassing CUPS entirely."""
|
|
devices = sorted(glob.glob("/dev/usb/lp*"))
|
|
if not devices:
|
|
print(" No /dev/usb/lp* devices found", file=sys.stderr)
|
|
return False
|
|
dev = devices[0]
|
|
print(f" Writing directly to {dev}")
|
|
try:
|
|
with open(dev, "wb") as f:
|
|
f.write(data)
|
|
return True
|
|
except PermissionError:
|
|
print(f" Permission denied on {dev} -- try: sudo chmod a+rw {dev}", file=sys.stderr)
|
|
return False
|
|
except Exception as e:
|
|
print(f" USB write error: {e}", file=sys.stderr)
|
|
return False
|
|
|
|
def strip(label, init_seq, font=FONT_A, ruler=RULER_42, via_usb=False):
|
|
body = (
|
|
f"\n[{label}]\n"
|
|
f"{ruler}\n"
|
|
f"The quick brown fox jumps over...\n"
|
|
f"\n"
|
|
).encode("ascii")
|
|
data = init_seq + font + body + b"\n\n" + CUT
|
|
ok = send_usb(data) if via_usb else send_lpr(data)
|
|
status = "OK" if ok else "FAILED"
|
|
print(f" {status}: {label}")
|
|
time.sleep(3)
|
|
|
|
print("=== Diagnostic v2: print area & spacing tests ===\n")
|
|
|
|
print("Test 1: Baseline (same as v1 test 1) via lpr")
|
|
strip("T1 Font-A baseline lpr",
|
|
INIT + SIZE_NORM)
|
|
|
|
print("Test 2: ESC SP 0 (zero right-side character spacing)")
|
|
strip("T2 Font-A + SP=0",
|
|
INIT + SIZE_NORM + SP_ZERO)
|
|
|
|
print("Test 3: GS L 0 + GS W 576 (full printable area)")
|
|
strip("T3 Font-A + margin=0 width=576",
|
|
INIT + SIZE_NORM + SP_ZERO + MARGIN_L + WIDTH_576)
|
|
|
|
print("Test 4: GS W 512")
|
|
strip("T4 Font-A + width=512",
|
|
INIT + SIZE_NORM + SP_ZERO + MARGIN_L + WIDTH_512)
|
|
|
|
print("Test 5: Font B + full area reset")
|
|
strip("T5 Font-B + SP=0 + width=576",
|
|
INIT + SIZE_NORM + SP_ZERO + MARGIN_L + WIDTH_576,
|
|
font=FONT_B, ruler=RULER_56)
|
|
|
|
print("\nTest 6: Direct USB write (bypasses CUPS entirely) -- Font A")
|
|
strip("T6 Font-A direct USB",
|
|
INIT + SIZE_NORM + SP_ZERO,
|
|
via_usb=True)
|
|
|
|
print("\nDone.")
|
|
print("Key question: does Test 6 (direct USB) give more chars than Test 1?")
|
|
print("If yes -> CUPS is modifying the raw data even with -o raw.")
|
|
print("If all same -> printer NV memory has a constrained print area.")
|
|
print("Report what you see on each strip.")
|