ソースを参照

More fixes - read below
tweaks to missed bolus - Still testing
snoozer to send stored variables instead of UI label text
chart max - do not move forward in time if current time exceeds chart max
alarms - fire every timer interval with new data pull or not. guarantees will fire within 15 seconds after download
minAgo update to run every timer interval
calendar - delete all events within last 2 hours
calendar - write data from stored variables, not UI - solves thread errors

Jon Fawcett 6 年 前
コミット
c018ae334c

+ 18 - 1
LoopFollow.xcodeproj/project.pbxproj

@@ -13,6 +13,7 @@
 		FC16A97D24996747003D6245 /* Alarms.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC16A97C24996747003D6245 /* Alarms.swift */; };
 		FC16A97F249969E2003D6245 /* Graphs.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC16A97E249969E2003D6245 /* Graphs.swift */; };
 		FC16A98124996C07003D6245 /* DateTime.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC16A98024996C07003D6245 /* DateTime.swift */; };
+		FC3AE7B5249E8E0E00AAE1E0 /* LoopFollow.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = FC3AE7B3249E8E0E00AAE1E0 /* LoopFollow.xcdatamodeld */; };
 		FC3CAB022493B6220068A152 /* BackgroundTaskAudio.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCC688592489554800A0279D /* BackgroundTaskAudio.swift */; };
 		FC5A5C3D2497B229009C550E /* Config.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = FC5A5C3C2497B229009C550E /* Config.xcconfig */; };
 		FC7CE518248ABE37001F83B8 /* Siri_Alert_Calibration_Needed.caf in Resources */ = {isa = PBXBuildFile; fileRef = FC7CE4A9248ABE2B001F83B8 /* Siri_Alert_Calibration_Needed.caf */; };
@@ -161,6 +162,7 @@
 		FC16A97C24996747003D6245 /* Alarms.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Alarms.swift; sourceTree = "<group>"; };
 		FC16A97E249969E2003D6245 /* Graphs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Graphs.swift; sourceTree = "<group>"; };
 		FC16A98024996C07003D6245 /* DateTime.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTime.swift; sourceTree = "<group>"; };
+		FC3AE7B4249E8E0E00AAE1E0 /* LoopFollow.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = LoopFollow.xcdatamodel; sourceTree = "<group>"; };
 		FC5A5C3C2497B229009C550E /* Config.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = "<group>"; };
 		FC7CE4A9248ABE2B001F83B8 /* Siri_Alert_Calibration_Needed.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Siri_Alert_Calibration_Needed.caf; sourceTree = "<group>"; };
 		FC7CE4AA248ABE2B001F83B8 /* Rise_And_Shine.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Rise_And_Shine.caf; sourceTree = "<group>"; };
@@ -511,6 +513,7 @@
 		FC97880B2485969B00A7906C = {
 			isa = PBXGroup;
 			children = (
+				FC3AE7B3249E8E0E00AAE1E0 /* LoopFollow.xcdatamodeld */,
 				FC5A5C3C2497B229009C550E /* Config.xcconfig */,
 				FC8DEEE32485D1680075863F /* LoopFollow */,
 				FC9788152485969B00A7906C /* Products */,
@@ -583,7 +586,6 @@
 				FC9788112485969B00A7906C /* Frameworks */,
 				FC9788122485969B00A7906C /* Resources */,
 				04DA71CCA0280FA5FA2DF7A6 /* [CP] Embed Pods Frameworks */,
-				FCE537CE249AAB2600F80BF8 /* Embed App Extensions */,
 			);
 			buildRules = (
 			);
@@ -808,6 +810,7 @@
 				FC7CE59F248D8D23001F83B8 /* SnoozeViewController.swift in Sources */,
 				FCC6886724898F8000A0279D /* UserDefaultsValue.swift in Sources */,
 				FC97881E2485969B00A7906C /* NightScoutViewController.swift in Sources */,
+				FC3AE7B5249E8E0E00AAE1E0 /* LoopFollow.xcdatamodeld in Sources */,
 				FCC6886F2489A53800A0279D /* AppConstants.swift in Sources */,
 				FC16A97A24996673003D6245 /* NightScout.swift in Sources */,
 				FCC6886924898FB100A0279D /* UserDefaultsValueGroups.swift in Sources */,
@@ -1029,6 +1032,20 @@
 			defaultConfigurationName = Release;
 		};
 /* End XCConfigurationList section */
+
+/* Begin XCVersionGroup section */
+		FC3AE7B3249E8E0E00AAE1E0 /* LoopFollow.xcdatamodeld */ = {
+			isa = XCVersionGroup;
+			children = (
+				FC3AE7B4249E8E0E00AAE1E0 /* LoopFollow.xcdatamodel */,
+			);
+			currentVersion = FC3AE7B4249E8E0E00AAE1E0 /* LoopFollow.xcdatamodel */;
+			name = LoopFollow.xcdatamodeld;
+			path = LoopFollow/LoopFollow.xcdatamodeld;
+			sourceTree = "<group>";
+			versionGroupType = wrapper.xcdatamodel;
+		};
+/* End XCVersionGroup section */
 	};
 	rootObject = FC97880C2485969B00A7906C /* Project object */;
 }

+ 3 - 3
LoopFollow/Controllers/Alarms.swift

@@ -182,8 +182,8 @@ extension MainViewController {
             if lastCarbTime > (now - (60 * 60)) {
                 // If low grams is active, the carbs and BG must both be higher
                 if (UserDefaultsRepository.alertMissedBolusLowGramsActive.value &&
-                    lastCarb >= Double(UserDefaultsRepository.alertMissedBolusLowGrams.value) &&
-                    currentBG >= UserDefaultsRepository.alertMissedBolusLowGramsBG.value) ||
+                    lastCarb > Double(UserDefaultsRepository.alertMissedBolusLowGrams.value) &&
+                    currentBG > UserDefaultsRepository.alertMissedBolusLowGramsBG.value) ||
                     !UserDefaultsRepository.alertMissedBolusLowGramsActive.value {
                     
                     // There is a current carb but no boluses at all
@@ -258,7 +258,7 @@ extension MainViewController {
     func triggerAlarm(sound: String, snooozedBGReadingTime: TimeInterval?)
     {
         guard let snoozer = self.tabBarController!.viewControllers?[2] as? SnoozeViewController else { return }
-        snoozer.updateDisplayWhenTriggered(bgVal: String(bgData[bgData.count - 1].sgv), directionVal: DirectionText.text ?? "", deltaVal: DeltaText.text ?? "", minAgoVal: MinAgoText.text ?? "", alertLabelVal: AlarmSound.whichAlarm)
+        snoozer.updateDisplayWhenTriggered(bgVal: String(bgData[bgData.count - 1].sgv), directionVal: latestDirectionString ?? "", deltaVal: latestDeltaString ?? "", minAgoVal: latestMinAgoString ?? "", alertLabelVal: AlarmSound.whichAlarm)
         snoozeTabItem.isEnabled = true;
         tabBarController?.selectedIndex = 2
         if snooozedBGReadingTime != nil {

+ 3 - 1
LoopFollow/Controllers/Graphs.swift

@@ -268,7 +268,9 @@ extension MainViewController {
             BGChart.zoom(scaleX: 18, scaleY: 1, x: 1, y: 1)
             firstGraphLoad = false
         }
-        BGChart.moveViewToAnimated(xValue: dateTimeUtils.getNowTimeIntervalUTC() - (BGChart.visibleXRange * 0.7), yValue: 0.0, axis: .right, duration: 1, easingOption: .easeInBack)
+        if BGChart.chartXMax > dateTimeUtils.getNowTimeIntervalUTC() {
+            BGChart.moveViewToAnimated(xValue: dateTimeUtils.getNowTimeIntervalUTC() - (BGChart.visibleXRange * 0.7), yValue: 0.0, axis: .right, duration: 1, easingOption: .easeInBack)
+        }
     }
     
     func updateBasalGraph() {

+ 19 - 0
LoopFollow/Controllers/NightScout.swift

@@ -86,6 +86,7 @@ extension MainViewController {
             webLoadNSSage()
             
             // Give the alarms and calendar 15 seconds delay to allow time for data to compile
+            print("Start View Timer")
             self.startViewTimer(time: viewTimeInterval)
         } else {
             // Things to do if we already have data and don't need a network call
@@ -99,6 +100,10 @@ extension MainViewController {
             if UserDefaultsRepository.downloadCarbs.value {
                 webLoadNSCarbs()
             }*/
+            if bgData.count > 0 {
+                           self.checkAlarms(bgs: bgData)
+            }
+            
         }
     }
     
@@ -157,6 +162,7 @@ extension MainViewController {
     // NS BG Data Response processor
     func ProcessNSBGData(data: [sgvData], onlyPullLastRecord: Bool){
         print("Enter BG Processor")
+        
         var pullDate = data[data.count - 1].date / 1000
         pullDate.round(FloatingPointRoundingRule.toNearestOrEven)
         
@@ -209,18 +215,22 @@ extension MainViewController {
             
             if let directionBG = entries[latestEntryi].direction {
                 DirectionText.text = bgDirectionGraphic(directionBG)
+                latestDirectionString = bgDirectionGraphic(directionBG)
             }
             else
             {
                 DirectionText.text = ""
+                latestDirectionString = ""
             }
             
             if deltaBG < 0 {
                 self.DeltaText.text = String(deltaBG)
+                latestDeltaString = String(deltaBG)
             }
             else
             {
                 self.DeltaText.text = "+" + String(deltaBG)
+                latestDeltaString = "+" + String(deltaBG)
             }
             self.updateBadge(val: latestBG)
             
@@ -314,6 +324,7 @@ extension MainViewController {
                 UserDefaultsRepository.alertLastLoopTime.value = lastLoopTime
                 if let failure = lastLoopRecord["failureReason"] {
                     LoopStatusLabel.text = "X"
+                    latestLoopStatusString = "X"
                 } else {
                     if let enacted = lastLoopRecord["enacted"] as? [String:AnyObject] {
                         if let lastTempBasal = enacted["rate"] as? Double {
@@ -322,9 +333,11 @@ extension MainViewController {
                     }
                     if let iobdata = lastLoopRecord["iob"] as? [String:AnyObject] {
                         tableData[0].value = String(format:"%.1f", (iobdata["iob"] as! Double))
+                        latestIOB = String(format:"%.1f", (iobdata["iob"] as! Double))
                     }
                     if let cobdata = lastLoopRecord["cob"] as? [String:AnyObject] {
                         tableData[1].value = String(format:"%.0f", cobdata["cob"] as! Double)
+                        latestCOB = String(format:"%.0f", cobdata["cob"] as! Double)
                     }
                     if let predictdata = lastLoopRecord["predicted"] as? [String:AnyObject] {
                         let prediction = predictdata["values"] as! [Double]
@@ -347,18 +360,22 @@ extension MainViewController {
                             }
                             if tempBasalTime > lastBGTime {
                                 LoopStatusLabel.text = "⏀"
+                                latestLoopStatusString = "⏀"
                             } else {
                                 LoopStatusLabel.text = "↻"
+                                latestLoopStatusString = "↻"
                             }
                         }
                     } else {
                         LoopStatusLabel.text = "↻"
+                        latestLoopStatusString = "↻"
                     }
                     
                 }
                 
                 if ((TimeInterval(Date().timeIntervalSince1970) - lastLoopTime) / 60) > 10 {
                     LoopStatusLabel.text = "⚠"
+                    latestLoopStatusString = "⚠"
                 }
             } // end lastLoopTime
         } // end lastLoop Record
@@ -709,6 +726,7 @@ extension MainViewController {
             if i == entries.count - 1 && dateTimeStamp + duration <= dateTimeUtils.getNowTimeIntervalUTC() {
                 lastEndDot = Date().timeIntervalSince1970 + (55 * 60)
                 tableData[2].value = String(format:"%.1f", basalRate)
+                latestBasal = String(format:"%.1f", basalRate)
             } else {
                 lastEndDot = dateTimeStamp + (duration * 60)
             }
@@ -754,6 +772,7 @@ extension MainViewController {
             }
             
             tableData[2].value = String(format:"%.1f", scheduled)
+            latestBasal = String(format:"%.1f", scheduled)
             // Make the starting dot at the last ending dot
             let startDot = basalGraphStruct(basalRate: scheduled, date: Double(lastEndDot))
             basalData.append(startDot)

+ 4 - 1
LoopFollow/LoopFollow.xcdatamodeld/.xccurrentversion

@@ -1,5 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
-<dict/>
+<dict>
+	<key>_XCCurrentVersionName</key>
+	<string>LoopFollow.xcdatamodel</string>
+</dict>
 </plist>

+ 31 - 14
LoopFollow/ViewControllers/MainViewController.swift

@@ -87,6 +87,13 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
     var predictionData: [Double] = []
     var chartData = LineChartData()
     var newBGPulled = false
+    var latestDirectionString = ""
+    var latestMinAgoString = ""
+    var latestDeltaString = ""
+    var latestLoopStatusString = ""
+    var latestCOB = ""
+    var latestBasal = ""
+    var latestIOB = ""
     
     // calendar setup
     let store = EKEventStore()
@@ -233,6 +240,7 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
     // Check for new data when timer ends
     @objc func timerDidEnd(_ timer:Timer) {
         print("main timer ended")
+        updateMinAgo()
         nightscoutLoader()
     }
 
@@ -242,8 +250,10 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
             let deltaTime = (TimeInterval(Date().timeIntervalSince1970)-bgData[bgData.count - 1].date) / 60
             minAgoBG = Double(TimeInterval(Date().timeIntervalSince1970)-bgData[bgData.count - 1].date)
             MinAgoText.text = String(Int(deltaTime)) + " min ago"
+            latestMinAgoString = String(Int(deltaTime)) + " min ago"
         } else {
             MinAgoText.text = ""
+            latestMinAgoString = ""
         }
         
     }
@@ -343,7 +353,7 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
             } else {
                 eventTitle = eventTitle.replacingOccurrences(of: "%OVERRIDE%", with: "")
             }
-            eventTitle = eventTitle.replacingOccurrences(of: "%LOOP%", with: self.LoopStatusLabel.text ?? "")
+            eventTitle = eventTitle.replacingOccurrences(of: "%LOOP%", with: self.latestLoopStatusString)
             var minAgo = ""
             if deltaTime > 9 {
                 // write old BG reading and continue pushing out end date to show last entry
@@ -351,16 +361,16 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
                 eventEndDate = eventStartDate.addingTimeInterval((60 * 10) + (deltaTime * 60))
             }
             var cob = "0"
-            if self.tableData[1].value != "" {
-                cob = self.tableData[1].value
+            if self.latestCOB != "" {
+                cob = self.latestCOB
             }
             var basal = "~"
-            if self.tableData[2].value != "" {
-                basal = self.tableData[2].value
+            if self.latestBasal != "" {
+                basal = self.latestBasal
             }
             var iob = "0"
-            if self.tableData[0].value != "" {
-                iob = self.tableData[0].value
+            if self.latestIOB != "" {
+                iob = self.latestIOB
             }
             eventTitle = eventTitle.replacingOccurrences(of: "%MINAGO%", with: minAgo)
             eventTitle = eventTitle.replacingOccurrences(of: "%IOB%", with: iob)
@@ -369,15 +379,22 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
             
             
             
-        // Delete Last Event
-            let eventToRemove = self.store.event(withIdentifier: UserDefaultsRepository.savedEventID.value)
-            if eventToRemove != nil {
-                do {
-                    try self.store.remove(eventToRemove!, span: .thisEvent, commit: true)
-                } catch {
-                    // Display error to user
+        // Delete Events from last 2 hours and 2 hours in future
+            var deleteStartDate = Date().addingTimeInterval(-60*60*2)
+            var deleteEndDate = Date().addingTimeInterval(60*60*2)
+            var deleteCalendar = self.store.calendar(withIdentifier: UserDefaultsRepository.calendarIdentifier.value) as! EKCalendar
+            var predicate2 = self.store.predicateForEvents(withStart: deleteStartDate, end: deleteEndDate, calendars: [deleteCalendar])
+            var eVDelete = self.store.events(matching: predicate2) as [EKEvent]?
+            if eVDelete != nil {
+                for i in eVDelete! {
+                    do {
+                        (try self.store.remove(i, span: EKSpan.thisEvent, commit: true))
+                    } catch let error {
+                        
+                    }
                 }
             }
+            
         // Write New Event
             var event = EKEvent(eventStore: self.store)
             event.title = eventTitle

+ 0 - 1
LoopFollow/ViewControllers/SnoozeViewController.swift

@@ -60,7 +60,6 @@ class SnoozeViewController: UIViewController {
         content.subtitle += bgVal + " "
         content.subtitle += directionVal + " "
         content.subtitle += deltaVal
-        //content.body = minAgoVal + " Min Ago"
         
         // show this notification 0 seconds from now
         let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)