|
|
@@ -94,8 +94,6 @@ extension Bolus {
|
|
|
|
|
|
let now = Date.now
|
|
|
|
|
|
- private let treatmentsVM = TreatmentsViewModel()
|
|
|
-
|
|
|
let context = CoreDataStack.shared.persistentContainer.viewContext
|
|
|
|
|
|
override func subscribe() {
|
|
|
@@ -243,37 +241,87 @@ extension Bolus {
|
|
|
.roundBolus(amount: max(insulinCalculated, 0))
|
|
|
}
|
|
|
|
|
|
+ func setupInsulinRequired() {
|
|
|
+ DispatchQueue.main.async {
|
|
|
+ self.insulinRequired = self.provider.suggestion?.insulinReq ?? 0
|
|
|
+
|
|
|
+ var conversion: Decimal = 1.0
|
|
|
+ if self.units == .mmolL {
|
|
|
+ conversion = 0.0555
|
|
|
+ }
|
|
|
+
|
|
|
+ self.evBG = self.provider.suggestion?.eventualBG ?? 0
|
|
|
+ self.insulin = self.provider.suggestion?.insulinForManualBolus ?? 0
|
|
|
+ self.target = self.provider.suggestion?.current_target ?? 0
|
|
|
+ self.isf = self.provider.suggestion?.isf ?? 0
|
|
|
+ self.iob = self.provider.suggestion?.iob ?? 0
|
|
|
+ self.currentBG = (self.provider.suggestion?.bg ?? 0)
|
|
|
+ self.cob = self.provider.suggestion?.cob ?? 0
|
|
|
+ self.basal = self.provider.suggestion?.rate ?? 0
|
|
|
+ self.carbRatio = self.provider.suggestion?.carbRatio ?? 0
|
|
|
+
|
|
|
+ if self.settingsManager.settings.insulinReqPercentage != 100 {
|
|
|
+ self.insulinRecommended = self.insulin * (self.settingsManager.settings.insulinReqPercentage / 100)
|
|
|
+ } else { self.insulinRecommended = self.insulin }
|
|
|
+
|
|
|
+ self.errorString = self.provider.suggestion?.manualBolusErrorString ?? 0
|
|
|
+ if self.errorString != 0 {
|
|
|
+ self.error = true
|
|
|
+ self.minGuardBG = (self.provider.suggestion?.minGuardBG ?? 0) * conversion
|
|
|
+ self.minDelta = (self.provider.suggestion?.minDelta ?? 0) * conversion
|
|
|
+ self.expectedDelta = (self.provider.suggestion?.expectedDelta ?? 0) * conversion
|
|
|
+ self.minPredBG = (self.provider.suggestion?.minPredBG ?? 0) * conversion
|
|
|
+ } else { self.error = false }
|
|
|
+
|
|
|
+ self.insulinRecommended = self.apsManager
|
|
|
+ .roundBolus(amount: max(self.insulinRecommended, 0))
|
|
|
+
|
|
|
+ if self.useCalc {
|
|
|
+ self.getCurrentBasal()
|
|
|
+ self.getDeltaBG()
|
|
|
+ self.insulinCalculated = self.calculateInsulin()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // MARK: - Button tasks
|
|
|
+
|
|
|
@MainActor func invokeTreatmentsTask() {
|
|
|
Task {
|
|
|
- if amount > 0 {
|
|
|
- if !externalInsulin {
|
|
|
- await add()
|
|
|
- } else {
|
|
|
- do {
|
|
|
- await addExternalInsulin()
|
|
|
- }
|
|
|
- }
|
|
|
+ let isInsulinGiven = amount > 0
|
|
|
+ let isCarbsPresent = carbs > 0
|
|
|
+
|
|
|
+ if isInsulinGiven {
|
|
|
+ try await handleInsulin(isExternal: externalInsulin)
|
|
|
+ } else if isCarbsPresent {
|
|
|
waitForSuggestion = true
|
|
|
} else {
|
|
|
- if carbs > 0 {
|
|
|
- waitForSuggestion = true
|
|
|
- } else {
|
|
|
- hideModal()
|
|
|
- }
|
|
|
+ hideModal()
|
|
|
+ return
|
|
|
}
|
|
|
- addCarbs()
|
|
|
+
|
|
|
+ saveMeal()
|
|
|
addButtonPressed = true
|
|
|
|
|
|
// if glucose data is stale end the custom loading animation by hiding the modal
|
|
|
- // alternatively only set waitforSuggestion to false...
|
|
|
- let lastGlucoseDate = glucoseStorage.lastGlucoseDate()
|
|
|
- guard lastGlucoseDate >= Date().addingTimeInterval(-12.minutes.timeInterval) else {
|
|
|
- return hideModal()
|
|
|
- }
|
|
|
+// guard glucoseOfLast20Min.first?.date ?? now >= Date().addingTimeInterval(-12.minutes.timeInterval) else {
|
|
|
+// return hideModal()
|
|
|
+// }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- @MainActor func add() async {
|
|
|
+ // MARK: - Insulin
|
|
|
+
|
|
|
+ @MainActor private func handleInsulin(isExternal: Bool) async throws {
|
|
|
+ if !isExternal {
|
|
|
+ await addPumpInsulin()
|
|
|
+ } else {
|
|
|
+ await addExternalInsulin()
|
|
|
+ }
|
|
|
+ waitForSuggestion = true
|
|
|
+ }
|
|
|
+
|
|
|
+ @MainActor func addPumpInsulin() async {
|
|
|
guard amount > 0 else {
|
|
|
showModal(for: nil)
|
|
|
return
|
|
|
@@ -285,6 +333,7 @@ extension Bolus {
|
|
|
let authenticated = try await unlockmanager.unlock()
|
|
|
if authenticated {
|
|
|
apsManager.enactBolus(amount: maxAmount, isSMB: false)
|
|
|
+ savePumpInsulin(amount: amount)
|
|
|
} else {
|
|
|
print("authentication failed")
|
|
|
}
|
|
|
@@ -299,54 +348,103 @@ extension Bolus {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- func setupInsulinRequired() {
|
|
|
- DispatchQueue.main.async {
|
|
|
- self.insulinRequired = self.provider.suggestion?.insulinReq ?? 0
|
|
|
-
|
|
|
- var conversion: Decimal = 1.0
|
|
|
- if self.units == .mmolL {
|
|
|
- conversion = 0.0555
|
|
|
+ private func savePumpInsulin(amount: Decimal) {
|
|
|
+ let newItem = InsulinStored(context: context)
|
|
|
+ newItem.id = UUID()
|
|
|
+ newItem.amount = amount as NSDecimalNumber
|
|
|
+ newItem.date = Date()
|
|
|
+ newItem.external = false
|
|
|
+ newItem.isSMB = false
|
|
|
+ self.context.perform {
|
|
|
+ do {
|
|
|
+ try self.context.save()
|
|
|
+ debugPrint(
|
|
|
+ "Bolus State: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved pump insulin to core data"
|
|
|
+ )
|
|
|
+ } catch {
|
|
|
+ debugPrint(
|
|
|
+ "Bolus State: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to save pump insulin to core data"
|
|
|
+ )
|
|
|
}
|
|
|
|
|
|
- self.evBG = self.provider.suggestion?.eventualBG ?? 0
|
|
|
- self.insulin = self.provider.suggestion?.insulinForManualBolus ?? 0
|
|
|
- self.target = self.provider.suggestion?.current_target ?? 0
|
|
|
- self.isf = self.provider.suggestion?.isf ?? 0
|
|
|
- self.iob = self.provider.suggestion?.iob ?? 0
|
|
|
- self.currentBG = (self.provider.suggestion?.bg ?? 0)
|
|
|
- self.cob = self.provider.suggestion?.cob ?? 0
|
|
|
- self.basal = self.provider.suggestion?.rate ?? 0
|
|
|
- self.carbRatio = self.provider.suggestion?.carbRatio ?? 0
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- if self.settingsManager.settings.insulinReqPercentage != 100 {
|
|
|
- self.insulinRecommended = self.insulin * (self.settingsManager.settings.insulinReqPercentage / 100)
|
|
|
- } else { self.insulinRecommended = self.insulin }
|
|
|
+ // MARK: - EXTERNAL INSULIN
|
|
|
|
|
|
- self.errorString = self.provider.suggestion?.manualBolusErrorString ?? 0
|
|
|
- if self.errorString != 0 {
|
|
|
- self.error = true
|
|
|
- self.minGuardBG = (self.provider.suggestion?.minGuardBG ?? 0) * conversion
|
|
|
- self.minDelta = (self.provider.suggestion?.minDelta ?? 0) * conversion
|
|
|
- self.expectedDelta = (self.provider.suggestion?.expectedDelta ?? 0) * conversion
|
|
|
- self.minPredBG = (self.provider.suggestion?.minPredBG ?? 0) * conversion
|
|
|
- } else { self.error = false }
|
|
|
+ @MainActor func addExternalInsulin() async {
|
|
|
+ guard amount > 0 else {
|
|
|
+ showModal(for: nil)
|
|
|
+ return
|
|
|
+ }
|
|
|
|
|
|
- self.insulinRecommended = self.apsManager
|
|
|
- .roundBolus(amount: max(self.insulinRecommended, 0))
|
|
|
+ amount = min(amount, maxBolus * 3)
|
|
|
|
|
|
- if self.useCalc {
|
|
|
- self.getCurrentBasal()
|
|
|
- self.getDeltaBG()
|
|
|
- self.insulinCalculated = self.calculateInsulin()
|
|
|
+ do {
|
|
|
+ let authenticated = try await unlockmanager.unlock()
|
|
|
+ if authenticated {
|
|
|
+ storeExternalInsulinEvent()
|
|
|
+ } else {
|
|
|
+ print("authentication failed")
|
|
|
+ }
|
|
|
+ } catch {
|
|
|
+ print("authentication error for external insulin: \(error.localizedDescription)")
|
|
|
+ DispatchQueue.main.async {
|
|
|
+ self.waitForSuggestion = false
|
|
|
+ if self.addButtonPressed {
|
|
|
+ self.hideModal()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private func storeExternalInsulinEvent() {
|
|
|
+ pumpHistoryStorage.storeEvents(
|
|
|
+ [
|
|
|
+ PumpHistoryEvent(
|
|
|
+ id: UUID().uuidString,
|
|
|
+ type: .bolus,
|
|
|
+ timestamp: date,
|
|
|
+ amount: amount,
|
|
|
+ duration: nil,
|
|
|
+ durationMin: nil,
|
|
|
+ rate: nil,
|
|
|
+ temp: nil,
|
|
|
+ carbInput: nil,
|
|
|
+ isExternal: true
|
|
|
+ )
|
|
|
+ ]
|
|
|
+ )
|
|
|
+ debug(.default, "External insulin saved to pumphistory.json")
|
|
|
+
|
|
|
+ // save to core data asynchronously
|
|
|
+ self.context.perform {
|
|
|
+ let newItem = InsulinStored(context: self.context)
|
|
|
+ newItem.amount = (self.amount) as NSDecimalNumber
|
|
|
+ newItem.date = Date()
|
|
|
+ newItem.external = true
|
|
|
+ newItem.isSMB = false
|
|
|
+ do {
|
|
|
+ try self.context.save()
|
|
|
+ debugPrint(
|
|
|
+ "Bolus State: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved carbs to core data"
|
|
|
+ )
|
|
|
+ } catch {
|
|
|
+ debugPrint(
|
|
|
+ "Bolus State: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to save carbs to core data"
|
|
|
+ )
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // perform determine basal sync
|
|
|
+ apsManager.determineBasalSync()
|
|
|
}
|
|
|
|
|
|
// MARK: - Carbs
|
|
|
|
|
|
// we need to also fetch the data after we have saved them in order to update the array and the UI because of the MVVM Architecture
|
|
|
|
|
|
- func addCarbs() {
|
|
|
+ func saveMeal() {
|
|
|
guard carbs > 0 || fat > 0 || protein > 0 else { return }
|
|
|
carbs = min(carbs, maxCarbs)
|
|
|
id_ = UUID().uuidString
|
|
|
@@ -383,15 +481,17 @@ extension Bolus {
|
|
|
newCarbEntry.carbs = Double(carbs)
|
|
|
newCarbEntry.fat = Double(fat)
|
|
|
newCarbEntry.protein = Double(protein)
|
|
|
- do {
|
|
|
- try self.context.save()
|
|
|
- debugPrint(
|
|
|
- "Bolus State: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved carbs to core data"
|
|
|
- )
|
|
|
- } catch {
|
|
|
- debugPrint(
|
|
|
- "Bolus State: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to save carbs to core data"
|
|
|
- )
|
|
|
+ self.context.perform {
|
|
|
+ do {
|
|
|
+ try self.context.save()
|
|
|
+ debugPrint(
|
|
|
+ "Bolus State: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved carbs to core data"
|
|
|
+ )
|
|
|
+ } catch {
|
|
|
+ debugPrint(
|
|
|
+ "Bolus State: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to save carbs to core data"
|
|
|
+ )
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -522,57 +622,6 @@ extension Bolus {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- // MARK: EXTERNAL INSULIN
|
|
|
-
|
|
|
- @MainActor func addExternalInsulin() async {
|
|
|
- guard amount > 0 else {
|
|
|
- showModal(for: nil)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- amount = min(amount, maxBolus * 3)
|
|
|
-
|
|
|
- do {
|
|
|
- let authenticated = try await unlockmanager.unlock()
|
|
|
- if authenticated {
|
|
|
- storeExternalInsulinEvent()
|
|
|
- } else {
|
|
|
- print("authentication failed")
|
|
|
- }
|
|
|
- } catch {
|
|
|
- print("authentication error for external insulin: \(error.localizedDescription)")
|
|
|
- DispatchQueue.main.async {
|
|
|
- self.waitForSuggestion = false
|
|
|
- if self.addButtonPressed {
|
|
|
- self.hideModal()
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private func storeExternalInsulinEvent() {
|
|
|
- pumpHistoryStorage.storeEvents(
|
|
|
- [
|
|
|
- PumpHistoryEvent(
|
|
|
- id: UUID().uuidString,
|
|
|
- type: .bolus,
|
|
|
- timestamp: date,
|
|
|
- amount: amount,
|
|
|
- duration: nil,
|
|
|
- durationMin: nil,
|
|
|
- rate: nil,
|
|
|
- temp: nil,
|
|
|
- carbInput: nil,
|
|
|
- isExternal: true
|
|
|
- )
|
|
|
- ]
|
|
|
- )
|
|
|
- debug(.default, "External insulin saved to pumphistory.json")
|
|
|
-
|
|
|
- // perform determine basal sync
|
|
|
- apsManager.determineBasalSync()
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
|