feat(rawcli): full INVENTORY_READ request body (mask + AFI) — 15693 complete

_inv_read_frame builds the complete ICODE inventory-read request body:
[AFI] | mask_len(bits) | mask value | first_block | count-1. INVENTORY_READ and
FAST_INVENTORY_READ gain optional mask_len/mask (selective anticollision, ceil(bits/8)
value bytes) and afi (filter byte + the 0x10 inventory flag, flags -> 0x36). Mask-less
stays the default, so existing frames are unchanged.

With this the ISO 15693 support is datasheet-complete end to end: the full request-flags
byte, both SLIX and SLIX2 command sets, and the inventory-read body. Verified live
(mask-less / 16-bit mask / AFI forms build + decode + round-trip) and unit-tested.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
michael
2026-07-16 13:08:27 -07:00
parent 251e276fbb
commit 72815e34eb
3 changed files with 34 additions and 13 deletions

View File

@@ -474,6 +474,9 @@ class TestCatalog:
assert _SLIX.get("FAST_INVENTORY_READ").build("2", "1") == bytes.fromhex("26a104000200")
assert _SLIX.by_opcode(0xA0).name == "INVENTORY_READ"
assert _SLIX.by_opcode(0xA1).name == "FAST_INVENTORY_READ"
# full body: 16-bit mask (selective anticollision), and AFI filter (flag 0x10 -> flags 0x36)
assert _SLIX.get("INVENTORY_READ").build("0", "4", "16", "abcd") == bytes.fromhex("26a00410abcd0003")
assert _SLIX.get("INVENTORY_READ").build("0", "4", afi="0x9a") == bytes.fromhex("36a0049a000003")
# dispatch: an identified SLIX (or generic ICODE) resolves to this catalog
s = RawSession(); s.protocol, s.transponder = "hf15", "ICODE SLIX"
assert catalog_for(s) is _SLIX