OmniBLE API Guide
This document summarizes the OmniBLE module API surface and how to use it within this
repo. It is based on the local source code under OmniBLE/OmniBLE/ and the integration
patterns used by LoopKit.
Overview
- OmniBLE is a LoopKit PumpManager implementation for Omnipod DASH over BLE.
- The primary integration point is
OmniBLEPumpManager. - UI integration is provided via
OmniBLEPlugin(LoopKitUI plugin). - State is persisted using
OmniBLEPumpManagerState(RawRepresentable).
Key modules:
- OmniBLE/OmniBLE/PumpManager/: pump manager, state, comms session.
- OmniBLE/OmniBLE/Bluetooth/: BLE session, pairing, encryption.
- OmniBLE/OmniBLE/OmnipodCommon/: pod models, dosing tables, commands.
- OmniBLE/OmniBLEPlugin/: LoopKit UI plugin.
- OmniBLE/Docs/InsulinDosingIntegration.md: dosing flow safety notes.
Core Types
OmniBLEPumpManager
Primary API for pairing, setup, status, and dosing. It conforms to LoopKit
DeviceManager and PumpManager interfaces.
Initialization and persistence:
- init(state: OmniBLEPumpManagerState)
- init?(rawState: PumpManager.RawStateValue)
- rawState: PumpManager.RawStateValue for persistence.
Delegates and queues:
- pumpManagerDelegate (LoopKit PumpManagerDelegate)
- delegateQueue (DispatchQueue)
State and status:
- state: OmniBLEPumpManagerState
- status: PumpManagerStatus
- lastSync: Date?
- deviceBLEName: String?
Observers:
- addPodStateObserver(_:queue:) / removePodStateObserver(_:)
- addStatusObserver(_:queue:) / removeStatusObserver(_:)
Setup lifecycle:
- pairAndPrime(completion:)
- insertCannula(completion:)
- checkCannulaInsertionFinished(completion:)
- resumingPodSetup()
- completeOnboard()
- forgetPod(completion:)
- deactivatePod(completion:)
Status and alerts:
- getPodStatus(completion:)
- getDetailedStatus() async throws
- acknowledgePodAlerts(_:completion:)
- setTime(completion:)
- updateExpirationReminder(_:completion:)
- updateLowReservoirReminder(_:completion:)
Dosing:
- enactBolus(units:activationType:completion:)
- cancelBolus(completion:)
- enactTempBasal(unitsPerHour:for:completion:)
- runTemporaryBasalProgram(unitsPerHour:for:automatic:completion:)
- suspendDelivery(completion:)
- suspendDelivery(withSuspendReminders:completion:)
- resumeDelivery(completion:)
Dose rounding and estimates:
- roundToSupportedBolusVolume(units:)
- roundToSupportedBasalRate(unitsPerHour:)
- estimatedDuration(toBolus:)
Diagnostics:
- playTestBeeps() async throws
- readPulseLog() async throws
- readPulseLogPlus() async throws
- readActivationTime() async throws
- readTriggeredAlerts() async throws
OmniBLEPumpManagerState
Persistent state container.
- Stores pod state, basal schedule, insulin type, reminders, controllerId, podId,
active alerts, and other pump configuration.
- Use rawValue to persist and init?(rawValue:) to restore.
OmniBLEPlugin (LoopKitUI)
OmniBLEPluginexposesOmniBLEPumpManagerto LoopKitUI viaPumpManagerUIPlugin.- The plugin is the entry point if you are using LoopKitUI discovery.
Typical Integration Flow
1) Create or restore pump manager
import OmniBLE
import LoopKit
let basalSchedule = BasalSchedule(entries: [])
let state = OmniBLEPumpManagerState(
podState: nil,
timeZone: TimeZone.current,
basalSchedule: basalSchedule,
insulinType: .novolog,
maximumTempBasalRate: 0
)
let pumpManager = OmniBLEPumpManager(state: state)
If restoring from persistence:
if let pumpManager = OmniBLEPumpManager(rawState: savedRawState) {
// use pumpManager
}
2) Set delegate and queue
pumpManager.delegateQueue = DispatchQueue(label: "PumpManager")
pumpManager.pumpManagerDelegate = self
3) Pair and prime a pod
pumpManager.pairAndPrime { result in
switch result {
case .success(let primeDuration):
// show countdown, then insert cannula
pumpManager.insertCannula { insertResult in
// handle insertResult
}
case .failure(let error):
// handle error
}
}
4) Configure time and basal schedule
pumpManager.setTime { error in
// handle error
}
pumpManager.setBasalSchedule(basalSchedule) { error in
// handle error
}
5) Dosing
pumpManager.enactBolus(units: 1.0, activationType: .manual) { error in
// handle error
}
pumpManager.enactTempBasal(unitsPerHour: 0.8, for: 30 * 60) { error in
// handle error
}
pumpManager.suspendDelivery { error in
// handle error
}
pumpManager.resumeDelivery { error in
// handle error
}
6) Status and alerts
pumpManager.getPodStatus { result in
// StatusResponse
}
Task {
let detailed = try await pumpManager.getDetailedStatus()
}
pumpManager.acknowledgePodAlerts(alertsToAcknowledge) { alerts in
// acknowledged alerts
}
Error Handling Notes
- Public errors are surfaced as
OmniBLEPumpManagerErroror LoopKitPumpManagerErrordepending on the operation. - Common errors include
noPodPaired,podAlreadyPaired, andinsulinTypeNotConfigured.
Expected BLE Connection Behavior
OmniPod DASH does not maintain a continuous BLE connection. The expected pattern is short, on-demand sessions for status and delivery commands, followed by disconnects.
getPodStatusand dosing commands will connect, perform a session, then allow the pod to disconnect.- Auto-reconnects are normal and managed via cached pod BLE identifiers.
- Frequent connect/disconnect cycles are expected, not necessarily an error.
- Use
ensureCurrentPumpDatato avoid unnecessary status fetches when data is fresh.
Safety and Validation
- See
OmniBLE/Docs/InsulinDosingIntegration.mdfor validation gates and safety requirements before issuing dosing commands. - Always round bolus and basal values using the provided rounding helpers.
- Validate pod state, reservoir, and setup progress before dosing.
Offline Basal Fallback Proposal
If algorithm runs fail for a defined window (e.g., no valid CGM + algorithm run for
= 15 minutes), switch the pod to a predefined offline basal schedule so the user continues receiving insulin. This is a safety fallback, not a primary control mode.
Proposed behavior: - Start offline mode after the threshold is reached and no algorithm output is available. - Set a conservative basal schedule derived from the algorithm’s projected basal needs or the last known safe rate. - Notify the user that the system is in offline mode. - Cap offline mode duration; require user action if it persists. - When a valid CGM arrives and the algorithm runs, cancel offline basal and resume explicit 5-minute dosing.
Reconciliation when returning online:
- Use PodCommsSession.dosesForStorage() to retrieve missing delivery events.
- Store events via NewPumpEvent to update core state and audit logs.
Where to Look in Code
- Pump manager API:
OmniBLE/OmniBLE/PumpManager/OmniBLEPumpManager.swift - State:
OmniBLE/OmniBLE/PumpManager/OmniBLEPumpManagerState.swift - Pod comms:
OmniBLE/OmniBLE/PumpManager/PodComms.swift - BLE session:
OmniBLE/OmniBLE/Bluetooth/ - UI plugin:
OmniBLE/OmniBLEPlugin/OmniBLEPlugin.swift