CommandResponseViewController.swift 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  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", using: 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 discoverCommands(ops: PumpOps?, device: RileyLinkDevice) -> T {
  54. return T { (completionHandler) -> String in
  55. ops?.runSession(withName: "Discover Commands", using: device) { (session) in
  56. session.discoverCommands(in: 0xf0...0xff, { (results) in
  57. DispatchQueue.main.async {
  58. completionHandler(results.joined(separator: "\n"))
  59. }
  60. })
  61. }
  62. return LocalizedString("Discovering commands…", comment: "Progress message for discovering commands.")
  63. }
  64. }
  65. static func getStatistics(ops: PumpOps?, device: RileyLinkDevice) -> T {
  66. return T { (completionHandler) -> String in
  67. ops?.runSession(withName: "Get Statistics", using: device) { (session) in
  68. let response: String
  69. do {
  70. let stats = try session.getStatistics()
  71. response = String(describing: stats)
  72. } catch let error {
  73. response = String(describing: error)
  74. }
  75. DispatchQueue.main.async {
  76. completionHandler(response)
  77. }
  78. }
  79. return LocalizedString("Get Statistics…", comment: "Progress message for getting statistics.")
  80. }
  81. }
  82. static func dumpHistory(ops: PumpOps?, device: RileyLinkDevice) -> T {
  83. return T { (completionHandler) -> String in
  84. let calendar = Calendar(identifier: Calendar.Identifier.gregorian)
  85. let oneDayAgo = calendar.date(byAdding: DateComponents(day: -1), to: Date())
  86. ops?.runSession(withName: "Get history events", using: device) { (session) in
  87. let response: String
  88. do {
  89. let (events, _) = try session.getHistoryEvents(since: oneDayAgo!)
  90. var responseText = String(format: "Found %d events since %@", events.count, oneDayAgo! as NSDate)
  91. for event in events {
  92. responseText += String(format:"\nEvent: %@", event.dictionaryRepresentation)
  93. }
  94. response = responseText
  95. } catch let error {
  96. response = String(describing: error)
  97. }
  98. DispatchQueue.main.async {
  99. completionHandler(response)
  100. }
  101. }
  102. return LocalizedString("Fetching history…", comment: "Progress message for fetching pump history.")
  103. }
  104. }
  105. static func fetchGlucose(ops: PumpOps?, device: RileyLinkDevice) -> T {
  106. return T { (completionHandler) -> String in
  107. let calendar = Calendar(identifier: Calendar.Identifier.gregorian)
  108. let oneDayAgo = calendar.date(byAdding: DateComponents(day: -1), to: Date())
  109. ops?.runSession(withName: "Get glucose history", using: device) { (session) in
  110. let response: String
  111. do {
  112. let events = try session.getGlucoseHistoryEvents(since: oneDayAgo!)
  113. var responseText = String(format: "Found %d events since %@", events.count, oneDayAgo! as NSDate)
  114. for event in events {
  115. responseText += String(format: "\nEvent: %@", event.dictionaryRepresentation)
  116. }
  117. response = responseText
  118. } catch let error {
  119. response = String(describing: error)
  120. }
  121. DispatchQueue.main.async {
  122. completionHandler(response)
  123. }
  124. }
  125. return LocalizedString("Fetching glucose…", comment: "Progress message for fetching pump glucose.")
  126. }
  127. }
  128. static func getPumpModel(ops: PumpOps?, device: RileyLinkDevice) -> T {
  129. return T { (completionHandler) -> String in
  130. ops?.runSession(withName: "Get Pump Model", using: device) { (session) in
  131. let response: String
  132. do {
  133. let model = try session.getPumpModel(usingCache: false)
  134. response = "Pump Model: \(model)"
  135. } catch let error {
  136. response = String(describing: error)
  137. }
  138. DispatchQueue.main.async {
  139. completionHandler(response)
  140. }
  141. }
  142. return LocalizedString("Fetching pump model…", comment: "Progress message for fetching pump model.")
  143. }
  144. }
  145. static func mySentryPair(ops: PumpOps?, device: RileyLinkDevice) -> T {
  146. return T { (completionHandler) -> String in
  147. var byteArray = [UInt8](repeating: 0, count: 16)
  148. (device.peripheralIdentifier as NSUUID).getBytes(&byteArray)
  149. let watchdogID = Data(byteArray[0..<3])
  150. ops?.runSession(withName: "Change watchdog marriage profile", using: device) { (session) in
  151. let response: String
  152. do {
  153. try session.changeWatchdogMarriageProfile(watchdogID)
  154. response = self.successText
  155. } catch let error {
  156. response = String(describing: error)
  157. }
  158. DispatchQueue.main.async {
  159. completionHandler(response)
  160. }
  161. }
  162. return LocalizedString(
  163. "On your pump, go to the Find Device screen and select \"Find Device\"." +
  164. "\n" +
  165. "\nMain Menu >" +
  166. "\nUtilities >" +
  167. "\nConnect Devices >" +
  168. "\nOther Devices >" +
  169. "\nOn >" +
  170. "\nFind Device",
  171. comment: "Pump find device instruction"
  172. )
  173. }
  174. }
  175. static func pressDownButton(ops: PumpOps?, device: RileyLinkDevice) -> T {
  176. return T { (completionHandler) -> String in
  177. ops?.runSession(withName: "Press down button", using: device) { (session) in
  178. let response: String
  179. do {
  180. try session.pressButton(.down)
  181. response = self.successText
  182. } catch let error {
  183. response = String(describing: error)
  184. }
  185. DispatchQueue.main.async {
  186. completionHandler(response)
  187. }
  188. }
  189. return LocalizedString("Sending button press…", comment: "Progress message for sending button press to pump.")
  190. }
  191. }
  192. static func readBasalSchedule(ops: PumpOps?, device: RileyLinkDevice, integerFormatter: NumberFormatter) -> T {
  193. return T { (completionHandler) -> String in
  194. ops?.runSession(withName: "Get Basal Settings", using: device) { (session) in
  195. let response: String
  196. do {
  197. let schedule = try session.getBasalSchedule(for: .profileB)
  198. 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))!)
  199. for entry in schedule?.entries ?? [] {
  200. str += "\(String(describing: entry))\n"
  201. }
  202. response = str
  203. } catch let error {
  204. response = String(describing: error)
  205. }
  206. DispatchQueue.main.async {
  207. completionHandler(response)
  208. }
  209. }
  210. return LocalizedString("Reading basal schedule…", comment: "Progress message for reading basal schedule")
  211. }
  212. }
  213. static func readPumpStatus(ops: PumpOps?, device: RileyLinkDevice, measurementFormatter: MeasurementFormatter) -> T {
  214. return T { (completionHandler) -> String in
  215. ops?.runSession(withName: "Read pump status", using: device) { (session) in
  216. let response: String
  217. do {
  218. let status = try session.getCurrentPumpStatus()
  219. 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))!)
  220. str += String(format: LocalizedString("Battery: %1$@ volts\n", comment: "The format string describing pump battery voltage: (1: battery voltage)"), measurementFormatter.string(from: status.batteryVolts))
  221. str += String(format: LocalizedString("Suspended: %1$@\n", comment: "The format string describing pump suspended state: (1: suspended)"), String(describing: status.suspended))
  222. str += String(format: LocalizedString("Bolusing: %1$@\n", comment: "The format string describing pump bolusing state: (1: bolusing)"), String(describing: status.bolusing))
  223. response = str
  224. } catch let error {
  225. response = String(describing: error)
  226. }
  227. DispatchQueue.main.async {
  228. completionHandler(response)
  229. }
  230. }
  231. return LocalizedString("Reading pump status…", comment: "Progress message for reading pump status")
  232. }
  233. }
  234. static func tuneRadio(ops: PumpOps?, device: RileyLinkDevice, measurementFormatter: MeasurementFormatter) -> T {
  235. return T { (completionHandler) -> String in
  236. ops?.runSession(withName: "Tune pump", using: device) { (session) in
  237. let response: String
  238. do {
  239. let scanResult = try session.tuneRadio()
  240. var resultDict: [String: Any] = [:]
  241. let intFormatter = NumberFormatter()
  242. 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)")
  243. resultDict[LocalizedString("Best Frequency", comment: "The label indicating the best radio frequency")] = measurementFormatter.string(from: scanResult.bestFrequency)
  244. resultDict[LocalizedString("Trials", comment: "The label indicating the results of each frequency trial")] = scanResult.trials.map({ (trial) -> String in
  245. return String(
  246. format: formatString,
  247. measurementFormatter.string(from: trial.frequency),
  248. intFormatter.string(from: NSNumber(value: trial.successes))!,
  249. intFormatter.string(from: NSNumber(value: trial.tries))!,
  250. intFormatter.string(from: NSNumber(value: trial.avgRSSI))!
  251. )
  252. })
  253. var responseText: String
  254. if let data = try? JSONSerialization.data(withJSONObject: resultDict, options: .prettyPrinted), let string = String(data: data, encoding: .utf8) {
  255. responseText = string
  256. } else {
  257. responseText = LocalizedString("No response", comment: "Message display when no response from tuning pump")
  258. }
  259. response = responseText
  260. } catch let error {
  261. response = String(describing: error)
  262. }
  263. DispatchQueue.main.async {
  264. completionHandler(response)
  265. }
  266. }
  267. return LocalizedString("Tuning radio…", comment: "Progress message for tuning radio")
  268. }
  269. }
  270. }