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
2 changes: 1 addition & 1 deletion Cartfile.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ github "loudnate/LoopKit" "66d8730823e33093635b2d57f48434f1fafeaada"
github "loudnate/SwiftCharts" "f3e61c6193f3c19ec6b05941cdd1ba031722f461"
github "mddub/dexcom-share-client-swift" "v0.1.3"
github "loudnate/xDripG5" "0.5.0"
github "ps2/rileylink_ios" "c948f4895507b4738e028d792ffc89b08a6a72c4"
github "ps2/rileylink_ios" "6010257f7b71f0c4dfabc2f5d34206d08975e112"
Binary file modified Carthage/Build/iOS/MinimedKit.framework/MinimedKit
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified Carthage/Build/iOS/RileyLinkBLEKit.framework/RileyLinkBLEKit
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified Carthage/Build/iOS/RileyLinkKit.framework/RileyLinkKit
Binary file not shown.
6 changes: 6 additions & 0 deletions Loop.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@
43F78D591C914C57002152D1 /* recommend_temp_basal_high_and_falling.json in Resources */ = {isa = PBXBuildFile; fileRef = 43F78D581C914C57002152D1 /* recommend_temp_basal_high_and_falling.json */; };
43F78D5B1C914CAB002152D1 /* recommend_temp_basal_in_range_and_rising.json in Resources */ = {isa = PBXBuildFile; fileRef = 43F78D5A1C914CAB002152D1 /* recommend_temp_basal_in_range_and_rising.json */; };
43F78D5D1C914CEA002152D1 /* recommend_temp_basal_high_and_rising.json in Resources */ = {isa = PBXBuildFile; fileRef = 43F78D5C1C914CEA002152D1 /* recommend_temp_basal_high_and_rising.json */; };
C10428971D17BAD400DD539A /* NightscoutUploadKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C10428961D17BAD400DD539A /* NightscoutUploadKit.framework */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -317,6 +318,7 @@
43F78D581C914C57002152D1 /* recommend_temp_basal_high_and_falling.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = recommend_temp_basal_high_and_falling.json; sourceTree = "<group>"; };
43F78D5A1C914CAB002152D1 /* recommend_temp_basal_in_range_and_rising.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = recommend_temp_basal_in_range_and_rising.json; sourceTree = "<group>"; };
43F78D5C1C914CEA002152D1 /* recommend_temp_basal_high_and_rising.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = recommend_temp_basal_high_and_rising.json; sourceTree = "<group>"; };
C10428961D17BAD400DD539A /* NightscoutUploadKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NightscoutUploadKit.framework; path = Carthage/Build/iOS/NightscoutUploadKit.framework; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand All @@ -331,6 +333,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
C10428971D17BAD400DD539A /* NightscoutUploadKit.framework in Frameworks */,
439897391CD2F82C00223065 /* AmplitudeFramework.framework in Frameworks */,
43F78D4C1C914197002152D1 /* CarbKit.framework in Frameworks */,
43EDDBF21C361C75007D89B5 /* CommonCrypto.framework in Frameworks */,
Expand Down Expand Up @@ -604,6 +607,7 @@
968DCD53F724DE56FFE51920 /* Frameworks */ = {
isa = PBXGroup;
children = (
C10428961D17BAD400DD539A /* NightscoutUploadKit.framework */,
43B371871CE597D10013C5A6 /* ShareClient.framework */,
439897381CD2F82C00223065 /* AmplitudeFramework.framework */,
43F78D481C914197002152D1 /* CarbKit.framework */,
Expand Down Expand Up @@ -846,6 +850,8 @@
"$(SRCROOT)/Carthage/Build/iOS/RileyLinkKit.framework",
"$(SRCROOT)/Carthage/Build/iOS/AmplitudeFramework.framework",
"$(SRCROOT)/Carthage/Build/iOS/ShareClient.framework",
"$(SRCROOT)/Carthage/Build/iOS/NightscoutUploadKit.framework",
"$(SRCROOT)/Carthage/Build/iOS/Crypto.framework",
);
outputPaths = (
);
Expand Down
75 changes: 62 additions & 13 deletions Loop/Managers/DeviceDataManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import MinimedKit
import RileyLinkKit
import ShareClient
import xDripG5
import NightscoutUploadKit

enum State<T> {
case NeedsConfiguration
Expand All @@ -40,6 +41,13 @@ class DeviceDataManager: CarbStoreDelegate, TransmitterDelegate {
/// The share server client
private let shareClient: ShareClient?

/// Nightscout Uploader
var nightscoutUploader: NightscoutUploader?

// Timestamp of last event we've retrieved from pump
var observingPumpEventsSince: NSDate = NSDate().dateByAddingTimeInterval(60*60*24*(-1))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NSDate(timeIntervalSinceNow: NSTimeInterval(hours: -24))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And you can remove the explicit type : NSDate

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think your extension is available in Loop

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind, it looks like it is; typo



/// The G5 transmitter object
var transmitter: Transmitter? {
switch transmitterState {
Expand All @@ -58,7 +66,7 @@ class DeviceDataManager: CarbStoreDelegate, TransmitterDelegate {

/**
Called when a new idle message is received by the RileyLink.

Only MySentryPumpStatus messages are handled.

- parameter note: The notification object
Expand Down Expand Up @@ -115,7 +123,7 @@ class DeviceDataManager: CarbStoreDelegate, TransmitterDelegate {

/**
Handles receiving a MySentry status message, which are only posted by MM x23 pumps.

This message has two important pieces of info about the pump: reservoir volume and battery.

Because the RileyLink must actively listen for these packets, they are not the most reliable heartbeat. However, we can still use them to assert glucose data is current.
Expand Down Expand Up @@ -144,6 +152,8 @@ class DeviceDataManager: CarbStoreDelegate, TransmitterDelegate {
if status.batteryRemainingPercent == 0 {
NotificationManager.sendPumpBatteryLowNotification()
}

nightscoutUploader?.handlePumpStatus(status, device: device.deviceURI)
}

/**
Expand Down Expand Up @@ -214,27 +224,50 @@ class DeviceDataManager: CarbStoreDelegate, TransmitterDelegate {
}

private func fetchPumpHistory() {

guard let device = rileyLinkManager.firstConnectedDevice else {
return
}

/*
This is where we fetch history.
*/
*/

let startDate = doseStore.pumpEventQueryAfterDate
// TODO: Reconcile these
//let startDate = doseStore.pumpEventQueryAfterDate
let startDate = nightscoutUploader?.observingPumpEventsSince ?? observingPumpEventsSince

device.ops?.getHistoryEventsSinceDate(startDate) { (result) in
switch result {
case let .Success(events, _):
case let .Success(events, pumpModel):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed this in a coming PR, since pumpModel ends up just returning the value set to device.ops?.pumpState.pumpModel

// TODO: Surface raw pump event data and add DoseEntry conformance
self.doseStore.addPumpEvents(events.map({ ($0.date, nil, nil, $0.isMutable()) })) { (error) in
if let error = error {
self.logger?.addError("Failed to store history: \(error)", fromSource: "DoseStore")
}
// self.doseStore.addPumpEvents(events.map({ ($0.date, nil, nil, $0.isMutable()) })) { (error) in
// if let error = error {
// self.logger?.addError("Failed to store history: \(error)", fromSource: "DoseStore")
// }
// }

NSNotificationCenter.defaultCenter().postNotificationName(self.dynamicType.PumpStatusUpdatedNotification, object: self)
self.nightscoutUploader?.processPumpEvents(events, source: device.deviceURI, pumpModel: pumpModel)


var lastFinalDate: NSDate?
var firstMutableDate: NSDate?

NSNotificationCenter.defaultCenter().postNotificationName(self.dynamicType.PumpStatusUpdatedNotification, object: self)
for event in events {
if event.isMutable() {
firstMutableDate = min(event.date, firstMutableDate ?? event.date)
} else {
lastFinalDate = max(event.date, lastFinalDate ?? event.date)
}
}
if let mutableDate = firstMutableDate {
self.observingPumpEventsSince = mutableDate
} else if let finalDate = lastFinalDate {
self.observingPumpEventsSince = finalDate
}


case .Failure(let error):
self.logger?.addError("Failed to fetch history: \(error)", fromSource: "RileyLink")
self.troubleshootPumpCommsWithDevice(device)
Expand All @@ -248,6 +281,7 @@ class DeviceDataManager: CarbStoreDelegate, TransmitterDelegate {
- parameter device: The RileyLink device
*/
private func troubleshootPumpCommsWithDevice(device: RileyLinkDevice) {

// How long we should wait before we re-tune the RileyLink
let tuneTolerance = NSTimeInterval(minutes: 14)

Expand Down Expand Up @@ -393,6 +427,8 @@ class DeviceDataManager: CarbStoreDelegate, TransmitterDelegate {
self.pumpState = nil
}

nightscoutUploader?.pumpID = pumpID

doseStore.pumpID = pumpID

NSUserDefaults.standardUserDefaults().pumpID = pumpID
Expand Down Expand Up @@ -481,7 +517,7 @@ class DeviceDataManager: CarbStoreDelegate, TransmitterDelegate {
ID: transmitterID,
startTimeInterval: NSUserDefaults.standardUserDefaults().transmitterStartTime,
passiveModeEnabled: true
))
))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary indent here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's where xcode puts it. I can move it if you want.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting, but it re-indented it even when code around it didn't change? Not a big deal. I think Xcode needs to get with it.

case (.Ready, .None):
transmitterState = .NeedsConfiguration
case (.Ready(let transmitter), let transmitterID?):
Expand Down Expand Up @@ -637,15 +673,28 @@ class DeviceDataManager: CarbStoreDelegate, TransmitterDelegate {
rileyLinkManager.idleListeningEnabled = idleListeningEnabled

if let settings = NSBundle.mainBundle().remoteSettings,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's two spaces in let settings so it aligns with the variables below it; if we move those indents up, we should move this back to one space: let settings.

username = settings["ShareAccountName"],
password = settings["ShareAccountPassword"]
username = settings["ShareAccountName"],
password = settings["ShareAccountPassword"]
where !username.isEmpty && !password.isEmpty
{
shareClient = ShareClient(username: username, password: password)
} else {
shareClient = nil
}

if let settings = NSBundle.mainBundle().remoteSettings,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra space between let and settings

siteURL = settings["NightscoutSiteURL"],
APISecret = settings["NightscoutAPISecret"]
{
nightscoutUploader = NightscoutUploader(siteURL: siteURL, APISecret: APISecret, pumpID: pumpID)
nightscoutUploader!.errorHandler = { (error: ErrorType, context: String) -> Void in
print("Error \(error), while \(context)")
}

} else {
nightscoutUploader = nil
}

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(receivedRileyLinkManagerNotification(_:)), name: nil, object: rileyLinkManager)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(receivedRileyLinkPacketNotification(_:)), name: RileyLinkDevice.DidReceiveIdleMessageNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(receivedRileyLinkTimerTickNotification(_:)), name: RileyLinkDevice.DidUpdateTimerTickNotification, object: nil)
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ In the Loop project's Build Settings, change the value of `MAIN_APP_BUNDLE_IDENT

Loop optionally supports select third-party remote services. While none of them are required to run the app, including [mLab](https://mlab.com) keys is strongly recommended at this time so loop diagnostic data can be stored in case retrospective analysis is needed.

If the Nightscout related entries are included, treatments and other pump data will be uploaded to your Nightscout site. Note you will need to set "Insulin Data Source" to "History" in Settings for treatments to be fetched from your pump and uploaded to Nightscout.

After a fresh clone of the repository, you'll need duplicate the template file and populate the copy with values.

```bash
Expand All @@ -93,6 +95,8 @@ $ cp Loop/RemoteSettings-template.plist Loop/RemoteSettings.plist
| `AmplitudeAPIKey` | Your Amplitude analytics API Key (for optional, private behavior tracking)
| `ShareAccountName` | Your username for Dexcom share (for backfilling glucose data)
| `ShareAccountPassword` | Your password for Dexcom share
| `NightscoutSiteURL` | Your Nightscout site URL
| `NightscoutAPISecret` | Your Nightscout API Secret (not hashed)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI I'm going to migrate these all eventually (rather than storing in plain text in the app bundle)
#35


# Making it Your Own

Expand Down