GlucoseStorage.swift 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import Foundation
  2. import SwiftDate
  3. import Swinject
  4. protocol GlucoseStorage {
  5. func storeGlucose(_ glucose: [BloodGlucose])
  6. func recent() -> [BloodGlucose]
  7. func syncDate() -> Date
  8. func filterTooFrequentGlucose(_ glucose: [BloodGlucose]) -> [BloodGlucose]
  9. }
  10. final class BaseGlucoseStorage: GlucoseStorage, Injectable {
  11. private let processQueue = DispatchQueue(label: "BaseGlucoseStorage.processQueue")
  12. @Injected() private var storage: FileStorage!
  13. @Injected() private var broadcaster: Broadcaster!
  14. private enum Config {
  15. static let filterTime: TimeInterval = 4.75 * 60
  16. }
  17. init(resolver: Resolver) {
  18. injectServices(resolver)
  19. }
  20. func storeGlucose(_ glucose: [BloodGlucose]) {
  21. processQueue.sync {
  22. let filtered = self.filterTooFrequentGlucose(glucose)
  23. let file = OpenAPS.Monitor.glucose
  24. self.storage.transaction { storage in
  25. storage.append(filtered, to: file, uniqBy: \.dateString)
  26. let uniqEvents = storage.retrieve(file, as: [BloodGlucose].self)?
  27. .filter { $0.dateString.addingTimeInterval(1.days.timeInterval) > Date() }
  28. .sorted { $0.dateString > $1.dateString } ?? []
  29. let glucose = Array(uniqEvents)
  30. storage.save(glucose, as: file)
  31. DispatchQueue.main.async {
  32. self.broadcaster.notify(GlucoseObserver.self, on: .main) {
  33. $0.glucoseDidUpdate(glucose.reversed())
  34. }
  35. }
  36. }
  37. }
  38. }
  39. func syncDate() -> Date {
  40. guard let events = storage.retrieve(OpenAPS.Monitor.glucose, as: [BloodGlucose].self),
  41. let recent = events.first
  42. else {
  43. return Date().addingTimeInterval(-1.days.timeInterval)
  44. }
  45. return recent.dateString.addingTimeInterval(Config.filterTime)
  46. }
  47. func recent() -> [BloodGlucose] {
  48. storage.retrieve(OpenAPS.Monitor.glucose, as: [BloodGlucose].self)?.reversed() ?? []
  49. }
  50. func filterTooFrequentGlucose(_ glucose: [BloodGlucose]) -> [BloodGlucose] {
  51. var lastDate = recent().first?.dateString ?? .distantPast
  52. var filtered: [BloodGlucose] = []
  53. for entry in glucose.reversed() {
  54. guard entry.dateString.addingTimeInterval(-Config.filterTime) > lastDate else {
  55. continue
  56. }
  57. filtered.append(entry)
  58. lastDate = entry.dateString
  59. }
  60. return filtered
  61. }
  62. }
  63. protocol GlucoseObserver {
  64. func glucoseDidUpdate(_ glucose: [BloodGlucose])
  65. }