Browse Source

Add: variable download timers

Jon Fawcett 5 years ago
parent
commit
9f575976f5

+ 105 - 95
LoopFollow/Controllers/NightScout.swift

@@ -38,106 +38,22 @@ extension MainViewController {
         var sgv: Int
     }
     
-    
-    // Main loader for all data
-    func nightscoutLoader(forceLoad: Bool = false) {
-        
-        var needsLoaded: Bool = false
-        var staleData: Bool = false
-        var onlyPullLastRecord = false
-        
-        // If we have existing data and it's within 5 minutes, we aren't going to do a BG network call
-        // if we have stale BG data 10 min or older, we're only going to attempt to pull BG and Loop status
-        // to not have a full refresh every 15 seconds. The remaining data will start pulling again on the
-        // next BG reading that comes in.
+    func isStaleData() -> Bool {
         if bgData.count > 0 {
             let now = NSDate().timeIntervalSince1970
-            let lastReadingTime = bgData[bgData.count - 1].date
+            let lastReadingTime = bgData.last!.date
             let secondsAgo = now - lastReadingTime
-            if secondsAgo >= 5*60 {
-                needsLoaded = true
-                if secondsAgo < 10*60 {
-                    onlyPullLastRecord = true
-                } else {
-                    staleData = true
-                }
-            }
-        } else {
-            needsLoaded = true
-        }
-        
-        
-        if forceLoad { needsLoaded = true}
-        // Only update if we don't have a current reading or forced to load
-        if needsLoaded {
-            
-            if UserDefaultsRepository.url.value != "" {
-                webLoadNSDeviceStatus()
-            }
-            
-            if UserDefaultsRepository.shareUserName.value != "" && UserDefaultsRepository.sharePassword.value != "" {
-                webLoadDexShare(onlyPullLastRecord: onlyPullLastRecord)
+            if secondsAgo >= 20*60 {
+                return true
             } else {
-                webLoadNSBGData(onlyPullLastRecord: onlyPullLastRecord)
-            }
-
-            
-            if !staleData && UserDefaultsRepository.url.value != "" {
-                webLoadNSProfile()
-                if UserDefaultsRepository.downloadBasal.value {
-                    WebLoadNSTempBasals()
-                }
-                if UserDefaultsRepository.downloadBolus.value {
-                    webLoadNSBoluses()
-                }
-                if UserDefaultsRepository.downloadCarbs.value {
-                    webLoadNSCarbs()
-                }
-                webLoadNSCage()
-                webLoadNSSage()
+                return false
             }
-
-            // Give the alarms and calendar 15 seconds delay to allow time for data to compile
-            self.startViewTimer(time: viewTimeInterval)
         } else {
-
-            if bgData.count > 0 {
-                self.checkAlarms(bgs: bgData)
-            }
-            
-            // Used for Min Ago watch readings
-            if UserDefaultsRepository.writeCalendarEvent.value {
-                writeCalendar()
-            }
-            
-            if UserDefaultsRepository.url.value != ""  {
-                if latestLoopTime == 0 {
-                    webLoadNSDeviceStatus()
-               
-                    if UserDefaultsRepository.shareUserName.value != "" && UserDefaultsRepository.sharePassword.value != "" {
-                        webLoadDexShare(onlyPullLastRecord: onlyPullLastRecord)
-                    } else {
-                        webLoadNSBGData(onlyPullLastRecord: onlyPullLastRecord)
-                    }
-           
-                    webLoadNSProfile()
-                    if UserDefaultsRepository.downloadBasal.value {
-                        WebLoadNSTempBasals()
-                    }
-                    if UserDefaultsRepository.downloadBolus.value {
-                        webLoadNSBoluses()
-                    }
-                    if UserDefaultsRepository.downloadCarbs.value {
-                        webLoadNSCarbs()
-                    }
-                    webLoadNSCage()
-                    webLoadNSSage()
-                }
-            }
-            
+            return false
         }
     }
     
+    
     // Dex Share Web Call
     func webLoadDexShare(onlyPullLastRecord: Bool = false) {
         var count = 288
@@ -183,6 +99,10 @@ extension MainViewController {
                 globalVariables.nsVerifiedAlert = dateTimeUtils.getNowTimeIntervalUTC()
                 //self.sendNotification(title: "Nightscout Error", body: "Please double check url, token, and internet connection. This may also indicate a temporary Nightscout issue")
             }
+            if bgTimer.isValid {
+                bgTimer.invalidate()
+            }
+            startBGTimer(time: 10)
             return
         }
         var request = URLRequest(url: urlBGData)
@@ -195,6 +115,10 @@ extension MainViewController {
                     globalVariables.nsVerifiedAlert = dateTimeUtils.getNowTimeIntervalUTC()
                     //self.sendNotification(title: "Nightscout Error", body: "Please double check url, token, and internet connection. This may also indicate a temporary Nightscout issue")
                 }
+                if self.bgTimer.isValid {
+                    self.bgTimer.invalidate()
+                }
+                self.startBGTimer(time: 10)
                 return
                 
             }
@@ -203,6 +127,10 @@ extension MainViewController {
                     globalVariables.nsVerifiedAlert = dateTimeUtils.getNowTimeIntervalUTC()
                     //self.sendNotification(title: "Nightscout Error", body: "Please double check url, token, and internet connection. This may also indicate a temporary Nightscout issue")
                 }
+                if self.bgTimer.isValid {
+                    self.bgTimer.invalidate()
+                }
+                self.startBGTimer(time: 10)
                 return
                 
             }
@@ -220,6 +148,10 @@ extension MainViewController {
                     globalVariables.nsVerifiedAlert = dateTimeUtils.getNowTimeIntervalUTC()
                     //self.sendNotification(title: "Nightscout Failure", body: "Please double check url, token, and internet connection. This may also indicate a temporary Nightscout issue")
                 }
+                if self.bgTimer.isValid {
+                    self.bgTimer.invalidate()
+                }
+                self.startBGTimer(time: 10)
                 return
                 
             }
@@ -261,8 +193,6 @@ extension MainViewController {
             if data.count > 0 {
                 self.updateBadge(val: data[data.count - 1].sgv)
             }
-            
-            // self.viewUpdateNSBG()
             return
         }
         
@@ -295,6 +225,39 @@ extension MainViewController {
                 let priorBG = entries[latestEntryi - 1].sgv
                 let deltaBG = latestBG - priorBG as Int
                 let lastBGTime = entries[latestEntryi].date
+                
+                // Start the BG timer based on the reading
+                let now = NSDate().timeIntervalSince1970
+                let secondsAgo = now - lastBGTime
+                
+                // if reading is overdue over: 20:00, re-attempt every 5 minutes
+                if secondsAgo >= (20 * 60) {
+                    self.startBGTimer(time: (5 * 60))
+                    print("started 5 minute bg timer")
+                    
+                // if the reading is overdue: 10:00-19:59, re-attempt every minute
+                } else if secondsAgo >= (10 * 60) {
+                    self.startBGTimer(time: 60)
+                    print("started 1 minute bg timer")
+                    
+                // if the reading is overdue: 7:00-9:59, re-attempt every 30 seconds
+                } else if secondsAgo >= (7 * 60) {
+                    self.startBGTimer(time: 30)
+                    print("started 30 second bg timer")
+                    
+                // if the reading is overdue: 5:00-6:59 re-attempt every 10 seconds
+                } else if secondsAgo >= (5 * 60) {
+                    self.startBGTimer(time: 10)
+                    print("started 10 second bg timer")
+                
+                // We have a current reading. Set timer to 5:10 from last reading
+                } else {
+                    self.startBGTimer(time: 310 - secondsAgo)
+                    let timerVal = 310 - secondsAgo
+                    print("started 5:10 bg timer: \(timerVal)")
+                }
+                
+                
                 let deltaTime = (TimeInterval(Date().timeIntervalSince1970)-lastBGTime) / 60
                 var userUnit = " mg/dL"
                 if self.mmol {
@@ -366,6 +329,10 @@ extension MainViewController {
                 globalVariables.nsVerifiedAlert = dateTimeUtils.getNowTimeIntervalUTC()
                 //self.sendNotification(title: "Nightscout Failure", body: "Please double check url, token, and internet connection. This may also indicate a temporary Nightscout issue")
             }
+            if self.deviceStatusTimer.isValid {
+                self.deviceStatusTimer.invalidate()
+            }
+            self.startDeviceStatusTimer(time: 10)
             return
         }
         
@@ -381,6 +348,10 @@ extension MainViewController {
                     globalVariables.nsVerifiedAlert = dateTimeUtils.getNowTimeIntervalUTC()
                     //self.sendNotification(title: "Nightscout Error", body: "Please double check url, token, and internet connection. This may also indicate a temporary Nightscout issue")
                 }
+                if self.deviceStatusTimer.isValid {
+                    self.deviceStatusTimer.invalidate()
+                }
+                self.startDeviceStatusTimer(time: 10)
                 return
             }
             
@@ -389,6 +360,10 @@ extension MainViewController {
                     globalVariables.nsVerifiedAlert = dateTimeUtils.getNowTimeIntervalUTC()
                     //self.sendNotification(title: "Nightscout Error", body: "Please double check url, token, and internet connection. This may also indicate a temporary Nightscout issue")
                 }
+                if self.deviceStatusTimer.isValid {
+                    self.deviceStatusTimer.invalidate()
+                }
+                self.startDeviceStatusTimer(time: 10)
                 return
             }
             
@@ -403,6 +378,10 @@ extension MainViewController {
                     globalVariables.nsVerifiedAlert = dateTimeUtils.getNowTimeIntervalUTC()
                     //self.sendNotification(title: "Nightscout Error", body: "Please double check url, token, and internet connection. This may also indicate a temporary Nightscout issue")
                 }
+                if self.deviceStatusTimer.isValid {
+                    self.deviceStatusTimer.invalidate()
+                }
+                self.startDeviceStatusTimer(time: 10)
                 return
             }
         }
@@ -448,7 +427,7 @@ extension MainViewController {
         
         // Loop
         if let lastLoopRecord = lastDeviceStatus?["loop"] as! [String : AnyObject]? {
-            print("Loop: \(lastLoopRecord)")
+            //print("Loop: \(lastLoopRecord)")
             if let lastLoopTime = formatter.date(from: (lastLoopRecord["timestamp"] as! String))?.timeIntervalSince1970  {
                 UserDefaultsRepository.alertLastLoopTime.value = lastLoopTime
                 if UserDefaultsRepository.debugLog.value { self.writeDebugLog(value: "lastLoopTime: " + String(lastLoopTime)) }
@@ -598,6 +577,37 @@ extension MainViewController {
         overrideData.reverse()
         updateOverrideGraph()
         checkOverrideAlarms()
+        
+        // Start the timer based on the timestamp
+        let now = NSDate().timeIntervalSince1970
+        let secondsAgo = now - latestLoopTime
+        
+        // if Loop is overdue over: 20:00, re-attempt every 5 minutes
+        if secondsAgo >= (20 * 60) {
+            self.startDeviceStatusTimer(time: (5 * 60))
+            print("started 5 minute device status timer")
+            
+        // if the Loop is overdue: 10:00-19:59, re-attempt every minute
+        } else if secondsAgo >= (10 * 60) {
+            self.startDeviceStatusTimer(time: 60)
+            print("started 1 minute device status timer")
+            
+        // if the Loop is overdue: 7:00-9:59, re-attempt every 30 seconds
+        } else if secondsAgo >= (7 * 60) {
+            self.startDeviceStatusTimer(time: 30)
+            print("started 30 second device status timer")
+            
+        // if the Loop is overdue: 5:00-6:59 re-attempt every 10 seconds
+        } else if secondsAgo >= (5 * 60) {
+            self.startDeviceStatusTimer(time: 10)
+            print("started 10 second bg timer")
+        
+        // We have a current Loop. Set timer to 5:10 from last reading
+        } else {
+            self.startDeviceStatusTimer(time: 310 - secondsAgo)
+            let timerVal = 310 - secondsAgo
+            print("started 5:10 device status timer: \(timerVal)")
+        }
     }
     
     // NS Cage Web Call
@@ -882,7 +892,7 @@ extension MainViewController {
         if UserDefaultsRepository.graphBasal.value {
             updateBasalScheduledGraph()
         }
-
+        
     }
     
     // NS Temp Basal Web Call

+ 191 - 26
LoopFollow/Controllers/Timers.swift

@@ -12,6 +12,16 @@ import UIKit
 
 extension MainViewController {
     
+    func restartAllTimers() {
+        if !deviceStatusTimer.isValid { startDeviceStatusTimer(time: 1) }
+        if !profileTimer.isValid { startProfileTimer(time: 1) }
+        if !bgTimer.isValid { startBGTimer(time: 1) }
+        if !treatmentsTimer.isValid { startTreatmentsTimer(time: 10) }
+        if !cageSageTimer.isValid { startCageSageTimer(time: 10) }
+        if !minAgoTimer.isValid { startMinAgoTimer(time: minAgoTimeInterval) }
+        if !calendarTimer.isValid { startCalendarTimer(time: 30) }
+        if !alarmTimer.isValid { startAlarmTimer(time: 30) }
+    }
     
     
     // min Ago Timer
@@ -64,19 +74,6 @@ extension MainViewController {
         
     }
     
-    // Main Download Timer
-    func startTimer(time: TimeInterval) {
-        timer = Timer.scheduledTimer(timeInterval: time,
-                                     target: self,
-                                     selector: #selector(MainViewController.timerDidEnd(_:)),
-                                     userInfo: nil,
-                                     repeats: true)
-    }
-    
-    // Check for new data when timer ends
-    @objc func timerDidEnd(_ timer:Timer) {
-        nightscoutLoader()
-    }
     
     // Runs a 60 second timer when an alarm is snoozed
     // Prevents the alarm from triggering again while saving the snooze time to settings
@@ -93,6 +90,160 @@ extension MainViewController {
     @objc func checkAlarmTimerDidEnd(_ timer:Timer) {
     }
     
+    // BG Timer
+    // Runs to 5:10 after last reading timestamp
+    // Failed or no reading re-attempts after 10 second delay
+    // Changes to 30 second increments after 7:00
+    // Changes to 1 minute increments after 10:00
+    // Changes to 5 minute increments after 20:00 stale data
+    func startBGTimer(time: TimeInterval =  60 * 5) {
+        bgTimer = Timer.scheduledTimer(timeInterval: time,
+                                               target: self,
+                                               selector: #selector(MainViewController.bgTimerDidEnd(_:)),
+                                               userInfo: nil,
+                                               repeats: false)
+    }
+    
+    @objc func bgTimerDidEnd(_ timer:Timer) {
+        
+        // reset timer to 1 minute if settings aren't entered
+        if UserDefaultsRepository.shareUserName.value == "" && UserDefaultsRepository.sharePassword.value == "" && UserDefaultsRepository.url.value == "" {
+            startBGTimer(time: 60)
+            return
+        }
+        
+        var onlyPullLastRecord = false
+        
+        // Check if the last reading is less than 10 minutes ago
+        // to only pull 1 reading if that's all we need
+        if bgData.count > 0 {
+            let now = NSDate().timeIntervalSince1970
+            let lastReadingTime = bgData.last!.date
+            let secondsAgo = now - lastReadingTime
+            if secondsAgo < 10*60 {
+                onlyPullLastRecord = true
+            }
+        }
+        
+        if UserDefaultsRepository.shareUserName.value != "" && UserDefaultsRepository.sharePassword.value != "" {
+            webLoadDexShare(onlyPullLastRecord: onlyPullLastRecord)
+        } else {
+            webLoadNSBGData(onlyPullLastRecord: onlyPullLastRecord)
+        }
+        
+    }
+    
+    // Device Status Timer
+    // Runs to 5:10 after last reading timestamp
+    // Failed or no update re-attempts after 10 second delay
+    // Changes to 30 second increments after 7:00
+    // Changes to 1 minute increments after 10:00
+    // Changes to 5 minute increments after 20:00 stale data
+    func startDeviceStatusTimer(time: TimeInterval =  60 * 5) {
+        deviceStatusTimer = Timer.scheduledTimer(timeInterval: time,
+                                               target: self,
+                                               selector: #selector(MainViewController.deviceStatusTimerDidEnd(_:)),
+                                               userInfo: nil,
+                                               repeats: false)
+    }
+    
+    @objc func deviceStatusTimerDidEnd(_ timer:Timer) {
+        
+        // reset timer to 1 minute if settings aren't entered
+        if UserDefaultsRepository.url.value == "" {
+            startDeviceStatusTimer(time: 60)
+            return
+        }
+        
+        if UserDefaultsRepository.url.value != "" {
+            webLoadNSDeviceStatus()
+        }
+    }
+    
+    // Treatments Timer
+    // Runs on 2 minute intervals
+    // Pauses with stale BG data
+    func startTreatmentsTimer(time: TimeInterval =  60 * 2) {
+        treatmentsTimer = Timer.scheduledTimer(timeInterval: time,
+                                               target: self,
+                                               selector: #selector(MainViewController.treatmentsTimerDidEnd(_:)),
+                                               userInfo: nil,
+                                               repeats: false)
+    }
+    
+    @objc func treatmentsTimerDidEnd(_ timer:Timer) {
+        
+        // reset timer to 1 minute if settings aren't entered
+        if UserDefaultsRepository.url.value == "" {
+            startTreatmentsTimer(time: 60)
+            return
+        }
+        
+        if !isStaleData() && UserDefaultsRepository.url.value != "" {
+            if UserDefaultsRepository.downloadBasal.value {
+                WebLoadNSTempBasals()
+            }
+            if UserDefaultsRepository.downloadBolus.value {
+                webLoadNSBoluses()
+            }
+            if UserDefaultsRepository.downloadCarbs.value {
+                webLoadNSCarbs()
+            }
+            startTreatmentsTimer()
+        }
+    }
+    
+    // Profile Timer
+    // Runs on 10 minute intervals
+    // Pauses with stale BG data
+    func startProfileTimer(time: TimeInterval =  60 * 10) {
+        profileTimer = Timer.scheduledTimer(timeInterval: time,
+                                               target: self,
+                                               selector: #selector(MainViewController.profileTimerDidEnd(_:)),
+                                               userInfo: nil,
+                                               repeats: false)
+    }
+    
+    @objc func profileTimerDidEnd(_ timer:Timer) {
+        
+        // reset timer to 1 minute if settings aren't entered
+        if UserDefaultsRepository.url.value == "" {
+            startProfileTimer(time: 60)
+            return
+        }
+        
+        if !isStaleData() && UserDefaultsRepository.url.value != "" {
+            webLoadNSProfile()
+            startProfileTimer()
+        }
+    }
+    
+    // Cage and Sage Timer
+    // Runs on 10 minute intervals
+    // Pauses with stale BG data
+    func startCageSageTimer(time: TimeInterval =  60 * 10) {
+        cageSageTimer = Timer.scheduledTimer(timeInterval: time,
+                                               target: self,
+                                               selector: #selector(MainViewController.cageSageTimerDidEnd(_:)),
+                                               userInfo: nil,
+                                               repeats: false)
+    }
+    
+    @objc func cageSageTimerDidEnd(_ timer:Timer) {
+        
+        // reset timer to 1 minute if settings aren't entered
+        if UserDefaultsRepository.url.value == "" {
+            startCageSageTimer(time: 60)
+            return
+        }
+        
+        if !isStaleData() && UserDefaultsRepository.url.value != "" {
+            webLoadNSCage()
+            webLoadNSSage()
+            startCageSageTimer()
+        }
+    }
+    
     // Cancel and reset the playing alarm if it has not been snoozed after 4 min 50 seconds.
     // This allows the next BG reading to either start the timer going or not fire if the situation has been resolved
     func startAlarmPlayingTimer(time: TimeInterval = 290) {
@@ -109,29 +260,43 @@ extension MainViewController {
         }
     }
     
-    // NS Loader Timer
-    func startViewTimer(time: TimeInterval) {
-        viewTimer = Timer.scheduledTimer(timeInterval: time,
+    
+    // Alarm Timer
+    // Run the alarm checker every 15 seconds
+    func startAlarmTimer(time: TimeInterval) {
+        alarmTimer = Timer.scheduledTimer(timeInterval: time,
                                          target: self,
-                                         selector: #selector(MainViewController.viewTimerDidEnd(_:)),
+                                         selector: #selector(MainViewController.alarmTimerDidEnd(_:)),
                                          userInfo: nil,
-                                         repeats: false)
+                                         repeats: true)
         
     }
     
-    // This delays a few things to hopefully all all data to arrive.
-    @objc func viewTimerDidEnd(_ timer:Timer) {
+    @objc func alarmTimerDidEnd(_ timer:Timer) {
         if bgData.count > 0 {
             self.checkAlarms(bgs: bgData)
-            //self.updateMinAgo()
-            // self.updateBadge(val: bgData[bgData.count - 1].sgv)
-            //self.viewUpdateNSBG()
-            if UserDefaultsRepository.writeCalendarEvent.value {
-                self.writeCalendar()
-            }
         }
     }
     
+    // Calendar Timer
+    // Run the calendar writer every 30 seconds
+    func startCalendarTimer(time: TimeInterval) {
+        calendarTimer = Timer.scheduledTimer(timeInterval: time,
+                                         target: self,
+                                         selector: #selector(MainViewController.calendarTimerDidEnd(_:)),
+                                         userInfo: nil,
+                                         repeats: true)
+        
+    }
+    
+    @objc func calendarTimerDidEnd(_ timer:Timer) {
+        if UserDefaultsRepository.writeCalendarEvent.value && UserDefaultsRepository.calendarIdentifier.value != "" {
+            self.writeCalendar()
+        }
+    }
+    
+    
+    
     // Timer to allow us to write min ago calendar entries but not update them every 30 seconds
     func startCalTimer(time: TimeInterval) {
         calTimer = Timer.scheduledTimer(timeInterval: time,

+ 18 - 17
LoopFollow/ViewControllers/MainViewController.swift

@@ -78,9 +78,6 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
     var minAgoTimer = Timer()
     var minAgoTimeInterval: TimeInterval = 1.0
     
-    // View Delay Timer
-    var viewTimer = Timer()
-    let viewTimeInterval: TimeInterval = UserDefaultsRepository.viewRefreshDelay.value
     
     // Check Alarms Timer
     // Don't check within 1 minute of alarm triggering to give the snoozer time to save data
@@ -89,6 +86,14 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
     
     var calTimer = Timer()
     
+    var bgTimer = Timer()
+    var cageSageTimer = Timer()
+    var profileTimer = Timer()
+    var deviceStatusTimer = Timer()
+    var treatmentsTimer = Timer()
+    var alarmTimer = Timer()
+    var calendarTimer = Timer()
+    
     // Info Table Setup
     var tableData : [infoData] = []
     var derivedTableData: [infoData] = []
@@ -202,15 +207,14 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
         // setup display for NS vs Dex
         showHideNSDetails()
         
-        // Load Data
-        if (UserDefaultsRepository.url.value != "" || (UserDefaultsRepository.shareUserName.value != "" && UserDefaultsRepository.sharePassword.value != "")) && firstGraphLoad {
-            nightscoutLoader()
-        }
-        
-        startMinAgoTimer(time: minAgoTimeInterval)
+        // Load Startup Data
+        restartAllTimers()
         
     }
     
+
+    
+    
     override func viewWillAppear(_ animated: Bool) {
         // set screen lock
         UIApplication.shared.isIdleTimerDisabled = UserDefaultsRepository.screenlockSwitchState.value;
@@ -232,7 +236,7 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
            
               // settings for appBadge changed
               if appState.generalSettingsChanges & GeneralSettingsChangeEnum.appBadgeChange.rawValue != 0 {
-                 self.nightscoutLoader(forceLoad: true)
+                 
               }
               
               // settings for textcolor changed
@@ -301,10 +305,7 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
         // Cancel the current timer and start a fresh background timer using the settings value only if background task is enabled
         
         if UserDefaultsRepository.backgroundRefresh.value {
-            timer.invalidate()
             backgroundTask.startBackgroundTask()
-            let refresh = UserDefaultsRepository.backgroundRefreshFrequency.value * 60
-            startTimer(time: TimeInterval(refresh))
         }
         
     }
@@ -316,12 +317,10 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
         // Cancel the background tasks, start a fresh timer
         if UserDefaultsRepository.backgroundRefresh.value {
             backgroundTask.stopBackgroundTask()
-            timer.invalidate()
-        }
-        if !timer.isValid {
-            startTimer(time: timeInterval)
         }
         
+        restartAllTimers()
+
     }
     
     @objc override func viewDidAppear(_ animated: Bool) {
@@ -377,6 +376,7 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
     }
     
     func updateBadge(val: Int) {
+        DispatchQueue.main.async {
         if UserDefaultsRepository.appBadge.value {
             let latestBG = String(val)
             UIApplication.shared.applicationIconBadgeNumber = Int(bgUnits.removePeriodForBadge(bgUnits.toDisplayUnits(latestBG))) ?? val
@@ -384,6 +384,7 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
             UIApplication.shared.applicationIconBadgeNumber = 0
         }
 //        if UserDefaultsRepository.debugLog.value { self.writeDebugLog(value: "updated badge") }
+        }
     }