Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions OmniBLE/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -14630,6 +14630,9 @@
}
}
},
"Delivery Stops" : {
"comment" : "Label for Delivery Stops row"
},
"Device Name" : {
"comment" : "description label for device name pod details row",
"localizations" : {
Expand Down Expand Up @@ -30863,7 +30866,7 @@
}
},
"Notification Settings" : {
"comment" : "Text for pod details disclosure row\nnavigation title for notification settings",
"comment" : "Text for Notification Settings disclosure row\nnavigation title for notification settings",
"localizations" : {
"ar" : {
"stringUnit" : {
Expand Down Expand Up @@ -35958,7 +35961,7 @@
}
},
"Pod Activated" : {
"comment" : "Label for pod insertion row\ndescription label for activated at time pod details row",
"comment" : "Label for Pod Activated row\ndescription label for activated at time pod details row",
"localizations" : {
"ar" : {
"stringUnit" : {
Expand Down Expand Up @@ -36692,7 +36695,7 @@
}
},
"Pod Details" : {
"comment" : "Text for pod details disclosure row\ntitle for pod details page",
"comment" : "Text for Pod Details row and page",
"localizations" : {
"ar" : {
"stringUnit" : {
Expand Down Expand Up @@ -36835,7 +36838,7 @@
}
},
"Pod Diagnostics" : {
"comment" : "Text for pod diagnostics row\nTitle for the pod diagnostic view",
"comment" : "Title for the Pod Diagnostic row and page",
"localizations" : {
"ar" : {
"stringUnit" : {
Expand Down Expand Up @@ -37120,6 +37123,9 @@
}
}
},
"Pod Expiration" : {
"comment" : "Label for Pod Expiration row"
},
"Pod expiration advisory alarm" : {
"comment" : "Description for expiration advisory alarm",
"extractionState" : "manual",
Expand Down Expand Up @@ -37725,7 +37731,7 @@
}
},
"Pod Expired" : {
"comment" : "Alert content title for podExpireImminent pod alert\nAlert content title for podExpiring pod alert\nError message for reservoir view when pod expired\nLabel for pod expiration row, past tense\nStatus highlight message for podExpired alarm.\nThe title for Pod Expired alarm notification",
"comment" : "Alert content title for podExpireImminent pod alert\nAlert content title for podExpiring pod alert\nError message for reservoir view when pod expired\nStatus highlight message for podExpired alarm.\nThe title for Pod Expired alarm notification",
"localizations" : {
"ar" : {
"stringUnit" : {
Expand Down Expand Up @@ -37869,6 +37875,7 @@
},
"Pod Expires" : {
"comment" : "Label for pod expiration row",
"extractionState" : "stale",
"localizations" : {
"ar" : {
"stringUnit" : {
Expand Down Expand Up @@ -38731,6 +38738,9 @@
}
}
},
"Pod Faulted" : {
"comment" : "Label for Pod Faulted row"
},
"Pod is not in a state ready for cannula insertion." : {
"comment" : "Error message when cannula insertion fails because the pod is in an unexpected state",
"localizations" : {
Expand Down Expand Up @@ -40934,6 +40944,7 @@
},
"Previous Pod" : {
"comment" : "title for previous pod page",
"extractionState" : "stale",
"localizations" : {
"ar" : {
"stringUnit" : {
Expand Down Expand Up @@ -41076,7 +41087,7 @@
}
},
"Previous Pod Details" : {
"comment" : "Text for previous pod details row",
"comment" : "Text for Previous Pod Details row and page",
"localizations" : {
"ar" : {
"stringUnit" : {
Expand Down
4 changes: 1 addition & 3 deletions OmniBLE/PumpManagerUI/OmniBLEHUDProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ internal class OmniBLEHUDProvider: NSObject, HUDProvider {
private let bluetoothProvider: BluetoothProvider

private let colorPalette: LoopUIColorPalette

private var refreshTimer: Timer?


private let allowedInsulinTypes: [InsulinType]

var visible: Bool = false {
Expand Down
52 changes: 36 additions & 16 deletions OmniBLE/PumpManagerUI/ViewModels/OmniBLESettingsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,28 @@ class OmniBLESettingsViewModel: ObservableObject {
}
}

var faultedAtString: String {
if let faultEventTimeSinceActivation = pumpManager.podDetails?.fault?.faultEventTimeSinceActivation,
let expiresAt = expiresAt
{
// Use expiresAt which slides with pod clock skew to compute an adjusted activatedAt
let adjustedActivatedAt = expiresAt - Pod.nominalPodLife
let faultedAt = adjustedActivatedAt + faultEventTimeSinceActivation
return dateFormatter.string(from: faultedAt)
}
return "—"
}

var deliveryStopsAtString: String {
if let expiresAt = expiresAt {
// Use expiresAt which slides with pod clock skew to compute an adjusted activatedAt
let adjustedActivatedAt = expiresAt - Pod.nominalPodLife
let deliveryStopsAt = adjustedActivatedAt + Pod.serviceDuration
return dateFormatter.string(from: deliveryStopsAt)
}
return "—"
}

var serviceTimeRemainingString: String? {
if let serviceTimeRemaining = pumpManager.podServiceTimeRemaining, let serviceTimeRemainingString = timeRemainingFormatter.string(from: serviceTimeRemaining) {
return serviceTimeRemainingString
Expand Down Expand Up @@ -548,25 +570,24 @@ extension OmniBLEPumpManager {
}

var basalDeliveryRate: Double? {
if let tempBasal = state.podState?.unfinalizedTempBasal, !tempBasal.isFinished() {
guard let podState = state.podState, !podState.isFaulted && !podState.isSuspended else {
return nil // no pod, pod is faulted, or pod is suspended
}
if let tempBasal = podState.unfinalizedTempBasal, !tempBasal.isFinished() {
// return the current unfinalized temp basal rate
return tempBasal.rate
} else {
switch state.podState?.suspendState {
case .resumed:
var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = state.timeZone
return state.basalSchedule.currentRate(using: calendar, at: dateGenerator())
case .suspended, .none:
return nil
}
}
// return the scheduled basal rate for the current time
var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = state.timeZone
return state.basalSchedule.currentRate(using: calendar, at: dateGenerator())
}

fileprivate var podServiceTimeRemaining : TimeInterval? {
guard let podTimeRemaining = podTimeRemaining else {
return nil;
guard let podTimeRemaining = podTimeRemaining, state.podState?.isFaulted == false else {
return nil
}
return max(0, Pod.serviceDuration - Pod.nominalPodLife + podTimeRemaining);
return max(0, Pod.serviceDuration - Pod.nominalPodLife + podTimeRemaining)
}

private func podDetails(fromPodState podState: PodState, andDeviceName deviceName: String?) -> PodDetails {
Expand All @@ -578,10 +599,9 @@ extension OmniBLEPumpManager {
deviceName: deviceName,
totalDelivery: podState.lastInsulinMeasurements?.delivered,
lastStatus: podState.lastInsulinMeasurements?.validTime,
fault: podState.fault?.faultEventCode,
fault: podState.fault,
activatedAt: podState.activatedAt,
activeTime: podState.activeTime,
pdmRef: podState.fault?.pdmRef
)
}

Expand Down
58 changes: 41 additions & 17 deletions OmniBLE/PumpManagerUI/Views/OmniBLESettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,15 @@ struct OmniBLESettingsView: View {
Button(action: {
sendingTestBeepsCommand = true
Task { @MainActor in
defer {
// Executed after playTestBeeps() returns or throws
sendingTestBeepsCommand = false
}
do {
try await viewModel.playTestBeeps()
}
sendingTestBeepsCommand = false
// No errors are displayed when using the sound icon to play test beeps.
// Pod Diagnostics->Play Test Beeps will play beeps & display any errors.
}
}) {
Image(systemName: "speaker.wave.2.circle")
Expand Down Expand Up @@ -349,45 +354,61 @@ struct OmniBLESettingsView: View {

Section() {
HStack {
FrameworkLocalText("Pod Activated", comment: "Label for pod insertion row")
FrameworkLocalText("Pod Activated", comment: "Label for Pod Activated row")
Spacer()
Text(self.viewModel.activatedAtString)
.foregroundColor(Color.secondary)
}

HStack {
if let expiresAt = viewModel.expiresAt, expiresAt < Date() {
FrameworkLocalText("Pod Expired", comment: "Label for pod expiration row, past tense")
} else {
FrameworkLocalText("Pod Expires", comment: "Label for pod expiration row")
}
FrameworkLocalText("Pod Expiration", comment: "Label for Pod Expiration row")
Spacer()
Text(self.viewModel.expiresAtString)
.foregroundColor(Color.secondary)
}

HStack {
if viewModel.podDetails?.fault != nil {
FrameworkLocalText("Pod Faulted", comment: "Label for Pod Faulted row")
Spacer()
Text(self.viewModel.faultedAtString)
.foregroundColor(Color.secondary)
} else if viewModel.podOk {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete the "if viewModel.podOk " portion of this line to prevent a blank row display for this row when there is no pod to match the behavior with no pod of all the other rows in this section

FrameworkLocalText("Delivery Stops", comment: "Label for Delivery Stops row")
Spacer()
Text(self.viewModel.deliveryStopsAtString)
.foregroundColor(Color.secondary)
}
}

let localizedPodDetailsStr = LocalizedString("Pod Details", comment: "Text for Pod Details row and page")
if let podDetails = self.viewModel.podDetails {
NavigationLink(destination: PodDetailsView(podDetails: podDetails, title: LocalizedString("Pod Details", comment: "title for pod details page"))) {
FrameworkLocalText("Pod Details", comment: "Text for pod details disclosure row")
NavigationLink(destination: PodDetailsView(podDetails: podDetails,
title: localizedPodDetailsStr))
{
Text(localizedPodDetailsStr)
.foregroundColor(Color.primary)
}
} else {
HStack {
FrameworkLocalText("Pod Details", comment: "Text for pod details disclosure row")
Text(localizedPodDetailsStr)
Spacer()
Text("—")
.foregroundColor(Color.secondary)
}
}

let localizedPreviousPodDetailsStr = LocalizedString("Previous Pod Details", comment: "Text for Previous Pod Details row and page")
if let previousPodDetails = viewModel.previousPodDetails {
NavigationLink(destination: PodDetailsView(podDetails: previousPodDetails, title: LocalizedString("Previous Pod", comment: "title for previous pod page"))) {
FrameworkLocalText("Previous Pod Details", comment: "Text for previous pod details row")
NavigationLink(destination: PodDetailsView(podDetails: previousPodDetails,
title: localizedPreviousPodDetailsStr))
{
Text(localizedPreviousPodDetailsStr)
.foregroundColor(Color.primary)
}
} else {
HStack {
FrameworkLocalText("Previous Pod Details", comment: "Text for previous pod details row")
Text(localizedPreviousPodDetailsStr)
Spacer()
Text("—")
.foregroundColor(Color.secondary)
Expand Down Expand Up @@ -416,7 +437,8 @@ struct OmniBLESettingsView: View {
onSaveScheduledExpirationReminder: self.viewModel.saveScheduledExpirationReminder,
onSaveLowReservoirReminder: self.viewModel.saveLowReservoirReminder))
{
FrameworkLocalText("Notification Settings", comment: "Text for pod details disclosure row").foregroundColor(Color.primary)
FrameworkLocalText("Notification Settings", comment: "Text for Notification Settings disclosure row")
.foregroundColor(Color.primary)
}
NavigationLink(destination: BeepPreferenceSelectionView(initialValue: viewModel.beepPreference, onSave: viewModel.setConfirmationBeeps)) {
HStack {
Expand All @@ -438,7 +460,8 @@ struct OmniBLESettingsView: View {
}
NavigationLink(destination: InsulinTypeSetting(initialValue: viewModel.insulinType, supportedInsulinTypes: supportedInsulinTypes, allowUnsetInsulinType: false, didChange: viewModel.didChangeInsulinType)) {
HStack {
FrameworkLocalText("Insulin Type", comment: "Text for insulin type navigation link").foregroundColor(Color.primary)
FrameworkLocalText("Insulin Type", comment: "Text for insulin type navigation link")
.foregroundColor(Color.primary)
if let currentTitle = viewModel.insulinType?.brandName {
Spacer()
Text(currentTitle)
Expand Down Expand Up @@ -479,13 +502,14 @@ struct OmniBLESettingsView: View {
}

Section() {
let localizedPodDiagnosticsStr = LocalizedString("Pod Diagnostics", comment: "Title for the Pod Diagnostic row and page")
NavigationLink(destination: PodDiagnosticsView(
title: LocalizedString("Pod Diagnostics", comment: "Title for the pod diagnostic view"),
title: localizedPodDiagnosticsStr,
diagnosticCommands: viewModel.diagnosticCommands,
podOk: viewModel.podOk,
noPod: viewModel.noPod))
{
FrameworkLocalText("Pod Diagnostics", comment: "Text for pod diagnostics row")
Text(localizedPodDiagnosticsStr)
.foregroundColor(Color.primary)
}
}
Expand Down
14 changes: 8 additions & 6 deletions OmniBLE/PumpManagerUI/Views/PodDetailsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ public struct PodDetails {
var deviceName: String?
var totalDelivery: Double?
var lastStatus: Date?
var fault: FaultEventCode?
var fault: DetailedStatus?
var activatedAt: Date?
var activeTime: TimeInterval?
var pdmRef: String?
}

struct PodDetailsView: View {
Expand Down Expand Up @@ -96,13 +95,15 @@ struct PodDetailsView: View {
row(LocalizedString("Firmware Version", comment: "description label for firmware version pod details row"), value: podDetails.firmwareVersion)
row(LocalizedString("BLE Firmware Version", comment: "description label for ble firmware version pod details row"), value: podDetails.bleFirmwareVersion)
row(LocalizedString("Total Delivery", comment: "description label for total delivery pod details row"), value: totalDeliveryText)
if let activeTime = podDetails.activeTime, let activatedAt = podDetails.activatedAt {
if let activatedAt = podDetails.activatedAt {
row(LocalizedString("Pod Activated", comment: "description label for activated at time pod details row"), value: dateFormatter.string(from: activatedAt))
}
if let activeTime = podDetails.activeTime {
row(LocalizedString("Active Time", comment: "description label for active time pod details row"), value: activeTimeText(activeTime))
} else {
row(LocalizedString("Last Status", comment: "description label for last status date pod details row"), value: lastStatusText)
}
if let fault = podDetails.fault, let pdmRef = podDetails.pdmRef {
if let fault = podDetails.fault, let pdmRef = fault.pdmRef {
Section {
VStack(alignment: .leading) {
HStack {
Expand All @@ -111,7 +112,8 @@ struct PodDetailsView: View {
Text(LocalizedString("Pod Fault Details", comment: "description label for pod fault details"))
.fontWeight(.semibold)
}.padding(.vertical, 4)
Text(String(format: LocalizedString("Internal Pod fault code %1$03d\n%2$@\nRef: %3$@\n", comment: "The format string for the pod fault info: (1: fault code) (2: fault description) (3: pdm ref string)"), fault.rawValue, fault.faultDescription, pdmRef))
let faultCode = fault.faultEventCode
Text(String(format: LocalizedString("Internal Pod fault code %1$03d\n%2$@\nRef: %3$@\n", comment: "The format string for the pod fault info: (1: fault code) (2: fault description) (3: pdm ref string)"), faultCode.rawValue, faultCode.faultDescription, pdmRef))
.fixedSize(horizontal: false, vertical: true)
.foregroundColor(.secondary)
}
Expand All @@ -124,6 +126,6 @@ struct PodDetailsView: View {

struct PodDetailsView_Previews: PreviewProvider {
static var previews: some View {
PodDetailsView(podDetails: PodDetails(lotNumber: 123456789, sequenceNumber: 1234567, firmwareVersion: "4.3.2", bleFirmwareVersion: "1.2.3", deviceName: "DashPreviewPod", totalDelivery: 99, lastStatus: Date(), fault: FaultEventCode(rawValue: 064), activatedAt: Date().addingTimeInterval(.days(2)), pdmRef: "19-02448-09951-064"), title: "Pod Details")
PodDetailsView(podDetails: PodDetails(lotNumber: 123456789, sequenceNumber: 1234567, firmwareVersion: "4.3.2", bleFirmwareVersion: "1.2.3", deviceName: "DashPreviewPod", totalDelivery: 99, lastStatus: Date(), fault: nil, activatedAt: Date().addingTimeInterval(.days(2))), title: "Pod Details")
}
}