RFID Exact Product Locator Development
Publicada el 2026-07-16
Descripción de la oferta
# Developer Spec — Exact-Product RFID Filter (58-bit Select) ### Battle Sports · Zebra MC3330xR · UHF RAIN RFID ## 1. Objective Build a small Android app for the **Zebra MC3330xR** that **inventories and locates a single exact product**, distinguishing products whose tag data differs by as little as **one bit**. Operator enters/scans a **UPC**; the app applies a precise **58-bit Gen2 Select pre-filter** so the reader responds to **only that product**, with a proximity readout to walk to it. This does **not** exist in Zebra's free *123RFID Mobile* app, whose pre-filter UI cannot reliably apply a sub-nibble (58-bit) mask. The Zebra RFID SDK exposes the bit-level Select parameters directly — hence a custom app. ## 2. Why 58 bits Tags are **GS1 SGTIN-96** (96-bit EPC): Header 8 (`0x30`) · Filter 3 (`1`) · Partition 3 · Company Prefix 20–40 · Item Reference 24–4 (prefix+itemref always = 44) · **Serial 38 (unique per unit)**. The **product identity (GTIN) is the first 58 bits** (96−38). The last 38 bits are a per-unit serial. To match "this product, any serial," Select on **exactly the first 58 bits**. Hex prefixes only express whole nibbles: - **56-bit (14 hex)** → too short; misses the distinguishing bit on near-twins. - **60-bit (15 hex)** → reaches into the per-unit serial; matches only *some* units. Only a **non-nibble-aligned 58-bit** mask works, and only the SDK can set it. That is the entire reason for this project. ## 3. Platform - **Device:** Zebra MC3330xR (integrated UHF RFID, model MC333U…). - **OS:** Android 11 (Zebra GMS build). - **SDK:** **Zebra RFID SDK for Android**, package `com.zebra.rfid.api3` ("RFID API3"). Use the current release; **verify method signatures against that version** — the API drifts across releases. - **Reader:** internal reader; enumerate via `Readers(context, ENUM_TRANSPORT.SERVICE_USB)` and connect the first available. - **Build:** Android Studio, signed APK; deploy via sideload/StageNow/MDM. ## 4. Core requirement — the 58-bit pre-filter (the crux) Apply a Gen2 Select before Inventory/Locate. Reference (verify vs your SDK version): ```java import com.zebra.rfid.api3.*; PreFilters preFilters = new PreFilters(); PreFilters.PreFilter pf = preFilters.new PreFilter(); pf.setMemoryBank(MEMORY_BANK.MEMORY_BANK_EPC); pf.setBitOffset(32); // *** skip StoredCRC(16)+StoredPC(16); EPC starts at bit 32 pf.setTagPattern("30343183AC045D0"); // 58-bit pattern packed into nibbles (see note) pf.setTagPatternBitCount(58); // *** THE KEY: compare exactly 58 bits, not 56 or 60 pf.setFilterAction(FILTER_ACTION.FILTER_ACTION_ASSERT_UNASSERT_SL); // assert SL on match, deassert others pf.setFilterTarget(TARGET.SESSION_S1); // hold state across rounds (verify enum name) reader.Actions.PreFilters.add(new PreFilters.PreFilter[]{ pf }); ``` Then inventory querying **only SL-asserted tags** so non-matches are silenced: ```java Antennas.SingulationControl s = reader.Config.Antennas.getSingulationControl(1); // configure state-aware (SL) singulation consistent with FILTER_ACTION above reader.Config.Antennas.setSingulationControl(1, s); reader.Actions.Inventory.perform(); // only the exact product returns ``` **Pattern packing:** `tagPattern` is nibble/byte-packed; `tagPatternBitCount = 58` tells the radio to compare only the first 58 bits (the last 2 bits of the 15th nibble are ignored padding). Confirm whether your build wants a hex `String` or `byte[]`. **Critical:** `setBitOffset(32)` and `setTagPatternBitCount(58)` make or break this. Wrong offset → mask lands on CRC/PC junk. bitCount 56 → near-twins collide. ## 5. UPC → 58-bit pattern (validated logic — reuse verbatim) ``` encode(UPC12, companyPrefixLen): gtin14 = leftPad(UPC12, 14, '0') indicator= gtin14[0]; middle12 = gtin14[1..12] companyPrefix = middle12[0 .. companyPrefixLen-1] itemRefGtin = middle12[companyPrefixLen .. end] itemField = indicator + itemRefGtin // decimal concat partition = {6->6,7->5,8->4,9->3,10->2,11->1,12->0}[companyPrefixLen] cpBits = {6->20,7->24,8->27,9->30,10->34,11->37,12->40}[companyPrefixLen] irBits = {6->24,7->20,8->17,9->14,10->10,11->7,12->4}[companyPrefixLen] bits = bin(0x30,8) + bin(1,3) + bin(partition,3) + bin(int(companyPrefix),cpBits) + bin(int(itemField),irBits) return first 58 bits of bits // Select pattern; bitCount=58, offset=32 ``` ### WARNING — Company-prefix-length ambiguity (must handle — real on this data) A UPC does not carry its GS1 company-prefix length, and **this supplier encodes inconsistently** — the same brand uses **7-digit (partition 5)** on some products, **8-digit (partition 4)** on others. A pure UPC->pattern compute will sometimes pick the wrong partition and match nothing. Resolve, in priority order: 1. **Seed from a reference tag (recommended).** On first encounter, operator scans **one physical unit's RFID tag**; app decodes its EPC (reverse of §5), extracts the **actual partition + first-58-bit pattern**, stores it keyed by UPC. All later locates use the stored pattern — ground truth, ambiguity gone. 2. **GS1 GCP Length Table** lookup (access restricted since Jan 2026; budget to license/cache a copy). 3. **Compute both 7- and 8-digit candidates, try in order** (fallback). Include an EPC-hex -> UPC+partition decoder for step 1 (also validated in scoping). ## 6. App features 1. **Product entry:** type a UPC, or scan the printed UPC barcode via the built-in imager (DataWedge -> field). 2. **Resolve pattern** per §5; if unknown, prompt to seed from a reference-tag scan. 3. **Apply pre-filter** (§4). 4. **Inventory mode:** live **count** of the exact product (near-twins excluded). 5. **Locate mode:** proximity (RSSI/%) + beeper intensifying with proximity, trigger-driven. 6. **Power control:** expose TX power (0–30 dBm) for close-range pinpointing. 7. **Session/target** handling so the filter persists across rounds. ## 7. Data model (minimum) `products`: `upc` (PK), `gtin14`, `company_prefix_len`, `partition`, `pattern_hex` (58-bit packed), `pattern_bitcount` (=58), `bit_offset` (=32), `source` (`reference_tag`|`gcp_table`|`computed`), `verified_at`. ## 8. Acceptance test (pass/fail — use these exact values) Two **real, different** products differing by one bit. Pass only if each is isolated. | UPC | Encoding | 58-bit pattern (hex, packed) | bitCount | bitOffset | |---|---|---|---|---| | **811243044689** | 7-digit / partition 5 | `30343183AC045D0` | 58 | 32 | | **811243044702** | 7-digit / partition 5 | `30343183AC045D8` | 58 | 32 | Both share the **first 56 bits** (`30343183AC045D`) — they collide at 14 hex chars and first differ at **bit index 56**. - **T1 (isolation):** with both present, load 689 -> report **only 689**, reject all 702. Repeat for 702. - **T2 (completeness):** with N units of 689 (varying serials) -> return **all N** (matches product, not one serial). - **T3 (negative control):** set `bitCount = 56` -> both appear (demonstrates the bug the fix resolves). - **T4 (mixed encoding):** include one 8-digit/partition-4 product -> reference-tag seeding (§5.1) resolves it. ## 9. Deliverables 1. Signed, installable **APK** for Android 11 on the MC3330xR. 2. **Source** (Android Studio project) + build instructions. 3. **UPC->pattern encoder** and **EPC->UPC decoder** as tested modules (unit tests using §8 vectors). 4. Short **operator guide** + deployment notes. 5. Demonstrated §8 tests passing on the physical device. ## 10. Skills / effort Required: **Android (Java/Kotlin)** + hands-on **Zebra RFID SDK for Android** experience (GS1/EPC a plus; encoding is fully specified). Scope is a focused single-purpose app (one reader, one filter type, two modes) — **days, not weeks** for an experienced dev. Main risks to flag to bidders: SDK-version signature drift (§3) and confirming Select/singulation interplay on the MC3330xR (§4). ## 11. References - Zebra **RFID SDK for Android** (`com.zebra.rfid.api3`), developer.zebra.com — `PreFilters.PreFilter`, `setTagPatternBitCount`, `setBitOffset`, `FILTER_ACTION`, `Antennas.SingulationControl`. - GS1 **EPC Tag Data Standard** — SGTIN-96 layout, GTIN EPC translation. - GS1 **GCP Length Table** — company-prefix-length resolution (access restricted since Jan 2026). *Everything to quote and build is here: exact SDK params (offset 32, bitCount 58), validated encoding, the prefix-length fix, and a concrete pass/fail test against real products.* Bottom line, I need the hex code to place into the find function of the RFID scanner.
Skills
Fuente original: freelancer