#!/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.")