Skip to content

Commit 15ef6e1

Browse files
authored
Merge pull request #23 from tidepool-org/Feature/LOOP-317/establish-transmitter-connection
Feature/LOOP-317/establish-transmitter-connection
2 parents 615f06a + 996f9ae commit 15ef6e1

File tree

6 files changed

+117
-29
lines changed

6 files changed

+117
-29
lines changed

Loop/Extensions/UIAlertController.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,35 +72,35 @@ extension UIAlertController {
7272
/// Initializes an action sheet-styled controller for selecting a CGMManager
7373
///
7474
/// - Parameters:
75-
/// - cgmManagers: An array of CGMManager-conforming types
75+
/// - cgmManagers: An array of CGMManagers
7676
/// - pumpManager: A PumpManager/CGMManager combo instance
7777
/// - selectionHandler: A closure to execute when either a new CGMManager or the current PumpManager is selected
78-
/// - cgmManager: The selected CGMManager type
79-
/// - pumpManager: The selected PumpManager instance
80-
internal convenience init(cgmManagers: [CGMManagerUI.Type], pumpManager: CGMManager?, selectionHandler: @escaping (_ cgmManager: CGMManagerUI.Type?, _ pumpManager: CGMManager?) -> Void) {
78+
/// - cgmManager: The selected CGMManager
79+
/// - pumpManager: The selected PumpManager
80+
internal convenience init(cgmManagers: [AvailableDevice], pumpManager: CGMManager?, selectionHandler: @escaping (_ identifier: String?, _ pumpManager: CGMManager?) -> Void) {
8181
self.init(
8282
title: NSLocalizedString("Add CGM", comment: "Action sheet title selecting CGM"),
8383
message: nil,
8484
preferredStyle: .actionSheet
8585
)
86-
86+
8787
if let pumpManager = pumpManager {
8888
addAction(UIAlertAction(
8989
title: pumpManager.localizedTitle,
9090
style: .default,
9191
handler: { (_) in
9292
selectionHandler(nil, pumpManager)
93-
}
93+
}
9494
))
9595
}
96-
96+
9797
for manager in cgmManagers {
9898
addAction(UIAlertAction(
9999
title: manager.localizedTitle,
100100
style: .default,
101101
handler: { (_) in
102-
selectionHandler(manager, nil)
103-
}
102+
selectionHandler(manager.identifier, nil)
103+
}
104104
))
105105
}
106106
}

Loop/Extensions/UserDefaults+Loop.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import LoopKit
1212
extension UserDefaults {
1313
private enum Key: String {
1414
case pumpManagerState = "com.loopkit.Loop.PumpManagerState"
15+
case cgmManagerState = "com.loopkit.Loop.CGMManagerState"
1516
}
1617

1718
var pumpManagerRawValue: [String: Any]? {
@@ -23,6 +24,15 @@ extension UserDefaults {
2324
}
2425
}
2526

27+
var cgmManagerRawValue: [String: Any]? {
28+
get {
29+
return dictionary(forKey: Key.cgmManagerState.rawValue)
30+
}
31+
set {
32+
set(newValue, forKey: Key.cgmManagerState.rawValue)
33+
}
34+
}
35+
2636
var cgmManager: CGMManager? {
2737
get {
2838
guard let rawValue = cgmManagerState else {

Loop/Managers/CGMManager.swift

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,33 +11,42 @@ import G4ShareSpy
1111
import ShareClient
1212
import MockKit
1313

14-
15-
let allCGMManagers: [CGMManager.Type] = [
14+
#if DEBUG
15+
let staticCGMManagers: [CGMManager.Type] = [
1616
G6CGMManager.self,
1717
G5CGMManager.self,
1818
G4CGMManager.self,
1919
ShareClientManager.self,
2020
MockCGMManager.self,
2121
]
22+
#else
23+
let staticCGMManagers: [CGMManager.Type] = [
24+
G6CGMManager.self,
25+
G5CGMManager.self,
26+
G4CGMManager.self,
27+
ShareClientManager.self,
28+
]
29+
#endif
2230

23-
24-
private let managersByIdentifier: [String: CGMManager.Type] = allCGMManagers.reduce(into: [:]) { (map, Type) in
31+
let staticCGMManagersByIdentifier: [String: CGMManager.Type] = staticCGMManagers.reduce(into: [:]) { (map, Type) in
2532
map[Type.managerIdentifier] = Type
2633
}
2734

35+
let availableStaticCGMManagers = staticCGMManagers.map { (Type) -> AvailableDevice in
36+
return AvailableDevice(identifier: Type.managerIdentifier, localizedTitle: Type.localizedTitle)
37+
}
2838

2939
func CGMManagerFromRawValue(_ rawValue: [String: Any]) -> CGMManager? {
3040
guard let managerIdentifier = rawValue["managerIdentifier"] as? String,
3141
let rawState = rawValue["state"] as? CGMManager.RawStateValue,
32-
let Manager = managersByIdentifier[managerIdentifier]
42+
let Manager = staticCGMManagersByIdentifier[managerIdentifier]
3343
else {
3444
return nil
3545
}
36-
46+
3747
return Manager.init(rawState: rawState)
3848
}
3949

40-
4150
extension CGMManager {
4251
var rawValue: [String: Any] {
4352
return [

Loop/Managers/DeviceDataManager.swift

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ final class DeviceDataManager {
3939
didSet {
4040
dispatchPrecondition(condition: .onQueue(.main))
4141
setupCGM()
42-
UserDefaults.appGroup?.cgmManager = cgmManager
42+
UserDefaults.appGroup?.cgmManagerRawValue = cgmManager?.rawValue
4343
}
4444
}
4545

@@ -90,12 +90,12 @@ final class DeviceDataManager {
9090
pumpManager = nil
9191
}
9292

93-
if let cgmManager = UserDefaults.appGroup?.cgmManager {
94-
self.cgmManager = cgmManager
93+
if let cgmManagerRawValue = UserDefaults.appGroup?.cgmManagerRawValue {
94+
cgmManager = cgmManagerFromRawValue(cgmManagerRawValue)
9595
} else if isCGMManagerValidPumpManager {
9696
self.cgmManager = pumpManager as? CGMManager
9797
}
98-
98+
9999
remoteDataManager.delegate = self
100100
statusExtensionManager = StatusExtensionDataManager(deviceDataManager: self)
101101
loopManager = LoopDataManager(
@@ -147,6 +147,32 @@ final class DeviceDataManager {
147147

148148
return Manager.init(rawState: rawState) as? PumpManagerUI
149149
}
150+
151+
var availableCGMManagers: [AvailableDevice] {
152+
return pluginManager.availableCGMManagers + availableStaticCGMManagers
153+
}
154+
155+
public func cgmManagerTypeByIdentifier(_ identifier: String) -> CGMManagerUI.Type? {
156+
return pluginManager.getCGMManagerTypeByIdentifier(identifier) ?? staticCGMManagersByIdentifier[identifier] as? CGMManagerUI.Type
157+
}
158+
159+
private func cgmManagerTypeFromRawValue(_ rawValue: [String: Any]) -> CGMManager.Type? {
160+
guard let managerIdentifier = rawValue["managerIdentifier"] as? String else {
161+
return nil
162+
}
163+
164+
return cgmManagerTypeByIdentifier(managerIdentifier)
165+
}
166+
167+
func cgmManagerFromRawValue(_ rawValue: [String: Any]) -> CGMManagerUI? {
168+
guard let rawState = rawValue["state"] as? CGMManager.RawStateValue,
169+
let Manager = cgmManagerTypeFromRawValue(rawValue)
170+
else {
171+
return nil
172+
}
173+
174+
return Manager.init(rawState: rawState) as? CGMManagerUI
175+
}
150176

151177
}
152178

@@ -295,8 +321,14 @@ extension DeviceDataManager: CGMManagerDelegate {
295321

296322
func cgmManagerDidUpdateState(_ manager: CGMManager) {
297323
dispatchPrecondition(condition: .onQueue(queue))
298-
UserDefaults.appGroup?.cgmManager = manager
324+
UserDefaults.appGroup?.cgmManagerRawValue = manager.rawValue
299325
}
326+
327+
func credentialStoragePrefix(for manager: CGMManager) -> String {
328+
// return string unique to this instance of the CGMManager
329+
return UUID().uuidString
330+
}
331+
300332
}
301333

302334

Loop/Plugins/LoopPlugins.swift

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,42 @@ class PluginManager {
6464
}
6565

6666
return AvailableDevice(identifier: identifier, localizedTitle: title)
67-
67+
})
68+
}
69+
70+
func getCGMManagerTypeByIdentifier(_ identifier: String) -> CGMManagerUI.Type? {
71+
for bundle in pluginBundles {
72+
if let name = bundle.object(forInfoDictionaryKey: LoopPluginBundleKey.cgmManagerIdentifier.rawValue) as? String, name == identifier {
73+
do {
74+
try bundle.loadAndReturnError()
75+
76+
if let principalClass = bundle.principalClass as? NSObject.Type {
77+
78+
if let plugin = principalClass.init() as? LoopUIPlugin {
79+
return plugin.cgmManagerType
80+
} else {
81+
fatalError("PrincipalClass does not conform to LoopUIPlugin")
82+
}
83+
84+
} else {
85+
fatalError("PrincipalClass not found")
86+
}
87+
} catch let error {
88+
print(error)
89+
}
90+
}
91+
}
92+
return nil
93+
}
94+
95+
var availableCGMManagers: [AvailableDevice] {
96+
return pluginBundles.compactMap({ (bundle) -> AvailableDevice? in
97+
guard let title = bundle.object(forInfoDictionaryKey: LoopPluginBundleKey.cgmManagerDisplayName.rawValue) as? String,
98+
let identifier = bundle.object(forInfoDictionaryKey: LoopPluginBundleKey.cgmManagerIdentifier.rawValue) as? String else {
99+
return nil
100+
}
101+
102+
return AvailableDevice(identifier: identifier, localizedTitle: title)
68103
})
69104
}
70105
}

Loop/View Controllers/SettingsTableViewController.swift

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -429,19 +429,21 @@ final class SettingsTableViewController: UITableViewController {
429429
present(alert, animated: true, completion: nil)
430430
} else {
431431
// Add new CGM
432-
let cgmManagers = allCGMManagers.compactMap({ $0 as? CGMManagerUI.Type })
432+
let cgmManagers = dataManager.availableCGMManagers
433433

434434
switch cgmManagers.count {
435435
case 1:
436-
if let CGMManagerType = cgmManagers.first {
436+
if let cgmManager = cgmManagers.first, let CGMManagerType = dataManager.cgmManagerTypeByIdentifier(cgmManager.identifier) {
437437
setupCGMManager(CGMManagerType, indexPath: indexPath)
438438
}
439439
case let x where x > 1:
440-
let alert = UIAlertController(cgmManagers: cgmManagers, pumpManager: dataManager.pumpManager as? CGMManager) { [weak self] (cgmManager, pumpManager) in
441-
if let CGMManagerType = cgmManager {
442-
self?.setupCGMManager(CGMManagerType, indexPath: indexPath)
443-
} else if let pumpManager = pumpManager {
444-
self?.completeCGMManagerSetup(pumpManager, indexPath: indexPath)
440+
let alert = UIAlertController(cgmManagers: cgmManagers, pumpManager: dataManager.pumpManager as? CGMManager) { [weak self] (identifier, pumpManager) in
441+
if let self = self {
442+
if let cgmManagerIdentifier = identifier, let CGMManagerType = self.dataManager.cgmManagerTypeByIdentifier(cgmManagerIdentifier) {
443+
self.setupCGMManager(CGMManagerType, indexPath: indexPath)
444+
} else if let pumpManager = pumpManager {
445+
self.completeCGMManagerSetup(pumpManager, indexPath: indexPath)
446+
}
445447
}
446448
}
447449

0 commit comments

Comments
 (0)