Timers.swift 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. //
  2. // Timers.swift
  3. // LoopFollow
  4. //
  5. // Created by Jon Fawcett on 9/3/20.
  6. // Copyright © 2020 Jon Fawcett. All rights reserved.
  7. //
  8. import Foundation
  9. import UIKit
  10. extension MainViewController {
  11. func restartAllTimers() {
  12. if !bgTimer.isValid { startBGTimer(time: 2) }
  13. if !profileTimer.isValid { startProfileTimer(time: 3) }
  14. if !deviceStatusTimer.isValid { startDeviceStatusTimer(time: 4) }
  15. if !treatmentsTimer.isValid { startTreatmentsTimer(time: 5) }
  16. if !cageSageTimer.isValid { startCageSageTimer(time: 6) }
  17. if !minAgoTimer.isValid { startMinAgoTimer(time: minAgoTimeInterval) }
  18. if !calendarTimer.isValid { startCalendarTimer(time: 15) }
  19. if !alarmTimer.isValid { startAlarmTimer(time: 30) }
  20. }
  21. func invalidateTimers() {
  22. bgTimer.invalidate()
  23. profileTimer.invalidate()
  24. deviceStatusTimer.invalidate()
  25. treatmentsTimer.invalidate()
  26. cageSageTimer.invalidate()
  27. minAgoTimer.invalidate()
  28. calendarTimer.invalidate()
  29. alarmTimer.invalidate()
  30. }
  31. // min Ago Timer
  32. func startMinAgoTimer(time: TimeInterval) {
  33. minAgoTimer = Timer.scheduledTimer(timeInterval: time,
  34. target: self,
  35. selector: #selector(MainViewController.minAgoTimerDidEnd(_:)),
  36. userInfo: nil,
  37. repeats: true)
  38. }
  39. // Updates Min Ago display
  40. @objc func minAgoTimerDidEnd(_ timer:Timer) {
  41. // print("min ago timer ended")
  42. if bgData.count > 0 {
  43. let bgSeconds = bgData.last!.date
  44. let now = Date().timeIntervalSince1970
  45. let secondsAgo = now - bgSeconds
  46. // Update Min Ago Displays
  47. let formatter = DateComponentsFormatter()
  48. formatter.unitsStyle = .positional // Use the appropriate positioning for the current locale
  49. if secondsAgo < 270 {
  50. formatter.allowedUnits = [ .minute] // Units to display in the formatted string
  51. } else {
  52. formatter.allowedUnits = [ .minute, .second] // Units to display in the formatted string
  53. }
  54. //formatter.zeroFormattingBehavior = [ .pad ] // Pad with zeroes where appropriate for the locale
  55. let formattedDuration = formatter.string(from: secondsAgo)
  56. MinAgoText.text = formattedDuration ?? ""
  57. MinAgoText.text! += " min ago"
  58. latestMinAgoString = formattedDuration ?? ""
  59. latestMinAgoString += " min ago"
  60. if let snoozer = self.tabBarController!.viewControllers?[2] as? SnoozeViewController {
  61. snoozer.MinAgoLabel.text = formattedDuration ?? ""
  62. snoozer.MinAgoLabel.text! += " min ago"
  63. } else { return }
  64. } else {
  65. MinAgoText.text = ""
  66. latestMinAgoString = ""
  67. if let snoozer = self.tabBarController!.viewControllers?[2] as? SnoozeViewController {
  68. snoozer.MinAgoLabel.text = ""
  69. } else { return }
  70. }
  71. }
  72. // Runs a 60 second timer when an alarm is snoozed
  73. // Prevents the alarm from triggering again while saving the snooze time to settings
  74. // End function needs nothing done
  75. func startGraphNowTimer(time: TimeInterval = 60) {
  76. graphNowTimer = Timer.scheduledTimer(timeInterval: time,
  77. target: self,
  78. selector: #selector(MainViewController.graphNowTimerDidEnd(_:)),
  79. userInfo: nil,
  80. repeats: true)
  81. }
  82. @objc func graphNowTimerDidEnd(_ timer:Timer) {
  83. createVerticalLines()
  84. }
  85. // Runs a 60 second timer when an alarm is snoozed
  86. // Prevents the alarm from triggering again while saving the snooze time to settings
  87. // End function needs nothing done
  88. func startCheckAlarmTimer(time: TimeInterval = 60) {
  89. checkAlarmTimer = Timer.scheduledTimer(timeInterval: time,
  90. target: self,
  91. selector: #selector(MainViewController.checkAlarmTimerDidEnd(_:)),
  92. userInfo: nil,
  93. repeats: false)
  94. }
  95. @objc func checkAlarmTimerDidEnd(_ timer:Timer) {
  96. }
  97. // BG Timer
  98. // Runs to 5:10 after last reading timestamp
  99. // Failed or no reading re-attempts after 10 second delay
  100. // Changes to 30 second increments after 7:00
  101. // Changes to 1 minute increments after 10:00
  102. // Changes to 5 minute increments after 20:00 stale data
  103. func startBGTimer(time: TimeInterval = 60 * 5) {
  104. bgTimer = Timer.scheduledTimer(timeInterval: time,
  105. target: self,
  106. selector: #selector(MainViewController.bgTimerDidEnd(_:)),
  107. userInfo: nil,
  108. repeats: false)
  109. }
  110. @objc func bgTimerDidEnd(_ timer:Timer) {
  111. // reset timer to 1 minute if settings aren't entered
  112. if UserDefaultsRepository.shareUserName.value == "" && UserDefaultsRepository.sharePassword.value == "" && UserDefaultsRepository.url.value == "" {
  113. startBGTimer(time: 60)
  114. return
  115. }
  116. if UserDefaultsRepository.shareUserName.value != "" && UserDefaultsRepository.sharePassword.value != "" {
  117. webLoadDexShare()
  118. } else {
  119. webLoadNSBGData()
  120. }
  121. }
  122. // Device Status Timer
  123. // Runs to 5:10 after last reading timestamp
  124. // Failed or no update re-attempts after 10 second delay
  125. // Changes to 30 second increments after 7:00
  126. // Changes to 1 minute increments after 10:00
  127. // Changes to 5 minute increments after 20:00 stale data
  128. func startDeviceStatusTimer(time: TimeInterval = 60 * 5) {
  129. deviceStatusTimer = Timer.scheduledTimer(timeInterval: time,
  130. target: self,
  131. selector: #selector(MainViewController.deviceStatusTimerDidEnd(_:)),
  132. userInfo: nil,
  133. repeats: false)
  134. }
  135. @objc func deviceStatusTimerDidEnd(_ timer:Timer) {
  136. // reset timer to 1 minute if settings aren't entered
  137. if UserDefaultsRepository.url.value == "" || !UserDefaultsRepository.loopUser.value {
  138. startDeviceStatusTimer(time: 60)
  139. return
  140. }
  141. if UserDefaultsRepository.url.value != "" {
  142. webLoadNSDeviceStatus()
  143. }
  144. }
  145. // Treatments Timer
  146. // Runs on 2 minute intervals
  147. // Pauses with stale BG data
  148. func startTreatmentsTimer(time: TimeInterval = 60 * 2) {
  149. treatmentsTimer = Timer.scheduledTimer(timeInterval: time,
  150. target: self,
  151. selector: #selector(MainViewController.treatmentsTimerDidEnd(_:)),
  152. userInfo: nil,
  153. repeats: false)
  154. }
  155. @objc func treatmentsTimerDidEnd(_ timer:Timer) {
  156. // reset timer to 1 minute if settings aren't entered
  157. if UserDefaultsRepository.url.value == "" || !UserDefaultsRepository.loopUser.value {
  158. startTreatmentsTimer(time: 60)
  159. return
  160. }
  161. if UserDefaultsRepository.url.value != "" && UserDefaultsRepository.downloadTreatments.value {
  162. WebLoadNSTreatments()
  163. }
  164. startTreatmentsTimer()
  165. }
  166. // Profile Timer
  167. // Runs on 10 minute intervals
  168. // Pauses with stale BG data
  169. func startProfileTimer(time: TimeInterval = 60 * 10) {
  170. profileTimer = Timer.scheduledTimer(timeInterval: time,
  171. target: self,
  172. selector: #selector(MainViewController.profileTimerDidEnd(_:)),
  173. userInfo: nil,
  174. repeats: false)
  175. }
  176. @objc func profileTimerDidEnd(_ timer:Timer) {
  177. // reset timer to 1 minute if settings aren't entered
  178. if UserDefaultsRepository.url.value == "" || !UserDefaultsRepository.loopUser.value {
  179. startProfileTimer(time: 60)
  180. return
  181. }
  182. if !isStaleData() && UserDefaultsRepository.url.value != "" {
  183. webLoadNSProfile()
  184. startProfileTimer()
  185. }
  186. }
  187. // Cage and Sage Timer
  188. // Runs on 10 minute intervals
  189. // Pauses with stale BG data
  190. func startCageSageTimer(time: TimeInterval = 60 * 10) {
  191. cageSageTimer = Timer.scheduledTimer(timeInterval: time,
  192. target: self,
  193. selector: #selector(MainViewController.cageSageTimerDidEnd(_:)),
  194. userInfo: nil,
  195. repeats: false)
  196. }
  197. @objc func cageSageTimerDidEnd(_ timer:Timer) {
  198. // reset timer to 1 minute if settings aren't entered
  199. if UserDefaultsRepository.url.value == "" || !UserDefaultsRepository.loopUser.value {
  200. startCageSageTimer(time: 60)
  201. return
  202. }
  203. if UserDefaultsRepository.url.value != "" {
  204. webLoadNSCage()
  205. webLoadNSSage()
  206. startCageSageTimer()
  207. }
  208. }
  209. // Cancel and reset the playing alarm if it has not been snoozed after 4 min 50 seconds.
  210. // This allows the next BG reading to either start the timer going or not fire if the situation has been resolved
  211. func startAlarmPlayingTimer(time: TimeInterval = 290) {
  212. let alarmPlayingTimer = Timer.scheduledTimer(timeInterval: time,
  213. target: self,
  214. selector: #selector(MainViewController.alarmPlayingTimerDidEnd(_:)),
  215. userInfo: nil,
  216. repeats: false)
  217. }
  218. @objc func alarmPlayingTimerDidEnd(_ timer:Timer) {
  219. if AlarmSound.isPlaying {
  220. stopAlarmAtNextReading()
  221. }
  222. }
  223. // Alarm Timer
  224. // Run the alarm checker every 15 seconds
  225. func startAlarmTimer(time: TimeInterval) {
  226. alarmTimer = Timer.scheduledTimer(timeInterval: time,
  227. target: self,
  228. selector: #selector(MainViewController.alarmTimerDidEnd(_:)),
  229. userInfo: nil,
  230. repeats: true)
  231. }
  232. @objc func alarmTimerDidEnd(_ timer:Timer) {
  233. if bgData.count > 0 {
  234. self.checkAlarms(bgs: bgData)
  235. }
  236. if overrideGraphData.count > 0 {
  237. self.checkOverrideAlarms()
  238. }
  239. }
  240. // Calendar Timer
  241. // Run the calendar writer every 30 seconds
  242. func startCalendarTimer(time: TimeInterval) {
  243. calendarTimer = Timer.scheduledTimer(timeInterval: time,
  244. target: self,
  245. selector: #selector(MainViewController.calendarTimerDidEnd(_:)),
  246. userInfo: nil,
  247. repeats: true)
  248. }
  249. @objc func calendarTimerDidEnd(_ timer:Timer) {
  250. if UserDefaultsRepository.writeCalendarEvent.value && UserDefaultsRepository.calendarIdentifier.value != "" {
  251. self.writeCalendar()
  252. }
  253. }
  254. // Timer to allow us to write min ago calendar entries but not update them every 30 seconds
  255. func startCalTimer(time: TimeInterval) {
  256. calTimer = Timer.scheduledTimer(timeInterval: time,
  257. target: self,
  258. selector: #selector(MainViewController.calTimerDidEnd(_:)),
  259. userInfo: nil,
  260. repeats: false)
  261. }
  262. // Nothing should be done when this timer ends because it just blocks the calendar from writing when it's active
  263. @objc func calTimerDidEnd(_ timer:Timer) {
  264. }
  265. }