CarbsStorage.swift 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import CoreData
  2. import Foundation
  3. import SwiftDate
  4. import Swinject
  5. protocol CarbsObserver {
  6. func carbsDidUpdate(_ carbs: [CarbsEntry])
  7. }
  8. protocol CarbsStorage {
  9. func storeCarbs(_ carbs: [CarbsEntry])
  10. func syncDate() -> Date
  11. func recent() -> [CarbsEntry]
  12. func nightscoutTretmentsNotUploaded() -> [NigtscoutTreatment]
  13. func deleteCarbs(at date: Date)
  14. }
  15. final class BaseCarbsStorage: CarbsStorage, Injectable {
  16. private let processQueue = DispatchQueue(label: "BaseCarbsStorage.processQueue")
  17. @Injected() private var storage: FileStorage!
  18. @Injected() private var broadcaster: Broadcaster!
  19. let coredataContext = CoreDataStack.shared.persistentContainer.newBackgroundContext()
  20. init(resolver: Resolver) {
  21. injectServices(resolver)
  22. }
  23. func storeCarbs(_ carbs: [CarbsEntry]) {
  24. processQueue.sync {
  25. let file = OpenAPS.Monitor.carbHistory
  26. var uniqEvents: [CarbsEntry] = []
  27. self.storage.transaction { storage in
  28. storage.append(carbs, to: file, uniqBy: \.createdAt)
  29. uniqEvents = storage.retrieve(file, as: [CarbsEntry].self)?
  30. .filter { $0.createdAt.addingTimeInterval(1.days.timeInterval) > Date() }
  31. .sorted { $0.createdAt > $1.createdAt } ?? []
  32. storage.save(Array(uniqEvents), as: file)
  33. }
  34. // MARK: Save to CoreData. TEST
  35. var cbs: Decimal = 0
  36. var carbDate = Date()
  37. if carbs.isNotEmpty {
  38. cbs = carbs[0].carbs
  39. carbDate = carbs[0].createdAt
  40. }
  41. if cbs != 0 {
  42. self.coredataContext.perform {
  43. let carbDataForStats = Carbohydrates(context: self.coredataContext)
  44. carbDataForStats.date = carbDate
  45. carbDataForStats.carbs = cbs as NSDecimalNumber
  46. try? self.coredataContext.save()
  47. }
  48. }
  49. broadcaster.notify(CarbsObserver.self, on: processQueue) {
  50. $0.carbsDidUpdate(uniqEvents)
  51. }
  52. }
  53. }
  54. func syncDate() -> Date {
  55. Date().addingTimeInterval(-1.days.timeInterval)
  56. }
  57. func recent() -> [CarbsEntry] {
  58. storage.retrieve(OpenAPS.Monitor.carbHistory, as: [CarbsEntry].self)?.reversed() ?? []
  59. }
  60. func deleteCarbs(at date: Date) {
  61. processQueue.sync {
  62. var allValues = storage.retrieve(OpenAPS.Monitor.carbHistory, as: [CarbsEntry].self) ?? []
  63. guard let entryIndex = allValues.firstIndex(where: { $0.createdAt == date }) else {
  64. return
  65. }
  66. // If deleteing a FPUs remove all of those with the same ID
  67. if allValues[entryIndex].isFPU != nil, allValues[entryIndex].isFPU ?? false {
  68. let fpuString = allValues[entryIndex].fpuID
  69. allValues.removeAll(where: { $0.fpuID == fpuString })
  70. storage.save(allValues, as: OpenAPS.Monitor.carbHistory)
  71. broadcaster.notify(CarbsObserver.self, on: processQueue) {
  72. $0.carbsDidUpdate(allValues)
  73. }
  74. } else {
  75. allValues.remove(at: entryIndex)
  76. storage.save(allValues, as: OpenAPS.Monitor.carbHistory)
  77. broadcaster.notify(CarbsObserver.self, on: processQueue) {
  78. $0.carbsDidUpdate(allValues)
  79. }
  80. }
  81. }
  82. }
  83. func nightscoutTretmentsNotUploaded() -> [NigtscoutTreatment] {
  84. let uploaded = storage.retrieve(OpenAPS.Nightscout.uploadedPumphistory, as: [NigtscoutTreatment].self) ?? []
  85. let eventsManual = recent().filter { $0.enteredBy == CarbsEntry.manual }
  86. let treatments = eventsManual.map {
  87. NigtscoutTreatment(
  88. duration: nil,
  89. rawDuration: nil,
  90. rawRate: nil,
  91. absolute: nil,
  92. rate: nil,
  93. eventType: .nsCarbCorrection,
  94. createdAt: $0.createdAt,
  95. enteredBy: CarbsEntry.manual,
  96. bolus: nil,
  97. insulin: nil,
  98. notes: nil,
  99. carbs: $0.carbs,
  100. targetTop: nil,
  101. targetBottom: nil
  102. )
  103. }
  104. return Array(Set(treatments).subtracting(Set(uploaded)))
  105. }
  106. }