CommandResponseViewController.swift 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. //
  2. // CommandResponseViewController.swift
  3. // MinimedKitUI
  4. //
  5. // Copyright © 2018 Pete Schwamb. All rights reserved.
  6. //
  7. import UIKit
  8. import LoopKit
  9. import LoopKitUI
  10. import MinimedKit
  11. import RileyLinkKit
  12. import RileyLinkBLEKit
  13. extension CommandResponseViewController {
  14. typealias T = CommandResponseViewController
  15. private static let successText = LocalizedString("Succeeded", comment: "A message indicating a command succeeded")
  16. static func changeTime(ops: PumpOps?, device: RileyLinkDevice) -> T {
  17. return T { (completionHandler) -> String in
  18. ops?.runSession(withName: "Set time", using: device) { (session) in
  19. let response: String
  20. do {
  21. try session.setTimeToNow(in: .current)
  22. response = self.successText
  23. } catch let error {
  24. response = String(describing: error)
  25. }
  26. DispatchQueue.main.async {
  27. completionHandler(response)
  28. }
  29. }
  30. return LocalizedString("Changing time…", comment: "Progress message for changing pump time.")
  31. }
  32. }
  33. static func changeTime(ops: PumpOps?, rileyLinkDeviceProvider: RileyLinkDeviceProvider) -> T {
  34. return T { (completionHandler) -> String in
  35. ops?.runSession(withName: "Set time", usingSelector: rileyLinkDeviceProvider.firstConnectedDevice) { (session) in
  36. let response: String
  37. do {
  38. guard let session = session else {
  39. throw PumpManagerError.connection(MinimedPumpManagerError.noRileyLink)
  40. }
  41. try session.setTimeToNow(in: .current)
  42. response = self.successText
  43. } catch let error {
  44. response = String(describing: error)
  45. }
  46. DispatchQueue.main.async {
  47. completionHandler(response)
  48. }
  49. }
  50. return LocalizedString("Changing time…", comment: "Progress message for changing pump time.")
  51. }
  52. }
  53. static func dumpHistory(ops: PumpOps?, device: RileyLinkDevice) -> T {
  54. return T { (completionHandler) -> String in
  55. let calendar = Calendar(identifier: Calendar.Identifier.gregorian)
  56. let oneDayAgo = calendar.date(byAdding: DateComponents(day: -1), to: Date())
  57. ops?.runSession(withName: "Get history events", using: device) { (session) in
  58. let response: String
  59. do {
  60. let (events, _) = try session.getHistoryEvents(since: oneDayAgo!)
  61. var responseText = String(format: "Found %d events since %@", events.count, oneDayAgo! as NSDate)
  62. for event in events {
  63. responseText += String(format:"\nEvent: %@", event.dictionaryRepresentation)
  64. }
  65. response = responseText
  66. } catch let error {
  67. response = String(describing: error)
  68. }
  69. DispatchQueue.main.async {
  70. completionHandler(response)
  71. }
  72. }
  73. return LocalizedString("Fetching history…", comment: "Progress message for fetching pump history.")
  74. }
  75. }
  76. static func fetchGlucose(ops: PumpOps?, device: RileyLinkDevice) -> T {
  77. return T { (completionHandler) -> String in
  78. let calendar = Calendar(identifier: Calendar.Identifier.gregorian)
  79. let oneDayAgo = calendar.date(byAdding: DateComponents(day: -1), to: Date())
  80. ops?.runSession(withName: "Get glucose history", using: device) { (session) in
  81. let response: String
  82. do {
  83. let events = try session.getGlucoseHistoryEvents(since: oneDayAgo!)
  84. var responseText = String(format: "Found %d events since %@", events.count, oneDayAgo! as NSDate)
  85. for event in events {
  86. responseText += String(format: "\nEvent: %@", event.dictionaryRepresentation)
  87. }
  88. response = responseText
  89. } catch let error {
  90. response = String(describing: error)
  91. }
  92. DispatchQueue.main.async {
  93. completionHandler(response)
  94. }
  95. }
  96. return LocalizedString("Fetching glucose…", comment: "Progress message for fetching pump glucose.")
  97. }
  98. }
  99. static func getPumpModel(ops: PumpOps?, device: RileyLinkDevice) -> T {
  100. return T { (completionHandler) -> String in
  101. ops?.runSession(withName: "Get Pump Model", using: device) { (session) in
  102. let response: String
  103. do {
  104. let model = try session.getPumpModel(usingCache: false)
  105. response = "Pump Model: \(model)"
  106. } catch let error {
  107. response = String(describing: error)
  108. }
  109. DispatchQueue.main.async {
  110. completionHandler(response)
  111. }
  112. }
  113. return LocalizedString("Fetching pump model…", comment: "Progress message for fetching pump model.")
  114. }
  115. }
  116. static func mySentryPair(ops: PumpOps?, device: RileyLinkDevice) -> T {
  117. return T { (completionHandler) -> String in
  118. var byteArray = [UInt8](repeating: 0, count: 16)
  119. (device.peripheralIdentifier as NSUUID).getBytes(&byteArray)
  120. let watchdogID = Data(byteArray[0..<3])
  121. ops?.runSession(withName: "Change watchdog marriage profile", using: device) { (session) in
  122. let response: String
  123. do {
  124. try session.changeWatchdogMarriageProfile(watchdogID)
  125. response = self.successText
  126. } catch let error {
  127. response = String(describing: error)
  128. }
  129. DispatchQueue.main.async {
  130. completionHandler(response)
  131. }
  132. }
  133. return LocalizedString(
  134. "On your pump, go to the Find Device screen and select \"Find Device\"." +
  135. "\n" +
  136. "\nMain Menu >" +
  137. "\nUtilities >" +
  138. "\nConnect Devices >" +
  139. "\nOther Devices >" +
  140. "\nOn >" +
  141. "\nFind Device",
  142. comment: "Pump find device instruction"
  143. )
  144. }
  145. }
  146. static func pressDownButton(ops: PumpOps?, device: RileyLinkDevice) -> T {
  147. return T { (completionHandler) -> String in
  148. ops?.runSession(withName: "Press down button", using: device) { (session) in
  149. let response: String
  150. do {
  151. try session.pressButton(.down)
  152. response = self.successText
  153. } catch let error {
  154. response = String(describing: error)
  155. }
  156. DispatchQueue.main.async {
  157. completionHandler(response)
  158. }
  159. }
  160. return LocalizedString("Sending button press…", comment: "Progress message for sending button press to pump.")
  161. }
  162. }
  163. static func readBasalSchedule(ops: PumpOps?, device: RileyLinkDevice, integerFormatter: NumberFormatter) -> T {
  164. return T { (completionHandler) -> String in
  165. ops?.runSession(withName: "Get Basal Settings", using: device) { (session) in
  166. let response: String
  167. do {
  168. let schedule = try session.getBasalSchedule(for: .profileB)
  169. var str = String(format: LocalizedString("%1$@ basal schedule entries\n", comment: "The format string describing number of basal schedule entries: (1: number of entries)"), integerFormatter.string(from: NSNumber(value: schedule?.entries.count ?? 0))!)
  170. for entry in schedule?.entries ?? [] {
  171. str += "\(String(describing: entry))\n"
  172. }
  173. response = str
  174. } catch let error {
  175. response = String(describing: error)
  176. }
  177. DispatchQueue.main.async {
  178. completionHandler(response)
  179. }
  180. }
  181. return LocalizedString("Reading basal schedule…", comment: "Progress message for reading basal schedule")
  182. }
  183. }
  184. static func readPumpStatus(ops: PumpOps?, device: RileyLinkDevice, measurementFormatter: MeasurementFormatter) -> T {
  185. return T { (completionHandler) -> String in
  186. ops?.runSession(withName: "Read pump status", using: device) { (session) in
  187. let response: String
  188. do {
  189. let status = try session.getCurrentPumpStatus()
  190. var str = String(format: LocalizedString("%1$@ Units of insulin remaining\n", comment: "The format string describing units of insulin remaining: (1: number of units)"), measurementFormatter.numberFormatter.string(from: NSNumber(value: status.reservoir))!)
  191. str += String(format: LocalizedString("Battery: %1$@ volts\n", comment: "The format string describing pump battery voltage: (1: battery voltage)"), measurementFormatter.string(from: status.batteryVolts))
  192. str += String(format: LocalizedString("Suspended: %1$@\n", comment: "The format string describing pump suspended state: (1: suspended)"), String(describing: status.suspended))
  193. str += String(format: LocalizedString("Bolusing: %1$@\n", comment: "The format string describing pump bolusing state: (1: bolusing)"), String(describing: status.bolusing))
  194. response = str
  195. } catch let error {
  196. response = String(describing: error)
  197. }
  198. DispatchQueue.main.async {
  199. completionHandler(response)
  200. }
  201. }
  202. return LocalizedString("Reading pump status…", comment: "Progress message for reading pump status")
  203. }
  204. }
  205. static func tuneRadio(ops: PumpOps?, device: RileyLinkDevice, measurementFormatter: MeasurementFormatter) -> T {
  206. return T { (completionHandler) -> String in
  207. ops?.runSession(withName: "Tune pump", using: device) { (session) in
  208. let response: String
  209. do {
  210. let scanResult = try session.tuneRadio()
  211. var resultDict: [String: Any] = [:]
  212. let intFormatter = NumberFormatter()
  213. let formatString = LocalizedString("%1$@ %2$@/%3$@ %4$@", comment: "The format string for displaying a frequency tune trial. Extra spaces added for emphesis: (1: frequency in MHz)(2: success count)(3: total count)(4: average RSSI)")
  214. resultDict[LocalizedString("Best Frequency", comment: "The label indicating the best radio frequency")] = measurementFormatter.string(from: scanResult.bestFrequency)
  215. resultDict[LocalizedString("Trials", comment: "The label indicating the results of each frequency trial")] = scanResult.trials.map({ (trial) -> String in
  216. return String(
  217. format: formatString,
  218. measurementFormatter.string(from: trial.frequency),
  219. intFormatter.string(from: NSNumber(value: trial.successes))!,
  220. intFormatter.string(from: NSNumber(value: trial.tries))!,
  221. intFormatter.string(from: NSNumber(value: trial.avgRSSI))!
  222. )
  223. })
  224. var responseText: String
  225. if let data = try? JSONSerialization.data(withJSONObject: resultDict, options: .prettyPrinted), let string = String(data: data, encoding: .utf8) {
  226. responseText = string
  227. } else {
  228. responseText = LocalizedString("No response", comment: "Message display when no response from tuning pump")
  229. }
  230. response = responseText
  231. } catch let error {
  232. response = String(describing: error)
  233. }
  234. DispatchQueue.main.async {
  235. completionHandler(response)
  236. }
  237. }
  238. return LocalizedString("Tuning radio…", comment: "Progress message for tuning radio")
  239. }
  240. }
  241. }