ViewController.swift 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. //
  2. // ViewController.swift
  3. // xDrip5
  4. //
  5. // Created by Nathan Racklyeft on 10/1/15.
  6. // Copyright © 2015 Nathan Racklyeft. All rights reserved.
  7. //
  8. import UIKit
  9. import HealthKit
  10. import CGMBLEKit
  11. class ViewController: UIViewController, TransmitterDelegate, UITextFieldDelegate {
  12. @IBOutlet weak var titleLabel: UILabel!
  13. @IBOutlet weak var subtitleLabel: UILabel!
  14. @IBOutlet weak var passiveModeEnabledSwitch: UISwitch!
  15. @IBOutlet weak var stayConnectedSwitch: UISwitch!
  16. @IBOutlet weak var transmitterIDField: UITextField!
  17. @IBOutlet weak var scanningIndicatorView: UIActivityIndicatorView!
  18. override func viewDidLoad() {
  19. super.viewDidLoad()
  20. passiveModeEnabledSwitch.isOn = AppDelegate.sharedDelegate.transmitter?.passiveModeEnabled ?? false
  21. stayConnectedSwitch.isOn = AppDelegate.sharedDelegate.transmitter?.stayConnected ?? false
  22. transmitterIDField.text = AppDelegate.sharedDelegate.transmitter?.ID
  23. }
  24. override func viewDidAppear(_ animated: Bool) {
  25. super.viewDidAppear(animated)
  26. updateIndicatorViewDisplay()
  27. }
  28. // MARK: - Actions
  29. func updateIndicatorViewDisplay() {
  30. if let transmitter = AppDelegate.sharedDelegate.transmitter, transmitter.isScanning {
  31. scanningIndicatorView.startAnimating()
  32. } else {
  33. scanningIndicatorView.stopAnimating()
  34. }
  35. }
  36. @IBAction func toggleStayConnected(_ sender: UISwitch) {
  37. AppDelegate.sharedDelegate.transmitter?.stayConnected = sender.isOn
  38. UserDefaults.standard.stayConnected = sender.isOn
  39. updateIndicatorViewDisplay()
  40. }
  41. @IBAction func togglePassiveMode(_ sender: UISwitch) {
  42. AppDelegate.sharedDelegate.transmitter?.passiveModeEnabled = sender.isOn
  43. UserDefaults.standard.passiveModeEnabled = sender.isOn
  44. }
  45. @IBAction func start(_ sender: UIButton) {
  46. let dialog = UIAlertController(title: "Confirm", message: "Start sensor session.", preferredStyle: .alert)
  47. dialog.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action: UIAlertAction!) in
  48. AppDelegate.sharedDelegate.commandQueue.enqueue(.startSensor(at: Date()))
  49. }))
  50. dialog.addAction(UIAlertAction(title: "Cancel", style: .cancel))
  51. present(dialog, animated: true, completion: nil)
  52. }
  53. @IBAction func calibrate(_ sender: UIButton) {
  54. let dialog = UIAlertController(title: "Enter BG", message: "Calibrate sensor.", preferredStyle: .alert)
  55. let unit = HKUnit.milligramsPerDeciliter
  56. dialog.addTextField { (textField : UITextField!) in
  57. textField.placeholder = unit.unitString
  58. textField.keyboardType = .numberPad
  59. }
  60. dialog.addAction(UIAlertAction(title: "Calibrate", style: .default, handler: { (action: UIAlertAction!) in
  61. let textField = dialog.textFields![0] as UITextField
  62. let minGlucose = HKQuantity(unit: HKUnit.milligramsPerDeciliter, doubleValue: 40)
  63. let maxGlucose = HKQuantity(unit: HKUnit.milligramsPerDeciliter, doubleValue: 400)
  64. if let text = textField.text, let entry = Double(text) {
  65. guard entry >= minGlucose.doubleValue(for: unit) && entry <= maxGlucose.doubleValue(for: unit) else {
  66. // TODO: notify the user if the glucose is not in range
  67. return
  68. }
  69. let glucose = HKQuantity(unit: unit, doubleValue: Double(entry))
  70. AppDelegate.sharedDelegate.commandQueue.enqueue(.calibrateSensor(to: glucose, at: Date()))
  71. }
  72. }))
  73. dialog.addAction(UIAlertAction(title: "Cancel", style: .cancel))
  74. present(dialog, animated: true, completion: nil)
  75. }
  76. @IBAction func stop(_ sender: UIButton) {
  77. let dialog = UIAlertController(title: "Confirm", message: "Stop sensor session.", preferredStyle: .alert)
  78. dialog.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action: UIAlertAction!) in
  79. AppDelegate.sharedDelegate.commandQueue.enqueue(.stopSensor(at: Date()))
  80. }))
  81. dialog.addAction(UIAlertAction(title: "Cancel", style: .cancel))
  82. present(dialog, animated: true, completion: nil)
  83. }
  84. // MARK: - UITextFieldDelegate
  85. func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
  86. if let text = textField.text {
  87. let newString = text.replacingCharacters(in: range.rangeOfString(text), with: string)
  88. if newString.count > 6 {
  89. return false
  90. } else if newString.count == 6 {
  91. AppDelegate.sharedDelegate.transmitterID = newString
  92. textField.text = newString
  93. textField.resignFirstResponder()
  94. return false
  95. }
  96. }
  97. return true
  98. }
  99. func textFieldDidEndEditing(_ textField: UITextField) {
  100. if textField.text?.count != 6 {
  101. textField.text = UserDefaults.standard.transmitterID
  102. }
  103. }
  104. func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
  105. return true
  106. }
  107. func textFieldShouldReturn(_ textField: UITextField) -> Bool {
  108. return true
  109. }
  110. // MARK: - TransmitterDelegate
  111. func transmitter(_ transmitter: Transmitter, didError error: Error) {
  112. print("Transmitter Error: \(error)")
  113. titleLabel.text = NSLocalizedString("Error", comment: "Title displayed during error response")
  114. subtitleLabel.text = "\(error)"
  115. }
  116. func transmitter(_ transmitter: Transmitter, didRead glucose: Glucose) {
  117. let unit = HKUnit.milligramsPerDeciliter
  118. if let value = glucose.glucose?.doubleValue(for: unit) {
  119. titleLabel.text = "\(value) \(unit.unitString)"
  120. } else {
  121. titleLabel.text = String(describing: glucose.state)
  122. }
  123. let date = glucose.readDate
  124. subtitleLabel.text = DateFormatter.localizedString(from: date, dateStyle: .none, timeStyle: .long)
  125. }
  126. func transmitter(_ transmitter: Transmitter, didReadUnknownData data: Data) {
  127. titleLabel.text = NSLocalizedString("Unknown Data", comment: "Title displayed during unknown data response")
  128. subtitleLabel.text = data.hexadecimalString
  129. }
  130. func transmitter(_ transmitter: Transmitter, didReadBackfill glucose: [Glucose]) {
  131. titleLabel.text = NSLocalizedString("Backfill", comment: "Title displayed during backfill response")
  132. subtitleLabel.text = String(describing: glucose.map { $0.glucose })
  133. }
  134. func transmitterDidConnect(_ transmitter: Transmitter) {
  135. // Ignore
  136. }
  137. }
  138. private extension NSRange {
  139. func rangeOfString(_ string: String) -> Range<String.Index> {
  140. let startIndex = string.index(string.startIndex, offsetBy: location)
  141. let endIndex = string.index(startIndex, offsetBy: length)
  142. return startIndex..<endIndex
  143. }
  144. }