PumpHistoryStorage.swift 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. import Foundation
  2. import LoopKit
  3. import SwiftDate
  4. import Swinject
  5. protocol PumpHistoryStorage {
  6. func storePumpEvents(_ events: [NewPumpEvent])
  7. func storeJournalCarbs(_ carbs: Int)
  8. }
  9. final class BasePumpHistoryStorage: PumpHistoryStorage, Injectable {
  10. private let processQueue = DispatchQueue(label: "BasePumpHistoryStorage.processQueue")
  11. @Injected() private var storage: FileStorage!
  12. init(resolver: Resolver) {
  13. injectServices(resolver)
  14. }
  15. func storePumpEvents(_ events: [NewPumpEvent]) {
  16. processQueue.async {
  17. let eventsToStore = events.flatMap { event -> [PumpHistoryEvent] in
  18. let id = event.raw.md5String
  19. switch event.type {
  20. case .bolus:
  21. print("[PUMP EVENT] Bolus event:\n\(event.title))")
  22. guard let dose = event.dose else { return [] }
  23. let amount = Decimal(string: dose.unitsInDeliverableIncrements.description)
  24. let minutes = Int((dose.endDate - dose.startDate).timeInterval / 60)
  25. return [PumpHistoryEvent(
  26. id: id,
  27. type: .bolus,
  28. timestamp: event.date,
  29. amount: amount,
  30. duration: minutes,
  31. durationMin: nil,
  32. rate: nil,
  33. temp: nil,
  34. carbInput: nil
  35. )]
  36. case .tempBasal:
  37. print("[PUMP EVENT] Temp basal event:\n\(event.title))")
  38. guard let dose = event.dose else { return [] }
  39. let rate = Decimal(string: dose.unitsPerHour.description)
  40. let minutes = Int((dose.endDate - dose.startDate).timeInterval / 60)
  41. return [
  42. PumpHistoryEvent(
  43. id: id,
  44. type: .tempBasalDuration,
  45. timestamp: event.date,
  46. amount: nil,
  47. duration: nil,
  48. durationMin: minutes,
  49. rate: rate,
  50. temp: nil,
  51. carbInput: nil
  52. ),
  53. PumpHistoryEvent(
  54. id: "_" + id,
  55. type: .tempBasal,
  56. timestamp: event.date,
  57. amount: nil,
  58. duration: nil,
  59. durationMin: nil,
  60. rate: rate,
  61. temp: .absolute,
  62. carbInput: nil
  63. )
  64. ]
  65. case .suspend:
  66. print("[PUMP EVENT] Suspend event:\n\(event.title))")
  67. return [
  68. PumpHistoryEvent(
  69. id: id,
  70. type: .pumpSuspend,
  71. timestamp: event.date,
  72. amount: nil,
  73. duration: nil,
  74. durationMin: nil,
  75. rate: nil,
  76. temp: nil,
  77. carbInput: nil
  78. )
  79. ]
  80. case .resume:
  81. print("[PUMP EVENT] Resume event:\n\(event.title))")
  82. return [
  83. PumpHistoryEvent(
  84. id: id,
  85. type: .pumpResume,
  86. timestamp: event.date,
  87. amount: nil,
  88. duration: nil,
  89. durationMin: nil,
  90. rate: nil,
  91. temp: nil,
  92. carbInput: nil
  93. )
  94. ]
  95. case .rewind:
  96. print("[PUMP EVENT] Rewind event:\n\(event.title))")
  97. return [
  98. PumpHistoryEvent(
  99. id: id,
  100. type: .rewind,
  101. timestamp: event.date,
  102. amount: nil,
  103. duration: nil,
  104. durationMin: nil,
  105. rate: nil,
  106. temp: nil,
  107. carbInput: nil
  108. )
  109. ]
  110. case .prime:
  111. print("[PUMP EVENT] Prime event:\n\(event.title))")
  112. return [
  113. PumpHistoryEvent(
  114. id: id,
  115. type: .prime,
  116. timestamp: event.date,
  117. amount: nil,
  118. duration: nil,
  119. durationMin: nil,
  120. rate: nil,
  121. temp: nil,
  122. carbInput: nil
  123. )
  124. ]
  125. default:
  126. return []
  127. }
  128. }
  129. self.processNewEvents(eventsToStore)
  130. }
  131. }
  132. func storeJournalCarbs(_ carbs: Int) {
  133. processQueue.async {
  134. let eventsToStore = [
  135. PumpHistoryEvent(
  136. id: UUID().uuidString,
  137. type: .journalCarbs,
  138. timestamp: Date(),
  139. amount: nil,
  140. duration: nil,
  141. durationMin: nil,
  142. rate: nil,
  143. temp: nil,
  144. carbInput: carbs
  145. )
  146. ]
  147. self.processNewEvents(eventsToStore)
  148. }
  149. }
  150. private func processNewEvents(_ events: [PumpHistoryEvent]) {
  151. dispatchPrecondition(condition: .onQueue(processQueue))
  152. try? storage.transaction { storage in
  153. try storage.append(events, to: OpenAPS.Monitor.pumpHistory, uniqBy: \.id)
  154. let uniqEvents = try storage.retrieve(OpenAPS.Monitor.pumpHistory, as: [PumpHistoryEvent].self)
  155. .filter { $0.timestamp.addingTimeInterval(1.days.timeInterval) > Date() }
  156. .sorted { $0.timestamp > $1.timestamp }
  157. print("[HISTORY] New Events\n\(uniqEvents)")
  158. try storage.save(Array(uniqEvents), as: OpenAPS.Monitor.pumpHistory)
  159. }
  160. }
  161. }