| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- import Foundation
- extension TrioRemoteControl {
- internal func handleBolusCommand(_ pushMessage: PushMessage) async {
- guard let bolusAmount = pushMessage.bolusAmount else {
- await logError("Command rejected: bolus amount is missing or invalid.", pushMessage: pushMessage)
- return
- }
- let maxBolus = await FreeAPSApp.resolver.resolve(SettingsManager.self)?.pumpSettings.maxBolus ?? Decimal(0)
- if bolusAmount > maxBolus {
- await logError(
- "Command rejected: bolus amount (\(bolusAmount) units) exceeds the maximum allowed (\(maxBolus) units).",
- pushMessage: pushMessage
- )
- return
- }
- let maxIOB = settings.preferences.maxIOB
- let currentIOB = await fetchCurrentIOB()
- if (currentIOB + bolusAmount) > maxIOB {
- await logError(
- "Command rejected: bolus amount (\(bolusAmount) units) would exceed max IOB (\(maxIOB) units). Current IOB: \(currentIOB) units.",
- pushMessage: pushMessage
- )
- return
- }
- let totalRecentBolusAmount = await fetchTotalRecentBolusAmount(since: Date(timeIntervalSince1970: pushMessage.timestamp))
- if totalRecentBolusAmount >= bolusAmount * 0.2 {
- await logError(
- "Command rejected: boluses totaling more than 20% of the requested amount have been delivered since the command was sent.",
- pushMessage: pushMessage
- )
- return
- }
- debug(.remoteControl, "Enacting bolus command with amount: \(bolusAmount) units.")
- guard let apsManager = await FreeAPSApp.resolver.resolve(APSManager.self) else {
- await logError(
- "Error: unable to process bolus command because the APS Manager is not available.",
- pushMessage: pushMessage
- )
- return
- }
- await apsManager.enactBolus(amount: Double(truncating: bolusAmount as NSNumber), isSMB: false)
- debug(
- .remoteControl,
- "Remote command processed successfully. \(pushMessage.humanReadableDescription())"
- )
- }
- private func fetchCurrentIOB() async -> Decimal {
- let predicate = NSPredicate.predicateFor30MinAgoForDetermination
- let determinations = await CoreDataStack.shared.fetchEntitiesAsync(
- ofType: OrefDetermination.self,
- onContext: pumpHistoryFetchContext,
- predicate: predicate,
- key: "timestamp",
- ascending: false,
- fetchLimit: 1,
- propertiesToFetch: ["iob"]
- )
- guard let fetchedResults = determinations as? [[String: Any]],
- let firstResult = fetchedResults.first,
- let iob = firstResult["iob"] as? Decimal
- else {
- await logError("Failed to fetch current IOB.")
- return Decimal(0)
- }
- return iob
- }
- private func fetchTotalRecentBolusAmount(since date: Date) async -> Decimal {
- let predicate = NSPredicate(
- format: "type == %@ AND timestamp > %@",
- PumpEventStored.EventType.bolus.rawValue,
- date as NSDate
- )
- let results: Any = await CoreDataStack.shared.fetchEntitiesAsync(
- ofType: PumpEventStored.self,
- onContext: pumpHistoryFetchContext,
- predicate: predicate,
- key: "timestamp",
- ascending: true,
- fetchLimit: nil,
- propertiesToFetch: ["bolus.amount"]
- )
- guard let bolusDictionaries = results as? [[String: Any]] else {
- await logError("Failed to cast fetched bolus events. Fetched entities type: \(type(of: results))")
- return 0
- }
- let totalAmount = bolusDictionaries.compactMap { ($0["bolus.amount"] as? NSNumber)?.decimalValue }.reduce(0, +)
- return totalAmount
- }
- }
|