PocketDigi

PocketDigi

Every now and then, a project comes along that perfectly blends curiosity, technical challenge, and sheer fun. For me, that project was PocketDigi. As an amateur radio operator, I’ve always been fascinated by APRS (Automatic Packet Reporting System), yet I was constantly frustrated by the clunky, temporary setups required for mobile or portable operations. The idea of a full-featured digipeater and iGate that could run entirely from my phone, paired with a small KISS TNC, was too good to pass up.

In this post, I’m pulling back the curtain on PocketDigi—from talking to hardware over Bluetooth to parsing decades-old AX.25 packets—all built with Flutter.


Designing for Clarity: Separation of Concerns

Before writing a single line of UI code, the priority was architecture. Without it, projects like this quickly turn into a tangled mess of Bluetooth streams, network sockets, and button handlers. My guiding principle: the UI should be a “dumb” client—just displaying data and sending commands—while all the heavy lifting happens in independent, well-tested services.

Here’s the structure that made PocketDigi manageable:

  • UI (ui/): A single stateful home screen. It knows nothing about AX.25, KISS, or APRS-IS. Its job is to display data streams and forward user actions like “connect” or “change callsign” to the services.
  • Services (services/): The brains of the operation, handling I/O, state, and logic.
    • tnc_service.dart — Manages the Bluetooth connection, frames/de-frames KISS packets, and handles digipeating.
    • aprs_is_service.dart — Handles TCP connections to APRS-IS, passcode generation, and bi-directional packet flow.
  • Parser (services/aprs_parser.dart): A stateless utility for converting raw AX.25 frames into structured AprsPacket objects and back.

This separation let me focus on decoding packets without worrying about UI quirks—and build a responsive interface without second-guessing the underlying logic.


Talking KISS to a TNC

The first challenge was getting Bluetooth communication working with a KISS TNC. I used the flutter_bluetooth_serial package, but the tricky part wasn’t connecting—it was managing the data stream.

KISS is simple in theory: raw AX.25 frames are wrapped between special 0xC0 (FEND) bytes. But in practice, Bluetooth streams are continuous: frames arrive fragmented, or sometimes multiple frames hit at once.

The solution: buffer everything in a List<int> and parse frames as FEND boundaries are detected. Complete frames get processed sequentially, and partial frames wait for more data—no packet ever gets lost.


Decoding the Airwaves

Once AX.25 frames are flowing, the next step is making sense of them. APRS is decades old and full of quirks—for example, callsigns are 7 bytes, with the six-character callsign left-shifted and the SSID in the upper nibble of the seventh byte.

Building the parser was meticulous work, but seeing it reliably decode packets was incredibly satisfying. Every field—from callsign to H-bit (to track digipeater hops)—was accounted for. Encoding worked in reverse, generating frames for beaconing or digipeating.


Bridging to the Internet: iGate and GPS

Adding iGate functionality brought new challenges: APRS-IS connectivity and mobile location awareness.

The APRS-IS service handles TCP connections, automated login, and passcode hashing. Location filters were trickier—early attempts failed. The fix? Using Flutter’s geolocator and permission_handler packages to:

  1. Request GPS permission on startup.
  2. Capture the device’s coordinates.
  3. Construct a valid APRS-IS filter (e.g., r/41.8519/-80.7930/50).

Now, PocketDigi only gates relevant local traffic to RF, making the iGate truly mobile-aware.


The Result

The end product is a portable APRS powerhouse. Its clean architecture makes future features—messaging, maps, or advanced filtering—easy to add. Core services are independent, reliable, and testable, letting the UI focus on presentation.

PocketDigi was a journey through Bluetooth streams, byte-level packet manipulation, and network protocols. It’s proof that with Flutter, a single developer can create a sophisticated app that bridges hardware and the internet seamlessly—perfect for hams who love experimenting with portable stations.

A copy can be downloaded from Sarah’s Forge.Dev: https://sarahsforge.dev/products/pocketdigi

SarahroseLives Avatar

Leave a Reply

Your email address will not be published. Required fields are marked *

Sarah Rose

An avid amateur radio operator and linux fan girl.