Today the Foxhunt Platform's three components talked to each other for the first time. The scanner running on a MacBook Air, the Android app on a Pixel phone, and the VPS backend — all connected over WebSocket in a live chain. It sounds simple. It was anything but.
The setup: two RTL-SDR dongles plugged into the MacBook via USB. One runs OP25, an open-source P25 trunked radio decoder, following the control channel and logging voice grants. The other is dedicated to measuring signal strength on the frequencies where officers' radios are transmitting. The MacBook has no GPS, so it connects to the Pixel phone over Wi-Fi, using the phone as both a GPS source and a relay to the cloud backend.
The first attempt at a desk test — launching scanner.py directly without the full launch script — connected to the Pixel's WebSocket server but stalled on the handshake. The scanner was sending its hello message, the Pixel was receiving it, but the acknowledgment wasn't flowing back. Debugging revealed a timing issue: the scanner was connecting before the Pixel's ScannerServer had finished initializing. A five-second reconnect backoff resolved it cleanly.
By late afternoon, the full launch script was running: OP25 started, locked the Frederick County P25 control channel within two seconds, scanner.py connected to the Pixel, and the handshake completed. The three-node pipeline was alive. No RF observations yet — that requires driving within range of active radio traffic — but the plumbing was confirmed end-to-end. MacBook captures RF, phone stamps GPS, server processes and returns insights.
A field launch checklist was written to document the startup sequence for use in the vehicle: turn on the Pixel hotspot, open the app, connect the MacBook to the hotspot, plug in both SDR dongles, and run the launch script. Simple enough to execute while sitting in a parked car before pulling out of the driveway.