Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions Loop/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -343,17 +343,29 @@
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="!" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Nps-jD-4lb">
<rect key="frame" x="102" y="6" width="18" height="18"/>
<constraints>
<constraint firstAttribute="height" constant="18" id="FG3-dI-VYg"/>
<constraint firstAttribute="width" constant="18" id="emP-bu-bja"/>
</constraints>
<fontDescription key="fontDescription" style="UICTFontTextStyleCaption2"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" summaryElement="YES"/>
<bool key="isElement" value="YES"/>
</accessibility>
<constraints>
<constraint firstAttribute="trailing" secondItem="Nps-jD-4lb" secondAttribute="trailing" id="5OT-1d-znT"/>
<constraint firstItem="DKc-Kc-dgR" firstAttribute="top" secondItem="kbE-jN-1cR" secondAttribute="bottom" constant="1" id="9cW-4R-GGV"/>
<constraint firstAttribute="trailing" secondItem="01f-Du-MVi" secondAttribute="trailing" id="EbP-QZ-v2O"/>
<constraint firstItem="DKc-Kc-dgR" firstAttribute="leading" secondItem="hJo-df-An0" secondAttribute="leading" id="LaF-v9-myA"/>
<constraint firstItem="01f-Du-MVi" firstAttribute="leading" secondItem="hJo-df-An0" secondAttribute="leading" id="U9a-jl-mu7"/>
<constraint firstItem="Nps-jD-4lb" firstAttribute="top" secondItem="hJo-df-An0" secondAttribute="top" constant="6" id="Wbe-rN-XLL"/>
<constraint firstItem="01f-Du-MVi" firstAttribute="top" secondItem="hJo-df-An0" secondAttribute="top" constant="8" id="axM-gE-UZC"/>
<constraint firstAttribute="trailing" secondItem="kbE-jN-1cR" secondAttribute="trailing" id="mtr-Xt-FOr"/>
<constraint firstItem="kbE-jN-1cR" firstAttribute="leading" secondItem="hJo-df-An0" secondAttribute="leading" id="nOa-rB-64f"/>
Expand All @@ -362,6 +374,7 @@
<constraint firstAttribute="bottom" secondItem="DKc-Kc-dgR" secondAttribute="bottom" id="ygo-QQ-xlW"/>
</constraints>
<connections>
<outlet property="alertLabel" destination="Nps-jD-4lb" id="UQv-FW-Ut3"/>
<outlet property="caption" destination="DKc-Kc-dgR" id="8HE-Yf-fpz"/>
<outlet property="glucoseLabel" destination="01f-Du-MVi" id="XKI-xs-Avm"/>
<outlet property="unitLabel" destination="kbE-jN-1cR" id="xgn-g1-Ovf"/>
Expand Down
8 changes: 6 additions & 2 deletions Loop/Managers/DeviceDataManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ final class DeviceDataManager: CarbStoreDelegate, DoseStoreDelegate, Transmitter
}

var sensorInfo: SensorDisplayable? {
return latestGlucoseG5 ?? latestGlucoseG4 ?? latestPumpStatusFromMySentry
return latestGlucoseG5 ?? latestGlucoseG4 ?? latestGlucoseFromShare ?? latestPumpStatusFromMySentry
}

// MARK: - RileyLink
Expand Down Expand Up @@ -492,6 +492,8 @@ final class DeviceDataManager: CarbStoreDelegate, DoseStoreDelegate, Transmitter

private var latestGlucoseG5: xDripG5.Glucose?

private var latestGlucoseFromShare: ShareGlucose?

/**
Attempts to backfill glucose data from the share servers if a G5 connection hasn't been established.

Expand Down Expand Up @@ -519,6 +521,8 @@ final class DeviceDataManager: CarbStoreDelegate, DoseStoreDelegate, Transmitter
return
}

self.latestGlucoseFromShare = glucose.first

// Ignore glucose values that are up to a minute newer than our previous value, to account for possible time shifting in Share data
let newGlucose = glucose.filterDateRange(glucoseStore.latestGlucose?.startDate.dateByAddingTimeInterval(NSTimeInterval(minutes: 1)), nil).map {
return (quantity: $0.quantity, date: $0.startDate, isDisplayOnly: false)
Expand Down Expand Up @@ -560,7 +564,7 @@ final class DeviceDataManager: CarbStoreDelegate, DoseStoreDelegate, Transmitter
let includeAfter = glucoseStore.latestGlucose?.startDate.dateByAddingTimeInterval(NSTimeInterval(minutes: 1))

let validGlucose = glucoseHistory.flatMap({
$0.isValid ? $0 : nil
$0.isStateValid ? $0 : nil
}).filterDateRange(includeAfter, nil).map({
(quantity: $0.quantity, date: $0.startDate, isDisplayOnly: $0.isDisplayOnly)
})
Expand Down
4 changes: 4 additions & 0 deletions Loop/Models/Glucose.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import xDripG5


extension Glucose: SensorDisplayable {
var isStateValid: Bool {
return state == .OK && status == .OK
}

var stateDescription: String {
let status: String
switch self.status {
Expand Down
17 changes: 7 additions & 10 deletions Loop/Models/GlucoseG4.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,6 @@ import HealthKit
import LoopKit


extension GlucoseG4 {
var isValid: Bool {
return glucose >= 20
}
}


extension GlucoseG4: GlucoseValue {
public var quantity: HKQuantity {
return HKQuantity(unit: HKUnit.milligramsPerDeciliterUnit(), doubleValue: Double(glucose))
Expand All @@ -31,11 +24,15 @@ extension GlucoseG4: GlucoseValue {


extension GlucoseG4: SensorDisplayable {
var isStateValid: Bool {
return glucose >= 20
}

var stateDescription: String {
if isValid {
return "✓"
if isStateValid {
return NSLocalizedString("OK", comment: "Sensor state description for the valid state")
} else {
return String(format: "%02x", glucose)
return NSLocalizedString("Needs Attention", comment: "Sensor state description for the non-valid state")
}
}

Expand Down
10 changes: 4 additions & 6 deletions Loop/Models/MySentryPumpStatusMessageBody.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,12 @@ import MinimedKit


extension MySentryPumpStatusMessageBody: SensorDisplayable {
var stateDescription: String {
var isStateValid: Bool {
switch glucose {
case .Active:
return "✓"
case .Off:
return ""
case .Active, .Off:
return true
default:
return String(glucose)
return false
}
}

Expand Down
18 changes: 17 additions & 1 deletion Loop/Models/SensorDisplayable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,27 @@
// Copyright © 2016 Nathan Racklyeft. All rights reserved.
//

import Foundation


protocol SensorDisplayable {
// Describes the state of the sensor in the current localization
/// Returns whether the current state is valid
var isStateValid: Bool { get }

/// Describes the state of the sensor in the current localization
var stateDescription: String { get }

/// Enumerates the trend of the sensor values
var trendType: GlucoseTrend? { get }
}


extension SensorDisplayable {
var stateDescription: String {
if isStateValid {
return NSLocalizedString("OK", comment: "Sensor state description for the valid state")
} else {
return NSLocalizedString("Needs Attention", comment: "Sensor state description for the non-valid state")
}
}
}
11 changes: 11 additions & 0 deletions Loop/Models/ShareGlucose+GlucoseKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,14 @@ extension ShareGlucose: GlucoseValue {
return HKQuantity(unit: HKUnit.milligramsPerDeciliterUnit(), doubleValue: Double(glucose))
}
}


extension ShareGlucose: SensorDisplayable {
var isStateValid: Bool {
return glucose >= 20
}

var trendType: GlucoseTrend? {
return GlucoseTrend(rawValue: Int(trend))
}
}
43 changes: 33 additions & 10 deletions Loop/View Controllers/PredictionTableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

import UIKit
import HealthKit
import LoopKit


class PredictionTableViewController: UITableViewController, IdentifiableClass {

Expand Down Expand Up @@ -85,12 +87,6 @@ class PredictionTableViewController: UITableViewController, IdentifiableClass {

var dataManager: DeviceDataManager!

private var active = true {
didSet {
reloadData()
}
}

private lazy var charts: StatusChartsManager = {
let charts = StatusChartsManager()

Expand All @@ -102,6 +98,14 @@ class PredictionTableViewController: UITableViewController, IdentifiableClass {
return charts
}()

private var retrospectivePredictedGlucose: [GlucoseValue]?

private var active = true {
didSet {
reloadData()
}
}

private var needsRefresh = true

private var visible = false {
Expand Down Expand Up @@ -149,11 +153,12 @@ class PredictionTableViewController: UITableViewController, IdentifiableClass {
}

dispatch_group_enter(reloadGroup)
dataManager.loopManager.getLoopStatus { (predictedGlucose, _, _, _, _, _, error) in
dataManager.loopManager.getLoopStatus { (predictedGlucose, retrospectivePredictedGlucose, _, _, _, _, error) in
if error != nil {
self.needsRefresh = true
}

self.retrospectivePredictedGlucose = retrospectivePredictedGlucose
self.charts.predictedGlucoseValues = predictedGlucose ?? []

dispatch_group_leave(reloadGroup)
Expand All @@ -180,7 +185,7 @@ class PredictionTableViewController: UITableViewController, IdentifiableClass {
self.charts.prerender()

self.tableView.reloadSections(NSIndexSet(indexesInRange: NSMakeRange(Section.charts.rawValue, 1)),
withRowAnimation: animated ? .Fade : .None
withRowAnimation: .None
)

self.reloading = false
Expand Down Expand Up @@ -242,11 +247,29 @@ class PredictionTableViewController: UITableViewController, IdentifiableClass {
let (input, selected) = selectedInputs[indexPath.row]

cell.titleLabel?.text = input.localizedTitle
cell.subtitleLabel?.text = input.localizedDescription(forGlucoseUnit: charts.glucoseUnit)
cell.accessoryType = selected ? .Checkmark : .None

cell.enabled = input != .retrospection || dataManager.loopManager.retrospectiveCorrectionEnabled

var subtitleText = input.localizedDescription(forGlucoseUnit: charts.glucoseUnit)

if input == .retrospection,
let startGlucose = retrospectivePredictedGlucose?.first,
let endGlucose = retrospectivePredictedGlucose?.last,
let currentGlucose = self.dataManager.glucoseStore?.latestGlucose
{
let formatter = NSNumberFormatter.glucoseFormatter(for: charts.glucoseUnit)
let values = [startGlucose, endGlucose, currentGlucose].map { formatter.stringFromNumber($0.quantity.doubleValueForUnit(charts.glucoseUnit)) ?? "?" }

let retro = String(
format: NSLocalizedString("Last comparison: %1$@ → %2$@ vs %3$@", comment: "Format string describing retrospective glucose prediction comparison. (1: Previous glucose)(2: Predicted glucose)(3: Actual glucose)"),
values[0], values[1], values[2]
)

subtitleText = String(format: "%@\n%@", subtitleText, retro)
}

cell.subtitleLabel?.text = subtitleText

cell.contentView.layoutMargins.left = tableView.separatorInset.left

return cell
Expand Down
48 changes: 2 additions & 46 deletions Loop/View Controllers/StatusTableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,6 @@ final class StatusTableViewController: UITableViewController, UIGestureRecognize
needsRefresh = false
reloading = true

tableView.reloadSections(NSIndexSet(indexesInRange: NSMakeRange(Section.Sensor.rawValue, Section.count - Section.Sensor.rawValue)
), withRowAnimation: visible ? .Automatic : .None)

let calendar = NSCalendar.currentCalendar()
let components = NSDateComponents()
components.minute = 0
Expand Down Expand Up @@ -265,9 +262,8 @@ final class StatusTableViewController: UITableViewController, UIGestureRecognize
private enum Section: Int {
case Charts = 0
case Status
case Sensor

static let count = 3
static let count = 2
}

// MARK: - Chart Section Data
Expand Down Expand Up @@ -367,32 +363,10 @@ final class StatusTableViewController: UITableViewController, UIGestureRecognize

// MARK: - Pump/Sensor Section Data

private enum SensorRow: Int {
case State

static let count = 1
}

private lazy var emptyValueString: String = NSLocalizedString("––",
comment: "The detail value of a numeric cell with no value"
)

private lazy var dateComponentsFormatter: NSDateComponentsFormatter = {
let formatter = NSDateComponentsFormatter()
formatter.unitsStyle = .Short

return formatter
}()

private lazy var numberFormatter = NSNumberFormatter()

private lazy var dateFormatter: NSDateFormatter = {
let formatter = NSDateFormatter()
formatter.dateStyle = .MediumStyle
formatter.timeStyle = .MediumStyle
return formatter
}()

private lazy var timeFormatter: NSDateFormatter = {
let formatter = NSDateFormatter()
formatter.dateStyle = .NoStyle
Expand All @@ -413,8 +387,6 @@ final class StatusTableViewController: UITableViewController, UIGestureRecognize
return ChartRow.count
case .Status:
return StatusRow.count
case .Sensor:
return SensorRow.count
}
}

Expand Down Expand Up @@ -483,18 +455,6 @@ final class StatusTableViewController: UITableViewController, UIGestureRecognize
}
}

return cell
case .Sensor:
let cell = tableView.dequeueReusableCellWithIdentifier(UITableViewCell.className, forIndexPath: indexPath)
cell.selectionStyle = .None

switch SensorRow(rawValue: indexPath.row)! {
case .State:
cell.textLabel?.text = NSLocalizedString("Sensor State", comment: "The title of the cell containing the current sensor state")

cell.detailTextLabel?.text = dataManager.sensorInfo?.stateDescription ?? emptyValueString
}

return cell
}
}
Expand All @@ -510,7 +470,7 @@ final class StatusTableViewController: UITableViewController, UIGestureRecognize
case .IOB, .Dose, .COB:
return 85
}
case .Status, .Sensor:
case .Status:
return UITableViewAutomaticDimension
}
}
Expand Down Expand Up @@ -548,10 +508,6 @@ final class StatusTableViewController: UITableViewController, UIGestureRecognize
}
}
}
case .Sensor:
if let URL = NSURL(string: "dexcomcgm://") {
UIApplication.sharedApplication().openURL(URL)
}
}
}

Expand Down
Loading