From 79215a5958439eb0c18041eff7ba796808ec79f0 Mon Sep 17 00:00:00 2001 From: jessikitty Date: Thu, 24 Sep 2026 00:14:25 +1000 Subject: [PATCH] docs: add session log for native QL protocol branch --- .../sessions/2026-09-07-native-ql-protocol.md | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 .claude-context/sessions/2026-09-07-native-ql-protocol.md diff --git a/.claude-context/sessions/2026-09-07-native-ql-protocol.md b/.claude-context/sessions/2026-09-07-native-ql-protocol.md new file mode 100644 index 0000000..1bb07a8 --- /dev/null +++ b/.claude-context/sessions/2026-09-07-native-ql-protocol.md @@ -0,0 +1,45 @@ +# 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