● CASE STUDY · IDENTIUM TECH SOLUTIONS
ReaderSense Edge
An RFID reader that keeps working when the network does not
OVERVIEW
Identium's RFID software used to need a Windows PC next to every reader. This project deletes that PC. The reader board runs the server, the database, the rules engine and the web UI on its own, and the cloud half exists only so a fleet of those boards can be seen and updated remotely. Tags are read, rules fire, alerts are raised and data is cached on the device, and nothing in that path waits on the internet.
THE CHALLENGE
The board is the whole computer, so every convenience of a PC deployment had to be rebuilt or given up. There was no serial port module, no I2C binding and no vendor driver that ran on ARM, so the reader protocol, the mDNS responder, the Modbus master and the I2C reads were all written against raw sockets, ttys and sysfs. The harder half was field safety: these units sit behind customer NAT with no reachable shell, and on the bench board sshd once died after a reboot while the app kept serving, which meant an update that failed to start would have been a site visit. Most of the work in the updater and the tunnel is about making every failure recoverable from a browser.
WHAT I BUILT
- 01
A pure Node driver that speaks the Impinj/M5e reader wire protocol straight over TCP: FF-framed packets, CRC-16/CCITT with the augmented-bit variant, the one-time Moduletech handshake, opcode 0x22 synchronous inventory drained through 0x29 get-tag-buffer, and status decoding so a disconnected antenna reports 'antenna not connected' instead of looking like an empty room. It replaced a Mono plus ModuleBridge.exe path that could not run on the ARM board.
- 02
A cloud fleet console where each device holds one outbound WebSocket open to the hub. Operator HTTP requests are replayed down that tunnel and piped back, so an iframe at /device/:id/ renders the board's real UI over NAT with no inbound firewall rule. Content-hashed Vite assets are cached at the hub inside a bounded 64 MB store, since every uncached byte otherwise crossed the board's WiFi once per operator per session.
- 03
Over-the-air updates through that same tunnel: a bundle is uploaded in chunks so no single request hits the 20 second tunnel timeout, the sha256 is checked before anything is unpacked, and the directory contents are swapped in place rather than renamed, because the supervisor shell holds the working directory by inode. A detached watchdog waits for the new build to write a port-bound marker and restores the old tree if it never appears.
- 04
A zone-presence engine that scores each antenna port from an EWMA of RSSI plus its share of the read rate in a sliding 2 s window, then assigns the tag winner-take-all with hysteresis to kill cross-reads. Confidence comes from the top-one to top-two margin, direction and radial speed come from RF phase, and the service refuses to emit x/y coordinates at all. The three.js digital twin draws zone-derived tags as a drifting cloud with an uncertainty ring, never a sharp dot.
- 05
The industrial I/O layer with no native modules anywhere: RS485 Modbus RTU driven by configuring the tty with stty and polling a non-blocking fd, I2C temperature/humidity and a DS3231 RTC through the i2c-tools binaries, four GPIO inputs and four outputs read and written over the carrier board's sysfs nodes, and a rules engine wiring GPI edges and tag events to relay pulses, alarm patterns, read bursts and webhooks.
- 06
Supporting pieces built dependency-free: a hand-written mDNS/DNS-SD responder plus a UDP beacon so a headless board announces itself on a customer switch, Ed25519 device-bound licensing keyed to a pinned hardware fingerprint, a pluggable NPU detector contract that correlates people seen on camera against tags read at the same moment, and Theil-Sen depletion forecasting chosen over least squares because a tag stream is spiky.
OUTCOME
Running at v0.8.1 on a bench board with the native driver, and the fleet console is deployed in production behind nginx at identiumone.com/MDM. A one-command installer flashes a fresh board over SSH, disables the vendor firmware, installs the auto-start service and verifies the dashboard is reading tags.