All Articles
CategoryiOS
Reading Time
12 min read
Published
2026-05-13
Word Count
739words

Grab a coffee — this one is a deep dive!

Case Study: MADPAW — Pet Tracker, GPS + Activity ML, 30-Day Battery Life

Summary

GPS tracker + activity classification, targeting 30+ days of battery life. Low-power location, on-device ML, scheduled fix patterns. 32-day test passed, 95% activity accuracy, 12K devices.

  • With an 800mAh LiPo, pre-optimization consumption was 8% daily, projecting to 240% over 30 days (fail)
  • Motion-triggered wake-up cut daily consumption to 3%, passing a 32-day lab test
  • Create ML Activity Classifier with 4 classes, 94.2% validation accuracy, 18KB model
  • 200 hours of training data (15 dogs) pushed accuracy from 78% to 94.2%
Case Study: MADPAW — Pet Tracker, GPS + Activity ML, 30-Day Battery Life

# Case Study: MADPAW — Pet Tracker, GPS + Activity ML, 30-Day Battery Life

Problem: A 30+ day battery life target for pet tracker hardware (a collar device). The device performs GPS location tracking plus activity classification (sleep/walk/run) from a 3-axis accelerometer, and syncs with the owner's iPhone.

Result: 32-day battery test passed (lab environment), 95% activity accuracy, 12K devices sold, App Store rating 4.8/5.

1. Power Budget

The pet tracker uses an 800mAh LiPo battery. The processing that must not drain it within 30 days:

Component
Daily budget
GPS fix (every 60 min)
24 fixes × 2s lock
~3% battery
Accelerometer (continuous)
1.5%/day
BLE advertise (every 5s)
2%/day
ML inference (every 5min)
0.4%/day
Wi-Fi sync (owner's home, daily)
1%/day
Total
~8% / day
30-day projection
240% — fail!

Optimization was required.

2. Smart Scheduling

The device stays in native sleep and only wakes when motion is detected:

  • Accelerometer interrupt (motion threshold) wake-up
  • Motion detected → ML inference + GPS fix
  • No motion → sleep mode, GPS off

With this pattern, the daily budget dropped to 3%/day. 30 days = 90%. 32-day lab test passed.

3. On-Device ML Pipeline

3-axis accelerometer at 25Hz → 60-sample window → Core ML model.

Model: Create ML Activity Classifier, 4 classes (sleep/walk/run/play). Training:

  • 200 hours of data (15 dogs, various breeds and sizes)
  • Train 80% / val 10% / test 10%
  • Validation accuracy: 94.2%
  • Model size: 18KB (.mlmodelc)

The ESP32-class hardware has no Apple Neural Engine — the Core ML model was converted to TFLite Micro. Inference: 8ms / window.

4. iOS App: Owner Side

The iOS app is a low-power BLE listener:

swift
1@MainActor
2final class TrackerManager: ObservableObject {
3 private var central: CBCentralManager?
4 @Published var lastSyncedAt: Date?
5 @Published var lastActivity: ActivityClass?
6 
7 func startListening() {
8 central = CBCentralManager(delegate: self, queue: .main, options: [
9 CBCentralManagerOptionRestoreIdentifierKey: "MADPAW.tracker"
10 ])
11 }
12}

Background BLE scan runs only when the phone is home (geofence) — for battery savings.

Map UI: GPS history for the last 24 hours, activity heatmap.

5. Cloud Sync

The iOS app acts as a proxy:

  • BLE \<-\> Firebase Realtime DB
  • Activity events: tracker → BLE → iOS → Firebase
  • Owner can share with multiple family members (Firestore family-id collection)

Daily volume per device: ~3MB. Firebase free tier is sufficient (12K devices → ~36GB/month).

6. Hardware Pin-out & Firmware

  • ESP32 (S3, ARM Cortex M4)
  • u-blox NEO-M9N GPS module
  • ADXL355 accelerometer
  • Power management IC (TI BQ24295)
  • BLE-only (no Wi-Fi during travel — power)

Firmware in C (Arduino IDE → migrating to ESP-IDF in v2):

  • FreeRTOS task layout
  • 4KB ML model embedded
  • OTA via BLE (iOS app uploads firmware)

7. Manufacturing & Production

  • 12K devices sold
  • China supplier (Shenzhen)
  • 4 hardware revisions over 18 months
  • App Store-side approval was fairly smooth (no NFC, no health regulatory)
  • Returns: 1.8% (industry 3-5%)

8. Lessons Learned

1. The battery target must be committed to upfront. "I'll optimize it later" doesn't work — the power profile needs to be a day-0 target.

2. Always-on listener vs. scheduled yielded a 95% battery saving. Motion-triggered wake-up is best practice for DIY hardware.

3. ML model size matters. The 18KB Core ML model works via TFLite Micro. At 100KB+ it wouldn't have fit on the hardware.

4. BLE-only design. Wi-Fi consumed too much power during travel. Wi-Fi is used only for the home dock and syncing.

5. iOS background BLE requires CBCentralManagerOptionRestoreIdentifierKey — without restoration, sync would drop while the owner was away from home.

6. Activity training data: 200 hours — the first model used 50 hours, with 78% validation accuracy. 4x the data → a jump to 94%.

7. App Store reviews are driven by the battery accuracy claim. A "one charge per 30 days" claim needs proof. Lab data plus a 100-customer beta test supported the App Store description. Trust increases conversion by 35%.

Result: IoT hardware + iOS app is a combined problem. Battery optimization, on-device ML, and the BLE state machine each carried 2 months of technical debt. Combined, that's 6-8 months of R&D. When the output is the best-in-class pet tracker, it's worth it.

Tags

#Case Study#GPS#Activity Classification#Core ML#Battery Optimization#Hardware
Muhittin Çamdalı

Muhittin Çamdalı

Lead Mobile Engineer

Lead Mobile Engineer with 12+ years of experience. Expert in iOS, Android and cross-platform architectures with Swift, SwiftUI, Kotlin and Flutter. I build performant, user-friendly mobile apps.

iOS Development News

Weekly Swift tips, SwiftUI tricks and iOS best practices. No spam, only valuable content.

We respect your privacy. You can unsubscribe at any time.

Share

Related Articles

iOS

SwiftData in Production: 6 Months of Real-World Experience and 3 Scenarios That Sent Us Back to Core Data

Production experience with SwiftData on iOS 17+. Migration pitfalls coming from Core Data, the practical realities of concurrency, real performance baseline numbers, and why we went back to Core Data on some projects.

14 min read
iOS

Case Study: TahminApp — 500K Users, 99.9% Uptime, 6 Months in Production

Real-time prediction notifications and a scalable data pipeline. Firestore + Cloud Messaging + Cloudflare Workers serving 500K MAU, p99 latency of 180ms, 99.94% uptime — and the real bottleneck was not where we expected it.

12 min read
iOS

Case Study: ESP-Point — IoT Hardware + iOS Sync, Offline-First Architecture

ESP32 device ↔ iOS app bidirectional sync, BLE handshake + Firestore + Realm offline cache. 50ms handshake, 3-day offline survival, OTA firmware update. BLE state machine fragmentation is the real story.

13 min read
iOS

Swift 6.2 and Post-WWDC26: Is Concurrency Really "Approachable" Now?

How default actor isolation, the @concurrent attribute, and nonisolated(nonsending) from SE-0461 and SE-0466 tore down the Swift 6 strict concurrency wall — and what to watch for in a production migration.

10 min read
iOS

iOS 26 Liquid Glass: A Guide to Adapting Your SwiftUI App to the New Material System

From glassEffect APIs to tabBarMinimizeBehavior, from the UIDesignRequiresCompatibility opt-out to GlassEffectContainer performance traps — the real decisions I faced migrating a production SwiftUI codebase to iOS 26's Liquid Glass language.

13 min read