From cd14e9fd14cde69b13da9cb139d09dac441bc16f Mon Sep 17 00:00:00 2001 From: Joe Moran Date: Wed, 13 Mar 2024 17:59:56 -0700 Subject: [PATCH 1/2] Display additional info in the Deactivate Pod view for a faulted pod + Add short sentence for Pod Expired, Empty Reservoir & Occlusion Detected + Display code value, fault description and PDM Ref code for other faults + Rework FaultEventCode struct to include new faultDescription var + Use OmniBLEPumpManagerError enum for OmniBLE DeactivationError --- OmniBLE/OmnipodCommon/FaultEventCode.swift | 596 +++++++++--------- .../ViewControllers/DashUICoordinator.swift | 2 +- .../ViewModels/DeactivatePodViewModel.swift | 54 +- 3 files changed, 331 insertions(+), 321 deletions(-) diff --git a/OmniBLE/OmnipodCommon/FaultEventCode.swift b/OmniBLE/OmnipodCommon/FaultEventCode.swift index 83633a75..b430d6eb 100644 --- a/OmniBLE/OmnipodCommon/FaultEventCode.swift +++ b/OmniBLE/OmnipodCommon/FaultEventCode.swift @@ -147,6 +147,7 @@ public struct FaultEventCode: CustomStringConvertible, Equatable { case bleTimeout = 0xA0 case bleInitiated = 0xA1 case bleUnkAlarm = 0xA2 + case bleIaas = 0xA6 case crcFailure = 0xA8 case bleWdPingTimeout = 0xA9 @@ -178,315 +179,304 @@ public struct FaultEventCode: CustomStringConvertible, Equatable { public var faultType: FaultEventType? { return FaultEventType(rawValue: rawValue) } - + init(rawValue: UInt8) { self.rawValue = rawValue } - - public var description: String { - let faultDescription: String - - if let faultType = faultType { - faultDescription = { - switch faultType { - case .noFaults: - return "No fault" - case .failedFlashErase: - return "Flash erase failed" - case .failedFlashStore: - return "Flash store failed" - case .tableCorruptionBasalSubcommand: - return "Basal subcommand table corruption" - case .basalPulseTableCorruption: - return "Basal pulse table corruption" - case .corruptionByte720: - return "Corruption in byte_720" - case .dataCorruptionInTestRTCInterrupt: - return "Data corruption error in test_RTC_interrupt" - case .rtcInterruptHandlerInconsistentState: - return "RTC interrupt handler called with inconsistent state" - case .valueGreaterThan8: - return "Value > 8" - case .invalidBeepRepeatPattern: - return "Invalid beep repeat pattern" - case .bf0notEqualToBF1: - return "Corruption in byte_BF0" - case .tableCorruptionTempBasalSubcommand: - return "Temp basal subcommand table corruption" - case .resetDueToCOP: - return "Reset due to COP" - case .resetDueToIllegalOpcode: - return "Reset due to illegal opcode" - case .resetDueToIllegalAddress: - return "Reset due to illegal address" - case .resetDueToSAWCOP: - return "Reset due to SAWCOP" - case .corruptionInByte_866: - return "Corruption in byte_866" - case .resetDueToLVD: - return "Reset due to LVD" - case .messageLengthTooLong: - return "Message length too long" - case .occluded: - return "Occluded" - case .corruptionInWord129: - return "Corruption in word_129 table/word_86A/dword_86E" - case .corruptionInByte868: - return "Corruption in byte_868" - case .corruptionInAValidatedTable: - return "Corruption in a validated table" - case .reservoirEmpty: - return "Reservoir empty or exceeded maximum pulse delivery" - case .badPowerSwitchArrayValue1: - return "Bad Power Switch Array Status and Control Register value 1 before starting pump" - case .badPowerSwitchArrayValue2: - return "Bad Power Switch Array Status and Control Register value 2 before starting pump" - case .badLoadCnthValue: - return "Bad LOADCNTH value when running pump" - case .exceededMaximumPodLife80Hrs: - return "Exceeded maximum Pod life of 80 hours" - case .badStateCommand1AScheduleParse: - return "Unexpected internal state in command_1A_schedule_parse_routine_wrapper" - case .unexpectedStateInRegisterUponReset: - return "Unexpected commissioned state in status and control register upon reset" - case .wrongSummaryForTable129: - return "Sum mismatch for word_129 table" - case .validateCountErrorWhenBolusing: - return "Validate encoder count error when bolusing" - case .badTimerVariableState: - return "Bad timer variable state" - case .unexpectedRTCModuleValueDuringReset: - return "Unexpected RTC Modulo Register value during reset" - case .problemCalibrateTimer: - return "Problem in calibrate_timer_case_3" - case .tickcntErrorRTC: - return "Tick count error RTC" - case .tickFailure: - return "Tick failure" - case .rtcInterruptHandlerUnexpectedCall: - return "RTC interrupt handler unexpectedly called" - case .missing2hourAlertToFillTank: - return "Failed to set up 2 hour alert for tank fill operation" - case .faultEventSetupPod: - return "Bad arg or state in update_insulin_variables, verify_and_start_pump or main_loop_control_pump" - case .autoOff0: - return "Alert #0 auto-off timeout" - case .autoOff1: - return "Alert #1 auto-off timeout" - case .autoOff2: - return "Alert #2 auto-off timeout" - case .autoOff3: - return "Alert #3 auto-off timeout" - case .autoOff4: - return "Alert #4 auto-off timeout" - case .autoOff5: - return "Alert #5 auto-off timeout" - case .autoOff6: - return "Alert #6 auto-off timeout" - case .autoOff7: - return "Alert #7 auto-off timeout" - case .insulinDeliveryCommandError: - return "Incorrect pod state for command or error during insulin command setup" - case .badValueStartupTest: - return "Bad value during startup testing" - case .connectedPodCommandTimeout: - return "Connected Pod command timeout" - case .resetFromUnknownCause: - return "Reset from unknown cause" - case .vetoNotSet: - return "Veto not set" - case .errorFlashInitialization: - return "Flash initialization error" - case .badPiezoValue: - return "Bad piezo value" - case .unexpectedValueByte358: - return "Unexpected byte_358 value" - case .problemWithLoad1and2: - return "Problem with LOAD1/LOAD2" - case .aGreaterThan7inMessage: - return "A > 7 in message processing" - case .failedTestSawReset: - return "SAW reset testing fail" - case .testInProgress: - return "Test in progress" - case .problemWithPumpAnchor: - return "Problem with pump anchor" - case .errorFlashWrite: - return "Flash initialization or write error" - case .encoderCountTooHigh: - return "Encoder count too high" - case .encoderCountExcessiveVariance: - return "Encoder count excessive variance" - case .encoderCountTooLow: - return "Encoder count too low" - case .encoderCountProblem: - return "Encoder count problem" - case .checkVoltageOpenWire1: - return "Check voltage open wire 1 problem" - case .checkVoltageOpenWire2: - return "Check voltage open wire 2 problem" - case .problemWithLoad1and2type46: - return "Problem with LOAD1/LOAD2" - case .problemWithLoad1and2type47: - return "Problem with LOAD1/LOAD2" - case .badTimerCalibration: - return "Bad timer calibration" - case .badTimerRatios: - return "Bad timer values: COP timer ratio bad" - case .badTimerValues: - return "Bad timer values" - case .trimICSTooCloseTo0x1FF: - return "ICS trim too close to 0x1FF" - case .problemFindingBestTrimValue: - return "find_best_trim_value problem" - case .badSetTPM1MultiCasesValue: - return "Bad set_TPM1_multi_cases value" - case .sawTrimError: - return "SAW Trim Error" - case .unexpectedRFErrorFlagDuringReset: - return "Unexpected TXSCR2 RF Tranmission Error Flag set during reset" - case .timerPulseWidthModulatorOverflow: - return "Timer pulse-width modulator overflow" - case .tickcntError: - return "Bad tick count state before starting pump" - case .badRfmXtalStart: - return "TXOK issue in process_input_buffer" - case .badRxSensitivity: - return "Bad Rx word_107 sensitivity value during input message processing" - case .packetFrameLengthTooLong: - return "Packet frame length too long" - case .unexpectedIRQHighinTimerTick: - return "Unexpected IRQ high in timer_tick" - case .unexpectedIRQLowinTimerTick: - return "Unexpected IRQ low in timer_tick" - case .badArgToGetEntry: - return "Corrupt constants table at byte_37A[] or flash byte_4036[]" - case .badArgToUpdate37ATable: - return "Bad argument to update_37A_table" - case .errorUpdating37ATable: - return "Error updating constants byte_37A table" - case .occlusionCheckValueTooHigh: - return "Occlusion check value too high for detection" - case .loadTableCorruption: - return "Load table corruption" - case .primeOpenCountTooLow: - return "Prime open count too low" - case .badValueByte109: - return "Bad byte_109 value" - case .disableFlashSecurityFailed: - return "Write flash byte to disable flash security failed" - case .checkVoltageFailure: - return "Two check voltage failures before starting pump" - case .occlusionCheckStartup1: - return "Occlusion check startup problem 1" - case .occlusionCheckStartup2: - return "Occlusion check startup problem 2" - case .occlusionCheckTimeouts1: - return "Occlusion check excess timeouts 1" - case .occlusionCheckTimeouts2: - return "Occlusion check excess timeouts 2" - case .occlusionCheckTimeouts3: - return "Occlusion check excess timeouts 3" - case .occlusionCheckPulseIssue: - return "Occlusion check pulse issue" - case .occlusionCheckBolusProblem: - return "Occlusion check bolus problem" - case .occlusionCheckAboveThreshold: - return "Occlusion check above threshold" - case .basalUnderInfusion: - return "Basal under infusion" - case .basalOverInfusion: - return "Basal over infusion" - case .tempBasalUnderInfusion: - return "Temp basal under infusion" - case .tempBasalOverInfusion: - return "Temp basal over infusion" - case .bolusUnderInfusion: - return "Bolus under infusion" - case .bolusOverInfusion: - return "Bolus over infusion" - case .basalOverInfusionPulse: - return "Basal over infusion pulse" - case .tempBasalOverInfusionPulse: - return "Temp basal over infusion pulse" - case .bolusOverInfusionPulse: - return "Bolus over infusion pulse" - case .immediateBolusOverInfusionPulse: - return "Immediate bolus under infusion pulse" - case .extendedBolusOverInfusionPulse: - return "Extended bolus over infusion pulse" - case .corruptionOfTables: - return "Corruption of $283/$2E3/$315 tables" - case .unrecognizedPulse: - return "Bad pulse value to verify_and_start_pump" - case .syncWithoutTempActive: - return "Pump sync req 5 with no temp basal active" - case .command1AParseUnexpectedFailed: - return "Command 1A parse routine unexpected failed" - case .illegalChanParam: - return "Bad parameter for $283/$2E3/$315 channel table specification" - case .basalPulseChanInactive: - return "Pump basal request with basal IST not set" - case .tempPulseChanInactive: - return "Pump temp basal request with temp basal IST not set" - case .bolusPulseChanInactive: - return "Pump bolus request and bolus IST not set" - case .intSemaphoreNotSet: - return "Bad table specifier field6 in 1A command" - case .illegalInterLockChan: - return "Illegal interlock channel" - case .badStateInClearBolusIST2AndVars: - return "Bad variable state in clear_Bolus_IST2_and_vars" - case .badStateInMaybeInc33D: - return "Bad variable state in maybe_inc_33D" - case .bleTimeout: - return "BLE timeout" - case .bleInitiated: - return "BLE initiated" - case .bleUnkAlarm: - return "BLE unknown alarm" - case .bleIaas: - return "BLE IAAS" - case .crcFailure: - return "CRC failure" - case .bleWdPingTimeout: - return "BLE WD ping timeout" - case .bleExcessiveResets: - return "BLE excessive resets" - case .bleNakError: - return "BLE NAK error" - case .bleReqHighTimeout: - return "BLE request high timeout" - case .bleUnknownResp: - return "BLE unknown response" - case .bleReqStuckHigh: - return "BLE request stuck high" - case .bleStateMachine1: - return "BLE state machine 1" - case .bleStateMachine2: - return "BLE state machine 2" - case .bleArbLost: - return "BLE arbitration lost" - case .bleEr48DualNack: - return "BLE dual Nack" - case .bleQnExceedMaxRetry: - return "BLE QN exceed max retry" - case .bleQnCritVarFail: - return "BLE QN critical variable fail" - case .unknown0xCB, .unknown0xD4, .unknown0xD5, .unknown0xD8, .unknown0xD9: - return "Unknown fault" - case .resetFault0xD6, .resetFault0xD7: - return "Reset fault of unknown origin" - case .valuesDoNotMatch: - return "Unknown fault code" - } - }() - } else { - faultDescription = "Unknown Fault" + + public var faultDescription: String { + switch faultType { + case .noFaults: + return "No fault" + case .failedFlashErase: + return "Flash erase failed" + case .failedFlashStore: + return "Flash store failed" + case .tableCorruptionBasalSubcommand: + return "Basal subcommand table corruption" + case .basalPulseTableCorruption: + return "Basal pulse table corruption" + case .corruptionByte720: + return "Corruption in byte_720" + case .dataCorruptionInTestRTCInterrupt: + return "Data corruption error in test_RTC_interrupt" + case .rtcInterruptHandlerInconsistentState: + return "RTC interrupt handler called with inconstent state" + case .valueGreaterThan8: + return "Value > 8" + case .invalidBeepRepeatPattern: + return "Invalid beep repeat pattern" + case .bf0notEqualToBF1: + return "Corruption in byte_BF0" + case .tableCorruptionTempBasalSubcommand: + return "Temp basal subcommand table corruption" + case .resetDueToCOP: + return "Reset due to COP" + case .resetDueToIllegalOpcode: + return "Reset due to illegal opcode" + case .resetDueToIllegalAddress: + return "Reset due to illegal address" + case .resetDueToSAWCOP: + return "Reset due to SAWCOP" + case .corruptionInByte_866: + return "Corruption in byte_866" + case .resetDueToLVD: + return "Reset due to LVD" + case .messageLengthTooLong: + return "Message length too long" + case .occluded: + return "Occluded" + case .corruptionInWord129: + return "Corruption in word_129 table/word_86A/dword_86E" + case .corruptionInByte868: + return "Corruption in byte_868" + case .corruptionInAValidatedTable: + return "Corruption in a validated table" + case .reservoirEmpty: + return "Reservoir empty or exceeded maximum pulse delivery" + case .badPowerSwitchArrayValue1: + return "Bad Power Switch Array Status and Control Register value 1 before starting pump" + case .badPowerSwitchArrayValue2: + return "Bad Power Switch Array Status and Control Register value 2 before starting pump" + case .badLoadCnthValue: + return "Bad LOADCNTH value when running pump" + case .exceededMaximumPodLife80Hrs: + return "Exceeded maximum Pod life of 80 hours" + case .badStateCommand1AScheduleParse: + return "Unexpected internal state in command_1A_schedule_parse_routine_wrapper" + case .unexpectedStateInRegisterUponReset: + return "Unexpected commissioned state in status and control register upon reset" + case .wrongSummaryForTable129: + return "Sum mismatch for word_129 table" + case .validateCountErrorWhenBolusing: + return "Validate encoder count error when bolusing" + case .badTimerVariableState: + return "Bad timer variable state" + case .unexpectedRTCModuleValueDuringReset: + return "Unexpected RTC Modulo Register value during reset" + case .problemCalibrateTimer: + return "Problem in calibrate_timer_case_3" + case .tickcntErrorRTC: + return "Tick count error RTC" + case .tickFailure: + return "Tick failure" + case .rtcInterruptHandlerUnexpectedCall: + return "RTC interrupt handler unexpectedly called" + case .missing2hourAlertToFillTank: + return "Failed to set up 2 hour alert for tank fill operation" + case .faultEventSetupPod: + return "Bad arg or state in update_insulin_variables, verify_and_start_pump or main_loop_control_pump" + case .autoOff0: + return "Alert #0 auto-off timeout" + case .autoOff1: + return "Alert #1 auto-off timeout" + case .autoOff2: + return "Alert #2 auto-off timeout" + case .autoOff3: + return "Alert #3 auto-off timeout" + case .autoOff4: + return "Alert #4 auto-off timeout" + case .autoOff5: + return "Alert #5 auto-off timeout" + case .autoOff6: + return "Alert #6 auto-off timeout" + case .autoOff7: + return "Alert #7 auto-off timeout" + case .insulinDeliveryCommandError: + return "Incorrect pod state for command or error during insulin command setup" + case .badValueStartupTest: + return "Bad value during startup testing" + case .connectedPodCommandTimeout: + return "Connected Pod command timeout" + case .resetFromUnknownCause: + return "Reset from unknown cause" + case .vetoNotSet: + return "Veto not set" + case .errorFlashInitialization: + return "Flash initialization error" + case .badPiezoValue: + return "Bad piezo value" + case .unexpectedValueByte358: + return "Unexpected byte_358 value" + case .problemWithLoad1and2: + return "Problem with LOAD1/LOAD2" + case .aGreaterThan7inMessage: + return "A > 7 in message processing" + case .failedTestSawReset: + return "SAW reset testing fail" + case .testInProgress: + return "test in progress" + case .problemWithPumpAnchor: + return "Problem with pump anchor" + case .errorFlashWrite: + return "Flash initialization or write error" + case .encoderCountTooHigh: + return "Encoder count too high" + case .encoderCountExcessiveVariance: + return "Encoder count excessive variance" + case .encoderCountTooLow: + return "Encoder count too low" + case .encoderCountProblem: + return "Encoder count problem" + case .checkVoltageOpenWire1: + return "Check voltage open wire 1 problem" + case .checkVoltageOpenWire2: + return "Check voltage open wire 2 problem" + case .problemWithLoad1and2type46: + return "Problem with LOAD1/LOAD2" + case .problemWithLoad1and2type47: + return "Problem with LOAD1/LOAD2" + case .badTimerCalibration: + return "Bad timer calibration" + case .badTimerRatios: + return "Bad timer values: COP timer ratio bad" + case .badTimerValues: + return "Bad timer values" + case .trimICSTooCloseTo0x1FF: + return "ICS trim too close to 0x1FF" + case .problemFindingBestTrimValue: + return "find_best_trim_value problem" + case .badSetTPM1MultiCasesValue: + return "Bad set_TPM1_multi_cases value" + case .unexpectedRFErrorFlagDuringReset: + return "Unexpected TXSCR2 RF Tranmission Error Flag set during reset" + case .timerPulseWidthModulatorOverflow: + return "Timer pulse-width modulator overflow" + case .tickcntError: + return "Bad tick count state before starting pump" + case .badRfmXtalStart: + return "TXOK issue in process_input_buffer" + case .badRxSensitivity: + return "Bad Rx word_107 sensitivity value during input message processing" + case .packetFrameLengthTooLong: + return "Packet frame length too long" + case .unexpectedIRQHighinTimerTick: + return "Unexpected IRQ high in timer_tick" + case .unexpectedIRQLowinTimerTick: + return "Unexpected IRQ low in timer_tick" + case .badArgToGetEntry: + return "Corrupt constants table at byte_37A[] or flash byte_4036[]" + case .badArgToUpdate37ATable: + return "Bad argument to update_37A_table" + case .errorUpdating37ATable: + return "Error updating constants byte_37A table" + case .occlusionCheckValueTooHigh: + return "Occlusion check value too high for detection" + case .loadTableCorruption: + return "Load table corruption" + case .primeOpenCountTooLow: + return "Prime open count too low" + case .badValueByte109: + return "Bad byte_109 value" + case .disableFlashSecurityFailed: + return "Write flash byte to disable flash security failed" + case .checkVoltageFailure: + return "Two check voltage failures before starting pump" + case .occlusionCheckStartup1: + return "Occlusion check startup problem 1" + case .occlusionCheckStartup2: + return "Occlusion check startup problem 2" + case .occlusionCheckTimeouts1: + return "Occlusion check excess timeouts 1" + case .occlusionCheckTimeouts2: + return "Occlusion check excess timeouts 2" + case .occlusionCheckTimeouts3: + return "Occlusion check excess timeouts 3" + case .occlusionCheckPulseIssue: + return "Occlusion check pulse issue" + case .occlusionCheckBolusProblem: + return "Occlusion check bolus problem" + case .occlusionCheckAboveThreshold: + return "Occlusion check above threshold" + case .basalUnderInfusion: + return "Basal under infusion" + case .basalOverInfusion: + return "Basal over infusion" + case .tempBasalUnderInfusion: + return "Temp basal under infusion" + case .tempBasalOverInfusion: + return "Temp basal over infusion" + case .bolusUnderInfusion: + return "Bolus under infusion" + case .bolusOverInfusion: + return "Bolus over infusion" + case .basalOverInfusionPulse: + return "Basal over infusion pulse" + case .tempBasalOverInfusionPulse: + return "Temp basal over infusion pulse" + case .bolusOverInfusionPulse: + return "Bolus over infusion pulse" + case .immediateBolusOverInfusionPulse: + return "Immediate bolus under infusion pulse" + case .extendedBolusOverInfusionPulse: + return "Extended bolus over infusion pulse" + case .corruptionOfTables: + return "Corruption of $283/$2E3/$315 tables" + case .unrecognizedPulse: + return "Bad pulse value to verify_and_start_pump" + case .syncWithoutTempActive: + return "Pump sync req 5 with no temp basal active" + case .command1AParseUnexpectedFailed: + return "Command 1A parse routine unexpected failed" + case .illegalChanParam: + return "Bad parameter for $283/$2E3/$315 channel table specification" + case .basalPulseChanInactive: + return "Pump basal request with basal IST not set" + case .tempPulseChanInactive: + return "Pump temp basal request with temp basal IST not set" + case .bolusPulseChanInactive: + return "Pump bolus request and bolus IST not set" + case .intSemaphoreNotSet: + return "Bad table specifier field6 in 1A command" + case .illegalInterLockChan: + return "Illegal interlock channel" + case .badStateInClearBolusIST2AndVars: + return "Bad variable state in clear_Bolus_IST2_and_vars" + case .badStateInMaybeInc33D: + return "Bad variable state in maybe_inc_33D" + case .bleTimeout: + return "BLE timeout" + case .bleInitiated: + return "BLE initiated" + case .bleUnkAlarm: + return "BLE unknown alarm" + case .bleIaas: + return "BLE IAAS" + case .crcFailure: + return "CRC failure" + case .bleWdPingTimeout: + return "BLE WD ping timeout" + case .bleExcessiveResets: + return "BLE excessive resets" + case .bleNakError: + return "BLE NAK error" + case .bleReqHighTimeout: + return "BLE request high timeout" + case .bleUnknownResp: + return "BLE unknown response" + case .bleReqStuckHigh: + return "BLE request stuck high" + case .bleStateMachine1: + return "BLE state machine 1" + case .bleStateMachine2: + return "BLE state machine 2" + case .bleArbLost: + return "BLE arbitration lost" + case .bleEr48DualNack: + return "BLE dual Nack" + case .bleQnExceedMaxRetry: + return "BLE QN exceed max retry" + case .bleQnCritVarFail: + return "BLE QN critical variable fail" + default: + return "Unknown fault code" } + } + + public var description: String { return String(format: "Fault Event Code 0x%02x: %@", rawValue, faultDescription) } - + public var localizedDescription: String { if let faultType = faultType { switch faultType { diff --git a/OmniBLE/PumpManagerUI/ViewControllers/DashUICoordinator.swift b/OmniBLE/PumpManagerUI/ViewControllers/DashUICoordinator.swift index a4e87612..68cafc57 100644 --- a/OmniBLE/PumpManagerUI/ViewControllers/DashUICoordinator.swift +++ b/OmniBLE/PumpManagerUI/ViewControllers/DashUICoordinator.swift @@ -149,7 +149,7 @@ class DashUICoordinator: UINavigationController, PumpManagerOnboarding, Completi hostedView.navigationItem.title = LocalizedString("Insulin Type", comment: "Title for insulin type selection screen") return hostedView case .deactivate: - let viewModel = DeactivatePodViewModel(podDeactivator: pumpManager, podAttachedToBody: pumpManager.podAttachmentConfirmed) + let viewModel = DeactivatePodViewModel(podDeactivator: pumpManager, podAttachedToBody: pumpManager.podAttachmentConfirmed, fault: pumpManager.state.podState?.fault) viewModel.didFinish = { [weak self] in self?.stepFinished() diff --git a/OmniBLE/PumpManagerUI/ViewModels/DeactivatePodViewModel.swift b/OmniBLE/PumpManagerUI/ViewModels/DeactivatePodViewModel.swift index 16ca82b9..c6dde287 100644 --- a/OmniBLE/PumpManagerUI/ViewModels/DeactivatePodViewModel.swift +++ b/OmniBLE/PumpManagerUI/ViewModels/DeactivatePodViewModel.swift @@ -10,8 +10,8 @@ import Foundation import LoopKitUI public protocol PodDeactivater { - func deactivatePod(completion: @escaping (OmniBLEPumpManagerError?) -> ()) - func forgetPod(completion: @escaping () -> ()) + func deactivatePod(completion: @escaping (OmniBLEPumpManagerError?) -> Void) + func forgetPod(completion: @escaping () -> Void) } extension OmniBLEPumpManager: PodDeactivater {} @@ -19,16 +19,6 @@ extension OmniBLEPumpManager: PodDeactivater {} class DeactivatePodViewModel: ObservableObject, Identifiable { - public var podAttachedToBody: Bool - - var instructionText: String { - if podAttachedToBody { - return LocalizedString("Please deactivate the pod. When deactivation is complete, you may remove it and pair a new pod.", comment: "Instructions for deactivate pod when pod is on body") - } else { - return LocalizedString("Please deactivate the pod. When deactivation is complete, you may pair a new pod.", comment: "Instructions for deactivate pod when pod not on body") - } - } - enum DeactivatePodViewModelState { case active case deactivating @@ -110,6 +100,7 @@ class DeactivatePodViewModel: ObservableObject, Identifiable { } @Published var state: DeactivatePodViewModelState = .active + public var stateNeedsDeliberateUserAcceptance : Bool { switch state { case .active: @@ -132,9 +123,38 @@ class DeactivatePodViewModel: ObservableObject, Identifiable { var podDeactivator: PodDeactivater - init(podDeactivator: PodDeactivater, podAttachedToBody: Bool) { + var podAttachedToBody: Bool + + var instructionText: String + + init(podDeactivator: PodDeactivater, podAttachedToBody: Bool, fault: DetailedStatus?) { + + var text: String = "" + if let faultEventCode = fault?.faultEventCode { + let notificationString = faultEventCode.notificationTitle + switch faultEventCode.faultType { + case .exceededMaximumPodLife80Hrs, .reservoirEmpty, .occluded: + // Just prepend a simple sentence with the notification string for these faults. + // Other occluded related 0x6? faults will be treated as a general pod error as per the PDM. + text = String(format: "%@. ", notificationString) + default: + // Display the fault code value, the fault description and the pdmRef string for other errors. + text = String(format: "⚠️ %1$@ (0x%2$02X)\n%3$@\n", notificationString, faultEventCode.rawValue, faultEventCode.faultDescription) + if let pdmRef = fault?.pdmRef { + text += LocalizedString("Ref: ", comment: "PDM Ref string line") + pdmRef + "\n\n" + } + } + } + + if podAttachedToBody { + text += LocalizedString("Please deactivate the pod. When deactivation is complete, you may remove it and pair a new pod.", comment: "Instructions for deactivate pod when pod is on body") + } else { + text += LocalizedString("Please deactivate the pod. When deactivation is complete, you may pair a new pod.", comment: "Instructions for deactivate pod when pod not on body") + } + self.podDeactivator = podDeactivator self.podAttachedToBody = podAttachedToBody + self.instructionText = text } public func continueButtonTapped() { @@ -145,7 +165,7 @@ class DeactivatePodViewModel: ObservableObject, Identifiable { podDeactivator.deactivatePod { (error) in DispatchQueue.main.async { if let error = error { - self.state = .resultError(DeactivationError.OmnipodPumpManagerError(error)) + self.state = .resultError(DeactivationError.OmniBLEPumpManagerError(error)) } else { self.discardPod(navigateOnCompletion: false) } @@ -168,18 +188,18 @@ class DeactivatePodViewModel: ObservableObject, Identifiable { } enum DeactivationError : LocalizedError { - case OmnipodPumpManagerError(OmniBLEPumpManagerError) + case OmniBLEPumpManagerError(OmniBLEPumpManagerError) var recoverySuggestion: String? { switch self { - case .OmnipodPumpManagerError: + case .OmniBLEPumpManagerError: return LocalizedString("There was a problem communicating with the pod. If this problem persists, tap Discard Pod. You can then activate a new Pod.", comment: "Format string for recovery suggestion during deactivate pod.") } } var errorDescription: String? { switch self { - case .OmnipodPumpManagerError(let error): + case .OmniBLEPumpManagerError(let error): return error.errorDescription } } From c1700cbfd633fe366e0046ffcde6f485ece243ae Mon Sep 17 00:00:00 2001 From: Joe Moran Date: Wed, 13 Mar 2024 19:36:05 -0700 Subject: [PATCH 2/2] Update fault description switch to include all possible values --- OmniBLE/OmnipodCommon/FaultEventCode.swift | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/OmniBLE/OmnipodCommon/FaultEventCode.swift b/OmniBLE/OmnipodCommon/FaultEventCode.swift index b430d6eb..913ca876 100644 --- a/OmniBLE/OmnipodCommon/FaultEventCode.swift +++ b/OmniBLE/OmnipodCommon/FaultEventCode.swift @@ -210,6 +210,7 @@ public struct FaultEventCode: CustomStringConvertible, Equatable { return "Corruption in byte_BF0" case .tableCorruptionTempBasalSubcommand: return "Temp basal subcommand table corruption" + case .resetDueToCOP: return "Reset due to COP" case .resetDueToIllegalOpcode: @@ -310,6 +311,7 @@ public struct FaultEventCode: CustomStringConvertible, Equatable { return "Problem with pump anchor" case .errorFlashWrite: return "Flash initialization or write error" + case .encoderCountTooHigh: return "Encoder count too high" case .encoderCountExcessiveVariance: @@ -338,6 +340,8 @@ public struct FaultEventCode: CustomStringConvertible, Equatable { return "find_best_trim_value problem" case .badSetTPM1MultiCasesValue: return "Bad set_TPM1_multi_cases value" + case .sawTrimError: + return "SAW Trim Error" case .unexpectedRFErrorFlagDuringReset: return "Unexpected TXSCR2 RF Tranmission Error Flag set during reset" case .timerPulseWidthModulatorOverflow: @@ -378,6 +382,7 @@ public struct FaultEventCode: CustomStringConvertible, Equatable { return "Occlusion check startup problem 2" case .occlusionCheckTimeouts1: return "Occlusion check excess timeouts 1" + case .occlusionCheckTimeouts2: return "Occlusion check excess timeouts 2" case .occlusionCheckTimeouts3: @@ -388,6 +393,7 @@ public struct FaultEventCode: CustomStringConvertible, Equatable { return "Occlusion check bolus problem" case .occlusionCheckAboveThreshold: return "Occlusion check above threshold" + case .basalUnderInfusion: return "Basal under infusion" case .basalOverInfusion: @@ -434,12 +440,14 @@ public struct FaultEventCode: CustomStringConvertible, Equatable { return "Bad variable state in clear_Bolus_IST2_and_vars" case .badStateInMaybeInc33D: return "Bad variable state in maybe_inc_33D" + case .bleTimeout: return "BLE timeout" case .bleInitiated: return "BLE initiated" case .bleUnkAlarm: return "BLE unknown alarm" + case .bleIaas: return "BLE IAAS" case .crcFailure: @@ -454,6 +462,7 @@ public struct FaultEventCode: CustomStringConvertible, Equatable { return "BLE request high timeout" case .bleUnknownResp: return "BLE unknown response" + case .bleReqStuckHigh: return "BLE request stuck high" case .bleStateMachine1: @@ -468,7 +477,13 @@ public struct FaultEventCode: CustomStringConvertible, Equatable { return "BLE QN exceed max retry" case .bleQnCritVarFail: return "BLE QN critical variable fail" - default: + + case .resetFault0xD6, .resetFault0xD7: + return "Reset fault of unknown origin" + case .unknown0xCB, .unknown0xD4, .unknown0xD5, .unknown0xD8, .unknown0xD9, .none: + return "Unknown fault" + + case .valuesDoNotMatch: return "Unknown fault code" } }