Debug/print flow#2
Open
mannes wants to merge 17 commits into
Open
Conversation
parseSkuInfo read the ESC U geometry fields as whole millimetres per the 550 reference table, but an on-the-wire S0722540 capture (a 57x32 mm roll reporting 571/317) shows the NFC tag encodes deci-millimetres. All *Mm geometry fields now convert from deci-mm, so detectedMedia reports 57.1 x 31.7 instead of 571 x 317. The MULTI_PURPOSE_MEDIUM catalogue entry was stored transposed (32x57); corrected to 57x32 (widthMm = across-head, heightMm = feed) with lengthDots recomputed to 378. findMediaByDimensions is marked @deprecated (removal in 0.7.0): nothing maps detectedMedia onto a catalogue entry, and its exact dimension equality cannot match the deci-mm values parseSkuInfo now produces. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A tag with a prerelease identifier (e.g. v0.6.3-debug.0) now publishes under that identifier as an npm dist-tag and is marked as a GitHub prerelease, leaving the `latest` dist-tag untouched. Stable tags are unaffected — they still publish to `latest` with make_latest: true. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a grep-able dbg() helper per package and console.debug calls at the crucial print-flow points — print start, 550 lock, media resolved, rotation/bitmap, encode, transport write — in the node + web doPrint() paths and the core encodeLabel/encodeDuoTapeLabel encoders. Temporary, debug/print-flow branch only. See DEBUG_RELEASE.md. Must not merge to main. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Instrumented prerelease of core/node/web. Publishes to the `debug` npm dist-tag via the prerelease-aware release workflow. Lockfile unchanged (version-only bump of workspace packages). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Welcome to Codecov 🎉Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests. ℹ️ You can also turn on project coverage checks and project coverage reporting on Pull Request comment Thanks for integrating Codecov - We've got you covered ☂️ |
…bels
The 550 print job is an interactive half-duplex exchange, not a
fire-and-forget blob. The firmware stops draining the bulk-OUT endpoint
after each label's ESC G footer until the host issues ESC A and reads
the 32-byte status reply — so the previous monolithic write hung
mid-job, leaving the printer lock-stuck (powercycle) and print()
unresolved (harness result section frozen).
Prior art: minlux/dymon (Wireshark RE of the DYMO Wireless + 550
protocol). Two confirmed bugs vs the DYMO 550 Tech Ref + dymon:
- core: encode550Label built a monolithic blob with no mid-job status
read. Add compose550Job -> { preamble, labels[], finalize }; the
driver writes preamble, then per label writes the segment + ESC A and
drains the 32-byte status, then writes ESC E + ESC Q. ESC A lock byte
is 0 for the last label (final query + lock release), 2 between
labels (host defers that read). encode550Label now concatenates the
segments — offline/test view only.
- core: build550LabelIndex emitted ESC n as u32; spec + dymon + our own
status parser (u16 echo) say u16. The 2 extra bytes desync the
firmware command parser ahead of ESC D.
- web + node: doPrint routes lw5-raster through the new interactive
write550Job. The web handshake read is timed (15s) so a wedged
firmware throws instead of hanging print() forever.
ESC M (1B 4D 00x8, seen in dymon) deliberately NOT added — undocumented
in the DYMO 550 Tech Ref and not stall-relevant.
Diagnosed from prior art; not yet bench-confirmed — no LW 550 on the
bench, external tester validates.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
550 interactive print-handshake fix (e526e06) — drives ESC A status between labels so the firmware no longer stalls the bulk-OUT endpoint; ESC n label index corrected u32 -> u16. Publishes core/node/web to the `debug` npm dist-tag via the prerelease-aware release workflow. Lockfile unchanged (version-only bump of workspace packages). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CI flagged web branch coverage at 89.71% after the interactive 550 print rewrite (e526e06): write550Job's deferred-handshake path (ESC A 2 between labels) had no test. Add a copies:2 web print test that exercises it, and drop two unreachable `?? -1` branches in the handshake debug logging. web branch coverage 89.71% -> 92.04%. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…CanvasDots
The pre-2026-05-23 encoder cropped `leading` mm of rows off the input
bitmap so the head's mechanically unreachable band wouldn't eat
authored content. That worked on rolls where the firmware didn't
itself compensate (older LW 3xx/4xx), but on newer LW 550 rolls the
NFC SKU dump's `marker1ToStart` already shifts the head past the
deadzone — chassis pre-trim then double-counted and left ~6 mm blank
on the trailing edge.
The architectural fix is to move dead-zone awareness off the wire-
encoding path and onto the authoring layer. Designer / harness code
sizes its canvas to what the head can physically reach; the encoder
trusts every row.
* `composeWireBitmap` / `composeWireBitmap550` collapse to width-only
fit (pad-right or crop-right to `headDots`, every row through).
* New `getPrintableCanvasDots(engine, media)` helper exposes the
dot-space deductions callers must subtract from the label length:
`{widthDots, leadingDots, trailingDots, leftDots, rightDots}`.
One place owns the mm→dot rounding.
* Suspended plan-08 §6 tests deleted; replaced with assertions that
the encoder ignores `printableArea` regardless of value, plus
coverage on the new helper.
The `printableArea` field stays on every device entry — its meaning
shifts from "crop this much from the wire" to "the authoring layer
must subtract this much from the canvas".
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Callers that author a bitmap at the printable-canvas size (label length minus leading + trailing dead zones) now author shorter than the physical label. `encodeLabel` defaults ESC L to `bitmap.heightPx`, which would shrink the form-feed pitch and compound across copies. `WebLabelWriterPrinter.print()` now back-fills `options.labelLengthDots = resolvedMedia.lengthDots` whenever: * the caller didn't supply one explicitly, AND * media exposes a `lengthDots` (i.e. die-cut), AND * the bitmap is shorter than that lengthDots. Explicit overrides still win; tape media (no lengthDots) falls through to the encoder's `bitmap.heightPx` default, unchanged. Pairs with the labelwriter-core change that exposes `getPrintableCanvasDots` for the authoring layer. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Plan stub for moving printable-area handling out of `labelwriter-core` has landed in core + web on this branch (commits 889491d, 105e7cc). Moves the doc from `plans/backlog/` to `plans/implemented/` and updates the status line. Bench confirmation on the LW 550 still pending. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…16; SKU lengths are deci-mm
Three on-the-wire facts that bench / prior-art surfaced and the
Tech Ref does not state clearly:
* The 550 print job is interactive half-duplex. After every label's
\`ESC G\` footer the firmware blocks bulk-OUT until the host reads
a 32-byte \`ESC A\` reply. Adds an "Inter-label status handshake"
subsection alongside the existing "Lock acquisition" subsection,
and annotates the job-structure ASCII diagram with the handshake
point. The host writes the job in segments, not one blob.
* \`ESC n\` parameter is u16 (2 bytes), not u32 — the status reply
echoes back as u16 and the wire field matches. Opcode table row
and body section corrected; a u32 emission leaks two stray null
bytes ahead of \`ESC D\` and desyncs the firmware command parser.
* \`ESC U\` length fields are encoded as deci-mm on the wire even
though the Tech Ref labels them "Length in mm". Bench-confirmed
against an S0722540 capture (57.1 x 31.7 mm reports 571 / 317).
Added a caveat block above the table and updated every length row
to "deci-mm (/10 for mm)". Count, strategy and date fields are
not affected.
References section gains minlux/dymon (prior-art Wireshark RE of the
DYMO 550 / Wireless protocol) alongside the DYMO Tech Ref.
\`ESC G\`'s own body section is intentionally left unchanged — the
handshake obligation is owned by the new subsection, not duplicated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The interactive 550 print loop (write segment -> ESC A -> drain status,
deferred between labels, sync on the last) was duplicated almost
byte-for-byte in WebLabelWriterPrinter and NodeLabelWriterPrinter. Only
real difference: web supplied a finite handshakeReadTimeoutMs because
WebUSB has no implicit deadline; node passed nothing.
It's pure protocol orchestration — no driver state, no transport-
specific behaviour — so the home is labelwriter-core, alongside
compose550Job (its natural pair).
* Add write550Job(transport, job, opts?) + Write550JobOptions in
protocol-550.ts. Loop body verbatim from the old copies.
* Export from labelwriter-core's index.
* Web/Node printers drop the private method and dispatch through
core; web passes its 15 s handshake deadline, node leaves the read
untimed (untouched behaviour for both).
* Five new core tests pin the orchestration contract: op order,
inter-label vs final ESC A lock byte, deferred-vs-sync read
timing, and the timeout pass-through.
Net effect on per-driver line count: web -47, node -36, core +83
(plus +140 test). Future bug fixes (mid-job error detection, parsing
the drained status, etc.) land in one place.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The bulk-OUT stall mechanic and the inter-label handshake contract
now live in docs/protocol/lw5-raster.md. Code sites point to that
doc instead of re-deriving it in JSDoc / call-site comments.
* Composed550Job, compose550Job, write550Job JSDoc — keep purpose +
pointer; drop the spec narrative.
* Web and node dispatch comments — one-line "see write550Job" plus
the local decision (web supplies a finite read deadline; node
leaves the read untimed).
No behaviour change. Typedoc output regenerated to match.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix reading label size on lw 5xx, add debugging to print flow