Public Access
46 lines
3.4 KiB
Markdown
46 lines
3.4 KiB
Markdown
# 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 `printPng` API** so `printer.js` can switch with a small patch rather than a rewrite.
|
||
- **Patch scripts instead of hand-edits** — `scripts/wire-native-printing.mjs` is brace-matching, idempotent and writes a `.bak` first.
|
||
- **Keep Python/`brother_ql` in 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` (`printPng` drop-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.js` wired to the native module (`a9e07b3`).
|
||
- (feature branch) Floyd–Steinberg dithering + fixed ink coverage.
|
||
- (feature branch) `docs/PRINTING.md`.
|
||
|
||
## Open Questions / Next Steps
|
||
- `deploy` has since gained its own photo halftoning and printing fixes (2026-09-16). Before merging, diff the feature branch against `deploy` — expect conflicts in `printer.js` and the photo pipeline.
|
||
- Handle the tri-state printer `ready` value (`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` (head `8664a1d`)
|
||
- `1b4b9d6` — Add native Brother QL raster command builder
|
||
- `b4001c9` — Correct the command stream against Brother's raster manual
|
||
- `851e021` — Make printer status best effort, not a precondition
|
||
- `a9e07b3` — Wire printer.js to the native QL protocol module
|
||
- Repo: https://gitea.hideawaygaming.com.au/jessikitty/visitor-signin
|