Files
visitor-signin/.claude-context/sessions/2026-09-07-native-ql-protocol.md
T

46 lines
3.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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