Просмотр исходного кода

- Added Snooze All
- Added Cage, Sage, Looping to info table
- Fixed direction arrow
- made dot/line colors change from BG setting, not alert level

Jon Fawcett 6 лет назад
Родитель
Сommit
d878805204

+ 18 - 0
LoopFollow.xcworkspace/xcuserdata/jon.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@@ -3,4 +3,22 @@
    uuid = "35B1BDC7-1374-42B0-9D79-1E7D694F0434"
    type = "0"
    version = "2.0">
+   <Breakpoints>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "E5126125-FBA4-408A-AF91-2BC39F36D908"
+            shouldBeEnabled = "Yes"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "LoopFollow/Controllers/MainViewController.swift"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "659"
+            endingLineNumber = "659"
+            landmarkName = "updateDeviceStatusDisplay(jsonDeviceStatus:)"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+   </Breakpoints>
 </Bucket>

+ 47 - 0
LoopFollow/Controllers/AlarmViewController.swift

@@ -44,6 +44,7 @@ class AlarmViewController: FormViewController {
     override func viewDidLoad() {
         super.viewDidLoad()
 
+        buildSnoozeAll()
         buildTemporaryAlert()
         buildUrgentLow()
         buildLow()
@@ -61,6 +62,52 @@ class AlarmViewController: FormViewController {
         
     }
 
+    func buildSnoozeAll(){
+        form
+            +++ Section(header: "Snooze All", footer: "Snooze All Alerts")
+        <<< DateTimeInlineRow("alertSnoozeAllTime") { row in
+            row.title = "Snooze All Until"
+            
+            if (UserDefaultsRepository.alertSnoozeAllTime.value != nil) {
+                row.value = UserDefaultsRepository.alertSnoozeAllTime.value
+            }
+            row.minuteInterval = 5
+            row.noValueDisplayText = "Not Snoozed"
+            }
+            .onChange { [weak self] row in
+                guard let value = row.value else { return }
+                UserDefaultsRepository.alertSnoozeAllTime.value = value
+                UserDefaultsRepository.alertSnoozeAllIsSnoozed.value = true
+                let otherRow = self?.form.rowBy(tag: "alertSnoozeAllIsSnoozed") as! SwitchRow
+                otherRow.value = true
+                otherRow.reload()
+            }
+            .onExpandInlineRow { [weak self] cell, row, inlineRow in
+                inlineRow.cellUpdate() { cell, row in
+                    cell.datePicker.datePickerMode = .dateAndTime
+                }
+                let color = cell.detailTextLabel?.textColor
+                row.onCollapseInlineRow { cell, _, _ in
+                    cell.detailTextLabel?.textColor = color
+                }
+                cell.detailTextLabel?.textColor = cell.tintColor
+        }
+            
+        <<< SwitchRow("alertSnoozeAllIsSnoozed"){ row in
+            row.title = "All Alerts Snoozed"
+            row.value = UserDefaultsRepository.alertSnoozeAllIsSnoozed.value
+            row.hidden = "$alertSnoozeAllTime == nil"
+        }.onChange { [weak self] row in
+                guard let value = row.value else { return }
+                UserDefaultsRepository.alertSnoozeAllIsSnoozed.value = value
+                if !value {
+                    UserDefaultsRepository.alertSnoozeAllTime.setNil(key: "alertSnoozeAllTime")
+                    let otherRow = self?.form.rowBy(tag: "alertSnoozeAllTime") as! DateTimeInlineRow
+                   otherRow.value = nil
+                   otherRow.reload()
+                }
+        }
+    }
     
     func buildTemporaryAlert(){
         form

+ 187 - 8
LoopFollow/Controllers/MainViewController.swift

@@ -29,6 +29,11 @@ class MainViewController: UIViewController, UITableViewDataSource {
         var direction: String?
     }
     
+    //NS Cage Struct
+    struct cageData: Codable {
+        var created_at: String
+    }
+    
     // Data Table Struct
     struct infoData {
         var name: String
@@ -194,6 +199,8 @@ class MainViewController: UIViewController, UITableViewDataSource {
             loadBGData(urlUser: urlUser, onlyPullLastRecord: onlyPullLastRecord)
             clearLastInfoData()
             loadDeviceStatus(urlUser: urlUser)
+            loadCage(urlUser: urlUser)
+            loadSage(urlUser: urlUser)
            // loadBoluses(urlUser: urlUser)
            // loadTempBasals(urlUser: urlUser)
         } else {
@@ -206,9 +213,11 @@ class MainViewController: UIViewController, UITableViewDataSource {
     
     // Post process new NS Data and feed all updates
     func ProcessNSBGData(data: [sgvData], onlyPullLastRecord: Bool){
+        var pullDate = data[data.count - 1].date / 1000
+        pullDate.round(FloatingPointRoundingRule.toNearestOrEven)
         if !onlyPullLastRecord {
             bgData.removeAll()
-        } else if bgData[bgData.count - 1].date != data[0].date {
+        } else if bgData[bgData.count - 1].date != pullDate {
             bgData.removeFirst()
         } else {
             self.updateBadge(entries: bgData)
@@ -302,7 +311,7 @@ class MainViewController: UIViewController, UITableViewDataSource {
             return
         }
         
-        if consoleLogging == true {print("entered 2nd task.")}
+        if consoleLogging == true {print("entered device status task.")}
         var requestDeviceStatus = URLRequest(url: urlDeviceStatus)
         requestDeviceStatus.cachePolicy = URLRequest.CachePolicy.reloadIgnoringLocalCacheData
         let deviceStatusTask = URLSession.shared.dataTask(with: requestDeviceStatus) { data, response, error in
@@ -385,6 +394,157 @@ class MainViewController: UIViewController, UITableViewDataSource {
         basalTask.resume()
     }
     
+    // Get last CAGE entry
+    func loadCage(urlUser: String) {
+        var urlString = urlUser + "/api/v1/treatments.json?find[eventType]=Site%20Change&count=1"
+        if token != "" {
+            urlString = urlUser + "/api/v1/treatments.json?token=" + token + "&find[eventType]=Site%20Change&count=1"
+        }
+        
+        guard let urlData = URL(string: urlString) else {
+            return
+        }
+        var request = URLRequest(url: urlData)
+        request.cachePolicy = URLRequest.CachePolicy.reloadIgnoringLocalCacheData
+        
+        let task = URLSession.shared.dataTask(with: request) { data, response, error in
+            if self.consoleLogging == true {print("start cage url")}
+            guard error == nil else {
+                return
+            }
+            guard let data = data else {
+                return
+            }
+            
+            let decoder = JSONDecoder()
+            let entriesResponse = try? decoder.decode([cageData].self, from: data)
+            if let entriesResponse = entriesResponse {
+                DispatchQueue.main.async {
+                    self.updateCage(data: entriesResponse)
+                }
+            }
+            else
+            {
+                
+                return
+            }
+        }
+        task.resume()
+    }
+    
+    // Parse Cage Data
+    func updateCage(data: [cageData]) {
+        if consoleLogging == true {print("in updateCage")}
+        if data.count == 0 {
+            return
+        }
+        
+        var lastCageString = data[0].created_at
+        
+        let formatter = ISO8601DateFormatter()
+        formatter.formatOptions = [.withFullDate,
+                                   .withTime,
+                                   .withDashSeparatorInDate,
+                                   .withColonSeparatorInTime]
+        if let cageTime = formatter.date(from: (lastCageString as! String))?.timeIntervalSince1970 {
+            let now = NSDate().timeIntervalSince1970
+            let secondsAgo = now - cageTime
+            let days = 24 * 60 * 60
+
+            let formatter = DateComponentsFormatter()
+            formatter.unitsStyle = .positional // Use the appropriate positioning for the current locale
+            formatter.allowedUnits = [ .hour, .minute ] // Units to display in the formatted string
+            formatter.zeroFormattingBehavior = [ .pad ] // Pad with zeroes where appropriate for the locale
+
+            let formattedDuration = formatter.string(from: secondsAgo)
+            tableData[8].value = formattedDuration ?? ""
+        }
+        infoTable.reloadData()
+
+   
+    }
+    
+    // Get last SAGE entry
+    func loadSage(urlUser: String) {
+        var dayComponent    = DateComponents()
+            dayComponent.day    = -10 // For removing 10 days
+            let theCalendar     = Calendar.current
+        
+        let startDate    = theCalendar.date(byAdding: dayComponent, to: Date())!
+            let dateFormatter = DateFormatter()
+            dateFormatter.dateFormat = "yyyy-MM-dd"
+        var startDateString = dateFormatter.string(from: startDate)
+
+        
+        var urlString = urlUser + "/api/v1/treatments.json?find[eventType]=Sensor%20Start&find[created_at][$gte]=2020-05-31&count=1"
+        if token != "" {
+            urlString = urlUser + "/api/v1/treatments.json?token=" + token + "&find[eventType]=Sensor%20Start&find[created_at][$gte]=2020-05-31&count=1"
+        }
+        
+        guard let urlData = URL(string: urlString) else {
+            return
+        }
+        var request = URLRequest(url: urlData)
+        request.cachePolicy = URLRequest.CachePolicy.reloadIgnoringLocalCacheData
+        
+        let task = URLSession.shared.dataTask(with: request) { data, response, error in
+            if self.consoleLogging == true {print("start cage url")}
+            guard error == nil else {
+                return
+            }
+            guard let data = data else {
+                return
+            }
+            
+            let decoder = JSONDecoder()
+            let entriesResponse = try? decoder.decode([cageData].self, from: data)
+            if let entriesResponse = entriesResponse {
+                DispatchQueue.main.async {
+                    self.updateSage(data: entriesResponse)
+                }
+            }
+            else
+            {
+                
+                return
+            }
+        }
+        task.resume()
+    }
+    
+    // Parse Sage Data
+    func updateSage(data: [cageData]) {
+        if consoleLogging == true {print("in updateSage")}
+        if data.count == 0 {
+            return
+        }
+        
+        var lastSageString = data[0].created_at
+        
+        let formatter = ISO8601DateFormatter()
+        formatter.formatOptions = [.withFullDate,
+                                    .withTime,
+                                    .withDashSeparatorInDate,
+                                    .withColonSeparatorInTime]
+        if let cageTime = formatter.date(from: (lastSageString as! String))?.timeIntervalSince1970 {
+            let now = NSDate().timeIntervalSince1970
+            let secondsAgo = now - cageTime
+            let days = 24 * 60 * 60
+
+            let formatter = DateComponentsFormatter()
+            formatter.unitsStyle = .positional // Use the appropriate positioning for the current locale
+        formatter.allowedUnits = [ .day, .hour] // Units to display in the formatted string
+            formatter.zeroFormattingBehavior = [ .pad ] // Pad with zeroes where appropriate for the locale
+
+            let formattedDuration = formatter.string(from: secondsAgo)
+            tableData[7].value = formattedDuration ?? ""
+        }
+        infoTable.reloadData()
+
+    
+    }
+    
+    
     func loadBoluses(urlUser: String){
         var calendar = Calendar.current
         let today = Date()
@@ -470,12 +630,12 @@ class MainViewController: UIViewController, UITableViewDataSource {
                 
             }
         }
-                
+            
+        // Loop
         if let lastLoopRecord = lastDeviceStatus?["loop"] as! [String : AnyObject]? {
             if let lastLoopTime = formatter.date(from: (lastLoopRecord["timestamp"] as! String))?.timeIntervalSince1970  {
                 if let failure = lastLoopRecord["failureReason"] {
-                    
-                    //LoopStatusText.text! += " Failure "
+                    tableData[6].value = "x"
                 }
                 else
                 {
@@ -495,6 +655,12 @@ class MainViewController: UIViewController, UITableViewDataSource {
                        // loopStatusText += " EBG " + bgOutputFormat(bg: prediction.last!, mmol: mmol)
                     }
                     
+                    if let loopStatus = lastLoopRecord["recommendedTempBasal"] as? [String:AnyObject] {
+                        tableData[6].value = "⏀"
+                    } else {
+                        tableData[6].value = "↻"
+                    }
+                    
                 }
             }
             
@@ -547,9 +713,9 @@ class MainViewController: UIViewController, UITableViewDataSource {
             let value = ChartDataEntry(x: Double(entries[i].date), y: Double(entries[i].sgv))
             bgChartEntry.append(value)
             
-            if Double(entries[i].sgv) >= Double(UserDefaultsRepository.alertHighBG.value) {
+            if Double(entries[i].sgv) >= Double(UserDefaultsRepository.highLine.value) {
                 colors.append(NSUIColor.yellow)
-            } else if Double(entries[i].sgv) <= Double(UserDefaultsRepository.alertLowBG.value) {
+            } else if Double(entries[i].sgv) <= Double(UserDefaultsRepository.lowLine.value) {
                 colors.append(NSUIColor.red)
             } else {
                 colors.append(NSUIColor.green)
@@ -671,7 +837,7 @@ class MainViewController: UIViewController, UITableViewDataSource {
             BGText.text = bgOutputFormat(bg: Double(latestBG), mmol: mmol)
             MinAgoText.text = String(Int(deltaTime)) + " min ago"
             print(String(Int(deltaTime)) + " min ago")
-            if let directionBG = entries[0].direction {
+            if let directionBG = entries[latestEntryi].direction {
                 DirectionText.text = bgDirectionGraphic(directionBG)
             }
             else
@@ -735,6 +901,11 @@ class MainViewController: UIViewController, UITableViewDataSource {
         
         clearOldSnoozes()
         
+        // Exit if all is snoozed
+        if UserDefaultsRepository.alertSnoozeAllIsSnoozed.value {
+            return
+        }
+        
         // BG Based Alarms
         // Check to make sure it is a current reading
         if now - currentBGTime <= (5*60) {
@@ -854,6 +1025,14 @@ class MainViewController: UIViewController, UITableViewDataSource {
         var needsReload: Bool = false
         guard let alarms = self.tabBarController!.viewControllers?[1] as? AlarmViewController else { return }
         
+        if date > UserDefaultsRepository.alertSnoozeAllTime.value ?? date {
+            UserDefaultsRepository.alertSnoozeAllTime.setNil(key: "alertSnoozeAllTime")
+            UserDefaultsRepository.alertSnoozeAllIsSnoozed.value = false
+            alarms.reloadSnoozeTime(key: "alertSnoozeAllTime", setNil: true)
+            alarms.reloadIsSnoozed(key: "alertSnoozeAllIsSnoozed", value: false)
+          
+        }
+        
         if date > UserDefaultsRepository.alertUrgentLowSnoozedTime.value ?? date {
             UserDefaultsRepository.alertUrgentLowSnoozedTime.setNil(key: "alertUrgentLowSnoozedTime")
             UserDefaultsRepository.alertUrgentLowIsSnoozed.value = false

+ 2 - 2
LoopFollow/Controllers/SettingsViewController.swift

@@ -72,7 +72,7 @@ class SettingsViewController: FormViewController {
                         
             }
             <<< StepperRow("lowLine") { row in
-                row.title = "Low Line Value"
+                row.title = "Low BG Display Value"
                 row.cell.stepper.stepValue = 1
                 row.cell.stepper.minimumValue = 150
                 row.cell.stepper.maximumValue = 400
@@ -86,7 +86,7 @@ class SettingsViewController: FormViewController {
                     UserDefaultsRepository.lowLine.value = Int(value)
             }
             <<< StepperRow("highLine") { row in
-                row.title = "High Line Value"
+                row.title = "High BG Display Value"
                 row.cell.stepper.stepValue = 1
                 row.cell.stepper.minimumValue = 150
                 row.cell.stepper.maximumValue = 400

+ 3 - 0
LoopFollow/repository/UserDefaults.swift

@@ -29,6 +29,9 @@ class UserDefaultsRepository {
     // Alarm Settings
     
     // Alerts
+    static let alertSnoozeAllTime = UserDefaultsValue<Date?>(key: "alertSnoozeAllTime", default: nil)
+    static let alertSnoozeAllIsSnoozed = UserDefaultsValue<Bool>(key: "alertSnoozeAllIsSnoozed", default: false)
+    
     static let alertUrgentLowActive = UserDefaultsValue<Bool>(key: "alertUrgentLowActive", default: true)
     static let alertUrgentLowBG = UserDefaultsValue<Int>(key: "alertUrgentLowBG", default: 55)
     static let alertUrgentLowSnooze = UserDefaultsValue<Int>(key: "alertUrgentLowSnooze", default: 5)