A thermal head has no grey, so an undithered photo gets thresholded into a
solid black mass — measured at 98% black coverage on a test portrait, against
44% once dithered.
Auto-levels first, because typical webcam captures sit in the middle of the
range and dithering those directly gives flat mush. Serpentine scan order to
avoid diagonal banding across skin tones.
Decodes the model code (byte 4) to a name, adds the cooling notification
values, and rewords the error-information-2 bit 0 message. That bit is a
media mismatch, which in practice means a monochrome job sent to a black/red
roll — the exact failure seen on the QL-820NWB here.
Checked against "Raster Command Reference, QL-800/810W/820NWB v1.01". Four
things were wrong, all inherited from brother_ql's older-model defaults:
- Invalidate is 400 bytes for this series, not 200.
- The print-quality bit (0x40) is documented as invalid for two-colour
printing; it was being set regardless.
- The media-length valid bit belongs to die-cut stock only. Brother's driver
sends 0x86 for continuous tape, and the manual warns that asserting a valid
flag the loaded media doesn't match returns a "replace media" error.
- ESC i ! (automatic status notification) was missing, and the control codes
now follow the manual's per-page order.
Also confirms the 62 mm geometry we were already using: 12 left margin pins,
696 print area pins, 12 right.
A silent printer no longer blocks printing or reports as unhealthy. printPng
returns confirmed:false when no status came back, so callers don't claim a
label came out when all we know is the bytes were delivered.
The QL-820NWB does not report status over TCP 9100 — brother_ql documents the
same limitation for its network backend. queryStatus therefore became
probeStatus, which reports reachable-with-unknown-state instead of failing.
Also fixes a real bug: the socket was destroyed straight after write, which can
discard data still queued in the kernel send buffer and truncate a ~190 KB job.
Now half-closes with end() and waits for flush, with a grace window for units
that never send FIN.
Takes the PNG renderBadgePng already produces, separates black and red
planes, and sends the job over TCP. Adds a serial queue per printer host so
simultaneous sign-ins cannot collide on the printer's single connection.
Not wired into printer.js yet.
Decodes the 32-byte status frames so cover open, roll empty, cutter jam and
wrong roll width are reported from the printer itself rather than inferred
from brother_ql stderr.
Implements the QL-8xx raster protocol in Node so badge printing no longer
needs the Python brother_ql CLI. Command sequence verified byte-for-byte
against a captured QL-8xx job.