Connected Pet Platform
Live pet tracking from collar to map -- BLE hardware, real-time GPS, geofencing
Connected Pet Platform
A connected pet platform pairing a GPS-enabled smart collar with a native iOS app -- live with real users tracking their pets. BLE was completely new territory for me, and the hardest part was the intersection of WebSocket, BLE, and WiFi architecture with custom hardware and proprietary protocols. Built on Swift 6 with strict concurrency, TCA for state management, and six modular Swift packages.
iOS
Platform
iOS Engineer
Role
From Hardware to Hands
BLE Protocol & Collar Integration
Wrote the Bluetooth Low Energy layer from scratch. The collar exposes multiple GATT services for location beacons, battery telemetry, firmware state, and command channels. I built a protocol abstraction over CoreBluetooth handling discovery, connection lifecycle, characteristic subscriptions, and write-with-response commands.
Real-Time Telemetry with SignalR
SignalR pushes location updates and collar status changes from the server. The collar reports GPS via cellular, backend streams to connected clients. I built the client layer with automatic reconnection, message deduplication, and backpressure handling. Rapid location pings from a moving dog will overwhelm you if you're not careful.
Modular Architecture at Scale
Six Swift packages covering API communication, Bluetooth hardware, geospatial computation, geographic utilities, shared helpers, and the main app target. SPM enforces strict dependency boundaries. TCA manages state composition across feature modules with swift-dependencies for injection.
Auth, Push & Production Hardening
OAuth/JWT auth with KeychainAccess for token persistence. Braze for push notification campaigns and in-app messaging. Then the big one: migrating to Swift 6 strict concurrency. Every BLE callback, SignalR handler, and UI state update had to be audited for data races.
Real-Time Meets Real World
Bluetooth Collar Communication
Full lifecycle collar interaction: scanning, pairing, bonded reconnection, characteristic monitoring. Firmware updates go over BLE as chunked binary writes with CRC verification. Real-time battery and signal strength monitoring, command dispatch for device configuration and operational modes. All BLE work runs on dedicated serial queues because CoreBluetooth will crash you if you touch it from the wrong thread.
Live Location & Geofencing
GPS coordinates stream from the collar through the backend via SignalR, rendering live on a map with breadcrumb trails. A dedicated geospatial package handles the geofence math: point-in-polygon tests, boundary crossing detection, fence overlap validation. A separate topology package processes terrain and elevation data for virtual fencing in areas where GPS alone isn't enough.
Swift 6 Strict Concurrency Migration
Migrated the entire codebase to Swift 6 strict concurrency. BLE delegate callbacks, SignalR event handlers, TCA reducers, all needed careful actor isolation and Sendable conformance. Tedious work. But it eliminated an entire class of race conditions that are basically inevitable when you mix hardware I/O with real-time networking.
Under the Hood
Key Technical Decisions
BLE Architecture
CoreBluetooth is a state machine whether you treat it like one or not. Connections drop, characteristics change, background execution is limited. I built a peripheral manager abstraction that encapsulates connection state as a TCA dependency, emitting actions for discovery, connection, disconnection, and characteristic updates. BLE operations serialize through an actor because concurrent writes crash CoreBluetooth. No exceptions.
SignalR + TCA Integration
SignalR is callback-heavy, which fights TCA's unidirectional data flow. I wrapped the SignalR client in an AsyncStream-based dependency that converts hub method invocations into typed actions. Automatic reconnection with exponential backoff handles the reality of mobile networks. WiFi to cellular handoffs were the biggest headache.
Six-Package SPM Architecture
The geospatial and topology packages have zero app dependencies. The BLE package depends only on helpers. The API package handles all network types. This prevents circular dependencies and enables parallel compilation. swift-identified-collections manages ordered, identity-stable collections across the map and device list features.
What I Learned
BLE was completely new territory and the tutorials lied
They show happy-path scanning and connecting. Production BLE is reconnection handling, background restoration, characteristic invalidation, and graceful degradation when the collar is out of range. I learned on the job, and I modeled every state transition explicitly in TCA so the reducer became the source of truth for what the hardware is actually doing.
The real challenge was the intersection of three protocols
WebSocket, BLE, and WiFi all talking to custom hardware with proprietary protocols. Each had its own connection lifecycle, failure modes, and threading requirements. Getting them to work together reliably on a moving dog was the hardest multi-protocol engineering problem I've tackled.
Swift 6 strict concurrency found three race conditions
They were in the BLE callback handling and had been causing intermittent crashes for months. The compiler found bugs that code review and testing missed. Making every closure and delegate Sendable-correct was tedious, but the stability improvement was immediate.
Cross-Platform Lifestyle App
Cross-platform travel and booking app with offline maps and editorial content