Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OSSTempo (iOS)

A native SwiftUI + CoreBluetooth controller for the OSSTempo / PuttTempo ESP32 LED tempo trainer (firmware + hardware spec live in the separate osstempo repo). Connect over Bluetooth, pick a mode, trigger strokes, and tune the swing with a live on-strip reach preview. Dev-only — no App Store.

Part of OSSGolf, open source golf projects.

Architecture

Four layers, one-way dependencies, Swift 6 strict concurrency:

UI (SwiftUI, @Observable bindings)
  → App  (pure AppReducer FSM + thin @MainActor TempoController shell)
    → BLE (TempoTransport seam in Sendable domain values; CoreBluetoothTransport / FakeTransport)
      → Domain (Param registry, GATTCodec, StrokeKinematics, VisualizerModel — pure, Foundation-only)

The connection FSM and write reconciliation live in a pure reducer (reduce(state, event) → (state, [effect])), so almost everything is tested in-process via FakeTransport + an injected Scheduler, with no clocks or sleeps. See DESIGN.md for the full low-level design.

Build, run, test

Open OSSTempo.xcodeproj in Xcode 26. To run on a real iPhone: select it as the destination, set your Team under Signing & Capabilities (bundle id com.ossgolf.OSSTempo), then build & run.

# Build
xcodebuild build -scheme OSSTempo -destination 'platform=iOS Simulator,name=iPhone 17'

# Test (use iPhone 17 — iPhone 16 isn't installed for iOS 26.5; parallel off avoids clone races)
xcodebuild test -scheme OSSTempo -destination 'platform=iOS Simulator,name=iPhone 17' \
  -parallel-testing-enabled NO

# Regenerate the app icon (headless Core Graphics)
swift Tools/generate_icon.swift

UI tests run against an in-memory mock via the -uitestMockBLE launch argument (scenarios: writeFail | dropConnect | btOff | missingChar | bootFull).

Hardware test

  1. Connect → Find my trainer → grant Bluetooth → it scans by service UUID for PuttTempo.
  2. If you just re-flashed the firmware with a changed characteristic set, toggle the iPhone's Bluetooth off/on first — iOS caches the GATT table and will otherwise serve a stale one.
  3. The Diagnostics sheet (overflow menu) shows every characteristic's decoded value + raw LE bytes — the fastest way to spot a contract mismatch on real hardware.

BLE contract

13 characteristics, tails 0002000e, service 6e400001-b5a3-f393-e0a9-e50e24dcca9e, all little-endian. The registry is mirrored in OSSTempo/Domain/Param.swift and verified against the firmware. See the GATT table in the osstempo repo's README.md.

About

Native SwiftUI + CoreBluetooth iOS controller for the OSSTempo golf tempo trainer (Swift 6, pure-reducer architecture).

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages