feat(nfc): OpenPrintTag NDEF/CBOR codec - #1112
Open
goeland86 wants to merge 2 commits into
Open
Conversation
Decodes the OpenPrintTag spec (NDEF-wrapped, CBOR-encoded meta/main/aux sections) from NFC-V tag memory, plus an aux-section consumed_weight encoder for scales that want to update a tag in place. Scoped deliberately narrow per discussion on Donkie#880: codec and tests only, no wiring into the tag scan/link endpoints from Donkie#1096, no hardware dependency (nfcpy/libusb) in core. cbor2 is a dev-only dependency here since nothing outside the test suite imports this module yet. Tests build synthetic NFC-V memory (capability container + NDEF TLV + CBOR payload) rather than relying on a hardware dump, since none was available while writing these. They exercise the codec's documented field semantics and error paths, not official spec test vectors -- real hardware/spec-vector validation is still open, per Donkie's ask in the PR thread. Also fixes a latent bug found while writing the aux round-trip test: encode_aux_consumed_weight assumed the decoded aux region was always a dict, but a misaligned/corrupt region can decode as valid CBOR of a different type (e.g. a stray zero byte decodes to the int 0), which raised an undocumented TypeError instead of failing cleanly.
13 tasks
Open
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.
Summary
Split out from #880, which proposed the full NFC feature (TigerTag/Qidi/OpenPrintTag
decoding, server-side reader endpoints, browser Web NFC UI, auto-create/bind) as one
large PR.
While #880 was in review, #1096 landed: a UID-only tag/scan-relay foundation, with
content decoding explicitly deferred to a later phase. @Donkie confirmed in
this thread
that decoding should be phase 2 built on top of #1096's tag table and scan relay, not
a parallel
/api/v1/nfc/*surface, and asked for the codec work split into small,separately reviewable pieces — OpenPrintTag first, since it's what ships on retail
spools today.
This PR is that first piece: just the OpenPrintTag codec and its unit tests.
#880 is being closed in favor of this PR and the ones that follow it.
What's in this PR
spoolman/openprinttag_codec.py— decodes the OpenPrintTag NDEF/CBOR format fromNFC-V (ISO 15693) tag memory: meta/main/aux CBOR sections, UUID/enum/color fields,
and an aux-section
consumed_weightencoder for in-place tag updates.tests/test_openprinttag_codec.py— 22 tests covering the documented fieldsemantics and error paths, built against synthetic NFC-V memory dumps (capability
container + NDEF TLV + CBOR payload) constructed in the test file itself.
(
nfcpy/libusb) anywhere in the diff.cbor2is a dev-only dependency here sincenothing outside the test suite imports the module yet.
What's next — PR2/3/4 already in the pipeline
This is PR1 of four planned pieces. The other three are built and tested locally,
ready to open as their own PRs once this one's shape is agreed on:
from Sunlu, Rosa3D, R3D and eSun, so there's a case for it following reasonably
soon.
key derivation buys nothing writable today.
default, lazily imported so core never loads it unless explicitly enabled, no new
dependency since it only uses what's already core to Spoolman).
None of the above touch #1096's endpoints either. Wiring a codec into
/tag/scan—decoding a scanned tag's
payload_b64, an opt-increate: trueflag forauto-creating spools (default off, per @Donkie's note that a reader shouldn't
silently manufacture records), and
consumed_weightsurfaced as something a personconfirms rather than something that silently overwrites tracked weight — is a
further PR once the codec shapes here are settled.
Verification gap — help wanted
I don't have real OpenPrintTag hardware or an official spec test-vector set, so
these tests validate internal consistency (round-trips, documented field mappings,
error paths) against my own reading of the spec, not ground truth. @Donkie suggested
test vectors from the spec repo or a dump from someone with a tagged spool as the
way to close that gap — if anyone reading this has a Prusament (or other
OpenPrintTag-tagged) spool and can pull a raw NFC-V memory dump, that would let me
add a real fixture and be a lot more confident this decodes correctly.
Test plan
uv run pytest tests— 286 passed (264 pre-existing + 22 new)uv run ruff check ./ruff format --check .— cleanuv lock --check— clean