TempTargetsStorage.swift 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import Foundation
  2. import SwiftDate
  3. import Swinject
  4. protocol TempTargetsObserver {
  5. func tempTargetsDidUpdate(_ targets: [TempTarget])
  6. }
  7. protocol TempTargetsStorage {
  8. func storeTempTargets(_ targets: [TempTarget])
  9. func syncDate() -> Date
  10. func recent() -> [TempTarget]
  11. func nightscoutTreatmentsNotUploaded() -> [NightscoutTreatment]
  12. func storePresets(_ targets: [TempTarget])
  13. func presets() -> [TempTarget]
  14. func current() -> TempTarget?
  15. }
  16. final class BaseTempTargetsStorage: TempTargetsStorage, Injectable {
  17. private let processQueue = DispatchQueue(label: "BaseTempTargetsStorage.processQueue")
  18. @Injected() private var storage: FileStorage!
  19. @Injected() private var broadcaster: Broadcaster!
  20. init(resolver: Resolver) {
  21. injectServices(resolver)
  22. }
  23. func storeTempTargets(_ targets: [TempTarget]) {
  24. storeTempTargets(targets, isPresets: false)
  25. }
  26. private func storeTempTargets(_ targets: [TempTarget], isPresets: Bool) {
  27. processQueue.sync {
  28. var targets = targets
  29. if !isPresets {
  30. if current() != nil, let newActive = targets.last(where: {
  31. $0.createdAt.addingTimeInterval(Int($0.duration).minutes.timeInterval) > Date()
  32. && $0.createdAt <= Date()
  33. }) {
  34. // cancel current
  35. targets += [TempTarget.cancel(at: newActive.createdAt.addingTimeInterval(-1))]
  36. }
  37. }
  38. let file = isPresets ? OpenAPS.FreeAPS.tempTargetsPresets : OpenAPS.Settings.tempTargets
  39. var uniqEvents: [TempTarget] = []
  40. self.storage.transaction { storage in
  41. storage.append(targets, to: file, uniqBy: \.createdAt)
  42. uniqEvents = storage.retrieve(file, as: [TempTarget].self)?
  43. .filter {
  44. guard !isPresets else { return true }
  45. return $0.createdAt.addingTimeInterval(1.days.timeInterval) > Date()
  46. }
  47. .sorted { $0.createdAt > $1.createdAt } ?? []
  48. storage.save(Array(uniqEvents), as: file)
  49. }
  50. broadcaster.notify(TempTargetsObserver.self, on: processQueue) {
  51. $0.tempTargetsDidUpdate(uniqEvents)
  52. }
  53. }
  54. }
  55. func syncDate() -> Date {
  56. Date().addingTimeInterval(-1.days.timeInterval)
  57. }
  58. func recent() -> [TempTarget] {
  59. storage.retrieve(OpenAPS.Settings.tempTargets, as: [TempTarget].self)?.reversed() ?? []
  60. }
  61. func current() -> TempTarget? {
  62. guard let last = recent().last else {
  63. return nil
  64. }
  65. guard last.createdAt.addingTimeInterval(Int(last.duration).minutes.timeInterval) > Date(), last.createdAt <= Date(),
  66. last.duration != 0
  67. else {
  68. return nil
  69. }
  70. return last
  71. }
  72. func nightscoutTreatmentsNotUploaded() -> [NightscoutTreatment] {
  73. let uploaded = storage.retrieve(OpenAPS.Nightscout.uploadedTempTargets, as: [NightscoutTreatment].self) ?? []
  74. let eventsManual = recent().filter { $0.enteredBy == TempTarget.manual }
  75. let treatments = eventsManual.map {
  76. NightscoutTreatment(
  77. duration: Int($0.duration),
  78. rawDuration: nil,
  79. rawRate: nil,
  80. absolute: nil,
  81. rate: nil,
  82. eventType: .nsTempTarget,
  83. createdAt: $0.createdAt,
  84. enteredBy: TempTarget.manual,
  85. bolus: nil,
  86. insulin: nil,
  87. notes: nil,
  88. carbs: nil,
  89. targetTop: $0.targetTop,
  90. targetBottom: $0.targetBottom
  91. )
  92. }
  93. return Array(Set(treatments).subtracting(Set(uploaded)))
  94. }
  95. func storePresets(_ targets: [TempTarget]) {
  96. storage.remove(OpenAPS.FreeAPS.tempTargetsPresets)
  97. storeTempTargets(targets, isPresets: true)
  98. }
  99. func presets() -> [TempTarget] {
  100. storage.retrieve(OpenAPS.FreeAPS.tempTargetsPresets, as: [TempTarget].self)?.reversed() ?? []
  101. }
  102. }