Fitness · Physical security
Fingerprint access that unlocks the moment payment clears
Cloud CRM talking to hardware behind a carrier-grade NAT — no static IP, no port forwarding.
The gym's provider blocks all incoming connections. So the connection is made in the other direction — the on-site agent opens it and holds it, and the cloud sends commands back down the same channel.
The problem
A fitness club wanted membership purchases online to translate immediately into working fingerprint access at the turnstile. The obstacle was network, not software: the club's internet came through carrier-grade NAT, where the provider shares one public IP across hundreds of subscribers. Incoming connections are simply blocked — port forwarding isn't misconfigured, it's unavailable. The standard fix, buying a static IP plus enterprise networking gear, was a real capital expense for a single entrance.
What we built
A reverse tunnel. A Raspberry Pi inside the gym holds a permanent outbound encrypted connection to our cloud relay, so the cloud ERP pushes commands inward through the firewall rather than trying to reach in from outside. Two scanners report to the Pi; the cloud decides; the turnstile opens. The reception desk gets a live screen showing who just walked in, their membership status, and whether it's about to expire.
What it changed
No infrastructure purchase
The club avoided both the enterprise router and the recurring static-IP fee — the whole network problem was solved in software on a Raspberry Pi.
Zero delay between payment and access
A membership bought online works at the turnstile immediately. Expired ones stop themselves — access is revoked by synchronization, not by a front-desk employee checking a screen.
Access keeps working when the internet doesn't
If the provider drops, the Pi buffers every scan locally and replays the backlog on reconnect. No lost entry records, no manual reconciliation afterwards.
How it worksthe engineering detail
Written for the person your CTO forwards this to.
CGNAT traversal via reverse tunnel
The on-premise agent (Python, in Docker on a Raspberry Pi 4) maintains a persistent outbound WebSocket over TLS on port 443 to a cloud-hosted FastAPI relay behind Traefik. Because the connection is client-initiated and looks like ordinary HTTPS, it passes through provider CGNAT and any corporate firewall. ping/pong frames every 15–30s keep the router's NAT table entry alive so the tunnel isn't silently dropped.
Protocol reverse-engineering
The Anviz GC150 speaks a proprietary binary protocol. We captured TCP traffic in Wireshark, reverse-engineered the A5 frame format, and built a custom TCP server that decodes biometric events and fingerprint templates natively — and issues commands back (ANVIZ_CC_OPENDOOR, 3-second relay pulse).
Scanners as clients, not servers
Both scanners run in reverse TCP mode and connect outward to the Pi on :5010 when an event happens. Nothing on the gym LAN needs a fixed address or special routing.
Offline resilience with backpressure handling
Every event is checksum-validated and appended to a local events.jsonl buffer before it leaves the building. On connection loss the agent reconnects automatically and drains the backlog in order.
Thread-safe socket multiplexing
A single client-initiated socket serves both a background non-blocking read loop (0.5s timeouts) and high-priority synchronous command injection from API threads, coordinated by threading.Lock.
Event-driven cloud path, exactly once
The WebSocket gateway publishes to Redis Pub/Sub; the Odoo core checks entitlements against PostgreSQL, writes the access log, and fans out in parallel — OPEN_DOOR back down the same tunnel, and a profile card to the reception dashboard. TTL-based deduplication on the edge node filters TCP retransmissions, so a check-in reaches the ERP exactly once.
Patterns — Observer (webhooks) · Strategy (pluggable event sinks) · Singleton (configuration) · Retry with exponential backoff · Store-and-forward buffer
Stack