● CASE STUDY · IDENTIUM TECH SOLUTIONS
Identium InvenX
RFID stock counts from a sealed box, reconciled against the database
OVERVIEW
Counting apparel stock by hand is slow and wrong. InvenX replaces the count with a sealed box that reads every UHF tag inside it at once and a backend that turns those reads into an answer. The box app opens a scan session, streams the EPCs it saw, and closes the session; the server diffs the read set against expected in-stock tags and returns the three lists that actually matter. Everything the box and handheld do pushes onto a live dashboard over Server-Sent Events, so a manager watching the web app sees each sale, each missing tag, and each reconcile as it happens.
THE CHALLENGE
The two readers had nothing in common. The handheld is a CX1500N on modern Android with a native UHF SDK; the box is a Rockchip RK3568 running Android 11 with only a vendor demo APK and a pure-Java jar, no docs. I pulled a full ADB dump of the box, 39 files covering build props, packages, input devices, and partitions, to work out what the hardware actually was and which SDK the vendor app used, then wrote both readers against a single six-method UhfReader interface so nothing above it cares which box it is running on. The other problem was testing: RFID reading only works on the real hardware, so both apps and the dashboard have a manual EPC path that exercises the same session, ingest, and reconcile calls on any device.
WHAT I BUILT
- 01
A reconciliation engine in the sessions route that pulls distinct EPCs read in a session, pulls expected in-stock tags for that location, and returns present, missing, and unknown as three arrays plus counts. Unknown EPCs get looked up so a sold or foreign tag is labelled instead of just listed.
- 02
An 11-table MySQL schema where products are item types and tags are individual physical units, one EPC each, with scan_sessions holding tag_reads (EPC, TID, RSSI, antenna, read count, time) and every status change writing a row to stock_movements as an audit trail.
- 03
One UhfReader interface in a shared core module with two implementations: the handheld talks to the CX1500N over UART /dev/ttysWK0 with continuous MULTI_TAG_FAST inventory and power set in centi-dBm, the box drives RealOpenIOT's RFIDApiManager on CORE1204 with two polling threads over RxJava schedulers. Everything above the interface is reader-agnostic, so both apps share the API client, auth, and DTOs.
- 04
A Server-Sent Events hub in the backend that broadcasts session.started, reads.ingested, session.reconciled, tag.update, and sale to every connected dashboard, with a JWT passed as a query param because EventSource cannot set headers, plus a client that reconnects on its own after three seconds.
- 05
An eight-page Astro dashboard: live KPIs and activity feed, inventory with per-status filters and bulk EPC assignment, products, box sessions, device registry with an online check on last_seen_at, users, and reports. Tag CSV import assigns EPCs to products by SKU inside one transaction.
OUTCOME
The full loop works end to end: start a session on the box, read tags, upload, reconcile, and watch the result land on the web dashboard live. Both APKs build against their own SDK, and the backend covers auth with three roles, products, tags, devices, locations, sessions, and reports.