Timers.swift 13 KB

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