Public Access
3.4 KiB
3.4 KiB
Native Brother QL Protocol (replacing brother_ql subprocess)
Date: 2026-09-07 Project: visitor-signin Status: ongoing Tags: printing, brother-ql, ql-820nwb, raster, tcp, node, dithering, feature-branch
Context
Badge printing shells out to Python brother_ql, whose network backend never reads the socket — so jobs the printer refuses can look successful — and which needed special handling for the two-colour DK-22251 roll. A native Node.js implementation of the QL raster protocol was built on a feature branch to remove the Python dependency and get honest error handling. This work is on feature/native-ql-protocol and has not been merged into deploy.
Key Decisions
- Native Node raster builder + TCP transport instead of
brother_ql— removes the Python subprocess and lets the app control the byte stream directly. - Command stream written against Brother's raster command manual, not reverse-engineered from
brother_ql— e.g. the invalidate sequence for this series is 400 bytes, not 200. - Printer status is best effort, not a precondition — the QL-820NWB does not return status frames over TCP (only USB, per the manual), so a silent printer is treated as normal. Flush before closing the socket.
- Drop-in
printPngAPI soprinter.jscan switch with a small patch rather than a rewrite. - Patch scripts instead of hand-edits —
scripts/wire-native-printing.mjsis brace-matching, idempotent and writes a.bakfirst. - Keep Python/
brother_qlin the Dockerfile for now as a rollback path; remove only after a stable day of native printing. - Floyd–Steinberg dithering targeting a fixed ink coverage (default 33.3%) for badge photos, to reduce blotchy faces.
Technical Details
- New modules:
ql-raster.js(command builder),ql-status.js(status frame decoder),ql-transport.js(TCP 9100),ql-print.js(printPngdrop-in). - Patch scripts:
scripts/wire-native-printing.mjs; a second patch script adds photo dithering. - Docs:
docs/PRINTING.md. - Badge bitmap width 696 dots (62 mm head) via
@napi-rs/canvas. - DK-22205 and DK-22251 share 62×90 mm dimensions — roll type must be part of media matching.
- Two labels printed successfully in shell-level testing.
Code Changes
- (feature branch)
ql-raster.js,ql-status.js,ql-transport.js,ql-print.js— new. - (feature branch)
printer.jswired to the native module (a9e07b3). - (feature branch) Floyd–Steinberg dithering + fixed ink coverage.
- (feature branch)
docs/PRINTING.md.
Open Questions / Next Steps
deployhas since gained its own photo halftoning and printing fixes (2026-09-16). Before merging, diff the feature branch againstdeploy— expect conflicts inprinter.jsand the photo pipeline.- Handle the tri-state printer
readyvalue (true/false/null= unknown) in the admin console. - After merge and a stable day: remove Python from the Dockerfile, delete dead
explainPrintError/runBrotherQl.
Artifacts
- Branch:
feature/native-ql-protocol(head8664a1d) 1b4b9d6— Add native Brother QL raster command builderb4001c9— Correct the command stream against Brother's raster manual851e021— Make printer status best effort, not a preconditiona9e07b3— Wire printer.js to the native QL protocol module- Repo: https://gitea.hideawaygaming.com.au/jessikitty/visitor-signin