Dry Fire Rep Tracking

Idea

Track the number of reps a user performs per dry fire drill. Dry fire drills are self-evaluating (start beep, perform, end beep, self-evaluate), but we currently don’t persist rep counts. Recording reps would let users see their practice volume over time and incentivize daily practice.

Motivation

  • Encourage consistent daily dry fire practice by making rep counts visible
  • Show practice trends over days/weeks (e.g., “150 draws this week”)
  • Gamification angle — streaks, volume milestones, progress charts

Hardware-Assisted Approach (Mantis TitanX)

The Mantis TitanX is a BLE 4.1 laser training pistol with a gyro/accelerometer and laser emitter. It connects to Mantis’ own apps (MantisX, Laser Academy) but has no public SDK or API. However, it likely emits a BLE notification on trigger pull, which is the only event we’d need.

Event-driven laser detection

Rather than running continuous camera-based laser dot detection (battery killer), use the BLE trigger event as a gate:

  1. BLE notify → “trigger pulled”
  2. App captures a single camera frame (or short burst, ~100ms window)
  3. Image processing checks just that frame for laser dot position on target
  4. Log the rep + optional hit location

The camera stays dormant 99% of the time, only waking for a snapshot per rep. Dramatically cheaper than continuous scanning.

Even without camera/laser detection, BLE trigger events alone give us:

  • Automatic rep counting (no manual entry)
  • Split times between reps (draw-to-first-shot, split-to-split)
  • Par time evaluation (did they finish within the beep?)

Integration paths (in order of preference)

  1. Contact Mantis about a partnership — they may expose trigger events to drive hardware sales
  2. BLE reverse engineering — scan GATT services with nRF Connect to find the trigger characteristic. Trigger events are simple boolean payloads, likely not buried in proprietary analytics. Fragile if firmware changes though.
  3. Software-only fallback — manual rep entry, par timer beep counting. Works for everyone regardless of hardware.

Open Questions

  • Should reps reuse the Score model (PassFail type, one score per rep)? This gives per-rep timestamps and ties into existing leaderboard/history infra, but could be noisy for high-rep drills.
  • Or is this a separate lightweight model — just a daily aggregate (drill_id, user_id, date, rep_count)? Simpler, but loses per-rep granularity.
  • Hybrid: each “session” is a Score (PassFail, with a rep_count field), so you get one record per practice session rather than one per rep?
  • Does the par timer already emit enough data to derive rep counts automatically (number of beep cycles), or does the user need to manually enter them?
  • How does this interact with offline/sync — are dry fire reps queued the same way as scores?
  • Can we define a generic BLE trigger-event interface so other laser trainers (not just TitanX) could plug in?