AppGroupSource.swift 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import Combine
  2. import Foundation
  3. struct AppGroupSource: GlucoseSource {
  4. func fetch() -> AnyPublisher<[BloodGlucose], Never> {
  5. guard let suiteName = Bundle.main.appGroupSuiteName,
  6. let sharedDefaults = UserDefaults(suiteName: suiteName)
  7. else {
  8. return Just([]).eraseToAnyPublisher()
  9. }
  10. return Just(fetchLastBGs(60, sharedDefaults)).eraseToAnyPublisher()
  11. }
  12. private func fetchLastBGs(_ count: Int, _ sharedDefaults: UserDefaults) -> [BloodGlucose] {
  13. guard let sharedData = sharedDefaults.data(forKey: "latestReadings") else {
  14. return []
  15. }
  16. let decoded = try? JSONSerialization.jsonObject(with: sharedData, options: [])
  17. guard let sgvs = decoded as? [AnyObject] else {
  18. return []
  19. }
  20. var results: [BloodGlucose] = []
  21. for sgv in sgvs.prefix(count) {
  22. guard
  23. let glucose = sgv["Value"] as? Int,
  24. let direction = sgv["direction"] as? String,
  25. let timestamp = sgv["DT"] as? String,
  26. let date = parseDate(timestamp)
  27. else { continue }
  28. results.append(
  29. BloodGlucose(
  30. sgv: glucose,
  31. direction: BloodGlucose.Direction(rawValue: direction),
  32. date: Decimal(Int(date.timeIntervalSince1970 * 1000)),
  33. dateString: date,
  34. filtered: nil,
  35. noise: nil,
  36. glucose: glucose,
  37. type: "sgv"
  38. )
  39. )
  40. }
  41. return results
  42. }
  43. private func parseDate(_ timestamp: String) -> Date? {
  44. // timestamp looks like "/Date(1462404576000)/"
  45. guard let re = try? NSRegularExpression(pattern: "\\((.*)\\)"),
  46. let match = re.firstMatch(in: timestamp, range: NSMakeRange(0, timestamp.count))
  47. else {
  48. return nil
  49. }
  50. let matchRange = match.range(at: 1)
  51. let epoch = Double((timestamp as NSString).substring(with: matchRange))! / 1000
  52. return Date(timeIntervalSince1970: epoch)
  53. }
  54. }
  55. public extension Bundle {
  56. var appGroupSuiteName: String? {
  57. object(forInfoDictionaryKey: "AppGroupID") as? String
  58. }
  59. }