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
6 changes: 3 additions & 3 deletions Cartfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
github "loudnate/LoopKit" ~> 0.8.0
github "loudnate/xDripG5" ~> 0.7.0
github "LoopKit/LoopKit" ~> 1.0
github "LoopKit/xDripG5" ~> 0.8.0
github "i-schuetz/SwiftCharts" ~> 0.5.0
github "mddub/dexcom-share-client-swift" ~> 0.2.0
github "mddub/G4ShareSpy" ~> 0.3.0
github "ps2/rileylink_ios" ~> 0.12.3
github "ps2/rileylink_ios" ~> 0.12.4
github "amplitude/Amplitude-iOS" ~> 3.8.5
6 changes: 3 additions & 3 deletions Cartfile.resolved
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
github "amplitude/Amplitude-iOS" "v3.8.5"
github "mddub/G4ShareSpy" "v0.3.0"
github "loudnate/LoopKit" "v0.8.0"
github "LoopKit/LoopKit" "v1.0"
github "i-schuetz/SwiftCharts" "0.5"
github "mddub/dexcom-share-client-swift" "v0.2.0"
github "ps2/rileylink_ios" "v0.12.3"
github "loudnate/xDripG5" "v0.7.0"
github "ps2/rileylink_ios" "v0.12.4"
github "LoopKit/xDripG5" "v0.8.0"
Binary file modified Carthage/Build/iOS/CarbKit.framework/CarbKit
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/CarbKit.framework/Info.plist
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 not shown.
Binary file not shown.
Binary file not shown.
Binary file modified Carthage/Build/iOS/Crypto.framework/Crypto
Binary file not shown.
Binary file modified Carthage/Build/iOS/Crypto.framework/Info.plist
Binary file not shown.
Binary file modified Carthage/Build/iOS/GlucoseKit.framework/GlucoseKit
Binary file not shown.
Binary file modified Carthage/Build/iOS/GlucoseKit.framework/Info.plist
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 not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified Carthage/Build/iOS/InsulinKit.framework/Info.plist
Binary file not shown.
Binary file modified Carthage/Build/iOS/InsulinKit.framework/InsulinKit
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 not shown.
Binary file not shown.
Binary file not shown.
Binary file modified Carthage/Build/iOS/LoopKit.framework/Assets.car
Binary file not shown.
Binary file not shown.
Binary file modified Carthage/Build/iOS/LoopKit.framework/GlucoseRangeTableViewCell.nib
Binary file not shown.
Binary file modified Carthage/Build/iOS/LoopKit.framework/Info.plist
Binary file not shown.
Binary file modified Carthage/Build/iOS/LoopKit.framework/LoopKit
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/LoopKit.framework/TextFieldTableViewCell.nib
Binary file not shown.
Binary file modified Carthage/Build/iOS/MinimedKit.framework/Info.plist
Binary file not shown.
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.
Binary file modified Carthage/Build/iOS/NightscoutUploadKit.framework/Info.plist
Binary file not shown.
Binary file not shown.
Binary file modified Carthage/Build/iOS/RileyLinkBLEKit.framework/Info.plist
Binary file not shown.
Binary file modified Carthage/Build/iOS/RileyLinkBLEKit.framework/RileyLinkBLEKit
Binary file not shown.
Binary file modified Carthage/Build/iOS/RileyLinkKit.framework/Info.plist
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.
Binary file not shown.
Binary file modified Carthage/Build/iOS/xDripG5.framework/Info.plist
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/xDripG5.framework/xDripG5
Binary file not shown.
2 changes: 1 addition & 1 deletion DoseMathTests/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>0.13.0</string>
<string>1.0rc1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
Expand Down
3 changes: 3 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
With exceptions for frameworks and graphics, noted below.

Copyright (c) 2015 Nathan Racklyeft
Copyright (c) 2016 LoopKit Authors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -37,6 +38,7 @@ Copyright (c) 2016 Mark Wilson
*Including CarbKit.framework, GlucoseKit.framework, and InsulinKit.framework*

Copyright (c) 2015 Nathan Racklyeft
Copyright (c) 2016 LoopKit Authors

## RileyLinkKit.framework
*Including MinimedKit.framework, NightscoutUploadKit.framework, and RileyLinkBLEKit.framework*
Expand All @@ -54,6 +56,7 @@ Copyright (c) 2016 Mark Wilson
## xDripG5.framework

Copyright (c) 2015 Nathan Racklyeft
Copyright (c) 2016 LoopKit Authors

> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
Expand Down
69 changes: 40 additions & 29 deletions Loop.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

35 changes: 16 additions & 19 deletions Loop/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

import UIKit
import UserNotifications
import CarbKit
import InsulinKit

Expand All @@ -20,7 +21,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window?.tintColor = UIColor.tintColor

NotificationManager.authorize()
NotificationManager.authorize(delegate: self)

AnalyticsManager.sharedManager.application(application, didFinishLaunchingWithOptions: launchOptions)

Expand Down Expand Up @@ -60,27 +61,25 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {

}

// MARK: - Notifications
// MARK: - 3D Touch

func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
if application.applicationState == .active {
if let message = notification.alertBody {
window?.rootViewController?.presentAlertController(withTitle: notification.alertTitle, message: message, animated: true, completion: nil)
}
}
func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
completionHandler(false)
}
}

func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, for notification: UILocalNotification, withResponseInfo responseInfo: [AnyHashable: Any], completionHandler: @escaping () -> Void) {

switch identifier {
case NotificationManager.Action.RetryBolus.rawValue?:
if let units = notification.userInfo?[NotificationManager.UserInfoKey.BolusAmount.rawValue] as? Double,
let startDate = notification.userInfo?[NotificationManager.UserInfoKey.BolusStartDate.rawValue] as? Date,
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
switch response.actionIdentifier {
case NotificationManager.Action.RetryBolus.rawValue:
if let units = response.notification.request.content.userInfo[NotificationManager.UserInfoKey.BolusAmount.rawValue] as? Double,
let startDate = response.notification.request.content.userInfo[NotificationManager.UserInfoKey.BolusStartDate.rawValue] as? Date,
startDate.timeIntervalSinceNow >= TimeInterval(minutes: -5)
{
AnalyticsManager.sharedManager.didRetryBolus()

dataManager.enactBolus(units) { (error) in
dataManager.enactBolus(units: units) { (error) in
if error != nil {
NotificationManager.sendBolusFailureNotificationForAmount(units, atStartDate: startDate)
}
Expand All @@ -92,13 +91,11 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
default:
break
}

completionHandler()
}

// MARK: - 3D Touch

func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
completionHandler(false)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.badge, .sound, .alert])
}
}
4 changes: 2 additions & 2 deletions Loop/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="guo-4Z-RoO"/>
</subviews>
<constraints>
<constraint firstItem="moR-fS-DWR" firstAttribute="leading" secondItem="D0A-EB-kmz" secondAttribute="leadingMargin" constant="7" id="3Zc-7R-Uft"/>
<constraint firstItem="moR-fS-DWR" firstAttribute="leading" secondItem="D0A-EB-kmz" secondAttribute="leadingMargin" id="3Zc-7R-Uft"/>
<constraint firstItem="moR-fS-DWR" firstAttribute="top" secondItem="D0A-EB-kmz" secondAttribute="topMargin" id="Sa2-TB-EcZ"/>
<constraint firstAttribute="trailingMargin" secondItem="guo-4Z-RoO" secondAttribute="trailing" constant="7" id="gb5-W2-roe"/>
<constraint firstAttribute="trailingMargin" secondItem="guo-4Z-RoO" secondAttribute="trailing" id="gb5-W2-roe"/>
<constraint firstAttribute="bottomMargin" secondItem="moR-fS-DWR" secondAttribute="bottom" priority="750" id="j5I-H8-Otk"/>
<constraint firstItem="guo-4Z-RoO" firstAttribute="leading" secondItem="moR-fS-DWR" secondAttribute="trailing" constant="8" symbolic="YES" id="tzW-RW-90H"/>
<constraint firstItem="guo-4Z-RoO" firstAttribute="centerY" secondItem="D0A-EB-kmz" secondAttribute="centerY" id="w98-m4-irJ"/>
Expand Down
File renamed without changes.
30 changes: 0 additions & 30 deletions Loop/Extensions/NSData.swift

This file was deleted.

12 changes: 12 additions & 0 deletions Loop/Extensions/NSUserDefaults.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import Foundation
import LoopKit
import MinimedKit


extension UserDefaults {
Expand All @@ -27,6 +28,7 @@ extension UserDefaults {
case PreferredInsulinDataSource = "com.loudnate.Loop.PreferredInsulinDataSource"
case PumpID = "com.loudnate.Naterade.PumpID"
case PumpModelNumber = "com.loudnate.Naterade.PumpModelNumber"
case PumpRegion = "com.loopkit.Loop.PumpRegion"
case PumpTimeZone = "com.loudnate.Naterade.PumpTimeZone"
case RetrospectiveCorrectionEnabled = "com.loudnate.Loop.RetrospectiveCorrectionEnabled"
}
Expand Down Expand Up @@ -177,6 +179,16 @@ extension UserDefaults {
}
}

var pumpRegion: PumpRegion? {
get {
// Defaults to 0 / northAmerica
return PumpRegion(rawValue: integer(forKey: Key.PumpRegion.rawValue))
}
set {
set(newValue?.rawValue, forKey: Key.PumpRegion.rawValue)
}
}

var pumpTimeZone: TimeZone? {
get {
if let offset = object(forKey: Key.PumpTimeZone.rawValue) as? NSNumber {
Expand Down
2 changes: 1 addition & 1 deletion Loop/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.13.0</string>
<string>1.0rc1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
Expand Down
62 changes: 46 additions & 16 deletions Loop/Managers/DeviceDataManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ final class DeviceDataManager: CarbStoreDelegate, DoseStoreDelegate, Transmitter
AnalyticsManager.sharedManager.didChangeRileyLinkConnectionState()

if connectedPeripheralIDs.count == 0 {
NotificationManager.clearLoopNotRunningNotifications()
NotificationManager.clearPendingNotificationRequests()
}
}

Expand Down Expand Up @@ -360,13 +360,12 @@ final class DeviceDataManager: CarbStoreDelegate, DoseStoreDelegate, Transmitter
}
}

/**
Send a bolus command and handle the result

- parameter completion: A closure called after the command is complete. This closure takes a single argument:
- error: An error describing why the command failed
*/
func enactBolus(_ units: Double, completion: @escaping (_ error: Error?) -> Void) {
/// Send a bolus command and handle the result
///
/// - parameter units: The number of units to deliver
/// - parameter completion: A clsure called after the command is complete. This closure takes a single argument:
/// - error: An error describing why the command failed
func enactBolus(units: Double, completion: @escaping (_ error: Error?) -> Void) {
guard units > 0 else {
completion(nil)
return
Expand Down Expand Up @@ -442,9 +441,7 @@ final class DeviceDataManager: CarbStoreDelegate, DoseStoreDelegate, Transmitter
}

// MARK: - G5 Transmitter
/**
The G5 transmitter is a reliable heartbeat by which we can assert the loop state.
*/
/// The G5 transmitter is a reliable heartbeat by which we can assert the loop state.

// MARK: TransmitterDelegate

Expand Down Expand Up @@ -485,11 +482,19 @@ final class DeviceDataManager: CarbStoreDelegate, DoseStoreDelegate, Transmitter
}
}

public func transmitter(_ transmitter: Transmitter, didReadUnknownData data: Data) {
logger.addMessage([
"unknownData": data.hexadecimalString,
"collectedAt": DateFormatter.ISO8601StrictDateFormatter().string(from: Date())
], toCollection: "g5"
)
}

// MARK: G5 data

private var latestGlucoseG5: xDripG5.Glucose?
fileprivate var latestGlucoseG5: xDripG5.Glucose?

private var latestGlucoseFromShare: ShareGlucose?
fileprivate var latestGlucoseFromShare: ShareGlucose?

/**
Attempts to backfill glucose data from the share servers if a G5 connection hasn't been established.
Expand Down Expand Up @@ -543,7 +548,7 @@ final class DeviceDataManager: CarbStoreDelegate, DoseStoreDelegate, Transmitter

// MARK: ReceiverDelegate

private var latestGlucoseG4: GlucoseG4?
fileprivate var latestGlucoseG4: GlucoseG4?

func receiver(_ receiver: Receiver, didReadGlucoseHistory glucoseHistory: [GlucoseG4]) {
assertCurrentPumpData()
Expand Down Expand Up @@ -613,7 +618,7 @@ final class DeviceDataManager: CarbStoreDelegate, DoseStoreDelegate, Transmitter
var pumpID = newValue

if let pumpID = pumpID, pumpID.characters.count == 6 {
let pumpState = PumpState(pumpID: pumpID, pumpRegion: .northAmerica)
let pumpState = PumpState(pumpID: pumpID, pumpRegion: self.pumpState?.pumpRegion ?? .northAmerica)

if let timeZone = self.pumpState?.timeZone {
pumpState.timeZone = timeZone
Expand Down Expand Up @@ -674,6 +679,8 @@ final class DeviceDataManager: CarbStoreDelegate, DoseStoreDelegate, Transmitter
}

UserDefaults.standard.pumpModelNumber = pumpState?.pumpModel?.rawValue
case "pumpRegion"?:
UserDefaults.standard.pumpRegion = pumpState?.pumpRegion
case "lastHistoryDump"?, "awakeUntil"?:
break
default:
Expand Down Expand Up @@ -884,14 +891,15 @@ final class DeviceDataManager: CarbStoreDelegate, DoseStoreDelegate, Transmitter
)

carbStore = CarbStore(
defaultAbsorptionTimes: (fast: TimeInterval(hours: 2), medium: TimeInterval(hours: 3), slow: TimeInterval(hours: 4)),
carbRatioSchedule: carbRatioSchedule,
insulinSensitivitySchedule: insulinSensitivitySchedule
)

var idleListeningEnabled = true

if let pumpID = pumpID {
let pumpState = PumpState(pumpID: pumpID, pumpRegion: .northAmerica)
let pumpState = PumpState(pumpID: pumpID, pumpRegion: UserDefaults.standard.pumpRegion ?? .northAmerica)

if let timeZone = UserDefaults.standard.pumpTimeZone {
pumpState.timeZone = timeZone
Expand Down Expand Up @@ -944,6 +952,28 @@ final class DeviceDataManager: CarbStoreDelegate, DoseStoreDelegate, Transmitter
}


extension DeviceDataManager: CustomDebugStringConvertible {
var debugDescription: String {
return [
"## DeviceDataManager",
"receiverEnabled: \(receiverEnabled)",
"latestPumpStatusFromMySentry: \(latestPumpStatusFromMySentry)",
"latestGlucoseG5: \(latestGlucoseG5)",
"latestGlucoseFromShare: \(latestGlucoseFromShare)",
"latestGlucoseG4: \(latestGlucoseG4)",
"pumpState: \(String(reflecting: pumpState))",
"preferredInsulinDataSource: \(preferredInsulinDataSource)",
"transmitterID: \(transmitterID)",
"glucoseTargetRangeSchedule: \(glucoseTargetRangeSchedule?.debugDescription ?? "")",
"workoutModeEnabled: \(workoutModeEnabled)",
"maximumBasalRatePerHour: \(maximumBasalRatePerHour)",
"maximumBolus: \(maximumBolus)",
String(reflecting: rileyLinkManager)
].joined(separator: "\n")
}
}


extension Notification.Name {
/// Notification posted by the instance when new glucose data was processed
static let GlucoseUpdated = Notification.Name(rawValue: "com.loudnate.Naterade.notification.GlucoseUpdated")
Expand Down
24 changes: 24 additions & 0 deletions Loop/Managers/LoopDataManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,30 @@ final class LoopDataManager {
}


extension LoopDataManager {
/// Generates a diagnostic report about the current state
///
/// This operation is performed asynchronously and the completion will be executed on an arbitrary background queue.
///
/// - parameter completionHandler: A closure called once the report has been generated. The closure takes a single argument of the report string.
func generateDiagnosticReport(_ completionHandler: @escaping (_ report: String) -> Void) {
getLoopStatus { (predictedGlucose, retrospectivePredictedGlucose, recommendedTempBasal, lastTempBasal, lastLoopCompleted, insulinOnBoard, error) in
let report = [
"## LoopDataManager",
"predictedGlucose: \(predictedGlucose ?? [])",
"retrospectivePredictedGlucose: \(retrospectivePredictedGlucose ?? [])",
"recommendedTempBasal: \(recommendedTempBasal)",
"lastTempBasal: \(lastTempBasal)",
"lastLoopCompleted: \(lastLoopCompleted ?? .distantPast)",
"insulinOnBoard: \(insulinOnBoard)",
"error: \(error)"
]
completionHandler(report.joined(separator: "\n"))
}
}
}


extension Notification.Name {
static let LoopDataUpdated = Notification.Name(rawValue: "com.loudnate.Naterade.notification.LoopDataUpdated")

Expand Down
Loading