CommandResponseViewController.swift 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. //
  2. // CommandResponseViewController.swift
  3. // OmniKitUI
  4. //
  5. // Created by Pete Schwamb on 8/28/18.
  6. // Copyright © 2018 Pete Schwamb. All rights reserved.
  7. //
  8. import Foundation
  9. import LoopKitUI
  10. import OmniKit
  11. import RileyLinkBLEKit
  12. extension CommandResponseViewController {
  13. typealias T = CommandResponseViewController
  14. // Returns an appropriately formatted error string or "Succeeded" if no error
  15. private static func resultString(error: Error?) -> String {
  16. guard let error = error else {
  17. return LocalizedString("Succeeded", comment: "A message indicating a command succeeded")
  18. }
  19. let errorStrings: [String]
  20. if let error = error as? LocalizedError {
  21. errorStrings = [error.errorDescription, error.failureReason, error.recoverySuggestion].compactMap { $0 }
  22. } else {
  23. errorStrings = [error.localizedDescription].compactMap { $0 }
  24. }
  25. let errorText = errorStrings.joined(separator: ". ")
  26. if errorText.isEmpty {
  27. return String(describing: error)
  28. }
  29. return errorText + "."
  30. }
  31. static func changeTime(pumpManager: OmnipodPumpManager) -> T {
  32. return T { (completionHandler) -> String in
  33. pumpManager.setTime() { (error) in
  34. DispatchQueue.main.async {
  35. completionHandler(resultString(error: error))
  36. }
  37. }
  38. return LocalizedString("Changing time…", comment: "Progress message for changing pod time.")
  39. }
  40. }
  41. private static func podStatusString(status: DetailedStatus, configuredAlerts: [AlertSlot: PodAlert]) -> String {
  42. var result, str: String
  43. let formatter = DateComponentsFormatter()
  44. formatter.allowedUnits = [.hour, .minute]
  45. formatter.unitsStyle = .short
  46. if let timeStr = formatter.string(from: status.timeActive) {
  47. str = timeStr
  48. } else {
  49. str = String(format: LocalizedString("%1$@ minutes", comment: "The format string for minutes (1: number of minutes string)"), String(describing: Int(status.timeActive / 60)))
  50. }
  51. result = String(format: LocalizedString("Pod Active Time: %1$@\n", comment: "The format string for Pod Active Time: (1: formatted time)"), str)
  52. result += String(format: LocalizedString("Delivery Status: %1$@\n", comment: "The format string for Delivery Status: (1: delivery status string)"), String(describing: status.deliveryStatus))
  53. result += String(format: LocalizedString("Pulse Count: %1$d\n", comment: "The format string for Pulse Count (1: pulse count)"), Int(round(status.totalInsulinDelivered / Pod.pulseSize)))
  54. result += String(format: LocalizedString("Reservoir Level: %1$@ U\n", comment: "The format string for Reservoir Level: (1: reservoir level string)"), status.reservoirLevel?.twoDecimals ?? "50+")
  55. result += String(format: LocalizedString("Last Bolus Not Delivered: %1$@ U\n", comment: "The format string for Last Bolus Not Delivered: (1: bolus not delivered string)"), status.bolusNotDelivered.twoDecimals)
  56. let alertsDescription = status.unacknowledgedAlerts.map { (slot) -> String in
  57. if let podAlert = configuredAlerts[slot] {
  58. return String(describing: podAlert)
  59. } else {
  60. return String(describing: slot)
  61. }
  62. }
  63. let alertString: String
  64. if status.unacknowledgedAlerts.isEmpty {
  65. alertString = String(describing: status.unacknowledgedAlerts)
  66. } else {
  67. alertString = alertsDescription.joined(separator: ", ")
  68. }
  69. result += String(format: LocalizedString("Alerts: %1$@\n", comment: "The format string for Alerts: (1: the alerts string)"), alertString)
  70. result += String(format: LocalizedString("RSSI: %1$@\n", comment: "The format string for RSSI: (1: RSSI value)"), String(describing: status.radioRSSI))
  71. result += String(format: LocalizedString("Receiver Low Gain: %1$@\n", comment: "The format string for receiverLowGain: (1: receiverLowGain)"), String(describing: status.receiverLowGain))
  72. if status.faultEventCode.faultType != .noFaults {
  73. result += "\n" // since we have a fault, report the additional fault related information in a separate section
  74. result += String(format: LocalizedString("Fault: %1$@\n", comment: "The format string for a fault: (1: The fault description)"), status.faultEventCode.localizedDescription)
  75. if let refStr = status.pdmRef {
  76. result += refStr + "\n" // add the PDM style Ref code info as a separate line
  77. }
  78. if let previousPodProgressStatus = status.previousPodProgressStatus {
  79. result += String(format: LocalizedString("Previous pod progress: %1$@\n", comment: "The format string for previous pod progress: (1: previous pod progress string)"), String(describing: previousPodProgressStatus))
  80. }
  81. if let faultEventTimeSinceActivation = status.faultEventTimeSinceActivation, let faultTimeStr = formatter.string(from: faultEventTimeSinceActivation) {
  82. result += String(format: LocalizedString("Fault time: %1$@\n", comment: "The format string for fault time: (1: fault time string)"), faultTimeStr)
  83. }
  84. }
  85. return result
  86. }
  87. static func readPodStatus(pumpManager: OmnipodPumpManager) -> T {
  88. return T { (completionHandler) -> String in
  89. pumpManager.readPodStatus() { (result) in
  90. DispatchQueue.main.async {
  91. switch result {
  92. case .success(let status):
  93. let configuredAlerts = pumpManager.state.podState!.configuredAlerts
  94. completionHandler(podStatusString(status: status, configuredAlerts: configuredAlerts))
  95. case .failure(let error):
  96. completionHandler(resultString(error: error))
  97. }
  98. }
  99. }
  100. return LocalizedString("Read Pod Status…", comment: "Progress message for reading Pod status.")
  101. }
  102. }
  103. static func testingCommands(pumpManager: OmnipodPumpManager) -> T {
  104. return T { (completionHandler) -> String in
  105. pumpManager.testingCommands() { (error) in
  106. DispatchQueue.main.async {
  107. completionHandler(resultString(error: error))
  108. }
  109. }
  110. return LocalizedString("Testing Commands…", comment: "Progress message for testing commands.")
  111. }
  112. }
  113. static func playTestBeeps(pumpManager: OmnipodPumpManager) -> T {
  114. return T { (completionHandler) -> String in
  115. pumpManager.playTestBeeps() { (error) in
  116. let response: String
  117. if let error = error {
  118. response = resultString(error: error)
  119. } else {
  120. response = LocalizedString("Play test beeps command sent successfully.\n\nIf you did not hear any beeps from your pod, the piezo speaker in your pod may be broken or disabled.", comment: "Success message for play test beeps.")
  121. }
  122. DispatchQueue.main.async {
  123. completionHandler(response)
  124. }
  125. }
  126. return LocalizedString("Play Test Beeps…", comment: "Progress message for play test beeps.")
  127. }
  128. }
  129. static func readPulseLog(pumpManager: OmnipodPumpManager) -> T {
  130. return T { (completionHandler) -> String in
  131. pumpManager.readPulseLog() { (result) in
  132. DispatchQueue.main.async {
  133. switch result {
  134. case .success(let pulseLogString):
  135. completionHandler(pulseLogString)
  136. case .failure(let error):
  137. completionHandler(resultString(error: error))
  138. }
  139. }
  140. }
  141. return LocalizedString("Reading Pulse Log…", comment: "Progress message for reading pulse log.")
  142. }
  143. }
  144. }
  145. extension Double {
  146. var twoDecimals: String {
  147. return String(format: "%.2f", self)
  148. }
  149. }