DeviceStatusOpenAPS.swift 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. //
  2. // DeviceStatusOpenAPS.swift
  3. // LoopFollow
  4. //
  5. // Created by Jonas Björkert on 2024-05-19.
  6. // Copyright © 2024 Jon Fawcett. All rights reserved.
  7. //
  8. import Foundation
  9. import UIKit
  10. extension MainViewController {
  11. func DeviceStatusOpenAPS(formatter: ISO8601DateFormatter, lastDeviceStatus: [String: AnyObject]?, lastLoopRecord: [String: AnyObject]) {
  12. if let lastLoopTime = formatter.date(from: (lastDeviceStatus?["created_at"] as! String))?.timeIntervalSince1970 {
  13. UserDefaultsRepository.alertLastLoopTime.value = lastLoopTime
  14. if lastLoopRecord["failureReason"] != nil {
  15. LoopStatusLabel.text = "X"
  16. latestLoopStatusString = "X"
  17. if UserDefaultsRepository.debugLog.value { self.writeDebugLog(value: "Loop Failure: X") }
  18. } else {
  19. var wasEnacted = false
  20. if let enacted = lastLoopRecord["enacted"] as? [String: AnyObject] {
  21. wasEnacted = true
  22. }
  23. if let iobdata = lastLoopRecord["iob"] as? [String: AnyObject],
  24. let iobValue = iobdata["iob"] as? Double {
  25. let formattedIOB = String(format: "%.2f", iobValue)
  26. infoManager.updateInfoData(type: .iob, value: formattedIOB)
  27. latestIOB = formattedIOB
  28. }
  29. if let cobdata = lastLoopRecord["enacted"] as? [String: AnyObject],
  30. let cobValue = cobdata["COB"] as? Double {
  31. let formattedCOB = String(format: "%.0f", cobValue)
  32. infoManager.updateInfoData(type: .cob, value: formattedCOB)
  33. latestCOB = formattedCOB
  34. }
  35. if let recbolusdata = lastLoopRecord["enacted"] as? [String: AnyObject],
  36. let insulinReq = recbolusdata["insulinReq"] as? Double {
  37. let formattedRecBolus = String(format: "%.2fU", insulinReq)
  38. infoManager.updateInfoData(type: .recBolus, value: formattedRecBolus)
  39. UserDefaultsRepository.deviceRecBolus.value = insulinReq
  40. } else {
  41. infoManager.updateInfoData(type: .recBolus, value: "N/A")
  42. UserDefaultsRepository.deviceRecBolus.value = 0
  43. }
  44. if let autosensdata = lastLoopRecord["enacted"] as? [String: AnyObject],
  45. let sens = autosensdata["sensitivityRatio"] as? Double {
  46. let formattedSens = String(format: "%.0f", sens * 100.0) + "%"
  47. infoManager.updateInfoData(type: .autosens, value: formattedSens)
  48. }
  49. if let eventualdata = lastLoopRecord["enacted"] as? [String: AnyObject] {
  50. if let eventualBGValue = eventualdata["eventualBG"] as? NSNumber {
  51. let eventualBGStringValue = String(describing: eventualBGValue)
  52. PredictionLabel.text = bgUnits.toDisplayUnits(eventualBGStringValue)
  53. }
  54. }
  55. var predictioncolor = UIColor.systemGray
  56. PredictionLabel.textColor = predictioncolor
  57. topPredictionBG = UserDefaultsRepository.minBGScale.value
  58. if let enactdata = lastLoopRecord["enacted"] as? [String: AnyObject],
  59. let predbgdata = enactdata["predBGs"] as? [String: AnyObject] {
  60. let predictionTypes: [(type: String, colorName: String, dataIndex: Int)] = [
  61. ("ZT", "ZT", 12),
  62. ("IOB", "Insulin", 13),
  63. ("COB", "LoopYellow", 14),
  64. ("UAM", "UAM", 15)
  65. ]
  66. var minPredBG = Double.infinity
  67. var maxPredBG = -Double.infinity
  68. for (type, colorName, dataIndex) in predictionTypes {
  69. var predictionData = [ShareGlucoseData]()
  70. if let graphdata = predbgdata[type] as? [Double] {
  71. var predictionTime = lastLoopTime
  72. let toLoad = Int(UserDefaultsRepository.predictionToLoad.value * 12)
  73. for i in 0...toLoad {
  74. if i < graphdata.count {
  75. let predictionValue = graphdata[i]
  76. minPredBG = min(minPredBG, predictionValue)
  77. maxPredBG = max(maxPredBG, predictionValue)
  78. let prediction = ShareGlucoseData(sgv: Int(round(predictionValue)), date: predictionTime, direction: "flat")
  79. predictionData.append(prediction)
  80. predictionTime += 300
  81. }
  82. }
  83. }
  84. let color = UIColor(named: colorName) ?? UIColor.systemPurple
  85. updatePredictionGraphGeneric(
  86. dataIndex: dataIndex,
  87. predictionData: predictionData,
  88. chartLabel: type,
  89. color: color
  90. )
  91. }
  92. if minPredBG != Double.infinity && maxPredBG != -Double.infinity {
  93. let value = "\(bgUnits.toDisplayUnits(String(minPredBG)))/\(bgUnits.toDisplayUnits(String(maxPredBG)))"
  94. infoManager.updateInfoData(type: .minMax, value: value)
  95. } else {
  96. infoManager.updateInfoData(type: .minMax, value: "N/A")
  97. }
  98. }
  99. if let loopStatus = lastLoopRecord["recommendedTempBasal"] as? [String: AnyObject] {
  100. if let tempBasalTime = formatter.date(from: (loopStatus["timestamp"] as! String))?.timeIntervalSince1970 {
  101. var lastBGTime = lastLoopTime
  102. if bgData.count > 0 {
  103. lastBGTime = bgData[bgData.count - 1].date
  104. }
  105. if tempBasalTime > lastBGTime && !wasEnacted {
  106. LoopStatusLabel.text = "⏀"
  107. latestLoopStatusString = "⏀"
  108. } else {
  109. LoopStatusLabel.text = "↻"
  110. latestLoopStatusString = "↻"
  111. }
  112. }
  113. } else {
  114. LoopStatusLabel.text = "↻"
  115. latestLoopStatusString = "↻"
  116. }
  117. }
  118. evaluateNotLooping(lastLoopTime: lastLoopTime)
  119. }
  120. }
  121. }