Skip to content

Commit 5399d46

Browse files
authored
[LOOP-993] Unify carb + bolus flow on watch (#63)
* [LOOP 993] Unify carb + bolus flow on watch * Reset bolus amount when returning to carb entry * Updates from review
1 parent af767ae commit 5399d46

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+2205
-1252
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// CarbAbsorptionTime.swift
3+
// WatchApp Extension
4+
//
5+
// Created by Michael Pangburn on 4/1/20.
6+
// Copyright © 2020 LoopKit Authors. All rights reserved.
7+
//
8+
9+
enum CarbAbsorptionTime: Int, CaseIterable {
10+
case fast = 0
11+
case medium
12+
case slow
13+
14+
var emoji: String {
15+
switch self {
16+
case .fast:
17+
return "🍭"
18+
case .medium:
19+
return "🌮"
20+
case .slow:
21+
return "🍕"
22+
}
23+
}
24+
}

Common/Models/SetBolusUserInfo.swift

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,13 @@
77
//
88

99
import Foundation
10+
import LoopKit
1011

1112

1213
struct SetBolusUserInfo {
1314
let value: Double
1415
let startDate: Date
15-
16-
init(value: Double, startDate: Date) {
17-
self.value = value
18-
self.startDate = startDate
19-
}
16+
let carbEntry: NewCarbEntry?
2017
}
2118

2219

@@ -37,14 +34,21 @@ extension SetBolusUserInfo: RawRepresentable {
3734

3835
self.value = value
3936
self.startDate = startDate
37+
self.carbEntry = (rawValue["ce"] as? NewCarbEntry.RawValue).flatMap(NewCarbEntry.init(rawValue:))
4038
}
4139

4240
var rawValue: RawValue {
43-
return [
41+
var raw: RawValue = [
4442
"v": type(of: self).version,
4543
"name": SetBolusUserInfo.name,
4644
"bv": value,
4745
"sd": startDate
4846
]
47+
48+
if let carbEntry = carbEntry {
49+
raw["ce"] = carbEntry.rawValue
50+
}
51+
52+
return raw
4953
}
5054
}

Common/Models/WatchContext.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ final class WatchContext: RawRepresentable {
3333
var lastNetTempBasalDate: Date?
3434
var recommendedBolusDose: Double?
3535

36+
var potentialCarbEntry: NewCarbEntry?
37+
var recommendedBolusDoseConsideringPotentialCarbEntry: Double?
38+
3639
var cob: Double?
3740
var iob: Double?
3841
var reservoir: Double?
@@ -68,6 +71,10 @@ final class WatchContext: RawRepresentable {
6871
lastNetTempBasalDose = rawValue["ba"] as? Double
6972
lastNetTempBasalDate = rawValue["bad"] as? Date
7073
recommendedBolusDose = rawValue["rbo"] as? Double
74+
if let rawPotentialCarbEntry = rawValue["pce"] as? NewCarbEntry.RawValue {
75+
potentialCarbEntry = NewCarbEntry(rawValue: rawPotentialCarbEntry)
76+
}
77+
recommendedBolusDoseConsideringPotentialCarbEntry = rawValue["rbce"] as? Double
7178
cob = rawValue["cob"] as? Double
7279

7380
cgmManagerState = rawValue["cgmManagerState"] as? CGMManager.RawStateValue
@@ -101,6 +108,8 @@ final class WatchContext: RawRepresentable {
101108
raw["ld"] = loopLastRunDate
102109
raw["r"] = reservoir
103110
raw["rbo"] = recommendedBolusDose
111+
raw["pce"] = potentialCarbEntry?.rawValue
112+
raw["rbce"] = recommendedBolusDoseConsideringPotentialCarbEntry
104113
raw["rp"] = reservoirPercentage
105114

106115
raw["pg"] = predictedGlucose?.rawValue

Loop.xcodeproj/project.pbxproj

Lines changed: 182 additions & 18 deletions
Large diffs are not rendered by default.

Loop/Managers/LoopDataManager.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,7 @@ extension LoopDataManager {
530530
/// - carbEntry: The new carb value
531531
/// - completion: A closure called once upon completion
532532
/// - result: The bolus recommendation
533-
func addCarbEntryAndRecommendBolus(_ carbEntry: NewCarbEntry, replacing replacingEntry: StoredCarbEntry? = nil, completion: @escaping (_ result: Result<BolusRecommendation?>) -> Void) {
533+
func addCarbEntry(_ carbEntry: NewCarbEntry, replacing replacingEntry: StoredCarbEntry? = nil, completion: @escaping (_ result: Result<Void>) -> Void) {
534534
let addCompletion: (CarbStoreResult<StoredCarbEntry>) -> Void = { (result) in
535535
self.dataAccessQueue.async {
536536
switch result {
@@ -544,7 +544,7 @@ extension LoopDataManager {
544544
do {
545545
try self.update()
546546

547-
completion(.success(self.recommendedBolus?.recommendation))
547+
completion(.success(()))
548548
} catch let error {
549549
completion(.failure(error))
550550
}

Loop/Managers/WatchDataManager.swift

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ final class WatchDataManager: NSObject {
139139
}
140140
}
141141

142-
private func createWatchContext(_ completion: @escaping (_ context: WatchContext) -> Void) {
142+
private func createWatchContext(recommendingBolusFor potentialCarbEntry: NewCarbEntry? = nil, _ completion: @escaping (_ context: WatchContext) -> Void) {
143143
let loopManager = deviceManager.loopManager!
144144

145145
let glucose = loopManager.glucoseStore.latestGlucose
@@ -160,6 +160,11 @@ final class WatchDataManager: NSObject {
160160
if let trend = self.deviceManager.cgmManager?.sensorState?.trendType {
161161
context.glucoseTrendRawValue = trend.rawValue
162162
}
163+
164+
if let potentialCarbEntry = potentialCarbEntry {
165+
context.potentialCarbEntry = potentialCarbEntry
166+
context.recommendedBolusDoseConsideringPotentialCarbEntry = try? state.recommendBolus(consideringPotentialCarbEntry: potentialCarbEntry, replacingCarbEntry: nil)?.amount
167+
}
163168

164169
if let glucose = glucose {
165170
updateGroup.enter()
@@ -201,21 +206,36 @@ final class WatchDataManager: NSObject {
201206
}
202207
}
203208

204-
private func addCarbEntryFromWatchMessage(_ message: [String: Any], completionHandler: ((_ error: Error?) -> Void)? = nil) {
205-
if let carbEntry = CarbEntryUserInfo(rawValue: message)?.carbEntry {
206-
deviceManager.loopManager.addCarbEntryAndRecommendBolus(carbEntry) { (result) in
209+
private func addCarbEntryAndBolusFromWatchMessage(_ message: [String: Any]) {
210+
guard let bolus = SetBolusUserInfo(rawValue: message as SetBolusUserInfo.RawValue) else {
211+
log.error("Could not enact bolus from from unknown message: %{public}@", String(describing: message))
212+
return
213+
}
214+
215+
func enactBolus() {
216+
guard bolus.value > 0 else { return }
217+
self.deviceManager.enactBolus(units: bolus.value, at: bolus.startDate) { (error) in
218+
if error == nil {
219+
self.deviceManager.analyticsServicesManager.didSetBolusFromWatch(bolus.value)
220+
}
221+
222+
// When we've successfully started the bolus, send a new context with our new prediction
223+
self.sendWatchContextIfNeeded()
224+
}
225+
}
226+
227+
if let carbEntry = bolus.carbEntry {
228+
deviceManager.loopManager.addCarbEntry(carbEntry) { (result) in
207229
switch result {
208230
case .success:
209231
self.deviceManager.analyticsServicesManager.didAddCarbsFromWatch()
210-
completionHandler?(nil)
232+
enactBolus()
211233
case .failure(let error):
212234
self.log.error("%{public}@", String(describing: error))
213-
completionHandler?(error)
214235
}
215236
}
216237
} else {
217-
log.error("Could not add carb entry from unknown message: %{public}@", String(describing: message))
218-
completionHandler?(nil)
238+
enactBolus()
219239
}
220240
}
221241
}
@@ -224,25 +244,18 @@ final class WatchDataManager: NSObject {
224244
extension WatchDataManager: WCSessionDelegate {
225245
func session(_ session: WCSession, didReceiveMessage message: [String: Any], replyHandler: @escaping ([String: Any]) -> Void) {
226246
switch message["name"] as? String {
227-
case CarbEntryUserInfo.name?:
228-
addCarbEntryFromWatchMessage(message) { (_) in
229-
self.createWatchContext { (context) in
230-
// Send back the updated prediction and recommended bolus
247+
case PotentialCarbEntryUserInfo.name?:
248+
if let potentialCarbEntry = PotentialCarbEntryUserInfo(rawValue: message)?.carbEntry {
249+
self.createWatchContext(recommendingBolusFor: potentialCarbEntry) { (context) in
231250
replyHandler(context.rawValue)
232251
}
252+
} else {
253+
log.error("Could not recommend bolus from from unknown message: %{public}@", String(describing: message))
254+
replyHandler([:])
233255
}
234256
case SetBolusUserInfo.name?:
235-
// Start the bolus and reply when it's successfully requested
236-
if let bolus = SetBolusUserInfo(rawValue: message as SetBolusUserInfo.RawValue) {
237-
self.deviceManager.enactBolus(units: bolus.value, at: bolus.startDate) { (error) in
238-
if error == nil {
239-
self.deviceManager.analyticsServicesManager.didSetBolusFromWatch(bolus.value)
240-
}
241-
242-
// When we've successfully started the bolus, send a new context with our new prediction
243-
self.sendWatchContextIfNeeded()
244-
}
245-
}
257+
// Add carbs if applicable; start the bolus and reply when it's successfully requested
258+
addCarbEntryAndBolusFromWatchMessage(message)
246259

247260
// Reply immediately
248261
replyHandler([:])
@@ -282,7 +295,7 @@ extension WatchDataManager: WCSessionDelegate {
282295
}
283296

284297
func session(_ session: WCSession, didReceiveUserInfo userInfo: [String: Any]) {
285-
addCarbEntryFromWatchMessage(userInfo)
298+
assertionFailure("We currently don't expect any userInfo messages transferred from the watch side")
286299
}
287300

288301
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {

Loop/View Controllers/CarbAbsorptionViewController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ final class CarbAbsorptionViewController: ChartsTableViewController, Identifiabl
528528
}
529529
}
530530

531-
deviceManager.loopManager.addCarbEntryAndRecommendBolus(updatedEntry, replacing: bolusViewController.originalCarbEntry) { (result) in
531+
deviceManager.loopManager.addCarbEntry(updatedEntry, replacing: bolusViewController.originalCarbEntry) { (result) in
532532
DispatchQueue.main.async {
533533
switch result {
534534
case .success:

Loop/View Controllers/StatusTableViewController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1124,7 +1124,7 @@ final class StatusTableViewController: ChartsTableViewController {
11241124
}
11251125
}
11261126

1127-
deviceManager.loopManager.addCarbEntryAndRecommendBolus(carbEntry) { result in
1127+
deviceManager.loopManager.addCarbEntry(carbEntry) { result in
11281128
DispatchQueue.main.async {
11291129
switch result {
11301130
case .success:
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// CarbEntryUserInfo.swift
2+
// PotentialCarbEntryUserInfo.swift
33
// Naterade
44
//
55
// Created by Nathan Racklyeft on 1/23/16.
@@ -10,7 +10,7 @@ import Foundation
1010
import LoopKit
1111

1212

13-
public struct CarbEntryUserInfo {
13+
public struct PotentialCarbEntryUserInfo {
1414
public let carbEntry: NewCarbEntry
1515

1616
public init(carbEntry: NewCarbEntry) {
@@ -19,14 +19,14 @@ public struct CarbEntryUserInfo {
1919
}
2020

2121

22-
extension CarbEntryUserInfo: RawRepresentable {
22+
extension PotentialCarbEntryUserInfo: RawRepresentable {
2323
public typealias RawValue = [String: Any]
2424

25-
static let version = 2
26-
public static let name = "CarbEntryUserInfo"
25+
static let version = 1
26+
public static let name = "PotentialCarbEntryUserInfo"
2727

2828
public init?(rawValue: RawValue) {
29-
guard rawValue["v"] as? Int == type(of: self).version && rawValue["name"] as? String == CarbEntryUserInfo.name,
29+
guard rawValue["v"] as? Int == type(of: self).version && rawValue["name"] as? String == PotentialCarbEntryUserInfo.name,
3030
let value = rawValue["ce"] as? NewCarbEntry.RawValue,
3131
let carbEntry = NewCarbEntry(rawValue: value)
3232
else {
@@ -39,7 +39,7 @@ extension CarbEntryUserInfo: RawRepresentable {
3939
public var rawValue: RawValue {
4040
return [
4141
"v": type(of: self).version,
42-
"name": CarbEntryUserInfo.name,
42+
"name": PotentialCarbEntryUserInfo.name,
4343
"ce": carbEntry.rawValue,
4444
]
4545
}

0 commit comments

Comments
 (0)