Prechádzať zdrojové kódy

Release/0.2.1 (#100)

Release/0.2.1
Ivan 4 rokov pred
rodič
commit
72036c37c8
100 zmenil súbory, kde vykonal 2383 pridanie a 21950 odobranie
  1. 0 21
      Dependecies/rileylink_ios/Common/IdentifiableClass.swift
  2. 0 22
      Dependecies/rileylink_ios/Common/NumberFormatter.swift
  3. 0 1285
      Dependecies/rileylink_ios/MinimedKit/PumpManager/MinimedPumpManager.swift
  4. 0 380
      Dependecies/rileylink_ios/MinimedKit/PumpManager/MinimedPumpManagerState.swift
  5. 0 160
      Dependecies/rileylink_ios/MinimedKit/PumpManager/PumpMessageSender.swift
  6. 0 153
      Dependecies/rileylink_ios/MinimedKit/PumpManager/PumpOps.swift
  7. 0 94
      Dependecies/rileylink_ios/MinimedKit/PumpManager/PumpState.swift
  8. 0 25
      Dependecies/rileylink_ios/MinimedKit/PumpManager/RileyLinkDevice.swift
  9. 0 442
      Dependecies/rileylink_ios/MinimedKitTests/PumpOpsSynchronousTests.swift
  10. 0 346
      Dependecies/rileylink_ios/MinimedKitUI/CommandResponseViewController.swift
  11. 0 401
      Dependecies/rileylink_ios/MinimedKitUI/MinimedPumpSettingsViewController.swift
  12. 0 37
      Dependecies/rileylink_ios/MinimedKitUI/RadioSelectionTableViewController.swift
  13. 0 570
      Dependecies/rileylink_ios/MinimedKitUI/RileyLinkMinimedDeviceTableViewController.swift
  14. 0 253
      Dependecies/rileylink_ios/OmniKit/MessageTransport/MessageBlocks/DetailedStatus.swift
  15. 0 71
      Dependecies/rileylink_ios/OmniKit/MessageTransport/MessageBlocks/StatusResponse.swift
  16. 0 122
      Dependecies/rileylink_ios/OmniKit/MessageTransport/MessageBlocks/VersionResponse.swift
  17. 0 304
      Dependecies/rileylink_ios/OmniKit/MessageTransport/MessageTransport.swift
  18. 0 288
      Dependecies/rileylink_ios/OmniKit/Model/AlertSlot.swift
  19. 0 236
      Dependecies/rileylink_ios/OmniKit/Model/BasalDeliveryTable.swift
  20. 0 107
      Dependecies/rileylink_ios/OmniKit/Model/Pod.swift
  21. 0 73
      Dependecies/rileylink_ios/OmniKit/Model/PodProgressStatus.swift
  22. 0 1737
      Dependecies/rileylink_ios/OmniKit/PumpManager/OmnipodPumpManager.swift
  23. 0 220
      Dependecies/rileylink_ios/OmniKit/PumpManager/OmnipodPumpManagerState.swift
  24. 0 469
      Dependecies/rileylink_ios/OmniKit/PumpManager/PodComms.swift
  25. 0 742
      Dependecies/rileylink_ios/OmniKit/PumpManager/PodCommsSession.swift
  26. 0 607
      Dependecies/rileylink_ios/OmniKit/PumpManager/PodState.swift
  27. 0 240
      Dependecies/rileylink_ios/OmniKitTests/MessageTests.swift
  28. 0 475
      Dependecies/rileylink_ios/OmniKitTests/PodInfoTests.swift
  29. 0 77
      Dependecies/rileylink_ios/OmniKitTests/StatusTests.swift
  30. 0 172
      Dependecies/rileylink_ios/OmniKitUI/ViewControllers/CommandResponseViewController.swift
  31. 0 253
      Dependecies/rileylink_ios/OmniKitUI/ViewControllers/InsertCannulaSetupViewController.swift
  32. 0 999
      Dependecies/rileylink_ios/OmniKitUI/ViewControllers/OmnipodSettingsViewController.swift
  33. 0 270
      Dependecies/rileylink_ios/OmniKitUI/ViewControllers/PairPodSetupViewController.swift
  34. 0 237
      Dependecies/rileylink_ios/OmniKitUI/ViewControllers/ReplacePodViewController.swift
  35. 0 5954
      Dependecies/rileylink_ios/RileyLink.xcodeproj/project.pbxproj
  36. 0 305
      Dependecies/rileylink_ios/RileyLinkBLEKit/CommandSession.swift
  37. 0 434
      Dependecies/rileylink_ios/RileyLinkBLEKit/PeripheralManager+RileyLink.swift
  38. 0 474
      Dependecies/rileylink_ios/RileyLinkBLEKit/PeripheralManager.swift
  39. 0 54
      Dependecies/rileylink_ios/RileyLinkBLEKit/PeripheralManagerError.swift
  40. 0 99
      Dependecies/rileylink_ios/RileyLinkBLEKit/RileyLinkConnectionManager.swift
  41. 0 426
      Dependecies/rileylink_ios/RileyLinkBLEKit/RileyLinkDevice.swift
  42. 0 54
      Dependecies/rileylink_ios/RileyLinkBLEKit/RileyLinkDeviceError.swift
  43. 0 1136
      Dependecies/rileylink_ios/RileyLinkKit/PumpOpsSession.swift
  44. 0 30
      Dependecies/rileylink_ios/RileyLinkKit/RileyLinkDevice.swift
  45. 0 107
      Dependecies/rileylink_ios/RileyLinkKit/RileyLinkPumpManager.swift
  46. 0 41
      Dependecies/rileylink_ios/RileyLinkKitUI/Base.lproj/Localizable.strings
  47. 0 413
      Dependecies/rileylink_ios/RileyLinkKitUI/RileyLinkDeviceTableViewController.swift
  48. 0 41
      Dependecies/rileylink_ios/RileyLinkKitUI/da.lproj/Localizable.strings
  49. 0 41
      Dependecies/rileylink_ios/RileyLinkKitUI/de.lproj/Localizable.strings
  50. 0 41
      Dependecies/rileylink_ios/RileyLinkKitUI/es.lproj/Localizable.strings
  51. 0 42
      Dependecies/rileylink_ios/RileyLinkKitUI/fi.lproj/Localizable.strings
  52. 0 41
      Dependecies/rileylink_ios/RileyLinkKitUI/fr.lproj/Localizable.strings
  53. 0 41
      Dependecies/rileylink_ios/RileyLinkKitUI/it.lproj/Localizable.strings
  54. 0 41
      Dependecies/rileylink_ios/RileyLinkKitUI/nb.lproj/Localizable.strings
  55. 0 41
      Dependecies/rileylink_ios/RileyLinkKitUI/nl.lproj/Localizable.strings
  56. 0 41
      Dependecies/rileylink_ios/RileyLinkKitUI/pl.lproj/Localizable.strings
  57. 0 42
      Dependecies/rileylink_ios/RileyLinkKitUI/pt-BR.lproj/Localizable.strings
  58. 0 41
      Dependecies/rileylink_ios/RileyLinkKitUI/ru.lproj/Localizable.strings
  59. 0 41
      Dependecies/rileylink_ios/RileyLinkKitUI/sv.lproj/Localizable.strings
  60. 0 41
      Dependecies/rileylink_ios/RileyLinkKitUI/zh-Hans.lproj/Localizable.strings
  61. 36 0
      Dependencies/CGMBLEKit/.gitignore
  62. 657 0
      Dependencies/CGMBLEKit/CGMBLEKit.xcodeproj/project.pbxproj
  63. 7 0
      Dependencies/CGMBLEKit/CGMBLEKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  64. 0 0
      Dependencies/CGMBLEKit/CGMBLEKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  65. 0 0
      Dependencies/CGMBLEKit/CGMBLEKit.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
  66. 67 0
      Dependencies/CGMBLEKit/CGMBLEKit.xcodeproj/xcshareddata/xcschemes/CGMBLEKit.xcscheme
  67. 19 0
      Dependencies/CGMBLEKit/CGMBLEKit/AESCrypt.h
  68. 33 0
      Dependencies/CGMBLEKit/CGMBLEKit/AESCrypt.m
  69. 39 0
      Dependencies/CGMBLEKit/CGMBLEKit/Base.lproj/Localizable.strings
  70. 350 0
      Dependencies/CGMBLEKit/CGMBLEKit/BluetoothManager.swift
  71. 87 0
      Dependencies/CGMBLEKit/CGMBLEKit/BluetoothServices.swift
  72. 45 0
      Dependencies/CGMBLEKit/CGMBLEKit/CBPeripheral.swift
  73. 17 0
      Dependencies/CGMBLEKit/CGMBLEKit/CGMBLEKit.h
  74. 27 0
      Dependencies/CGMBLEKit/CGMBLEKit/Calibration.swift
  75. 106 0
      Dependencies/CGMBLEKit/CGMBLEKit/CalibrationState.swift
  76. 79 0
      Dependencies/CGMBLEKit/CGMBLEKit/Command.swift
  77. 67 0
      Dependencies/CGMBLEKit/CGMBLEKit/Glucose+SensorDisplayable.swift
  78. 105 0
      Dependencies/CGMBLEKit/CGMBLEKit/Glucose.swift
  79. 26 0
      Dependencies/CGMBLEKit/CGMBLEKit/Info.plist
  80. 28 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/AuthChallengeRxMessage.swift
  81. 20 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/AuthChallengeTxMessage.swift
  82. 28 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/AuthRequestRxMessage.swift
  83. 29 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/AuthRequestTxMessage.swift
  84. 16 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/BatteryStatusTxMessage.swift
  85. 17 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/BondRequestTxMessage.swift
  86. 22 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/CalibrateGlucoseRxMessage.swift
  87. 24 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/CalibrateGlucoseTxMessage.swift
  88. 28 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/CalibrationDataRxMessage.swift
  89. 18 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/CalibrationDataTxMessage.swift
  90. 16 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/DisconnectTxMessage.swift
  91. 14 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/FirmwareVersionTxMessage.swift
  92. 122 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/GlucoseBackfillMessage.swift
  93. 14 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/GlucoseHistoryTxMessage.swift
  94. 88 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/GlucoseRxMessage.swift
  95. 18 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/GlucoseTxMessage.swift
  96. 20 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/KeepAliveTxMessage.swift
  97. 30 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/ResetMessage.swift
  98. 37 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/SessionStartRxMessage.swift
  99. 27 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/SessionStartTxMessage.swift
  100. 0 0
      Dependencies/CGMBLEKit/CGMBLEKit/Messages/SessionStopRxMessage.swift

+ 0 - 21
Dependecies/rileylink_ios/Common/IdentifiableClass.swift

@@ -1,21 +0,0 @@
-//
-//  IdentifiableClass.swift
-//  Naterade
-//
-//  Created by Nathan Racklyeft on 2/9/16.
-//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
-//
-
-import Foundation
-
-
-protocol IdentifiableClass: class {
-    static var className: String { get }
-}
-
-
-extension IdentifiableClass {
-    static var className: String {
-        return NSStringFromClass(self).components(separatedBy: ".").last!
-    }
-}

+ 0 - 22
Dependecies/rileylink_ios/Common/NumberFormatter.swift

@@ -1,22 +0,0 @@
-//
-//  NumberFormatter.swift
-//  RileyLink
-//
-//  Copyright © 2017 Pete Schwamb. All rights reserved.
-//
-
-import Foundation
-
-extension NumberFormatter {
-    func decibleString(from decibles: Int?) -> String? {
-        if let decibles = decibles, let formatted = string(from: NSNumber(value: decibles)) {
-            return String(format: LocalizedString("%@ dB", comment: "Unit format string for an RSSI value in decibles"), formatted)
-        } else {
-            return nil
-        }
-    }
-    
-    func string(from number: Double) -> String? {
-        return string(from: NSNumber(value: number))
-    }
-}

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 1285
Dependecies/rileylink_ios/MinimedKit/PumpManager/MinimedPumpManager.swift


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 380
Dependecies/rileylink_ios/MinimedKit/PumpManager/MinimedPumpManagerState.swift


+ 0 - 160
Dependecies/rileylink_ios/MinimedKit/PumpManager/PumpMessageSender.swift

@@ -1,160 +0,0 @@
-//
-//  PumpMessageSender.swift
-//  RileyLink
-//
-//  Created by Jaim Zuber on 3/2/17.
-//  Copyright © 2017 Pete Schwamb. All rights reserved.
-//
-
-import Foundation
-import RileyLinkBLEKit
-import os.log
-
-private let standardPumpResponseWindow: TimeInterval = .milliseconds(200)
-
-private let log = OSLog(category: "PumpMessageSender")
-
-
-protocol PumpMessageSender {
-    /// - Throws: LocalizedError
-    func resetRadioConfig() throws
-
-    /// - Throws: LocalizedError
-    func updateRegister(_ address: CC111XRegister, value: UInt8) throws
-
-    /// - Throws: LocalizedError
-    func setBaseFrequency(_ frequency: Measurement<UnitFrequency>) throws
-
-    /// Sends data to the pump, listening for a reply
-    ///
-    /// - Parameters:
-    ///   - data: The data to send
-    ///   - repeatCount: The number of times to repeat the message before listening begins
-    ///   - timeout: The length of time to listen for a response before timing out
-    ///   - retryCount: The number of times to repeat the send & listen sequence
-    /// - Returns: The packet reply
-    /// - Throws: LocalizedError
-    func sendAndListen(_ data: Data, repeatCount: Int, timeout: TimeInterval, retryCount: Int) throws -> RFPacket
-
-    /// - Throws: LocalizedError
-    func listen(onChannel channel: Int, timeout: TimeInterval) throws -> RFPacket?
-
-    /// - Throws: LocalizedError
-    func send(_ data: Data, onChannel channel: Int, timeout: TimeInterval) throws
-    
-    /// - Throws: LocalizedError
-    func enableCCLEDs() throws
-    
-    /// - Throws: LocalizedError
-    func getRileyLinkStatistics() throws -> RileyLinkStatistics
-}
-
-extension PumpMessageSender {
-    /// - Throws: PumpOpsError.deviceError
-    func send(_ msg: PumpMessage) throws {
-        do {
-            try send(MinimedPacket(outgoingData: msg.txData).encodedData(), onChannel: 0, timeout: 0)
-        } catch let error as LocalizedError {
-            throw PumpOpsError.deviceError(error)
-        }
-    }
-
-    /// Sends a message to the pump, expecting a specific response body
-    ///
-    /// - Parameters:
-    ///   - message: The message to send
-    ///   - responseType: The expected response message type
-    ///   - repeatCount: The number of times to repeat the message before listening begins
-    ///   - timeout: The length of time to listen for a pump response
-    ///   - retryCount: The number of times to repeat the send & listen sequence
-    /// - Returns: The expected response message body
-    /// - Throws:
-    ///     - PumpOpsError.couldNotDecode
-    ///     - PumpOpsError.crosstalk
-    ///     - PumpOpsError.deviceError
-    ///     - PumpOpsError.noResponse
-    ///     - PumpOpsError.pumpError
-    ///     - PumpOpsError.unexpectedResponse
-    ///     - PumpOpsError.unknownResponse
-    func getResponse<T: MessageBody>(to message: PumpMessage, responseType: MessageType = .pumpAck, repeatCount: Int = 0, timeout: TimeInterval = standardPumpResponseWindow, retryCount: Int = 3) throws -> T {
-        
-        log.debug("getResponse(%{public}@, %d, %f, %d)", String(describing: message), repeatCount, timeout, retryCount)
-        
-        let response = try sendAndListen(message, repeatCount: repeatCount, timeout: timeout, retryCount: retryCount)
-        
-        guard response.messageType == responseType, let body = response.messageBody as? T else {
-            if let body = response.messageBody as? PumpErrorMessageBody {
-                switch body.errorCode {
-                case .known(let code):
-                    throw PumpOpsError.pumpError(code)
-                case .unknown(let code):
-                    throw PumpOpsError.unknownPumpErrorCode(code)
-                }
-            } else {
-                throw PumpOpsError.unexpectedResponse(response, from: message)
-            }
-        }
-        return body
-    }
-
-    /// Sends a message to the pump, listening for a message in reply
-    ///
-    /// - Parameters:
-    ///   - message: The message to send
-    ///   - repeatCount: The number of times to repeat the message before listening begins
-    ///   - timeout: The length of time to listen for a pump response
-    ///   - retryCount: The number of times to repeat the send & listen sequence
-    /// - Returns: The message reply
-    /// - Throws: An error describing a failure in the sending or receiving of a message:
-    ///     - PumpOpsError.couldNotDecode
-    ///     - PumpOpsError.crosstalk
-    ///     - PumpOpsError.deviceError
-    ///     - PumpOpsError.noResponse
-    ///     - PumpOpsError.unknownResponse
-    func sendAndListen(_ message: PumpMessage, repeatCount: Int = 0, timeout: TimeInterval = standardPumpResponseWindow, retryCount: Int = 3) throws -> PumpMessage {
-        let rfPacket = try sendAndListenForPacket(message, repeatCount: repeatCount, timeout: timeout, retryCount: retryCount)
-
-        guard let packet = MinimedPacket(encodedData: rfPacket.data) else {
-            throw PumpOpsError.couldNotDecode(rx: rfPacket.data, during: message)
-        }
-
-        guard let response = PumpMessage(rxData: packet.data) else {
-            // Unknown packet type or message type
-            throw PumpOpsError.unknownResponse(rx: packet.data, during: message)
-        }
-
-        guard response.address == message.address else {
-            throw PumpOpsError.crosstalk(response, during: message)
-        }
-
-        return response
-    }
-
-    /// - Throws:
-    ///     - PumpOpsError.noResponse
-    ///     - PumpOpsError.deviceError
-    func sendAndListenForPacket(_ message: PumpMessage, repeatCount: Int = 0, timeout: TimeInterval = standardPumpResponseWindow, retryCount: Int = 3) throws -> RFPacket {
-        let packet: RFPacket?
-
-        do {
-            packet = try sendAndListen(MinimedPacket(outgoingData: message.txData).encodedData(), repeatCount: repeatCount, timeout: timeout, retryCount: retryCount)
-        } catch let error as LocalizedError {
-            throw PumpOpsError.deviceError(error)
-        }
-
-        guard let rfPacket = packet else {
-            throw PumpOpsError.noResponse(during: message)
-        }
-
-        return rfPacket
-    }
-
-    /// - Throws: PumpOpsError.deviceError
-    func listenForPacket(onChannel channel: Int, timeout: TimeInterval) throws -> RFPacket? {
-        do {
-            return try listen(onChannel: channel, timeout: timeout)
-        } catch let error as LocalizedError {
-            throw PumpOpsError.deviceError(error)
-        }
-    }
-}

+ 0 - 153
Dependecies/rileylink_ios/MinimedKit/PumpManager/PumpOps.swift

@@ -1,153 +0,0 @@
-//
-//  PumpOps.swift
-//  RileyLink
-//
-//  Created by Pete Schwamb on 3/14/16.
-//  Copyright © 2016 Pete Schwamb. All rights reserved.
-//
-
-import Foundation
-import RileyLinkKit
-import RileyLinkBLEKit
-import os.log
-import LoopKit
-
-
-public protocol PumpOpsDelegate: class {
-    // TODO: Audit clients of this as its called on the session queue
-    func pumpOps(_ pumpOps: PumpOps, didChange state: PumpState)
-}
-
-
-public class PumpOps {
-    private let log = OSLog(category: "PumpOps")
-
-    public let pumpSettings: PumpSettings
-
-    public let pumpState: Locked<PumpState>
-
-    private let configuredDevices: Locked<Set<RileyLinkDevice>> = Locked(Set())
-
-    // Isolated to RileyLinkDeviceManager.sessionQueue
-    private var sessionDevice: RileyLinkDevice?
-
-    private weak var delegate: PumpOpsDelegate?
-    
-    public init(pumpSettings: PumpSettings, pumpState: PumpState?, delegate: PumpOpsDelegate?) {
-        self.pumpSettings = pumpSettings
-        self.delegate = delegate
-
-        if let pumpState = pumpState {
-            self.pumpState = Locked(pumpState)
-        } else {
-            let pumpState = PumpState()
-            self.pumpState = Locked(pumpState)
-            self.delegate?.pumpOps(self, didChange: pumpState)
-        }
-    }
-
-    public func runSession(withName name: String, using deviceSelector: @escaping (_ completion: @escaping (_ device: RileyLinkDevice?) -> Void) -> Void, _ block: @escaping (_ session: PumpOpsSession?) -> Void) {
-        deviceSelector { (device) in
-            guard let device = device else {
-                block(nil)
-                return
-            }
-
-            self.runSession(withName: name, using: device, block)
-        }
-    }
-
-    public func runSession(withName name: String, using device: RileyLinkDevice, _ block: @escaping (_ session: PumpOpsSession) -> Void) {
-        device.runSession(withName: name) { (commandSession) in
-            let session = PumpOpsSession(settings: self.pumpSettings, pumpState: self.pumpState.value, session: commandSession, delegate: self)
-            self.sessionDevice = device
-            if !commandSession.firmwareVersion.isUnknown {
-                self.configureDevice(device, with: session)
-            } else {
-                self.log.error("Skipping device configuration due to unknown firmware version")
-            }
-
-            block(session)
-            self.sessionDevice = nil
-        }
-    }
-
-    // Must be called from within the RileyLinkDevice sessionQueue
-    private func configureDevice(_ device: RileyLinkDevice, with session: PumpOpsSession) {
-        guard !self.configuredDevices.value.contains(device) else {
-            return
-        }
-
-        log.default("Configuring RileyLinkDevice: %{public}@", String(describing: device.deviceURI))
-
-        do {
-            _ = try session.configureRadio(for: pumpSettings.pumpRegion, frequency: pumpState.value.lastValidFrequency)
-        } catch let error {
-            // Ignore the error and let the block run anyway
-            log.error("Error configuring device: %{public}@", String(describing: error))
-            return
-        }
-
-        NotificationCenter.default.post(name: .DeviceRadioConfigDidChange, object: device)
-        NotificationCenter.default.addObserver(self, selector: #selector(deviceRadioConfigDidChange(_:)), name: .DeviceRadioConfigDidChange, object: device)
-        NotificationCenter.default.addObserver(self, selector: #selector(deviceRadioConfigDidChange(_:)), name: .DeviceConnectionStateDidChange, object: device)
-        _ = configuredDevices.mutate { (value) in
-            value.insert(device)
-        }
-    }
-
-    @objc private func deviceRadioConfigDidChange(_ note: Notification) {
-        guard let device = note.object as? RileyLinkDevice else {
-            return
-        }
-
-        NotificationCenter.default.removeObserver(self, name: .DeviceRadioConfigDidChange, object: device)
-        NotificationCenter.default.removeObserver(self, name: .DeviceConnectionStateDidChange, object: device)
-
-        _ = configuredDevices.mutate { (value) in
-            value.remove(device)
-        }
-    }
-}
-
-// Delivered on RileyLinkDeviceManager.sessionQueue
-extension PumpOps: PumpOpsSessionDelegate {
-    func pumpOpsSessionDidChangeRadioConfig(_ session: PumpOpsSession) {
-        if let sessionDevice = self.sessionDevice {
-            self.configuredDevices.value = [sessionDevice]
-        }
-    }
-    
-    func pumpOpsSession(_ session: PumpOpsSession, didChange state: PumpState) {
-        self.pumpState.value = state
-        delegate?.pumpOps(self, didChange: state)
-        NotificationCenter.default.post(
-            name: .PumpOpsStateDidChange,
-            object: self,
-            userInfo: [PumpOps.notificationPumpStateKey: pumpState]
-        )
-    }
-}
-
-
-extension PumpOps: CustomDebugStringConvertible {
-    public var debugDescription: String {
-        return [
-            "### PumpOps",
-            "pumpSettings: \(String(reflecting: pumpSettings))",
-            "pumpState: \(String(reflecting: pumpState.value))",
-            "configuredDevices: \(configuredDevices.value.map({ $0.peripheralIdentifier.uuidString }))",
-        ].joined(separator: "\n")
-    }
-}
-
-
-/// Provide a notification contract that clients can use to inform RileyLink UI of changes to PumpOps.PumpState
-extension PumpOps {
-    public static let notificationPumpStateKey = "com.rileylink.RileyLinkKit.PumpOps.PumpState"
-}
-
-
-extension Notification.Name {
-    public static let PumpOpsStateDidChange = Notification.Name(rawValue: "com.rileylink.RileyLinkKit.PumpOpsStateDidChange")
-}

+ 0 - 94
Dependecies/rileylink_ios/MinimedKit/PumpManager/PumpState.swift

@@ -1,94 +0,0 @@
-//
-//  PumpState.swift
-//  RileyLink
-//
-//  Created by Nathan Racklyeft on 4/9/16.
-//  Copyright © 2016 Pete Schwamb. All rights reserved.
-//
-
-import Foundation
-
-
-public struct PumpState: RawRepresentable, Equatable {
-    public typealias RawValue = [String: Any]
-
-    public var timeZone: TimeZone
-    
-    public var pumpModel: PumpModel?
-    
-    public var awakeUntil: Date?
-    
-    public var lastValidFrequency: Measurement<UnitFrequency>?
-    
-    public var lastTuned: Date?
-
-    var isAwake: Bool {
-        if let awakeUntil = awakeUntil {
-            return awakeUntil.timeIntervalSinceNow > 0
-        }
-
-        return false
-    }
-    
-    var lastWakeAttempt: Date?
-
-    public init() {
-        self.timeZone = .currentFixed
-    }
-
-    public init(timeZone: TimeZone, pumpModel: PumpModel) {
-        self.timeZone = timeZone
-        self.pumpModel = pumpModel
-    }
-
-    public init?(rawValue: RawValue) {
-        guard
-            let timeZoneSeconds = rawValue["timeZone"] as? Int,
-            let timeZone = TimeZone(secondsFromGMT: timeZoneSeconds)
-        else {
-            return nil
-        }
-
-        self.timeZone = timeZone
-        
-        if let pumpModelNumber = rawValue["pumpModel"] as? PumpModel.RawValue {
-            pumpModel = PumpModel(rawValue: pumpModelNumber)
-        }
-        
-        if let frequencyRaw = rawValue["lastValidFrequency"] as? Double {
-            lastValidFrequency = Measurement<UnitFrequency>(value: frequencyRaw, unit: .megahertz)
-        }
-    }
-
-    public var rawValue: RawValue {
-        var rawValue: RawValue = [
-            "timeZone": timeZone.secondsFromGMT(),
-        ]
-
-        if let pumpModel = pumpModel {
-            rawValue["pumpModel"] = pumpModel.rawValue
-        }
-        
-        if let frequency = lastValidFrequency?.converted(to: .megahertz) {
-            rawValue["lastValidFrequency"] = frequency.value
-        }
-
-        return rawValue
-    }
-}
-
-
-extension PumpState: CustomDebugStringConvertible {
-    public var debugDescription: String {
-
-        return [
-            "## PumpState",
-            "timeZone: \(timeZone)",
-            "pumpModel: \(pumpModel?.rawValue ?? "")",
-            "awakeUntil: \(awakeUntil ?? .distantPast)",
-            "lastValidFrequency: \(String(describing: lastValidFrequency))",
-            "lastTuned: \(awakeUntil ?? .distantPast))",
-            "lastWakeAttempt: \(String(describing: lastWakeAttempt))"
-        ].joined(separator: "\n")
-    }
-}

+ 0 - 25
Dependecies/rileylink_ios/MinimedKit/PumpManager/RileyLinkDevice.swift

@@ -1,25 +0,0 @@
-//
-//  RileyLinkDevice.swift
-//  Loop
-//
-//  Copyright © 2017 LoopKit Authors. All rights reserved.
-//
-
-import HealthKit
-import RileyLinkBLEKit
-
-
-extension RileyLinkDevice.Status {
-    func device(pumpID: String, pumpModel: PumpModel) -> HKDevice {
-        return HKDevice(
-            name: name,
-            manufacturer: "Medtronic",
-            model: pumpModel.rawValue,
-            hardwareVersion: nil,
-            firmwareVersion: radioFirmwareVersion?.description,
-            softwareVersion: String(MinimedKitVersionNumber),
-            localIdentifier: pumpID,
-            udiDeviceIdentifier: nil
-        )
-    }
-}

+ 0 - 442
Dependecies/rileylink_ios/MinimedKitTests/PumpOpsSynchronousTests.swift

@@ -1,442 +0,0 @@
-//
-//  PumpOpsSynchronousTests.swift
-//  RileyLink
-//
-//  Created by Jaim Zuber on 2/21/17.
-//  Copyright © 2017 Pete Schwamb. All rights reserved.
-//
-
-import XCTest
-
-@testable import RileyLinkKit
-@testable import MinimedKit
-@testable import RileyLinkBLEKit
-
-class PumpOpsSynchronousTests: XCTestCase {
-    
-    var sut: PumpOpsSession!
-    var pumpSettings: PumpSettings!
-    var pumpState: PumpState!
-    var pumpID: String!
-    var pumpRegion: PumpRegion!
-    var pumpModel: PumpModel!
-    var messageSenderStub: PumpMessageSenderStub!
-
-    let dateComponents2007 = DateComponents(calendar: Calendar.current, year: 2007, month: 1, day: 1)
-    let dateComponents2017 = DateComponents(calendar: Calendar.current, year: 2017, month: 1, day: 1)
-    
-    let squareBolusDataLength = 26
-    
-    lazy var datePast2007: Date = {
-        return self.dateComponents2017.date!.addingTimeInterval(TimeInterval(minutes:60))
-    }()
-    
-    lazy var datePast2017: Date = {
-        return self.dateComponents2017.date!.addingTimeInterval(TimeInterval(minutes:60))
-    }()
-    
-    lazy var dateTimestamp2010: DateComponents = {
-        self.createSquareBolusEvent2010().timestamp
-    }()
-    
-    override func setUp() {
-        super.setUp()
-        
-        pumpID = "350535"
-        pumpRegion = .worldWide
-        pumpModel = PumpModel.model523
-
-        messageSenderStub = PumpMessageSenderStub()
-        
-        setUpSUT()
-    }
-    
-    /// Creates the System Under Test. This is needed because our SUT has dependencies injected through the constructor
-    func setUpSUT() {
-        pumpSettings = PumpSettings(pumpID: pumpID, pumpRegion: pumpRegion)
-        pumpState = PumpState()
-        pumpState.pumpModel = pumpModel
-        pumpState.awakeUntil = Date(timeIntervalSinceNow: 100) // pump is awake
-        
-        sut = PumpOpsSession(settings: pumpSettings, pumpState: pumpState, session: messageSenderStub, delegate: messageSenderStub)
-    }
-    
-    /// Duplicates logic in setUp with a new PumpModel
-    ///
-    /// - Parameter newPumpModel: model of the pump to test
-    func setUpTestWithPumpModel(_ newPumpModel: PumpModel) {
-        pumpModel = newPumpModel
-        setUpSUT()
-    }
-    
-    func testShouldContinueIfTimestampBeforeStartDateNotEncountered() {
-        let page = HistoryPage(events: [createBatteryEvent()])
-
-        let (_, hasMoreEvents, _) = page.timestampedEvents(after: .distantPast, timeZone: pumpState.timeZone, model: pumpModel)
-        
-        XCTAssertTrue(hasMoreEvents)
-    }
-    
-    func testShouldFinishIfTimestampBeforeStartDateEncountered() {
-        let batteryEvent = createBatteryEvent()
-        let page = HistoryPage(events: [batteryEvent])
-        
-        let afterBatteryEventDate = batteryEvent.timestamp.date!.addingTimeInterval(TimeInterval(hours: 10))
-        
-        let (_, hasMoreEvents, _) = page.timestampedEvents(after: afterBatteryEventDate, timeZone: pumpState.timeZone, model: pumpModel)
-        
-        XCTAssertFalse(hasMoreEvents)
-    }
-
-    func testEventsAfterStartDateAreReturned() {
-        let batteryEvent2007 = createBatteryEvent(withDateComponent: dateComponents2007)
-        let batteryEvent2017 = createBatteryEvent(withDateComponent: dateComponents2017)
-        let page = HistoryPage(events: [batteryEvent2007, batteryEvent2017])
-        
-        let (events, _, _) = page.timestampedEvents(after: .distantPast, timeZone: pumpState.timeZone, model: pumpModel)
-        
-        XCTAssertEqual(events.count, 2)
-    }
-
-    func testEventBeforeStartDateIsFiltered() {
-        let datePast2007 = dateComponents2007.date!.addingTimeInterval(TimeInterval(minutes: 60))
-        
-        let batteryEvent2007 = createBatteryEvent(withDateComponent: dateComponents2007)
-        let batteryEvent2017 = createBatteryEvent(withDateComponent: dateComponents2017)
-        let page = HistoryPage(events: [batteryEvent2007, batteryEvent2017])
-        
-        let (events, hasMoreEvents, cancelled) = page.timestampedEvents(after: datePast2007, timeZone: pumpState.timeZone, model: pumpModel)
-        
-        assertArray(events, doesntContainPumpEvent: batteryEvent2007)
-        XCTAssertEqual(events.count, 1)
-        XCTAssertFalse(hasMoreEvents)
-        XCTAssertFalse(cancelled)
-    }
-
-    func testPumpLostTimeCancelsFetchEarly() {
-        let batteryEvent2007 = createBatteryEvent(withDateComponent: dateComponents2007)
-        let batteryEvent2017 = createBatteryEvent(withDateComponent: dateComponents2017)
-        let page = HistoryPage(events: [batteryEvent2017, batteryEvent2007])
-
-        let (events, hasMoreEvents, cancelledEarly) = page.timestampedEvents(after: Date.distantPast,  timeZone: pumpState.timeZone, model: pumpModel)
-
-        XCTAssertTrue(cancelledEarly)
-        XCTAssertFalse(hasMoreEvents)
-        XCTAssertEqual(events.count, 1)
-        assertArray(events, doesntContainPumpEvent: batteryEvent2017)
-    }
-    
-    func testEventsWithSameDataArentAddedTwice() {
-        let page = HistoryPage(events: [createBolusEvent2009(), createBolusEvent2009()])
-        let (events, _, _) = page.timestampedEvents(after: Date.distantPast, timeZone: pumpState.timeZone, model: pumpModel)
-        XCTAssertEqual(events.count, 1)
-    }
-
-    func testNonMutableSquareWaveBolusFor522IsReturned() {
-        // device that can have out of order events
-        setUpTestWithPumpModel(.model522)
-        // 2009-07-31 09:00:00 +0000
-        // 120 minute duration
-        let squareWaveBolus = BolusNormalPumpEvent(availableData: Data(hexadecimalString: "010080048000240009a24a1510")!, pumpModel: pumpModel)!
-        
-        let page = HistoryPage(events: [squareWaveBolus])
-        
-        let (timeStampedEvents, _, _) = page.timestampedEvents(after: .distantPast, timeZone: pumpState.timeZone, model: pumpModel)
-        
-        // It should be included
-        XCTAssertTrue(array(timeStampedEvents, containsPumpEvent: squareWaveBolus))
-    }
-
-    // This sets up a square wave bolus that has a timestamp four hours before a temp basal, but is appended to history
-    // "after" the temp basal.  This is an important condition to test, because the temp basal could be filtered out erroneously
-    // if we were just filtering on startDate, and startDate was after the bolus timestamp, but before the temp basal.
-    // Previously, convertPumpEventToTimestampedEvents was being called with startDate: Date.distantPast
-    // Changing it to use a time in that important window to cover
-    func testDelayedAppendEventDoesNotCauseValidEventsToBeFilteredOut() {
-        setUpTestWithPumpModel(.model522)
-
-        let tempEventBasal = createTempEventBasal2016()
-        let dateComponents = tempEventBasal.timestamp.addingTimeInterval(TimeInterval(hours:-4))
-        let squareBolusEventFourHoursBefore = createSquareBolusEvent(dateComponents: dateComponents)
-        
-        let page = HistoryPage(events: [tempEventBasal, squareBolusEventFourHoursBefore])
-        let (timeStampedEvents, hasMoreEvents, cancelled) = page.timestampedEvents(after: .distantPast, timeZone: pumpState.timeZone, model: pumpModel)
-
-        // Debatable (undefined) whether this should be returned. It is tested to avoid inadvertantly changing behavior
-        assertArray(timeStampedEvents, containsPumpEvent: squareBolusEventFourHoursBefore)
-        XCTAssertTrue(hasMoreEvents)
-        XCTAssertFalse(cancelled)
-    }
-
-    // MARK: Regular Bolus Event before starttime (offset 9 minutes)
-    func test522RegularBolusEventBeforeStartTimeShouldNotCancel() {
-        setUpTestWithPumpModel(.model522)
-        
-        let pumpEvent = createSquareBolusEvent2010()
-        let page = HistoryPage(events: [pumpEvent])
-        
-        let startDate = pumpEvent.timestamp.date!.addingTimeInterval(TimeInterval(minutes:9))
-        
-        let (timestampedEvents, hasMoreEvents, cancelled) = page.timestampedEvents(after: startDate, timeZone: pumpState.timeZone, model: pumpModel)
-        
-        assertArray(timestampedEvents, containsPumpEvent: pumpEvent)
-        //We found an event before the start time but we can't verify the timestamp from the Square Bolus so there could be more valid events
-        XCTAssertTrue(hasMoreEvents)
-        XCTAssertFalse(cancelled)
-    }
-
-    // The test the border condition sof the pump lost time detection, the main behavior of which is covered
-    // in testPumpLostTimeCancelsFetchEarly. The precise point at which we decide pump time is lost (the one hour mark) is aribtrary.
-    
-    func testOutOfOrderEventUnderAnHourDoesntCancel() {
-        setUpTestWithPumpModel(.model523)
-
-        let after2007Date = dateComponents2007.date!.addingTimeInterval(TimeInterval(minutes:59))
-
-        let batteryEvent = createBatteryEvent(withDateComponent: dateComponents2007)
-        let laterBatteryEvent = createBatteryEvent(atTime: after2007Date)
-
-        let page = HistoryPage(events: [laterBatteryEvent, batteryEvent])
-
-        let (_, _, cancelled) = page.timestampedEvents(after: .distantPast, timeZone: pumpState.timeZone, model: pumpModel)
-
-        XCTAssertFalse(cancelled)
-    }
-
-    // MARK: Test Sanity Checks
-    func test2010EventSanityWith523() {
-        setUpTestWithPumpModel(.model523)
-        let bolusEvent = createSquareBolusEvent2010()
-        XCTAssertEqual(bolusEvent.timestamp.year!, 2010)
-        XCTAssertEqual(bolusEvent.timestamp.timeZone, pumpState.timeZone)
-    }
-    
-    func test2009EventSanityWith523() {
-        setUpTestWithPumpModel(.model523)
-        let bolusEvent = createBolusEvent2009()
-        XCTAssertEqual(bolusEvent.timestamp.year!, 2009)
-        XCTAssertEqual(bolusEvent.timestamp.timeZone, pumpState.timeZone)
-    }
-    
-    func test2009EventSavityWith522() {
-        setUpTestWithPumpModel(.model522)
-        XCTAssertEqual(createBolusEvent2009().timestamp.year!, 2009)
-    }
-    
-    func test2010EventSanityWith522() {
-        setUpTestWithPumpModel(.model522)
-        XCTAssertEqual(createSquareBolusEvent2010().timestamp.year!, 2010)
-    }
-
-    func createBatteryEvent(withDateComponent dateComponents: DateComponents) -> BatteryPumpEvent {
-        return createBatteryEvent(atTime: dateComponents.date!)
-    }
-    
-    func createBatteryEvent(atTime date: Date = Date()) -> BatteryPumpEvent {
-     
-        let calendar = Calendar.current
-        
-        let year = calendar.component(.year, from: date) - 2000
-        let month = calendar.component(.month, from: date)
-        let day = calendar.component(.day, from: date)
-        let hour = calendar.component(.hour, from: date)
-        let minute = calendar.component(.minute, from: date)
-        let second = calendar.component(.second, from: date)
-        
-        let secondByte = UInt8(second) & 0b00111111
-        let minuteByte = UInt8(minute) & 0b00111111
-        let hourByte = UInt8(hour) & 0b00011111
-        let dayByte = UInt8(day) & 0b00011111
-        let monthUpperComponent = (UInt8(month) & 0b00001100) << 4
-        let monthLowerComponent = (UInt8(month) & 0b00000011) << 6
-        let secondMonthByte = secondByte | monthUpperComponent
-        let minuteMonthByte = minuteByte | monthLowerComponent
-        let yearByte = UInt8(year) & 0b01111111
-
-        let batteryData = Data([0,0, secondMonthByte, minuteMonthByte, hourByte, dayByte, yearByte])
-        let batteryPumpEvent = BatteryPumpEvent(availableData: batteryData, pumpModel: PumpModel.model523)!
-        return batteryPumpEvent
-    }
-    
-    func createSquareBolusEvent2010() -> BolusNormalPumpEvent {
-        //2010-08-01 05:00:16 +000
-        let dateComponents = DateComponents(calendar: Calendar.current, timeZone: pumpState.timeZone, year: 2010, month: 8, day: 1, hour: 5, minute: 0, second: 16)
-        let data = Data(hexadecimalString: "01009000900058008a344b1010")!
-        return BolusNormalPumpEvent(length: BolusNormalPumpEvent.calculateLength(pumpModel.larger), rawData: data, timestamp: dateComponents, unabsorbedInsulinRecord: nil, amount: 0.0, programmed: 0.0, unabsorbedInsulinTotal: 0.0, type: .square, duration: TimeInterval(minutes: 120), wasRemotelyTriggered: false)
-    }
-    
-    func createSquareBolusEvent(dateComponents: DateComponents) -> BolusNormalPumpEvent {
-        let data = Data(hexadecimalString: randomDataString(length: squareBolusDataLength))!
-        return BolusNormalPumpEvent(length: BolusNormalPumpEvent.calculateLength(pumpModel.larger), rawData: data, timestamp: dateComponents, unabsorbedInsulinRecord: nil, amount: 0.0, programmed: 0.0, unabsorbedInsulinTotal: 0.0, type: .square, duration: TimeInterval(hours: 8), wasRemotelyTriggered: false)
-    }
-    
-    func createBolusEvent2011() -> BolusNormalPumpEvent {
-        //2010-08-01 05:00:11 +000
-        let dateComponents = DateComponents(calendar: Calendar.current, timeZone: pumpState.timeZone, year: 2011, month: 8, day: 1, hour: 5, minute: 0, second: 16)
-        let data = Data(hexadecimalString: "01009000900058008a344b10FF")!
-        return BolusNormalPumpEvent(length: BolusNormalPumpEvent.calculateLength(pumpModel.larger), rawData: data, timestamp: dateComponents, unabsorbedInsulinRecord: nil, amount: 0.0, programmed: 0.0, unabsorbedInsulinTotal: 0.0, type: .normal, duration: TimeInterval(minutes: 120), wasRemotelyTriggered: false)
-    }
-    
-    func createTempEventBasal2016() -> TempBasalPumpEvent {
-        // 2016-05-30 01:21:00 +0000
-        let tempEventBasal = TempBasalPumpEvent(availableData: Data(hexadecimalString:"338c4055145d1000")!, pumpModel: pumpModel)!
-        return tempEventBasal
-    }
-    
-    func createBolusEvent2009() -> BolusNormalPumpEvent {
-        
-        let dateComponents = DateComponents(calendar: Calendar.current, timeZone: pumpState.timeZone, year: 2009, month: 7, day: 31, hour: 9, minute: 0, second: 0)
-        let timeInterval: TimeInterval = TimeInterval(minutes: 2)
-        let data = Data(hexadecimalString:"338c4055145d2000")!
-        
-        return BolusNormalPumpEvent(length: 13, rawData: data, timestamp: dateComponents, unabsorbedInsulinRecord: nil, amount: 2.0, programmed: 1.0, unabsorbedInsulinTotal: 0.0, type: .normal, duration: timeInterval, wasRemotelyTriggered: false)
-    }
-    
-    func createNonDelayedEvent2009() -> BolusReminderPumpEvent {
-        let dateComponents = DateComponents(calendar: Calendar.current, timeZone: pumpState.timeZone, year: 2009, month: 7, day: 31, hour: 9, minute: 0, second: 0)
-        let data = Data(hexadecimalString:"338c48FFF45d2000")!
-        let length = 7
-        
-        return BolusReminderPumpEvent(length: length, rawData: data, timestamp: dateComponents)
-    }
-}
-
-// from comment at https://gist.github.com/szhernovoy/276e69eb90a0de84dd90
-func randomDataString(length:Int) -> String {
-    let charSet = "abcdef0123456789"
-    let c = charSet.map { String($0) }
-    var s:String = ""
-    for _ in 0..<length {
-        s.append(c[Int(arc4random()) % c.count])
-    }
-    return s
-}
-
-class PumpMessageSenderStub: PumpMessageSender {
-    func getRileyLinkStatistics() throws -> RileyLinkStatistics {
-        throw PumpOpsError.noResponse(during: "Tests")
-    }
-    
-    func sendAndListen(_ data: Data, repeatCount: Int, timeout: TimeInterval, retryCount: Int) throws -> RFPacket {
-        guard let decoded = MinimedPacket(encodedData: data),
-              let messageType = MessageType(rawValue: decoded.data[4])
-        else {
-            throw PumpOpsError.noResponse(during: "Tests")
-        }
-
-        let response: PumpMessage
-
-        if let responseArray = responses[messageType] {
-            let numberOfResponsesReceived: Int
-
-            if let someValue = responsesHaveOccured[messageType] {
-                numberOfResponsesReceived = someValue
-            } else {
-                numberOfResponsesReceived = 0
-            }
-
-            let nextNumberOfResponsesReceived = numberOfResponsesReceived + 1
-            responsesHaveOccured[messageType] = nextNumberOfResponsesReceived
-
-            if numberOfResponsesReceived >= responseArray.count {
-                XCTFail()
-            }
-
-            response = responseArray[numberOfResponsesReceived]
-        } else {
-            response = PumpMessage(rxData: Data())!
-        }
-
-        var encoded = MinimedPacket(outgoingData: response.txData).encodedData()
-        encoded.insert(contentsOf: [0, 0], at: 0)
-        
-        guard let rfPacket = RFPacket(rfspyResponse: encoded) else {
-            throw PumpOpsError.noResponse(during: data)
-        }
-
-        return rfPacket
-    }
-
-    func listen(onChannel channel: Int, timeout: TimeInterval) throws -> RFPacket? {
-        throw PumpOpsError.noResponse(during: "Tests")
-    }
-
-    func send(_ data: Data, onChannel channel: Int, timeout: TimeInterval) throws {
-        // Do nothing
-    }
-
-    func updateRegister(_ address: CC111XRegister, value: UInt8) throws {
-        throw PumpOpsError.noResponse(during: "Tests")
-    }
-    
-    func resetRadioConfig() throws {
-        throw PumpOpsError.noResponse(during: "Tests")
-    }
-
-    func setBaseFrequency(_ frequency: Measurement<UnitFrequency>) throws {
-        throw PumpOpsError.noResponse(during: "Tests")
-    }
-    
-    func enableCCLEDs() throws {
-        throw PumpOpsError.noResponse(during: "Tests")
-    }
-    
-    var responses = [MessageType: [PumpMessage]]()
-    
-    // internal tracking of how many times a response type has been received
-    private var responsesHaveOccured = [MessageType: Int]()
-}
-
-extension PumpMessageSenderStub: PumpOpsSessionDelegate {
-    func pumpOpsSession(_ session: PumpOpsSession, didChange state: PumpState) {
-
-    }
-    
-    func pumpOpsSessionDidChangeRadioConfig(_ session: PumpOpsSession) {
-        
-    }
-
-}
-
-func array(_ timestampedEvents: [TimestampedHistoryEvent], containsPumpEvent pumpEvent: PumpEvent) -> Bool {
-    let event = timestampedEvents.first { $0.pumpEvent.rawData == pumpEvent.rawData }
-    
-    return event != nil
-}
-
-func assertArray(_ timestampedEvents: [TimestampedHistoryEvent], containsPumpEvent pumpEvent: PumpEvent) {
-    XCTAssertNotNil(timestampedEvents.first { $0.pumpEvent.rawData == pumpEvent.rawData})
-}
-
-func assertArray(_ timestampedEvents: [TimestampedHistoryEvent], containsPumpEvents pumpEvents: [PumpEvent]) {
-    pumpEvents.forEach { assertArray(timestampedEvents, containsPumpEvent: $0) }
-}
-
-func assertArray(_ timestampedEvents: [TimestampedHistoryEvent], doesntContainPumpEvent pumpEvent: PumpEvent) {
-    XCTAssertNil(timestampedEvents.first { $0.pumpEvent.rawData == pumpEvent.rawData })
-}
-
-// from http://jernejstrasner.com/2015/07/08/testing-throwable-methods-in-swift-2.html - transferred to Swift 3
-func assertThrows<T>(_ expression: @autoclosure  () throws -> T, _ message: String = "", file: StaticString = #file, line: UInt = #line) {
-    do {
-        let _ = try expression()
-        XCTFail("No error to catch! - \(message)", file: file, line: line)
-    } catch {
-    }
-}
-
-func assertNoThrow<T>(_ expression: @autoclosure  () throws -> T, _ message: String = "", file: StaticString = #file, line: UInt = #line) {
-    do {
-        let _ = try expression()
-    } catch let error {
-        XCTFail("Caught error: \(error) - \(message)", file: file, line: line)
-    }
-}
-
-extension DateComponents {
-    func addingTimeInterval(_ timeInterval: TimeInterval) -> DateComponents {
-        let newDate = self.date!.addingTimeInterval(timeInterval)
-        let newDateComponents = Calendar.current.dateComponents(in: TimeZone.currentFixed, from: newDate)
-        return newDateComponents
-    }
-}

+ 0 - 346
Dependecies/rileylink_ios/MinimedKitUI/CommandResponseViewController.swift

@@ -1,346 +0,0 @@
-//
-//  CommandResponseViewController.swift
-//  MinimedKitUI
-//
-//  Copyright © 2018 Pete Schwamb. All rights reserved.
-//
-
-import UIKit
-import LoopKit
-import LoopKitUI
-import MinimedKit
-import RileyLinkKit
-import RileyLinkBLEKit
-
-
-extension CommandResponseViewController {
-    typealias T = CommandResponseViewController
-
-    private static let successText = LocalizedString("Succeeded", comment: "A message indicating a command succeeded")
-
-    static func changeTime(ops: PumpOps?, device: RileyLinkDevice) -> T {
-        return T { (completionHandler) -> String in
-            ops?.runSession(withName: "Set time", using: device) { (session) in
-                let response: String
-                do {
-                    try session.setTimeToNow(in: .current)
-                    response = self.successText
-                } catch let error {
-                    response = String(describing: error)
-                }
-
-                DispatchQueue.main.async {
-                    completionHandler(response)
-                }
-            }
-
-            return LocalizedString("Changing time…", comment: "Progress message for changing pump time.")
-        }
-    }
-
-    static func changeTime(ops: PumpOps?, rileyLinkDeviceProvider: RileyLinkDeviceProvider) -> T {
-        return T { (completionHandler) -> String in
-            ops?.runSession(withName: "Set time", using: rileyLinkDeviceProvider.firstConnectedDevice) { (session) in
-                let response: String
-                do {
-                    guard let session = session else {
-                        throw PumpManagerError.connection(MinimedPumpManagerError.noRileyLink)
-                    }
-
-                    try session.setTimeToNow(in: .current)
-                    response = self.successText
-                } catch let error {
-                    response = String(describing: error)
-                }
-
-                DispatchQueue.main.async {
-                    completionHandler(response)
-                }
-            }
-
-            return LocalizedString("Changing time…", comment: "Progress message for changing pump time.")
-        }
-    }
-
-    static func discoverCommands(ops: PumpOps?, device: RileyLinkDevice) -> T {
-        return T { (completionHandler) -> String in
-            ops?.runSession(withName: "Discover Commands", using: device) { (session) in
-                session.discoverCommands(in: 0xf0...0xff, { (results) in
-                    DispatchQueue.main.async {
-                        completionHandler(results.joined(separator: "\n"))
-                    }
-                })
-            }
-
-            return LocalizedString("Discovering commands…", comment: "Progress message for discovering commands.")
-        }
-    }
-    
-    static func getStatistics(ops: PumpOps?, device: RileyLinkDevice) -> T {
-        return T { (completionHandler) -> String in
-            ops?.runSession(withName: "Get Statistics", using: device) { (session) in
-                let response: String
-                do {
-                    let stats = try session.getStatistics()
-                    response = String(describing: stats)
-                } catch let error {
-                    response = String(describing: error)
-                }
-
-                DispatchQueue.main.async {
-                    completionHandler(response)
-                }
-            }
-            
-            return LocalizedString("Get Statistics…", comment: "Progress message for getting statistics.")
-        }
-    }
-
-
-    static func dumpHistory(ops: PumpOps?, device: RileyLinkDevice) -> T {
-        return T { (completionHandler) -> String in
-            let calendar = Calendar(identifier: Calendar.Identifier.gregorian)
-            let oneDayAgo = calendar.date(byAdding: DateComponents(day: -1), to: Date())
-
-            ops?.runSession(withName: "Get history events", using: device) { (session) in
-                let response: String
-                do {
-                    let (events, _) = try session.getHistoryEvents(since: oneDayAgo!)
-                    var responseText = String(format: "Found %d events since %@", events.count, oneDayAgo! as NSDate)
-                    for event in events {
-                        responseText += String(format:"\nEvent: %@", event.dictionaryRepresentation)
-                    }
-
-                    response = responseText
-                } catch let error {
-                    response = String(describing: error)
-                }
-
-                DispatchQueue.main.async {
-                    completionHandler(response)
-                }
-            }
-
-            return LocalizedString("Fetching history…", comment: "Progress message for fetching pump history.")
-        }
-    }
-
-    static func fetchGlucose(ops: PumpOps?, device: RileyLinkDevice) -> T {
-        return T { (completionHandler) -> String in
-            let calendar = Calendar(identifier: Calendar.Identifier.gregorian)
-            let oneDayAgo = calendar.date(byAdding: DateComponents(day: -1), to: Date())
-
-            ops?.runSession(withName: "Get glucose history", using: device) { (session) in
-                let response: String
-                do {
-                    let events = try session.getGlucoseHistoryEvents(since: oneDayAgo!)
-                    var responseText = String(format: "Found %d events since %@", events.count, oneDayAgo! as NSDate)
-                    for event in events {
-                        responseText += String(format: "\nEvent: %@", event.dictionaryRepresentation)
-                    }
-
-                    response = responseText
-                } catch let error {
-                    response = String(describing: error)
-                }
-
-                DispatchQueue.main.async {
-                    completionHandler(response)
-                }
-            }
-
-            return LocalizedString("Fetching glucose…", comment: "Progress message for fetching pump glucose.")
-        }
-    }
-
-    static func getPumpModel(ops: PumpOps?, device: RileyLinkDevice) -> T {
-        return T { (completionHandler) -> String in
-            ops?.runSession(withName: "Get Pump Model", using: device) { (session) in
-                let response: String
-                do {
-                    let model = try session.getPumpModel(usingCache: false)
-                    response = "Pump Model: \(model)"
-                } catch let error {
-                    response = String(describing: error)
-                }
-
-                DispatchQueue.main.async {
-                    completionHandler(response)
-                }
-            }
-
-            return LocalizedString("Fetching pump model…", comment: "Progress message for fetching pump model.")
-        }
-    }
-
-    static func mySentryPair(ops: PumpOps?, device: RileyLinkDevice) -> T {
-        return T { (completionHandler) -> String in
-            var byteArray = [UInt8](repeating: 0, count: 16)
-            (device.peripheralIdentifier as NSUUID).getBytes(&byteArray)
-            let watchdogID = Data(byteArray[0..<3])
-
-            ops?.runSession(withName: "Change watchdog marriage profile", using: device) { (session) in
-                let response: String
-                do {
-                    try session.changeWatchdogMarriageProfile(watchdogID)
-                    response = self.successText
-                } catch let error {
-                    response = String(describing: error)
-                }
-
-                DispatchQueue.main.async {
-                    completionHandler(response)
-                }
-            }
-
-            return LocalizedString(
-                "On your pump, go to the Find Device screen and select \"Find Device\"." +
-                    "\n" +
-                    "\nMain Menu >" +
-                    "\nUtilities >" +
-                    "\nConnect Devices >" +
-                    "\nOther Devices >" +
-                    "\nOn >" +
-                "\nFind Device",
-                comment: "Pump find device instruction"
-            )
-        }
-    }
-
-    static func pressDownButton(ops: PumpOps?, device: RileyLinkDevice) -> T {
-        return T { (completionHandler) -> String in
-            ops?.runSession(withName: "Press down button", using: device) { (session) in
-                let response: String
-                do {
-                    try session.pressButton(.down)
-                    response = self.successText
-                } catch let error {
-                    response = String(describing: error)
-                }
-
-                DispatchQueue.main.async {
-                    completionHandler(response)
-                }
-            }
-
-            return LocalizedString("Sending button press…", comment: "Progress message for sending button press to pump.")
-        }
-    }
-
-    static func readBasalSchedule(ops: PumpOps?, device: RileyLinkDevice, integerFormatter: NumberFormatter) -> T {
-        return T { (completionHandler) -> String in
-            ops?.runSession(withName: "Get Basal Settings", using: device) { (session) in
-                let response: String
-                do {
-                    let schedule = try session.getBasalSchedule(for: .profileB)
-                    var str = String(format: LocalizedString("%1$@ basal schedule entries\n", comment: "The format string describing number of basal schedule entries: (1: number of entries)"), integerFormatter.string(from: NSNumber(value: schedule?.entries.count ?? 0))!)
-                    for entry in schedule?.entries ?? [] {
-                        str += "\(String(describing: entry))\n"
-                    }
-                    response = str
-                } catch let error {
-                    response = String(describing: error)
-                }
-
-                DispatchQueue.main.async {
-                    completionHandler(response)
-                }
-            }
-
-            return LocalizedString("Reading basal schedule…", comment: "Progress message for reading basal schedule")
-        }
-    }
-
-    static func enableLEDs(ops: PumpOps?, device: RileyLinkDevice) -> T {
-        return T { (completionHandler) -> String in
-            device.enableBLELEDs()
-            ops?.runSession(withName: "Enable LEDs", using: device) { (session) in
-                let response: String
-                do {
-                    try session.enableCCLEDs()
-                    response = "OK"
-                } catch let error {
-                    response = String(describing: error)
-                }
-
-                DispatchQueue.main.async {
-                    completionHandler(response)
-                }
-            }
-
-            return LocalizedString("Enabled Diagnostic LEDs", comment: "Progress message for enabling diagnostic LEDs")
-        }
-    }
-
-    static func readPumpStatus(ops: PumpOps?, device: RileyLinkDevice, measurementFormatter: MeasurementFormatter) -> T {
-        return T { (completionHandler) -> String in
-            ops?.runSession(withName: "Read pump status", using: device) { (session) in
-                let response: String
-                do {
-                    let status = try session.getCurrentPumpStatus()
-
-                    var str = String(format: LocalizedString("%1$@ Units of insulin remaining\n", comment: "The format string describing units of insulin remaining: (1: number of units)"), measurementFormatter.numberFormatter.string(from: NSNumber(value: status.reservoir))!)
-                    str += String(format: LocalizedString("Battery: %1$@ volts\n", comment: "The format string describing pump battery voltage: (1: battery voltage)"), measurementFormatter.string(from: status.batteryVolts))
-                    str += String(format: LocalizedString("Suspended: %1$@\n", comment: "The format string describing pump suspended state: (1: suspended)"), String(describing: status.suspended))
-                    str += String(format: LocalizedString("Bolusing: %1$@\n", comment: "The format string describing pump bolusing state: (1: bolusing)"), String(describing: status.bolusing))
-                    
-                    response = str
-                } catch let error {
-                    response = String(describing: error)
-                }
-
-                DispatchQueue.main.async {
-                    completionHandler(response)
-                }
-            }
-
-            return LocalizedString("Reading pump status…", comment: "Progress message for reading pump status")
-        }
-    }
-
-    static func tuneRadio(ops: PumpOps?, device: RileyLinkDevice, measurementFormatter: MeasurementFormatter) -> T {
-        return T { (completionHandler) -> String in
-            ops?.runSession(withName: "Tune pump", using: device) { (session) in
-                let response: String
-                do {
-                    let scanResult = try session.tuneRadio()
-
-                    var resultDict: [String: Any] = [:]
-
-                    let intFormatter = NumberFormatter()
-                    let formatString = LocalizedString("%1$@  %2$@/%3$@  %4$@", comment: "The format string for displaying a frequency tune trial. Extra spaces added for emphesis: (1: frequency in MHz)(2: success count)(3: total count)(4: average RSSI)")
-
-                    resultDict[LocalizedString("Best Frequency", comment: "The label indicating the best radio frequency")] = measurementFormatter.string(from: scanResult.bestFrequency)
-                    resultDict[LocalizedString("Trials", comment: "The label indicating the results of each frequency trial")] = scanResult.trials.map({ (trial) -> String in
-
-                        return String(
-                            format: formatString,
-                            measurementFormatter.string(from: trial.frequency),
-                            intFormatter.string(from: NSNumber(value: trial.successes))!,
-                            intFormatter.string(from: NSNumber(value: trial.tries))!,
-                            intFormatter.string(from: NSNumber(value: trial.avgRSSI))!
-                        )
-                    })
-
-                    var responseText: String
-
-                    if let data = try? JSONSerialization.data(withJSONObject: resultDict, options: .prettyPrinted), let string = String(data: data, encoding: .utf8) {
-                        responseText = string
-                    } else {
-                        responseText = LocalizedString("No response", comment: "Message display when no response from tuning pump")
-                    }
-
-                    response = responseText
-                } catch let error {
-                    response = String(describing: error)
-                }
-
-                DispatchQueue.main.async {
-                    completionHandler(response)
-                }
-            }
-
-            return LocalizedString("Tuning radio…", comment: "Progress message for tuning radio")
-        }
-    }
-}

+ 0 - 401
Dependecies/rileylink_ios/MinimedKitUI/MinimedPumpSettingsViewController.swift

@@ -1,401 +0,0 @@
-//
-//  MinimedPumpSettingsViewController.swift
-//  Loop
-//
-//  Copyright © 2018 LoopKit Authors. All rights reserved.
-//
-
-import UIKit
-import LoopKitUI
-import MinimedKit
-import RileyLinkKitUI
-import LoopKit
-
-class MinimedPumpSettingsViewController: RileyLinkSettingsViewController {
-
-    let pumpManager: MinimedPumpManager
-    
-    init(pumpManager: MinimedPumpManager) {
-        self.pumpManager = pumpManager
-        super.init(rileyLinkPumpManager: pumpManager, devicesSectionIndex: Section.rileyLinks.rawValue, style: .grouped)
-    }
-
-    required init?(coder aDecoder: NSCoder) {
-        fatalError("init(coder:) has not been implemented")
-    }
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-
-        title = LocalizedString("Pump Settings", comment: "Title of the pump settings view controller")
-
-        tableView.rowHeight = UITableView.automaticDimension
-        tableView.estimatedRowHeight = 44
-
-        tableView.sectionHeaderHeight = UITableView.automaticDimension
-        tableView.estimatedSectionHeaderHeight = 55
-
-        tableView.register(SettingsTableViewCell.self, forCellReuseIdentifier: SettingsTableViewCell.className)
-        tableView.register(TextButtonTableViewCell.self, forCellReuseIdentifier: TextButtonTableViewCell.className)
-        tableView.register(SuspendResumeTableViewCell.self, forCellReuseIdentifier: SuspendResumeTableViewCell.className)
-
-        let imageView = UIImageView(image: pumpManager.state.largePumpImage)
-        imageView.contentMode = .bottom
-        imageView.frame.size.height += 18  // feels right
-        tableView.tableHeaderView = imageView
-
-        pumpManager.addStatusObserver(self, queue: .main)
-
-        let button = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneTapped(_:)))
-        self.navigationItem.setRightBarButton(button, animated: false)
-
-    }
-
-    @objc func doneTapped(_ sender: Any) {
-        done()
-    }
-
-    private func done() {
-        if let nav = navigationController as? SettingsNavigationViewController {
-            nav.notifyComplete()
-        }
-        if let nav = navigationController as? MinimedPumpManagerSetupViewController {
-            nav.finishedSettingsDisplay()
-        }
-    }
-
-    override func viewWillAppear(_ animated: Bool) {
-        if clearsSelectionOnViewWillAppear {
-            // Manually invoke the delegate for rows deselecting on appear
-            for indexPath in tableView.indexPathsForSelectedRows ?? [] {
-                _ = tableView(tableView, willDeselectRowAt: indexPath)
-            }
-        }
-
-        super.viewWillAppear(animated)
-    }
-
-    // MARK: - Data Source
-
-    private enum Section: Int, CaseIterable {
-        case info = 0
-        case actions
-        case settings
-        case rileyLinks
-        case delete
-    }
-
-    private enum InfoRow: Int, CaseIterable {
-        case pumpID = 0
-        case pumpModel
-        case pumpFirmware
-        case pumpRegion
-    }
-
-    private enum ActionsRow: Int, CaseIterable {
-        case suspendResume = 0
-    }
-
-    private enum SettingsRow: Int, CaseIterable {
-        case timeZoneOffset = 0
-        case batteryChemistry
-        case preferredInsulinDataSource
-        case insulinType
-    }
-
-    // MARK: UITableViewDataSource
-
-    override func numberOfSections(in tableView: UITableView) -> Int {
-        return Section.allCases.count
-    }
-
-    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-        switch Section(rawValue: section)! {
-        case .info:
-            return InfoRow.allCases.count
-        case .actions:
-            return ActionsRow.allCases.count
-        case .settings:
-            return SettingsRow.allCases.count
-        case .rileyLinks:
-            return super.tableView(tableView, numberOfRowsInSection: section)
-        case .delete:
-            return 1
-        }
-    }
-
-    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
-        switch Section(rawValue: section)! {
-        case .settings:
-            return LocalizedString("Configuration", comment: "The title of the configuration section in settings")
-        case .rileyLinks:
-            return super.tableView(tableView, titleForHeaderInSection: section)
-        case .delete:
-            return " "  // Use an empty string for more dramatic spacing
-        case .info, .actions:
-            return nil
-        }
-    }
-
-    override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
-        switch Section(rawValue: section)! {
-        case .rileyLinks:
-            return super.tableView(tableView, viewForHeaderInSection: section)
-        case .info, .settings, .delete, .actions:
-            return nil
-        }
-    }
-
-    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        switch Section(rawValue: indexPath.section)! {
-        case .info:
-            switch InfoRow(rawValue: indexPath.row)! {
-            case .pumpID:
-                let cell = tableView.dequeueReusableCell(withIdentifier: SettingsTableViewCell.className, for: indexPath)
-                cell.textLabel?.text = LocalizedString("Pump ID", comment: "The title text for the pump ID config value")
-                cell.detailTextLabel?.text = pumpManager.state.pumpID
-                return cell
-            case .pumpModel:
-                let cell = tableView.dequeueReusableCell(withIdentifier: SettingsTableViewCell.className, for: indexPath)
-                cell.textLabel?.text = LocalizedString("Pump Model", comment: "The title of the cell showing the pump model number")
-                cell.detailTextLabel?.text = String(describing: pumpManager.state.pumpModel)
-                return cell
-            case .pumpFirmware:
-                let cell = tableView.dequeueReusableCell(withIdentifier: SettingsTableViewCell.className, for: indexPath)
-                cell.textLabel?.text = LocalizedString("Firmware Version", comment: "The title of the cell showing the pump firmware version")
-                cell.detailTextLabel?.text = String(describing: pumpManager.state.pumpFirmwareVersion)
-                return cell
-            case .pumpRegion:
-                let cell = tableView.dequeueReusableCell(withIdentifier: SettingsTableViewCell.className, for: indexPath)
-                cell.textLabel?.text = LocalizedString("Region", comment: "The title of the cell showing the pump region")
-                cell.detailTextLabel?.text = String(describing: pumpManager.state.pumpRegion)
-                return cell
-            }
-        case .actions:
-            switch ActionsRow(rawValue: indexPath.row)! {
-            case .suspendResume:
-                let cell = tableView.dequeueReusableCell(withIdentifier: SuspendResumeTableViewCell.className, for: indexPath) as! SuspendResumeTableViewCell
-                cell.basalDeliveryState = pumpManager.status.basalDeliveryState
-                return cell
-            }
-        case .settings:
-            let cell = tableView.dequeueReusableCell(withIdentifier: SettingsTableViewCell.className, for: indexPath)
-
-            switch SettingsRow(rawValue: indexPath.row)! {
-            case .batteryChemistry:
-                cell.textLabel?.text = LocalizedString("Pump Battery Type", comment: "The title text for the battery type value")
-                cell.detailTextLabel?.text = String(describing: pumpManager.batteryChemistry)
-            case .preferredInsulinDataSource:
-                cell.textLabel?.text = LocalizedString("Preferred Data Source", comment: "The title text for the preferred insulin data source config")
-                cell.detailTextLabel?.text = String(describing: pumpManager.preferredInsulinDataSource)
-            case .timeZoneOffset:
-                cell.textLabel?.text = LocalizedString("Change Time Zone", comment: "The title of the command to change pump time zone")
-
-                let localTimeZone = TimeZone.current
-                let localTimeZoneName = localTimeZone.abbreviation() ?? localTimeZone.identifier
-
-                let timeZoneDiff = TimeInterval(pumpManager.state.timeZone.secondsFromGMT() - localTimeZone.secondsFromGMT())
-                let formatter = DateComponentsFormatter()
-                formatter.allowedUnits = [.hour, .minute]
-                let diffString = timeZoneDiff != 0 ? formatter.string(from: abs(timeZoneDiff)) ?? String(abs(timeZoneDiff)) : ""
-
-                cell.detailTextLabel?.text = String(format: LocalizedString("%1$@%2$@%3$@", comment: "The format string for displaying an offset from a time zone: (1: GMT)(2: -)(3: 4:00)"), localTimeZoneName, timeZoneDiff != 0 ? (timeZoneDiff < 0 ? "-" : "+") : "", diffString)
-            case .insulinType:
-                cell.prepareForReuse()
-                cell.textLabel?.text = "Insulin Type"
-                cell.detailTextLabel?.text = pumpManager.insulinType?.brandName
-            }
-
-            cell.accessoryType = .disclosureIndicator
-            return cell
-        case .rileyLinks:
-            return super.tableView(tableView, cellForRowAt: indexPath)
-        case .delete:
-            let cell = tableView.dequeueReusableCell(withIdentifier: TextButtonTableViewCell.className, for: indexPath) as! TextButtonTableViewCell
-
-            cell.textLabel?.text = LocalizedString("Delete Pump", comment: "Title text for the button to remove a pump from Loop")
-            cell.textLabel?.textAlignment = .center
-            cell.tintColor = .deleteColor
-            cell.isEnabled = true
-            return cell
-        }
-    }
-
-    override func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
-        switch Section(rawValue: indexPath.section)! {
-        case .info:
-            return false
-        case .actions, .settings, .rileyLinks, .delete:
-            return true
-        }
-    }
-
-    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        let sender = tableView.cellForRow(at: indexPath)
-
-        switch Section(rawValue: indexPath.section)! {
-        case .info:
-            break
-        case .actions:
-            switch ActionsRow(rawValue: indexPath.row)! {
-            case .suspendResume:
-                suspendResumeCellTapped(sender as! SuspendResumeTableViewCell)
-                tableView.deselectRow(at: indexPath, animated: true)
-            }
-        case .settings:
-            switch SettingsRow(rawValue: indexPath.row)! {
-            case .timeZoneOffset:
-                let vc = CommandResponseViewController.changeTime(ops: pumpManager.pumpOps, rileyLinkDeviceProvider: pumpManager.rileyLinkDeviceProvider)
-                vc.title = sender?.textLabel?.text
-
-                show(vc, sender: indexPath)
-            case .batteryChemistry:
-                let vc = RadioSelectionTableViewController.batteryChemistryType(pumpManager.batteryChemistry)
-                vc.title = sender?.textLabel?.text
-                vc.delegate = self
-
-                show(vc, sender: sender)
-            case .preferredInsulinDataSource:
-                let vc = RadioSelectionTableViewController.insulinDataSource(pumpManager.preferredInsulinDataSource)
-                vc.title = sender?.textLabel?.text
-                vc.delegate = self
-
-                show(vc, sender: sender)
-            case .insulinType:
-                let view = InsulinTypeSetting(initialValue: pumpManager.insulinType ?? .novolog, supportedInsulinTypes: InsulinType.allCases) { (newType) in
-                    self.pumpManager.insulinType = newType
-                }
-                let vc = DismissibleHostingController(rootView: view)
-                vc.title = LocalizedString("Insulin Type", comment: "Controller title for insulin type selection screen")
-                
-                show(vc, sender: sender)
-            }
-        case .rileyLinks:
-            let device = devicesDataSource.devices[indexPath.row]
-
-            let vc = RileyLinkMinimedDeviceTableViewController(
-                device: device,
-                pumpOps: pumpManager.pumpOps
-            )
-
-            self.show(vc, sender: sender)
-        case .delete:
-            let confirmVC = UIAlertController(pumpDeletionHandler: {
-                self.pumpManager.notifyDelegateOfDeactivation {
-                    DispatchQueue.main.async {
-                        self.done()
-                    }
-                }
-            })
-
-            present(confirmVC, animated: true) {
-                tableView.deselectRow(at: indexPath, animated: true)
-            }
-        }
-    }
-
-    override func tableView(_ tableView: UITableView, willDeselectRowAt indexPath: IndexPath) -> IndexPath? {
-        switch Section(rawValue: indexPath.section)! {
-        case .settings:
-            switch SettingsRow(rawValue: indexPath.row)! {
-            case .timeZoneOffset, .insulinType:
-                tableView.reloadRows(at: [indexPath], with: .fade)
-            case .batteryChemistry:
-                break
-            case .preferredInsulinDataSource:
-                break
-            }
-        case .info, .actions, .rileyLinks, .delete:
-            break
-        }
-
-        return indexPath
-    }
-}
-
-
-extension MinimedPumpSettingsViewController: RadioSelectionTableViewControllerDelegate {
-    func radioSelectionTableViewControllerDidChangeSelectedIndex(_ controller: RadioSelectionTableViewController) {
-        guard let indexPath = self.tableView.indexPathForSelectedRow else {
-            return
-        }
-
-        switch Section(rawValue: indexPath.section)! {
-        case .settings:
-            switch SettingsRow(rawValue: indexPath.row)! {
-            case .preferredInsulinDataSource:
-                if let selectedIndex = controller.selectedIndex, let dataSource = InsulinDataSource(rawValue: selectedIndex) {
-                    pumpManager.preferredInsulinDataSource = dataSource
-                }
-            case .batteryChemistry:
-                if let selectedIndex = controller.selectedIndex, let dataSource = MinimedKit.BatteryChemistryType(rawValue: selectedIndex) {
-                    pumpManager.batteryChemistry = dataSource
-                }
-            default:
-                assertionFailure()
-            }
-        default:
-            assertionFailure()
-        }
-
-        tableView.reloadRows(at: [indexPath], with: .none)
-    }
-
-    private func suspendResumeCellTapped(_ cell: SuspendResumeTableViewCell) {
-        guard cell.isEnabled else {
-            return
-        }
-        
-        switch cell.shownAction {
-        case .resume:
-            pumpManager.resumeDelivery { (error) in
-                if let error = error {
-                    DispatchQueue.main.async {
-                        let title = LocalizedString("Error Resuming", comment: "The alert title for a resume error")
-                        self.present(UIAlertController(with: error, title: title), animated: true)
-                    }
-                }
-            }
-        case .suspend:
-            pumpManager.suspendDelivery { (error) in
-                if let error = error {
-                    DispatchQueue.main.async {
-                        let title = LocalizedString("Error Suspending", comment: "The alert title for a suspend error")
-                        self.present(UIAlertController(with: error, title: title), animated: true)
-                    }
-                }
-            }
-        default:
-            break
-        }
-    }
-}
-
-extension MinimedPumpSettingsViewController: PumpManagerStatusObserver {
-    public func pumpManager(_ pumpManager: PumpManager, didUpdate status: PumpManagerStatus, oldStatus: PumpManagerStatus) {
-        dispatchPrecondition(condition: .onQueue(.main))
-        let suspendResumeTableViewCell = self.tableView?.cellForRow(at: IndexPath(row: ActionsRow.suspendResume.rawValue, section: Section.actions.rawValue)) as! SuspendResumeTableViewCell
-        suspendResumeTableViewCell.basalDeliveryState = status.basalDeliveryState
-    }
-}
-
-private extension UIAlertController {
-    convenience init(pumpDeletionHandler handler: @escaping () -> Void) {
-        self.init(
-            title: nil,
-            message: LocalizedString("Are you sure you want to delete this pump?", comment: "Confirmation message for deleting a pump"),
-            preferredStyle: .actionSheet
-        )
-
-        addAction(UIAlertAction(
-            title: LocalizedString("Delete Pump", comment: "Button title to delete pump"),
-            style: .destructive,
-            handler: { (_) in
-                handler()
-            }
-        ))
-
-        let cancel = LocalizedString("Cancel", comment: "The title of the cancel action in an action sheet")
-        addAction(UIAlertAction(title: cancel, style: .cancel, handler: nil))
-    }
-}

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 37
Dependecies/rileylink_ios/MinimedKitUI/RadioSelectionTableViewController.swift


+ 0 - 570
Dependecies/rileylink_ios/MinimedKitUI/RileyLinkMinimedDeviceTableViewController.swift

@@ -1,570 +0,0 @@
-//
-//  RileyLinkMinimedDeviceTableViewController.swift
-//  Naterade
-//
-//  Created by Nathan Racklyeft on 3/5/16.
-//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
-//
-
-import UIKit
-import CoreBluetooth
-import LoopKitUI
-import MinimedKit
-import RileyLinkBLEKit
-import RileyLinkKit
-import RileyLinkKitUI
-
-let CellIdentifier = "Cell"
-
-public class RileyLinkMinimedDeviceTableViewController: UITableViewController {
-
-    public let device: RileyLinkDevice
-
-    private let ops: PumpOps
-
-    private var pumpState: PumpState? {
-        didSet {
-            // Update the UI if its visible
-            guard rssiFetchTimer != nil else { return }
-
-            if let cell = cellForRow(.awake) {
-                cell.setAwakeUntil(pumpState?.awakeUntil, formatter: dateFormatter)
-            }
-
-            if let cell = cellForRow(.model) {
-                cell.setPumpModel(pumpState?.pumpModel)
-            }
-            
-            if let cell = cellForRow(.tune) {
-                cell.setTuneInfo(lastValidFrequency: pumpState?.lastValidFrequency, lastTuned: pumpState?.lastTuned, measurementFormatter: measurementFormatter, dateFormatter: dateFormatter)
-            }
-        }
-    }
-
-    private var bleRSSI: Int?
-
-    private var firmwareVersion: String? {
-        didSet {
-            guard isViewLoaded else {
-                return
-            }
-            
-            cellForRow(.version)?.detailTextLabel?.text = firmwareVersion
-        }
-    }
-    
-    private var uptime: TimeInterval? {
-        didSet {
-            guard isViewLoaded else {
-                return
-            }
-            
-            cellForRow(.uptime)?.setDetailAge(uptime)
-        }
-    }
-
-    private var lastIdle: Date? {
-        didSet {
-            guard isViewLoaded else {
-                return
-            }
-
-            cellForRow(.idleStatus)?.setDetailDate(lastIdle, formatter: dateFormatter)
-        }
-    }
-    
-    private var rssiFetchTimer: Timer? {
-        willSet {
-            rssiFetchTimer?.invalidate()
-        }
-    }
-
-    private var appeared = false
-
-    public init(device: RileyLinkDevice, pumpOps: PumpOps) {
-        self.device = device
-        self.ops = pumpOps
-        self.pumpState = pumpOps.pumpState.value
-
-        super.init(style: .grouped)
-
-        updateDeviceStatus()
-    }
-
-    required public init?(coder aDecoder: NSCoder) {
-        fatalError("init(coder:) has not been implemented")
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-
-        title = device.name
-
-        self.observe()
-    }
-    
-    @objc func updateRSSI() {
-        device.readRSSI()
-    }
-    
-    func updateUptime() {
-        device.runSession(withName: "Get stats for uptime") { (session) in
-            do {
-                let statistics = try session.getRileyLinkStatistics()
-                DispatchQueue.main.async {
-                    self.uptime = statistics.uptime
-                }
-            } catch { }
-        }
-    }
-
-    private func updateDeviceStatus() {
-        device.getStatus { (status) in
-            DispatchQueue.main.async {
-                self.lastIdle = status.lastIdle
-                self.firmwareVersion = status.firmwareDescription
-            }
-        }
-    }
-
-    // References to registered notification center observers
-    private var notificationObservers: [Any] = []
-    
-    deinit {
-        for observer in notificationObservers {
-            NotificationCenter.default.removeObserver(observer)
-        }
-    }
-
-    private func observe() {
-        let center = NotificationCenter.default
-        let mainQueue = OperationQueue.main
-        
-        notificationObservers = [
-            center.addObserver(forName: .DeviceNameDidChange, object: device, queue: mainQueue) { [weak self] (note) -> Void in
-                if let cell = self?.cellForRow(.customName) {
-                    cell.detailTextLabel?.text = self?.device.name
-                }
-
-                self?.title = self?.device.name
-            },
-            center.addObserver(forName: .DeviceConnectionStateDidChange, object: device, queue: mainQueue) { [weak self] (note) -> Void in
-                if let cell = self?.cellForRow(.connection) {
-                    cell.detailTextLabel?.text = self?.device.peripheralState.description
-                }
-            },
-            center.addObserver(forName: .DeviceRSSIDidChange, object: device, queue: mainQueue) { [weak self] (note) -> Void in
-                self?.bleRSSI = note.userInfo?[RileyLinkDevice.notificationRSSIKey] as? Int
-
-                if let cell = self?.cellForRow(.rssi), let formatter = self?.integerFormatter {
-                    cell.setDetailRSSI(self?.bleRSSI, formatter: formatter)
-                }
-            },
-            center.addObserver(forName: .DeviceDidStartIdle, object: device, queue: mainQueue) { [weak self] (note) in
-                self?.updateDeviceStatus()
-            },
-            center.addObserver(forName: .PumpOpsStateDidChange, object: ops, queue: mainQueue) { [weak self] (note) in
-                if let state = note.userInfo?[PumpOps.notificationPumpStateKey] as? PumpState {
-                    self?.pumpState = state
-                }
-            }
-        ]
-    }
-    
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-
-        if appeared {
-            tableView.reloadData()
-        }
-        
-        rssiFetchTimer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(updateRSSI), userInfo: nil, repeats: true)
-        
-        appeared = true
-        
-        updateRSSI()
-        
-        updateUptime()
-    }
-    
-    public override func viewWillDisappear(_ animated: Bool) {
-        super.viewWillDisappear(animated)
-        rssiFetchTimer = nil
-    }
-
-
-    // MARK: - Formatters
-
-    private lazy var dateFormatter: DateFormatter = {
-        let dateFormatter = DateFormatter()
-
-        dateFormatter.dateStyle = .none
-        dateFormatter.timeStyle = .medium
-
-        return dateFormatter
-    }()
-    
-    private lazy var integerFormatter = NumberFormatter()
-
-    private lazy var measurementFormatter: MeasurementFormatter = {
-        let formatter = MeasurementFormatter()
-
-        formatter.numberFormatter = decimalFormatter
-
-        return formatter
-    }()
-
-    private lazy var decimalFormatter: NumberFormatter = {
-        let decimalFormatter = NumberFormatter()
-
-        decimalFormatter.numberStyle = .decimal
-        decimalFormatter.minimumSignificantDigits = 5
-
-        return decimalFormatter
-    }()
-
-    // MARK: - Table view data source
-
-    private enum Section: Int, CaseCountable {
-        case device
-        case pump
-        case commands
-    }
-
-    private enum DeviceRow: Int, CaseCountable {
-        case customName
-        case version
-        case rssi
-        case connection
-        case uptime
-        case idleStatus
-    }
-
-    private enum PumpRow: Int, CaseCountable {
-        case id
-        case model
-        case awake
-    }
-
-    private enum CommandRow: Int, CaseCountable {
-        case tune
-        case changeTime
-        case mySentryPair
-        case dumpHistory
-        case fetchGlucose
-        case getPumpModel
-        case pressDownButton
-        case readPumpStatus
-        case readBasalSchedule
-        case enableLED
-        case discoverCommands
-        case getStatistics
-    }
-
-    private func cellForRow(_ row: DeviceRow) -> UITableViewCell? {
-        return tableView.cellForRow(at: IndexPath(row: row.rawValue, section: Section.device.rawValue))
-    }
-
-    private func cellForRow(_ row: PumpRow) -> UITableViewCell? {
-        return tableView.cellForRow(at: IndexPath(row: row.rawValue, section: Section.pump.rawValue))
-    }
-
-    private func cellForRow(_ row: CommandRow) -> UITableViewCell? {
-        return tableView.cellForRow(at: IndexPath(row: row.rawValue, section: Section.commands.rawValue))
-    }
-
-    public override func numberOfSections(in tableView: UITableView) -> Int {
-        return Section.count
-    }
-
-    public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-        switch Section(rawValue: section)! {
-        case .device:
-            return DeviceRow.count
-        case .pump:
-            return PumpRow.count
-        case .commands:
-            return CommandRow.count
-        }
-    }
-
-    public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        let cell: UITableViewCell
-
-        if let reusableCell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier) {
-            cell = reusableCell
-        } else {
-            cell = UITableViewCell(style: .value1, reuseIdentifier: CellIdentifier)
-        }
-
-        cell.accessoryType = .none
-
-        switch Section(rawValue: indexPath.section)! {
-        case .device:
-            switch DeviceRow(rawValue: indexPath.row)! {
-            case .customName:
-                cell.textLabel?.text = LocalizedString("Name", comment: "The title of the cell showing device name")
-                cell.detailTextLabel?.text = device.name
-                cell.accessoryType = .disclosureIndicator
-            case .version:
-                cell.textLabel?.text = LocalizedString("Firmware", comment: "The title of the cell showing firmware version")
-                cell.detailTextLabel?.text = firmwareVersion
-            case .connection:
-                cell.textLabel?.text = LocalizedString("Connection State", comment: "The title of the cell showing BLE connection state")
-                cell.detailTextLabel?.text = device.peripheralState.description
-            case .rssi:
-                cell.textLabel?.text = LocalizedString("Signal Strength", comment: "The title of the cell showing BLE signal strength (RSSI)")
-                cell.setDetailRSSI(bleRSSI, formatter: integerFormatter)
-            case .uptime:
-                cell.textLabel?.text = LocalizedString("Uptime", comment: "The title of the cell showing uptime")
-                cell.setDetailAge(uptime)
-            case .idleStatus:
-                cell.textLabel?.text = LocalizedString("On Idle", comment: "The title of the cell showing the last idle")
-                cell.setDetailDate(lastIdle, formatter: dateFormatter)
-            }
-        case .pump:
-            switch PumpRow(rawValue: indexPath.row)! {
-            case .id:
-                cell.textLabel?.text = LocalizedString("Pump ID", comment: "The title of the cell showing pump ID")
-                cell.detailTextLabel?.text = ops.pumpSettings.pumpID
-            case .model:
-                cell.textLabel?.text = LocalizedString("Pump Model", comment: "The title of the cell showing the pump model number")
-                cell.setPumpModel(pumpState?.pumpModel)
-            case .awake:
-                cell.setAwakeUntil(pumpState?.awakeUntil, formatter: dateFormatter)
-            }
-        case .commands:
-            cell.accessoryType = .disclosureIndicator
-            cell.detailTextLabel?.text = nil
-
-            switch CommandRow(rawValue: indexPath.row)! {
-            case .tune:
-                cell.setTuneInfo(lastValidFrequency: pumpState?.lastValidFrequency, lastTuned: pumpState?.lastTuned, measurementFormatter: measurementFormatter, dateFormatter: dateFormatter)
-            case .changeTime:
-                cell.textLabel?.text = LocalizedString("Change Time", comment: "The title of the command to change pump time")
-
-                let localTimeZone = TimeZone.current
-                let localTimeZoneName = localTimeZone.abbreviation() ?? localTimeZone.identifier
-
-                if let pumpTimeZone = pumpState?.timeZone {
-                    let timeZoneDiff = TimeInterval(pumpTimeZone.secondsFromGMT() - localTimeZone.secondsFromGMT())
-                    let formatter = DateComponentsFormatter()
-                    formatter.allowedUnits = [.hour, .minute]
-                    let diffString = timeZoneDiff != 0 ? formatter.string(from: abs(timeZoneDiff)) ?? String(abs(timeZoneDiff)) : ""
-
-                    cell.detailTextLabel?.text = String(format: LocalizedString("%1$@%2$@%3$@", comment: "The format string for displaying an offset from a time zone: (1: GMT)(2: -)(3: 4:00)"), localTimeZoneName, timeZoneDiff != 0 ? (timeZoneDiff < 0 ? "-" : "+") : "", diffString)
-                } else {
-                    cell.detailTextLabel?.text = localTimeZoneName
-                }
-            case .mySentryPair:
-                cell.textLabel?.text = LocalizedString("MySentry Pair", comment: "The title of the command to pair with mysentry")
-
-            case .dumpHistory:
-                cell.textLabel?.text = LocalizedString("Fetch Recent History", comment: "The title of the command to fetch recent history")
-
-            case .fetchGlucose:
-                cell.textLabel?.text = LocalizedString("Fetch Enlite Glucose", comment: "The title of the command to fetch recent glucose")
-                
-            case .getPumpModel:
-                cell.textLabel?.text = LocalizedString("Get Pump Model", comment: "The title of the command to get pump model")
-
-            case .pressDownButton:
-                cell.textLabel?.text = LocalizedString("Send Button Press", comment: "The title of the command to send a button press")
-
-            case .readPumpStatus:
-                cell.textLabel?.text = LocalizedString("Read Pump Status", comment: "The title of the command to read pump status")
-
-            case .readBasalSchedule:
-                cell.textLabel?.text = LocalizedString("Read Basal Schedule", comment: "The title of the command to read basal schedule")
-            
-            case .enableLED:
-                cell.textLabel?.text = LocalizedString("Enable Diagnostic LEDs", comment: "The title of the command to enable diagnostic LEDs")
-
-            case .discoverCommands:
-                cell.textLabel?.text = LocalizedString("Discover Commands", comment: "The title of the command to discover commands")
-                
-            case .getStatistics:
-                cell.textLabel?.text = LocalizedString("RileyLink Statistics", comment: "The title of the command to fetch RileyLink statistics")
-            }
-        }
-
-        return cell
-    }
-
-    public override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
-        switch Section(rawValue: section)! {
-        case .device:
-            return LocalizedString("Device", comment: "The title of the section describing the device")
-        case .pump:
-            return LocalizedString("Pump", comment: "The title of the section describing the pump")
-        case .commands:
-            return LocalizedString("Commands", comment: "The title of the section describing commands")
-        }
-    }
-
-    // MARK: - UITableViewDelegate
-
-    public override func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
-        switch Section(rawValue: indexPath.section)! {
-        case .device:
-            switch DeviceRow(rawValue: indexPath.row)! {
-            case .customName:
-                return true
-            default:
-                return false
-            }
-        case .pump:
-            return false
-        case .commands:
-            return device.peripheralState == .connected
-        }
-    }
-
-    public override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        switch Section(rawValue: indexPath.section)! {
-        case .device:
-            switch DeviceRow(rawValue: indexPath.row)! {
-            case .customName:
-                let vc = TextFieldTableViewController()
-                if let cell = tableView.cellForRow(at: indexPath) {
-                    vc.title = cell.textLabel?.text
-                    vc.value = device.name
-                    vc.delegate = self
-                    vc.keyboardType = .default
-                }
-
-                show(vc, sender: indexPath)
-            default:
-                break
-            }
-        case .commands:
-            let vc: CommandResponseViewController
-
-            switch CommandRow(rawValue: indexPath.row)! {
-            case .tune:
-                vc = .tuneRadio(ops: ops, device: device, measurementFormatter: measurementFormatter)
-            case .changeTime:
-                vc = .changeTime(ops: ops, device: device)
-            case .mySentryPair:
-                vc = .mySentryPair(ops: ops, device: device)
-            case .dumpHistory:
-                vc = .dumpHistory(ops: ops, device: device)
-            case .fetchGlucose:
-                vc = .fetchGlucose(ops: ops, device: device)
-            case .getPumpModel:
-                vc = .getPumpModel(ops: ops, device: device)
-            case .pressDownButton:
-                vc = .pressDownButton(ops: ops, device: device)
-            case .readPumpStatus:
-                vc = .readPumpStatus(ops: ops, device: device, measurementFormatter: measurementFormatter)
-            case .readBasalSchedule:
-                vc = .readBasalSchedule(ops: ops, device: device, integerFormatter: integerFormatter)
-            case .enableLED:
-                vc = .enableLEDs(ops: ops, device: device)
-            case .discoverCommands:
-                vc = .discoverCommands(ops: ops, device: device)
-            case .getStatistics:
-                vc = .getStatistics(ops: ops, device: device)
-            }
-
-            if let cell = tableView.cellForRow(at: indexPath) {
-                vc.title = cell.textLabel?.text
-            }
-
-            show(vc, sender: indexPath)
-        case .pump:
-            break
-        }
-    }
-}
-
-
-extension RileyLinkMinimedDeviceTableViewController: TextFieldTableViewControllerDelegate {
-    public func textFieldTableViewControllerDidReturn(_ controller: TextFieldTableViewController) {
-        _ = navigationController?.popViewController(animated: true)
-    }
-
-    public func textFieldTableViewControllerDidEndEditing(_ controller: TextFieldTableViewController) {
-        if let indexPath = tableView.indexPathForSelectedRow {
-            switch Section(rawValue: indexPath.section)! {
-            case .device:
-                switch DeviceRow(rawValue: indexPath.row)! {
-                case .customName:
-                    device.setCustomName(controller.value!)
-                default:
-                    break
-                }
-            default:
-                break
-
-            }
-        }
-    }
-}
-
-private extension TimeInterval {
-    func format(using units: NSCalendar.Unit) -> String? {
-        let formatter = DateComponentsFormatter()
-        formatter.allowedUnits = units
-        formatter.unitsStyle = .full
-        formatter.zeroFormattingBehavior = .dropLeading
-        formatter.maximumUnitCount = 2
-        
-        return formatter.string(from: self)
-    }
-}
-
-
-private extension UITableViewCell {
-    func setDetailDate(_ date: Date?, formatter: DateFormatter) {
-        if let date = date {
-            detailTextLabel?.text = formatter.string(from: date)
-        } else {
-            detailTextLabel?.text = "-"
-        }
-    }
-
-    func setDetailRSSI(_ decibles: Int?, formatter: NumberFormatter) {
-        detailTextLabel?.text = formatter.decibleString(from: decibles) ?? "-"
-    }
-
-    func setDetailAge(_ age: TimeInterval?) {
-        if let age = age {
-            detailTextLabel?.text = age.format(using: [.day, .hour, .minute])
-        } else {
-            detailTextLabel?.text = ""
-        }
-    }
-    
-    func setAwakeUntil(_ awakeUntil: Date?, formatter: DateFormatter) {
-        switch awakeUntil {
-        case let until? where until.timeIntervalSinceNow < 0:
-            textLabel?.text = LocalizedString("Last Awake", comment: "The title of the cell describing an awake radio")
-            setDetailDate(until, formatter: formatter)
-        case let until?:
-            textLabel?.text = LocalizedString("Awake Until", comment: "The title of the cell describing an awake radio")
-            setDetailDate(until, formatter: formatter)
-        default:
-            textLabel?.text = LocalizedString("Listening Off", comment: "The title of the cell describing no radio awake data")
-            detailTextLabel?.text = nil
-        }
-    }
-
-    func setPumpModel(_ pumpModel: PumpModel?) {
-        if let pumpModel = pumpModel {
-            detailTextLabel?.text = String(describing: pumpModel)
-        } else {
-            detailTextLabel?.text = LocalizedString("Unknown", comment: "The detail text for an unknown pump model")
-        }
-    }
-    
-    func setTuneInfo(lastValidFrequency: Measurement<UnitFrequency>?, lastTuned: Date?, measurementFormatter: MeasurementFormatter, dateFormatter: DateFormatter) {
-        if let frequency = lastValidFrequency, let date = lastTuned {
-            textLabel?.text = measurementFormatter.string(from: frequency)
-            setDetailDate(date, formatter: dateFormatter)
-        } else {
-            textLabel?.text = LocalizedString("Tune Radio Frequency", comment: "The title of the command to re-tune the radio")
-        }
-    }
-
-}

+ 0 - 253
Dependecies/rileylink_ios/OmniKit/MessageTransport/MessageBlocks/DetailedStatus.swift

@@ -1,253 +0,0 @@
-//
-//  DetailedStatus.swift
-//  OmniKit
-//
-//  Created by Pete Schwamb on 2/23/18.
-//  Copyright © 2018 Pete Schwamb. All rights reserved.
-//
-
-import Foundation
-
-// DetailedStatus is the PodInfo subtype 2 returned for a type 2 GetStatus command and
-// is also returned on a pod fault for any command normally returning a StatusResponse
-public struct DetailedStatus : PodInfo, Equatable {
-    // CMD 1  2  3  4  5 6  7  8 9 10 1112 1314 1516 17 18 19 20 21 2223
-    // DATA   0  1  2  3 4  5  6 7  8  910 1112 1314 15 16 17 18 19 2021
-    // 02 16 02 0J 0K LLLL MM NNNN PP QQQQ RRRR SSSS TT UU VV WW 0X YYYY
-
-    public let podInfoType: PodInfoResponseSubType = .detailedStatus
-    public let podProgressStatus: PodProgressStatus
-    public let deliveryStatus: DeliveryStatus
-    public let bolusNotDelivered: Double
-    public let podMessageCounter: UInt8
-    public let totalInsulinDelivered: Double
-    public let faultEventCode: FaultEventCode
-    public let faultEventTimeSinceActivation: TimeInterval?
-    public let reservoirLevel: Double?
-    public let timeActive: TimeInterval
-    public let unacknowledgedAlerts: AlertSet
-    public let faultAccessingTables: Bool
-    public let errorEventInfo: ErrorEventInfo?
-    public let receiverLowGain: UInt8
-    public let radioRSSI: UInt8
-    public let previousPodProgressStatus: PodProgressStatus?
-    public let unknownValue: Data
-    public let data: Data
-    
-    public init(encodedData: Data) throws {
-        guard encodedData.count >= 21 else {
-            throw MessageBlockError.notEnoughData
-        }
-        
-        guard PodProgressStatus(rawValue: encodedData[1]) != nil else {
-            throw MessageError.unknownValue(value: encodedData[1], typeDescription: "PodProgressStatus")
-        }
-        self.podProgressStatus = PodProgressStatus(rawValue: encodedData[1])!
-        
-        self.deliveryStatus = DeliveryStatus(rawValue: encodedData[2] & 0xf)!
-        
-        self.bolusNotDelivered = Pod.pulseSize * Double((Int(encodedData[3] & 0x3) << 8) | Int(encodedData[4]))
-        
-        self.podMessageCounter = encodedData[5]
-        
-        self.totalInsulinDelivered = Pod.pulseSize * Double(encodedData[6...7].toBigEndian(UInt16.self))
-        
-        self.faultEventCode = FaultEventCode(rawValue: encodedData[8])
-        
-        let minutesSinceActivation = encodedData[9...10].toBigEndian(UInt16.self)
-        if minutesSinceActivation != 0xffff {
-            self.faultEventTimeSinceActivation = TimeInterval(minutes: Double(minutesSinceActivation))
-        } else {
-            self.faultEventTimeSinceActivation = nil
-        }
-        
-        let reservoirValue = Double((Int(encodedData[11] & 0x3) << 8) + Int(encodedData[12])) * Pod.pulseSize
-        
-        if reservoirValue <= Pod.maximumReservoirReading {
-            self.reservoirLevel = reservoirValue
-        } else {
-            self.reservoirLevel =  nil
-        }
-        
-        self.timeActive = TimeInterval(minutes: Double(encodedData[13...14].toBigEndian(UInt16.self)))
-        
-        self.unacknowledgedAlerts =  AlertSet(rawValue: encodedData[15])
-        
-        self.faultAccessingTables = encodedData[16] == 2
-        
-        if encodedData[17] == 0x00 {
-           self.errorEventInfo = nil // this byte is not valid (no fault has occurred)
-        } else {
-            self.errorEventInfo = ErrorEventInfo(rawValue: encodedData[17])
-        }
-        
-        self.receiverLowGain = UInt8(encodedData[18] >> 6)
-        self.radioRSSI =  UInt8(encodedData[18] & 0x3F)
-        
-        if encodedData[19] == 0xFF {
-            self.previousPodProgressStatus = nil // this byte is not valid (no fault has occurred)
-        } else {
-            self.previousPodProgressStatus = PodProgressStatus(rawValue: encodedData[19] & 0xF)!
-        }
-        
-        self.unknownValue = encodedData[20...21]
-        
-        self.data = Data(encodedData)
-    }
-
-    public var isFaulted: Bool {
-        return faultEventCode.faultType != .noFaults || podProgressStatus == .activationTimeExceeded
-    }
-
-    // Returns an appropropriate PDM style Ref string for the Detailed Status.
-    // For most types, Ref: TT-VVVHH-IIIRR-FFF computed as {19|17}-{VV}{SSSS/60}-{NNNN/20}{RRRR/20}-PP
-    public var pdmRef: String? {
-        let TT, VVV, HH, III, RR, FFF: UInt8
-        let refStr = LocalizedString("Ref", comment: "PDM style 'Ref' string")
-
-        switch faultEventCode.faultType {
-        case .noFaults, .reservoirEmpty, .exceededMaximumPodLife80Hrs:
-            return nil      // no PDM Ref # generated for these cases
-        case .insulinDeliveryCommandError:
-            // This fault is treated as a PDM fault which uses an alternate Ref format
-            return String(format: "%@:\u{00a0}11-144-0018-00049", refStr) // all fixed values for this fault
-        case .occluded:
-            // Ref: 17-000HH-IIIRR-000
-            TT = 17         // Occlusion detected Ref type
-            VVV = 0         // no VVV value for an occlusion fault
-            FFF = 0         // no FFF value for an occlusion fault
-        default:
-            // Ref: 19-VVVHH-IIIRR-FFF
-            TT = 19         // pod fault Ref type
-            VVV = data[17]  // use the raw VV byte value
-            FFF = faultEventCode.rawValue
-        }
-
-        HH = UInt8(timeActive.hours)
-        III = UInt8(totalInsulinDelivered)
-
-        if let reservoirLevel = self.reservoirLevel {
-            RR = UInt8(reservoirLevel)
-        } else {
-            RR = 51         // value used for 50+ U
-        }
-
-        return String(format: "%@:\u{00a0}%02d-%03d%02d-%03d%02d-%03d", refStr, TT, VVV, HH, III, RR, FFF)
-    }
-}
-
-extension DetailedStatus: CustomDebugStringConvertible {
-    public typealias RawValue = Data
-    public var debugDescription: String {
-        return [
-            "## DetailedStatus",
-            "* rawHex: \(data.hexadecimalString)",
-            "* podProgressStatus: \(podProgressStatus)",
-            "* deliveryStatus: \(deliveryStatus.description)",
-            "* bolusNotDelivered: \(bolusNotDelivered.twoDecimals) U",
-            "* podMessageCounter: \(podMessageCounter)",
-            "* totalInsulinDelivered: \(totalInsulinDelivered.twoDecimals) U",
-            "* faultEventCode: \(faultEventCode.description)",
-            "* faultEventTimeSinceActivation: \(faultEventTimeSinceActivation?.stringValue ?? "none")",
-            "* reservoirLevel: \(reservoirLevel?.twoDecimals ?? "50+") U",
-            "* timeActive: \(timeActive.stringValue)",
-            "* unacknowledgedAlerts: \(unacknowledgedAlerts)",
-            "* faultAccessingTables: \(faultAccessingTables)",
-            "* errorEventInfo: \(errorEventInfo?.description ?? "NA")",
-            "* receiverLowGain: \(receiverLowGain)",
-            "* radioRSSI: \(radioRSSI)",
-            "* previousPodProgressStatus: \(previousPodProgressStatus?.description ?? "NA")",
-            "* unknownValue: 0x\(unknownValue.hexadecimalString)",
-            "",
-            ].joined(separator: "\n")
-    }
-}
-
-extension DetailedStatus: RawRepresentable {
-    public init?(rawValue: Data) {
-        do {
-            try self.init(encodedData: rawValue)
-        } catch {
-            return nil
-        }
-    }
-    
-    public var rawValue: Data {
-        return data
-    }
-}
-
-extension TimeInterval {
-    var stringValue: String {
-        let totalSeconds = self
-        let minutes = Int(totalSeconds / 60) % 60
-        let hours = Int(totalSeconds / 3600) - (Int(self / 3600)/24 * 24)
-        let days = Int((totalSeconds / 3600) / 24)
-        var pluralFormOfDays = "days"
-        if days == 1 {
-            pluralFormOfDays = "day"
-        }
-        let timeComponent = String(format: "%02d:%02d", hours, minutes)
-        if days > 0 {
-            return String(format: "%d \(pluralFormOfDays) plus %@", days, timeComponent)
-        } else {
-            return timeComponent
-        }
-    }
-}
-
-extension Double {
-    var twoDecimals: String {
-        let reservoirLevel = self
-        return String(format: "%.2f", reservoirLevel)
-    }
-}
-
-// Type for the ErrorEventInfo VV byte if valid
-//    a: insulin state table corruption found during error logging
-//   bb: internal 2-bit variable set and manipulated in main loop routines
-//    c: immediate bolus in progress during error
-// dddd: Pod Progress at time of first logged fault event
-//
-public struct ErrorEventInfo: CustomStringConvertible, Equatable {
-    let rawValue: UInt8
-    let insulinStateTableCorruption: Bool // 'a' bit
-    let internalVariable: Int // 'bb' 2-bit internal variable
-    let immediateBolusInProgress: Bool // 'c' bit
-    let podProgressStatus: PodProgressStatus // 'dddd' bits
-
-    public var errorEventInfo: ErrorEventInfo? {
-        return ErrorEventInfo(rawValue: rawValue)
-    }
-
-    public var description: String {
-        let hexString = String(format: "%02X", rawValue)
-        return [
-            "rawValue: 0x\(hexString)",
-            "insulinStateTableCorruption: \(insulinStateTableCorruption)",
-            "internalVariable: \(internalVariable)",
-            "immediateBolusInProgress: \(immediateBolusInProgress)",
-            "podProgressStatus: \(podProgressStatus)",
-            ].joined(separator: ", ")
-    }
-
-    init(rawValue: UInt8)  {
-        self.rawValue = rawValue
-        self.insulinStateTableCorruption = (rawValue & 0x80) != 0
-        self.internalVariable = Int((rawValue & 0x60) >> 5)
-        self.immediateBolusInProgress = (rawValue & 0x10) != 0
-        self.podProgressStatus = PodProgressStatus(rawValue: rawValue & 0xF)!
-    }
-}
-
-
-extension DetailedStatus {
-    var highlightText: String {
-        switch faultEventCode.faultType {
-        case .exceededMaximumPodLife80Hrs:
-            return LocalizedString("Pod Expired", comment: "Highlight string for pod expired (80hrs).")
-        default:
-            return LocalizedString("Pod Fault", comment: "Highlight string for pod faults.")
-        }
-    }
-}

+ 0 - 71
Dependecies/rileylink_ios/OmniKit/MessageTransport/MessageBlocks/StatusResponse.swift

@@ -1,71 +0,0 @@
-//
-//  StatusResponse.swift
-//  OmniKit
-//
-//  Created by Pete Schwamb on 10/23/17.
-//  Copyright © 2017 Pete Schwamb. All rights reserved.
-//
-
-import Foundation
-
-public struct StatusResponse : MessageBlock {
-    public let blockType: MessageBlockType = .statusResponse
-    public let length: UInt8 = 10
-    public let deliveryStatus: DeliveryStatus
-    public let podProgressStatus: PodProgressStatus
-    public let timeActive: TimeInterval
-    public let reservoirLevel: Double?
-    public let insulin: Double
-    public let bolusNotDelivered: Double
-    public let podMessageCounter: UInt8
-    public let alerts: AlertSet
-    
-    
-    public let data: Data
-    
-    public init(encodedData: Data) throws {
-        if encodedData.count < length {
-            throw MessageBlockError.notEnoughData
-        }
-        
-        data = encodedData.prefix(upTo: Int(length))
-        
-        guard let deliveryStatus = DeliveryStatus(rawValue: encodedData[1] >> 4) else {
-            throw MessageError.unknownValue(value: encodedData[1] >> 4, typeDescription: "DeliveryStatus")
-        }
-        self.deliveryStatus = deliveryStatus
-        
-        guard let podProgressStatus = PodProgressStatus(rawValue: encodedData[1] & 0xf) else {
-            throw MessageError.unknownValue(value: encodedData[1] & 0xf, typeDescription: "PodProgressStatus")
-        }
-        self.podProgressStatus = podProgressStatus
-
-        let minutes = ((Int(encodedData[7]) & 0x7f) << 6) + (Int(encodedData[8]) >> 2)
-        self.timeActive = TimeInterval(minutes: Double(minutes))
-        
-        let highInsulinBits = Int(encodedData[2] & 0xf) << 9
-        let midInsulinBits = Int(encodedData[3]) << 1
-        let lowInsulinBits = Int(encodedData[4] >> 7)
-        self.insulin = Double(highInsulinBits | midInsulinBits | lowInsulinBits) / Pod.pulsesPerUnit
-        
-        self.podMessageCounter = (encodedData[4] >> 3) & 0xf
-        
-        self.bolusNotDelivered = Double((Int(encodedData[4] & 0x3) << 8) | Int(encodedData[5])) / Pod.pulsesPerUnit
-
-        self.alerts = AlertSet(rawValue: ((encodedData[6] & 0x7f) << 1) | (encodedData[7] >> 7))
-        
-        let reservoirValue = Double((Int(encodedData[8] & 0x3) << 8) + Int(encodedData[9])) / Pod.pulsesPerUnit
-        if reservoirValue <= Pod.maximumReservoirReading {
-                self.reservoirLevel = reservoirValue
-        } else {
-            self.reservoirLevel = nil
-        }
-    }
-}
-
-extension StatusResponse: CustomDebugStringConvertible {
-    public var debugDescription: String {
-        return "StatusResponse(deliveryStatus:\(deliveryStatus), progressStatus:\(podProgressStatus), timeActive:\(timeActive.stringValue), reservoirLevel:\(String(describing: reservoirLevel)), delivered:\(insulin), bolusNotDelivered:\(bolusNotDelivered), seq:\(podMessageCounter), alerts:\(alerts))"
-    }
-}
-

+ 0 - 122
Dependecies/rileylink_ios/OmniKit/MessageTransport/MessageBlocks/VersionResponse.swift

@@ -1,122 +0,0 @@
-//
-//  VersionResponse.swift
-//  OmniKit
-//
-//  Created by Pete Schwamb on 2/12/18.
-//  Copyright © 2018 Pete Schwamb. All rights reserved.
-//
-
-import Foundation
-
-fileprivate let assignAddressVersionLength: UInt8 = 0x15
-fileprivate let setupPodVersionLength: UInt8 = 0x1B
-
-public struct VersionResponse : MessageBlock {
-    
-    public struct FirmwareVersion : CustomStringConvertible {
-        let major: UInt8
-        let minor: UInt8
-        let patch: UInt8
-        
-        public init(encodedData: Data) {
-            major = encodedData[0]
-            minor = encodedData[1]
-            patch = encodedData[2]
-        }
-        
-        public var description: String {
-            return "\(major).\(minor).\(patch)"
-        }
-    }
-    
-    public let blockType: MessageBlockType = .versionResponse
-
-    public let pmVersion: FirmwareVersion
-    public let piVersion: FirmwareVersion
-    public let podProgressStatus: PodProgressStatus
-    public let lot: UInt32
-    public let tid: UInt32
-    public let gain: UInt8? // Only in the shorter assignAddress response
-    public let rssi: UInt8? // Only in the shorter assignAddress response
-    public let address: UInt32
-    
-    public let data: Data
-    
-    public init(encodedData: Data) throws {
-        let responseLength = encodedData[1]
-        data = encodedData.subdata(in: 0..<Int(responseLength + 2))
-
-        switch responseLength {
-        case assignAddressVersionLength:
-            // This is the shorter 0x15 response to the 07 AssignAddress command
-            // 01 15 020700 020700 02 02 0000a377 0003ab37 9f 1f00ee87
-            // 0  1  2      5      8  9  10       14       18 19
-            // 01 LL MXMYMZ IXIYIZ 02 0J LLLLLLLL TTTTTTTT GS IIIIIIII
-            // LL = 0x15 (assignAddressVersionLength)
-            // PM = MX.MY.MZ
-            // PI = IX.IY.IZ
-            // 0J = Pod progress state (typically 02, could be 01)
-            // LLLLLLLL = Lot
-            // TTTTTTTT = Tid
-            // GS = ggssssss (Gain/RSSI)
-            // IIIIIIII = address
-
-            pmVersion = FirmwareVersion(encodedData: encodedData.subdata(in: 2..<5))
-            piVersion = FirmwareVersion(encodedData: encodedData.subdata(in: 5..<8))
-            if let podProgress = PodProgressStatus(rawValue: encodedData[9]) {
-                self.podProgressStatus = podProgress
-            } else {
-                throw MessageBlockError.parseError
-            }
-            lot = encodedData[10...].toBigEndian(UInt32.self)
-            tid = encodedData[14...].toBigEndian(UInt32.self)
-            gain = (encodedData[18] & 0xc0) >> 6
-            rssi = encodedData[18] & 0x3f
-            address = encodedData[19...].toBigEndian(UInt32.self)
-            
-        case setupPodVersionLength:
-            // This is the longer 0x1B response to the 03 SetupPod command
-            // 01 1b 13881008340a50 020700 020700 02 03 0000a62b 00044794 1f00ee87
-            // 0  1  2              9      12        16 17       21       25
-            // 01 LL 13881008340A50 MXMYMZ IXIYIZ 02 0J LLLLLLLL TTTTTTTT IIIIIIII
-            // LL = 0x1B (setupPodVersionMessageLength)
-            // PM = MX.MY.MZ
-            // PI = IX.IY.IZ
-            // 0J = Pod progress state (should always be 03)
-            // LLLLLLLL = Lot
-            // TTTTTTTT = Tid
-            // IIIIIIII = address
-
-            pmVersion = FirmwareVersion(encodedData: encodedData.subdata(in: 9..<12))
-            piVersion = FirmwareVersion(encodedData: encodedData.subdata(in: 12..<15))
-            if let podProgress = PodProgressStatus(rawValue: encodedData[16]) {
-                self.podProgressStatus = podProgress
-            } else {
-                throw MessageBlockError.parseError
-            }
-            lot = encodedData[17...].toBigEndian(UInt32.self)
-            tid = encodedData[21...].toBigEndian(UInt32.self)
-            gain = nil // No GS byte in the longer SetupPod response
-            rssi = nil // No GS byte in the longer SetupPod response
-            address = encodedData[25...].toBigEndian(UInt32.self)
-
-        default:
-            throw MessageBlockError.parseError
-        }
-    }
-
-    public var isAssignAddressVersionResponse: Bool {
-        return self.data.count == assignAddressVersionLength + 2
-    }
-
-    public var isSetupPodVersionResponse: Bool {
-        return self.data.count == setupPodVersionLength + 2
-    }
-}
-
-extension VersionResponse: CustomDebugStringConvertible {
-    public var debugDescription: String {
-        return "VersionResponse(lot:\(lot), tid:\(tid), gain:\(gain?.description ?? "NA"), rssi:\(rssi?.description ?? "NA") address:\(Data(bigEndian: address).hexadecimalString), podProgressStatus:\(podProgressStatus), pmVersion:\(pmVersion), piVersion:\(piVersion))"
-    }
-}
-

+ 0 - 304
Dependecies/rileylink_ios/OmniKit/MessageTransport/MessageTransport.swift

@@ -1,304 +0,0 @@
-//
-//  MessageTransport.swift
-//  OmniKit
-//
-//  Created by Pete Schwamb on 8/5/18.
-//  Copyright © 2018 Pete Schwamb. All rights reserved.
-//
-
-import Foundation
-import os.log
-
-import RileyLinkBLEKit
-
-protocol MessageLogger: class {
-    // Comms logging
-    func didSend(_ message: Data)
-    func didReceive(_ message: Data)
-}
-
-public struct MessageTransportState: Equatable, RawRepresentable {
-    public typealias RawValue = [String: Any]
-
-    public var packetNumber: Int
-    public var messageNumber: Int
-    
-    init(packetNumber: Int, messageNumber: Int) {
-        self.packetNumber = packetNumber
-        self.messageNumber = messageNumber
-    }
-    
-    // RawRepresentable
-    public init?(rawValue: RawValue) {
-        guard
-            let packetNumber = rawValue["packetNumber"] as? Int,
-            let messageNumber = rawValue["messageNumber"] as? Int
-            else {
-                return nil
-        }
-        self.packetNumber = packetNumber
-        self.messageNumber = messageNumber
-    }
-    
-    public var rawValue: RawValue {
-        return [
-            "packetNumber": packetNumber,
-            "messageNumber": messageNumber
-        ]
-    }
-
-}
-
-protocol MessageTransportDelegate: class {
-    func messageTransport(_ messageTransport: MessageTransport, didUpdate state: MessageTransportState)
-}
-
-protocol MessageTransport {
-    var delegate: MessageTransportDelegate? { get set }
-
-    var messageNumber: Int { get }
-
-    func sendMessage(_ message: Message) throws -> Message
-
-    /// Asserts that the caller is currently on the session's queue
-    func assertOnSessionQueue()
-}
-
-class PodMessageTransport: MessageTransport {
-    
-    private let session: CommandSession
-    
-    private let log = OSLog(category: "PodMessageTransport")
-    
-    private var state: MessageTransportState {
-        didSet {
-            self.delegate?.messageTransport(self, didUpdate: state)
-        }
-    }
-    
-    private(set) var packetNumber: Int {
-        get {
-            return state.packetNumber
-        }
-        set {
-            state.packetNumber = newValue
-        }
-    }
-    
-    private(set) var messageNumber: Int {
-        get {
-            return state.messageNumber
-        }
-        set {
-            state.messageNumber = newValue
-        }
-    }
-    
-    private let address: UInt32
-    private var ackAddress: UInt32 // During pairing, PDM acks with address it is assigning to channel
-    
-    weak var messageLogger: MessageLogger?
-    weak var delegate: MessageTransportDelegate?
-
-    init(session: CommandSession, address: UInt32 = 0xffffffff, ackAddress: UInt32? = nil, state: MessageTransportState) {
-        self.session = session
-        self.address = address
-        self.ackAddress = ackAddress ?? address
-        self.state = state
-    }
-    
-    private func incrementPacketNumber(_ count: Int = 1) {
-        packetNumber = (packetNumber + count) & 0b11111
-    }
-    
-    private func incrementMessageNumber(_ count: Int = 1) {
-        messageNumber = (messageNumber + count) & 0b1111
-    }
-    
-    func makeAckPacket() -> Packet {
-        return Packet(address: address, packetType: .ack, sequenceNum: packetNumber, data: Data(bigEndian: ackAddress))
-    }
-    
-    func ackUntilQuiet() {
-        
-        let packetData = makeAckPacket().encoded()
-        
-        var lastHeardAt = Date()
-        let quietWindow = TimeInterval(milliseconds: 300)
-        while lastHeardAt.timeIntervalSinceNow > -quietWindow {
-            do {
-                let rfPacket = try session.sendAndListen(packetData, repeatCount: 1, timeout: quietWindow, retryCount: 0, preambleExtension: TimeInterval(milliseconds: 40))
-                let packet = try Packet(rfPacket: rfPacket)
-                if packet.address == address {
-                    lastHeardAt = Date() // Pod still sending
-                }
-            } catch RileyLinkDeviceError.responseTimeout {
-                // Haven't heard anything in 300ms.  POD heard our ack.
-                break
-            } catch {
-                continue
-            }
-        }
-        incrementPacketNumber()
-    }
-    
-
-    /// Encodes and sends a packet to the pod, and receives and decodes its response
-    ///
-    /// - Parameters:
-    ///   - packet: The packet to send
-    ///   - repeatCount: Number of times to repeat packet before listening for a response. 0 = send once and do not repeat.
-    ///   - packetResponseTimeout: The amount of time to wait before retrying
-    ///   - exchangeTimeout: The amount of time to continue retrying before giving up
-    ///   - preambleExtension: Duration of preamble. Default is 127ms
-    /// - Returns: The received response packet
-    /// - Throws:
-    ///     - PodCommsError.noResponse
-    ///     - RileyLinkDeviceError
-    func exchangePackets(packet: Packet, repeatCount: Int = 0, packetResponseTimeout: TimeInterval = .milliseconds(333), exchangeTimeout:TimeInterval = .seconds(9), preambleExtension: TimeInterval = .milliseconds(127)) throws -> Packet {
-        let packetData = packet.encoded()
-        let radioRetryCount = 9
-        
-        let start = Date()
-        
-        incrementPacketNumber()
-        
-        while (-start.timeIntervalSinceNow < exchangeTimeout)  {
-            do {
-                let rfPacket = try session.sendAndListen(packetData, repeatCount: repeatCount, timeout: packetResponseTimeout, retryCount: radioRetryCount, preambleExtension: preambleExtension)
-                
-                let candidatePacket: Packet
-                
-                do {
-                    candidatePacket = try Packet(rfPacket: rfPacket)
-                    log.default("Received packet (%d): %@", rfPacket.rssi, rfPacket.data.hexadecimalString)
-                } catch PacketError.insufficientData {
-                    log.default("Insufficient packet data: %@", rfPacket.data.hexadecimalString)
-                    continue
-                } catch let error {
-                    log.default("Packet error: %@", String(describing: error))
-                    continue
-                }
-
-                guard candidatePacket.address == packet.address || candidatePacket.address == 0xFFFFFFFF else {
-                    log.default("Packet address 0x%x does not match 0x%x", candidatePacket.address, packet.address)
-                    continue
-                }
-                
-                guard candidatePacket.sequenceNum == ((packet.sequenceNum + 1) & 0b11111) else {
-                    log.default("Packet sequence %@ does not match %@", String(describing: candidatePacket.sequenceNum), String(describing: ((packet.sequenceNum + 1) & 0b11111)))
-                    continue
-                }
-                
-                // Once we have verification that the POD heard us, we can increment our counters
-                incrementPacketNumber()
-                
-                return candidatePacket
-            } catch RileyLinkDeviceError.responseTimeout {
-                continue
-            }
-        }
-        
-        throw PodCommsError.noResponse
-    }
-
-    /// Packetizes a message, and performs a set of packet exchanges to send a message and receive the response
-    ///
-    /// - Parameters:
-    ///   - message: The message to send
-    /// - Returns: The received message response
-    /// - Throws:
-    ///     - PodCommsError.noResponse
-    ///     - PodCommsError.podAckedInsteadOfReturningResponse
-    ///     - PodCommsError.unexpectedPacketType
-    ///     - PodCommsError.emptyResponse
-    ///     - MessageError.invalidCrc
-    ///     - MessageError.invalidSequence
-    ///     - MessageError.invalidAddress
-    ///     - RileyLinkDeviceError
-    func sendMessage(_ message: Message) throws -> Message {
-        
-        messageNumber = message.sequenceNum
-        incrementMessageNumber()
-
-        do {
-            let responsePacket = try { () throws -> Packet in
-                var firstPacket = true
-                log.debug("Send: %@", String(describing: message))
-                var dataRemaining = message.encoded()
-                log.default("Send(Hex): %@", dataRemaining.hexadecimalString)
-                messageLogger?.didSend(dataRemaining)
-                while true {
-                    let packetType: PacketType = firstPacket ? .pdm : .con
-                    let sendPacket = Packet(address: address, packetType: packetType, sequenceNum: self.packetNumber, data: dataRemaining)
-                    dataRemaining = dataRemaining.subdata(in: sendPacket.data.count..<dataRemaining.count)
-                    firstPacket = false
-                    let response = try self.exchangePackets(packet: sendPacket)
-                    if dataRemaining.count == 0 {
-                        return response
-                    }
-                }
-            }()
-            
-            guard responsePacket.packetType != .ack else {
-                messageLogger?.didReceive(responsePacket.encoded())
-                log.default("Pod responded with ack instead of response: %@", String(describing: responsePacket))
-                throw PodCommsError.podAckedInsteadOfReturningResponse
-            }
-            
-            // Assemble fragmented message from multiple packets
-            let response = try { () throws -> Message in
-                var responseData = responsePacket.data
-                while true {
-                    do {
-                        let msg = try Message(encodedData: responseData)
-                        log.default("Recv(Hex): %@", responseData.hexadecimalString)
-                        guard msg.address == address else {
-                            throw MessageError.invalidAddress(address: msg.address)
-                        }
-                        guard msg.sequenceNum == messageNumber else {
-                            throw MessageError.invalidSequence
-                        }
-                        messageLogger?.didReceive(responseData)
-                        return msg
-                    } catch MessageError.notEnoughData {
-                        log.debug("Sending ACK for CON")
-                        let conPacket = try self.exchangePackets(packet: makeAckPacket(), repeatCount: 3, preambleExtension:TimeInterval(milliseconds: 40))
-                        
-                        guard conPacket.packetType == .con else {
-                            log.default("Expected CON packet, received; %@", String(describing: conPacket))
-                            throw PodCommsError.unexpectedPacketType(packetType: conPacket.packetType)
-                        }
-                        responseData += conPacket.data
-                    } catch MessageError.invalidCrc {
-                        // throw the error without any logging for a garbage message
-                        throw MessageError.invalidCrc
-                    } catch let error {
-                        // log any other non-garbage messages that generate errors
-                        log.error("Error (%{public}@) Recv(Hex): %@", String(describing: error), responseData.hexadecimalString)
-                        messageLogger?.didReceive(responseData)
-                        throw error
-                    }
-                }
-            }()
-
-            ackUntilQuiet()
-            
-            guard response.messageBlocks.count > 0 else {
-                log.default("Empty response")
-                throw PodCommsError.emptyResponse
-            }
-            
-            incrementMessageNumber()
-            
-            return response
-        } catch let error {
-            log.error("Error during communication with POD: %@", String(describing: error))
-            throw error
-        }
-    }
-
-    func assertOnSessionQueue() {
-        session.assertOnSessionQueue()
-    }
-}

+ 0 - 288
Dependecies/rileylink_ios/OmniKit/Model/AlertSlot.swift

@@ -1,288 +0,0 @@
-//
-//  Alert.swift
-//  OmniKit
-//
-//  Created by Pete Schwamb on 10/24/18.
-//  Copyright © 2018 Pete Schwamb. All rights reserved.
-//
-
-import Foundation
-
-public enum AlertTrigger {
-    case unitsRemaining(Double)
-    case timeUntilAlert(TimeInterval)
-}
-
-public enum BeepRepeat: UInt8 {
-    case once = 0
-    case every1MinuteFor3MinutesAndRepeatEvery60Minutes = 1
-    case every1MinuteFor15Minutes = 2
-    case every1MinuteFor3MinutesAndRepeatEvery15Minutes = 3
-    case every3MinutesFor60minutesStartingAt2Minutes = 4
-    case every60Minutes = 5
-    case every15Minutes = 6
-    case every15MinutesFor60minutesStartingAt14Minutes = 7
-    case every5Minutes = 8
-}
-
-
-public struct AlertConfiguration {
-
-    let slot: AlertSlot
-    let trigger: AlertTrigger
-    let active: Bool
-    let duration: TimeInterval
-    let beepRepeat: BeepRepeat
-    let beepType: BeepType
-    let autoOffModifier: Bool
-
-    static let length = 6
-
-    public init(alertType: AlertSlot, active: Bool = true, autoOffModifier: Bool = false, duration: TimeInterval, trigger: AlertTrigger, beepRepeat: BeepRepeat, beepType: BeepType) {
-        self.slot = alertType
-        self.active = active
-        self.autoOffModifier = autoOffModifier
-        self.duration = duration
-        self.trigger = trigger
-        self.beepRepeat = beepRepeat
-        self.beepType = beepType
-    }
-}
-
-extension AlertConfiguration: CustomDebugStringConvertible {
-    public var debugDescription: String {
-        return "AlertConfiguration(slot:\(slot), active:\(active), autoOffModifier:\(autoOffModifier), duration:\(duration), trigger:\(trigger), beepRepeat:\(beepRepeat), beepType:\(beepType))"
-    }
-}
-
-
-
-public enum PodAlert: CustomStringConvertible, RawRepresentable, Equatable {
-    public typealias RawValue = [String: Any]
-
-    // 2 hours long, time for user to start pairing process
-    case waitingForPairingReminder
-
-    // 1 hour long, time for user to finish priming, cannula insertion
-    case finishSetupReminder
-
-    // User configurable with PDM (1-24 hours before 72 hour expiration) "Change Pod Soon"
-    case expirationAlert(TimeInterval)
-
-    // 72 hour alarm
-    case expirationAdvisoryAlarm(alarmTime: TimeInterval, duration: TimeInterval)
-
-    // 79 hour alarm (1 hour before shutdown)
-    case shutdownImminentAlarm(TimeInterval)
-
-    // reservoir below configured value alarm
-    case lowReservoirAlarm(Double)
-
-    // auto-off timer; requires user input every x minutes
-    case autoOffAlarm(active: Bool, countdownDuration: TimeInterval)
-
-    public var description: String {
-        var alertName: String
-        switch self {
-        case .waitingForPairingReminder:
-            return LocalizedString("Waiting for pairing reminder", comment: "Description waiting for pairing reminder")
-        case .finishSetupReminder:
-            return LocalizedString("Finish setup ", comment: "Description for finish setup")
-        case .expirationAlert:
-            alertName = LocalizedString("Expiration alert", comment: "Description for expiration alert")
-        case .expirationAdvisoryAlarm:
-            alertName = LocalizedString("Pod expiration advisory alarm", comment: "Description for expiration advisory alarm")
-        case .shutdownImminentAlarm:
-            alertName = LocalizedString("Shutdown imminent alarm", comment: "Description for shutdown imminent alarm")
-        case .lowReservoirAlarm:
-            alertName = LocalizedString("Low reservoir advisory alarm", comment: "Description for low reservoir alarm")
-        case .autoOffAlarm:
-            alertName = LocalizedString("Auto-off alarm", comment: "Description for auto-off alarm")
-        }
-        if self.configuration.active == false {
-            alertName += LocalizedString(" (inactive)", comment: "Description for an inactive alert modifier")
-        }
-        return alertName
-    }
-
-    public var configuration: AlertConfiguration {
-        switch self {
-        case .waitingForPairingReminder:
-            return AlertConfiguration(alertType: .slot7, duration: .minutes(110), trigger: .timeUntilAlert(.minutes(10)), beepRepeat: .every5Minutes, beepType: .bipBeepBipBeepBipBeepBipBeep)
-        case .finishSetupReminder:
-            return AlertConfiguration(alertType: .slot7, duration: .minutes(55), trigger: .timeUntilAlert(.minutes(5)), beepRepeat: .every5Minutes, beepType: .bipBeepBipBeepBipBeepBipBeep)
-        case .expirationAlert(let alertTime):
-            let active = alertTime != 0 // disable if alertTime is 0
-            return AlertConfiguration(alertType: .slot3, active: active, duration: 0, trigger: .timeUntilAlert(alertTime), beepRepeat: .every1MinuteFor3MinutesAndRepeatEvery15Minutes, beepType: .bipBeepBipBeepBipBeepBipBeep)
-        case .expirationAdvisoryAlarm(let alarmTime, let duration):
-            let active = alarmTime != 0 // disable if alarmTime is 0
-            return AlertConfiguration(alertType: .slot7, active: active, duration: duration, trigger: .timeUntilAlert(alarmTime), beepRepeat: .every60Minutes, beepType: .bipBeepBipBeepBipBeepBipBeep)
-        case .shutdownImminentAlarm(let alarmTime):
-            let active = alarmTime != 0 // disable if alarmTime is 0
-            return AlertConfiguration(alertType: .slot2, active: active, duration: 0, trigger: .timeUntilAlert(alarmTime), beepRepeat: .every15Minutes, beepType: .bipBeepBipBeepBipBeepBipBeep)
-        case .lowReservoirAlarm(let units):
-            let active = units != 0 // disable if units is 0
-            return AlertConfiguration(alertType: .slot4, active: active, duration: 0, trigger: .unitsRemaining(units), beepRepeat: .every1MinuteFor3MinutesAndRepeatEvery60Minutes, beepType: .bipBeepBipBeepBipBeepBipBeep)
-        case .autoOffAlarm(let active, let countdownDuration):
-            return AlertConfiguration(alertType: .slot0, active: active, autoOffModifier: true, duration: .minutes(15), trigger: .timeUntilAlert(countdownDuration), beepRepeat: .every1MinuteFor15Minutes, beepType: .bipBeepBipBeepBipBeepBipBeep)
-        }
-    }
-
-
-    // MARK: - RawRepresentable
-    public init?(rawValue: RawValue) {
-
-        guard let name = rawValue["name"] as? String else {
-            return nil
-        }
-
-        switch name {
-        case "waitingForPairingReminder":
-            self = .waitingForPairingReminder
-        case "finishSetupReminder":
-            self = .finishSetupReminder
-        case "expirationAlert":
-            guard let alertTime = rawValue["alertTime"] as? Double else {
-                return nil
-            }
-            self = .expirationAlert(TimeInterval(alertTime))
-        case "expirationAdvisoryAlarm":
-            guard let alarmTime = rawValue["alarmTime"] as? Double,
-                let duration = rawValue["duration"] as? Double else
-            {
-                return nil
-            }
-            self = .expirationAdvisoryAlarm(alarmTime: TimeInterval(alarmTime), duration: TimeInterval(duration))
-        case "shutdownImminentAlarm":
-            guard let alarmTime = rawValue["alarmTime"] as? Double else {
-                return nil
-            }
-            self = .shutdownImminentAlarm(alarmTime)
-        case "lowReservoirAlarm":
-            guard let units = rawValue["units"] as? Double else {
-                return nil
-            }
-            self = .lowReservoirAlarm(units)
-        case "autoOffAlarm":
-            guard let active = rawValue["active"] as? Bool,
-                let countdownDuration = rawValue["countdownDuration"] as? Double else
-            {
-                return nil
-            }
-            self = .autoOffAlarm(active: active, countdownDuration: TimeInterval(countdownDuration))
-        default:
-            return nil
-        }
-    }
-
-    public var rawValue: RawValue {
-
-        let name: String = {
-            switch self {
-            case .waitingForPairingReminder:
-                return "waitingForPairingReminder"
-            case .finishSetupReminder:
-                return "finishSetupReminder"
-            case .expirationAlert:
-                return "expirationAlert"
-            case .expirationAdvisoryAlarm:
-                return "expirationAdvisoryAlarm"
-            case .shutdownImminentAlarm:
-                return "shutdownImminentAlarm"
-            case .lowReservoirAlarm:
-                return "lowReservoirAlarm"
-            case .autoOffAlarm:
-                return "autoOffAlarm"
-            }
-        }()
-
-
-        var rawValue: RawValue = [
-            "name": name,
-        ]
-
-        switch self {
-        case .expirationAlert(let alertTime):
-            rawValue["alertTime"] = alertTime
-        case .expirationAdvisoryAlarm(let alarmTime, let duration):
-            rawValue["alarmTime"] = alarmTime
-            rawValue["duration"] = duration
-        case .shutdownImminentAlarm(let alarmTime):
-            rawValue["alarmTime"] = alarmTime
-        case .lowReservoirAlarm(let units):
-            rawValue["units"] = units
-        case .autoOffAlarm(let active, let countdownDuration):
-            rawValue["active"] = active
-            rawValue["countdownDuration"] = countdownDuration
-        default:
-            break
-        }
-
-        return rawValue
-    }
-}
-
-public enum AlertSlot: UInt8 {
-    case slot0 = 0x00
-    case slot1 = 0x01
-    case slot2 = 0x02
-    case slot3 = 0x03
-    case slot4 = 0x04
-    case slot5 = 0x05
-    case slot6 = 0x06
-    case slot7 = 0x07
-
-    public var bitMaskValue: UInt8 {
-        return 1<<rawValue
-    }
-
-    public typealias AllCases = [AlertSlot]
-    
-    static var allCases: AllCases {
-        return (0..<8).map { AlertSlot(rawValue: $0)! }
-    }
-}
-
-public struct AlertSet: RawRepresentable, Collection, CustomStringConvertible, Equatable {
-    
-    public typealias RawValue = UInt8
-    public typealias Index = Int
-    
-    public let startIndex: Int
-    public let endIndex: Int
-    
-    private let elements: [AlertSlot]
-    
-    public static let none = AlertSet(rawValue: 0)
-    
-    public var rawValue: UInt8 {
-        return elements.reduce(0) { $0 | $1.bitMaskValue }
-    }
-    
-    public init(slots: [AlertSlot]) {
-        self.elements = slots
-        self.startIndex = 0
-        self.endIndex = self.elements.count
-    }
-
-    public init(rawValue: UInt8) {
-        self.init(slots: AlertSlot.allCases.filter { rawValue & $0.bitMaskValue != 0 })
-    }
-
-    public subscript(index: Index) -> AlertSlot {
-        return elements[index]
-    }
-    
-    public func index(after i: Int) -> Int {
-        return i+1
-    }
-    
-    public var description: String {
-        if elements.count == 0 {
-            return LocalizedString("No alerts", comment: "Pod alert state when no alerts are active")
-        } else {
-            let alarmDescriptions = elements.map { String(describing: $0) }
-            return alarmDescriptions.joined(separator: ", ")
-        }
-    }
-}

+ 0 - 236
Dependecies/rileylink_ios/OmniKit/Model/BasalDeliveryTable.swift

@@ -1,236 +0,0 @@
-//
-//  BasalDeliveryTable.swift
-//  OmniKit
-//
-//  Created by Pete Schwamb on 4/4/18.
-//  Copyright © 2018 Pete Schwamb. All rights reserved.
-//
-
-import Foundation
-
-public struct BasalTableEntry {
-    let segments: Int
-    let pulses: Int
-    let alternateSegmentPulse: Bool
-    
-    public init(encodedData: Data) {
-        segments = Int(encodedData[0] >> 4) + 1
-        pulses = (Int(encodedData[0] & 0b11) << 8) + Int(encodedData[1])
-        alternateSegmentPulse = (encodedData[0] >> 3) & 0x1 == 1
-    }
-    
-    public init(segments: Int, pulses: Int, alternateSegmentPulse: Bool) {
-        self.segments = segments
-        self.pulses = pulses
-        self.alternateSegmentPulse = alternateSegmentPulse
-    }
-    
-    public var data: Data {
-        let pulsesHighBits = UInt8((pulses >> 8) & 0b11)
-        let pulsesLowBits = UInt8(pulses & 0xff)
-        return Data([
-            UInt8((segments - 1) << 4) + UInt8((alternateSegmentPulse ? 1 : 0) << 3) + pulsesHighBits,
-            UInt8(pulsesLowBits)
-            ])
-    }
-    
-    public func checksum() -> UInt16 {
-        let checksumPerSegment = (pulses & 0xff) + (pulses >> 8)
-        return UInt16(checksumPerSegment * segments + (alternateSegmentPulse ? segments / 2 : 0))
-    }
-}
-
-extension BasalTableEntry: CustomDebugStringConvertible {
-    public var debugDescription: String {
-        return "BasalTableEntry(segments:\(segments), pulses:\(pulses), alternateSegmentPulse:\(alternateSegmentPulse))"
-    }
-}
-
-
-public struct BasalDeliveryTable {
-    static let segmentDuration: TimeInterval = .minutes(30)
-    
-    let entries: [BasalTableEntry]
-    
-    public init(entries: [BasalTableEntry]) {
-        self.entries = entries
-    }
-    
-    
-    public init(schedule: BasalSchedule) {
-        
-        struct TempSegment {
-            let pulses: Int
-        }
-        
-        let numSegments = 48
-        let maxSegmentsPerEntry = 16
-        
-        var halfPulseRemainder = false
-        
-        let expandedSegments = stride(from: 0, to: numSegments, by: 1).map { (index) -> TempSegment in
-            let rate = schedule.rateAt(offset: Double(index) * .minutes(30))
-            let pulsesPerHour = Int(round(rate / Pod.pulseSize))
-            let pulsesPerSegment = pulsesPerHour >> 1
-            let halfPulse = pulsesPerHour & 0b1 != 0
-            
-            let segment = TempSegment(pulses: pulsesPerSegment + ((halfPulseRemainder && halfPulse) ? 1 : 0))
-            halfPulseRemainder = halfPulseRemainder != halfPulse
-
-            return segment
-        }
-        
-        var tableEntries = [BasalTableEntry]()
-
-        let addEntry = { (segments: [TempSegment], alternateSegmentPulse: Bool) in
-            tableEntries.append(BasalTableEntry(
-                segments: segments.count,
-                pulses: segments.first!.pulses,
-                alternateSegmentPulse: alternateSegmentPulse
-            ))
-        }
-
-        var altSegmentPulse = false
-        var segmentsToMerge = [TempSegment]()
-        
-        for segment in expandedSegments {
-            guard let firstSegment = segmentsToMerge.first else {
-                segmentsToMerge.append(segment)
-                continue
-            }
-            
-            let delta = segment.pulses - firstSegment.pulses
-            
-            if segmentsToMerge.count == 1 {
-                altSegmentPulse = delta == 1
-            }
-            
-            let expectedDelta: Int
-            
-            if !altSegmentPulse {
-                expectedDelta = 0
-            } else {
-                expectedDelta = segmentsToMerge.count % 2
-            }
-            
-            if expectedDelta != delta || segmentsToMerge.count == maxSegmentsPerEntry {
-                addEntry(segmentsToMerge, altSegmentPulse)
-                segmentsToMerge.removeAll()
-            }
-            
-            segmentsToMerge.append(segment)
-        }
-        addEntry(segmentsToMerge, altSegmentPulse)
-
-        self.entries = tableEntries
-    }
-    
-    public init(tempBasalRate: Double, duration: TimeInterval) {
-        self.entries = BasalDeliveryTable.rateToTableEntries(rate: tempBasalRate, duration: duration)
-    }
-    
-    private static func rateToTableEntries(rate: Double, duration: TimeInterval) -> [BasalTableEntry] {
-        var tableEntries = [BasalTableEntry]()
-        
-        let pulsesPerHour = Int(round(rate / Pod.pulseSize))
-        let pulsesPerSegment = pulsesPerHour >> 1
-        let alternateSegmentPulse = pulsesPerHour & 0b1 != 0
-        
-        var remaining = Int(round(duration / BasalDeliveryTable.segmentDuration))
-        
-        while remaining > 0 {
-            let segments = min(remaining, 16)
-            let tableEntry = BasalTableEntry(segments: segments, pulses: Int(pulsesPerSegment), alternateSegmentPulse: segments > 1 ? alternateSegmentPulse : false)
-            tableEntries.append(tableEntry)
-            remaining -= segments
-        }
-        return tableEntries
-    }
-    
-    public func numSegments() -> Int {
-        return entries.reduce(0) { $0 + $1.segments }
-    }
-}
-
-extension BasalDeliveryTable: CustomDebugStringConvertible {
-    public var debugDescription: String {
-        return "BasalDeliveryTable(\(entries))"
-    }
-}
-
-public struct RateEntry {
-    let totalPulses: Double
-    let delayBetweenPulses: TimeInterval
-    
-    public init(totalPulses: Double, delayBetweenPulses: TimeInterval) {
-        self.totalPulses = totalPulses
-        self.delayBetweenPulses = delayBetweenPulses
-    }
-    
-    public var rate: Double {
-        if totalPulses == 0 {
-            return 0
-        } else {
-            return round(TimeInterval(hours: 1) / delayBetweenPulses) / Pod.pulsesPerUnit
-        }
-    }
-    
-    public var duration: TimeInterval {
-        if totalPulses == 0 {
-            return delayBetweenPulses
-        } else {
-            return round(delayBetweenPulses * Double(totalPulses))
-        }
-    }
-    
-    public var data: Data {
-        var data = Data()
-        data.appendBigEndian(UInt16(round(totalPulses * 10)))
-        if totalPulses == 0 {
-            data.appendBigEndian(UInt32(delayBetweenPulses.hundredthsOfMilliseconds) * 10)
-        } else {
-            data.appendBigEndian(UInt32(delayBetweenPulses.hundredthsOfMilliseconds))
-        }
-        return data
-    }
-    
-    public static func makeEntries(rate: Double, duration: TimeInterval) -> [RateEntry] {
-        let maxPulsesPerEntry: Double = 6400
-        var entries = [RateEntry]()
-        
-        var remainingSegments = Int(round(duration.minutes / 30))
-        
-        let pulsesPerSegment = round(rate / Pod.pulseSize) / 2
-        let maxSegmentsPerEntry = pulsesPerSegment > 0 ? Int(maxPulsesPerEntry / pulsesPerSegment) : 1
-        
-        var remainingPulses = rate * duration.hours / Pod.pulseSize
-        let delayBetweenPulses = TimeInterval(hours: 1) / rate * Pod.pulseSize
-        
-        while (remainingSegments > 0) {
-            if rate == 0 {
-                entries.append(RateEntry(totalPulses: 0, delayBetweenPulses: .minutes(30)))
-                remainingSegments -= 1
-            } else {
-                let numSegments = min(maxSegmentsPerEntry, Int(round(remainingPulses / pulsesPerSegment)))
-                remainingSegments -= numSegments
-                let pulseCount = pulsesPerSegment * Double(numSegments)
-                let entry = RateEntry(totalPulses: pulseCount, delayBetweenPulses: delayBetweenPulses)
-                entries.append(entry)
-                remainingPulses -= pulseCount
-            }
-        }
-        return entries
-    }
-}
-
-extension RateEntry: CustomDebugStringConvertible {
-    public var debugDescription: String {
-        return "RateEntry(rate:\(rate) duration:\(duration.stringValue))"
-    }
-}
-
-
-
-
-
-

+ 0 - 107
Dependecies/rileylink_ios/OmniKit/Model/Pod.swift

@@ -1,107 +0,0 @@
-//
-//  Pod.swift
-//  OmniKit
-//
-//  Created by Pete Schwamb on 4/4/18.
-//  Copyright © 2018 Pete Schwamb. All rights reserved.
-//
-
-import Foundation
-
-public struct Pod {
-    // Volume of insulin in one motor pulse
-    public static let pulseSize: Double = 0.05
-
-    // Number of pulses required to deliver one unit of insulin
-    public static let pulsesPerUnit: Double = 1 / Pod.pulseSize
-
-    // Seconds per pulse for boluses
-    public static let secondsPerBolusPulse: Double = 2
-
-    // Units per second for boluses
-    public static let bolusDeliveryRate: Double = Pod.pulseSize / Pod.secondsPerBolusPulse
-
-    // Seconds per pulse for priming/cannula insertion
-    public static let secondsPerPrimePulse: Double = 1
-
-    // Units per second for priming/cannula insertion
-    public static let primeDeliveryRate: Double = Pod.pulseSize / Pod.secondsPerPrimePulse
-
-    // User configured time before expiration advisory (PDM allows 1-24 hours)
-    public static let expirationAlertWindow = TimeInterval(hours: 2)
-
-    // Expiration advisory window: time after expiration alert, and end of service imminent alarm
-    public static let expirationAdvisoryWindow = TimeInterval(hours: 7)
-
-    // End of service imminent window, relative to pod end of service
-    public static let endOfServiceImminentWindow = TimeInterval(hours: 1)
-
-    // Total pod service time. A fault is triggered if this time is reached before pod deactivation.
-    public static let serviceDuration = TimeInterval(hours: 80)
-
-    // Nomimal pod life (72 hours)
-    public static let nominalPodLife = Pod.serviceDuration - Pod.endOfServiceImminentWindow - Pod.expirationAdvisoryWindow
-
-    // Maximum reservoir level reading
-    public static let maximumReservoirReading: Double = 50
-
-    // Reservoir Capacity
-    public static let reservoirCapacity: Double = 200
-
-    // Supported basal rates
-    public static let supportedBasalRates: [Double] = (1...600).map { Double($0) / Double(pulsesPerUnit) }
-
-    // Maximum number of basal schedule entries supported
-    public static let maximumBasalScheduleEntryCount: Int = 24
-
-    // Minimum duration of a single basal schedule entry
-    public static let minimumBasalScheduleEntryDuration = TimeInterval.minutes(30)
-
-    // Amount of insulin delivered with 1 second between pulses for priming
-    public static let primeUnits = 2.6
-
-    // Amount of insulin delivered with 1 second between pulses for cannula insertion
-    public static let cannulaInsertionUnitsBase = 0.5
-    public static let cannulaInsertionUnitsExtra = 0.0 // edit to add a fixed additional amount of insulin during cannula insertion
-    public static let cannulaInsertionUnits = cannulaInsertionUnitsBase + cannulaInsertionUnitsExtra
-
-    // Default and limits for expiration reminder alerts
-    public static let expirationReminderAlertDefaultTimeBeforeExpiration = TimeInterval.hours(2)
-    public static let expirationReminderAlertMinTimeBeforeExpiration = TimeInterval.hours(1)
-    public static let expirationReminderAlertMaxTimeBeforeExpiration = TimeInterval.hours(24)
-}
-
-// DeliveryStatus used in StatusResponse and DetailedStatus
-public enum DeliveryStatus: UInt8, CustomStringConvertible {
-    case suspended = 0
-    case scheduledBasal = 1
-    case tempBasalRunning = 2
-    case priming = 4
-    case bolusInProgress = 5
-    case bolusAndTempBasal = 6
-    
-    public var bolusing: Bool {
-        return self == .bolusInProgress || self == .bolusAndTempBasal
-    }
-    
-    public var tempBasalRunning: Bool {
-        return self == .tempBasalRunning || self == .bolusAndTempBasal
-    }
-
-    public var description: String {
-        switch self {
-        case .suspended:
-            return LocalizedString("Suspended", comment: "Delivery status when insulin delivery is suspended")
-        case .scheduledBasal:
-            return LocalizedString("Scheduled basal", comment: "Delivery status when scheduled basal is running")
-        case .tempBasalRunning:
-            return LocalizedString("Temp basal running", comment: "Delivery status when temp basal is running")
-        case .priming:
-            return LocalizedString("Priming", comment: "Delivery status when pod is priming")
-        case .bolusInProgress:
-            return LocalizedString("Bolusing", comment: "Delivery status when bolusing")
-        case .bolusAndTempBasal:
-            return LocalizedString("Bolusing with temp basal", comment: "Delivery status when bolusing and temp basal is running")
-        }
-    }
-}

+ 0 - 73
Dependecies/rileylink_ios/OmniKit/Model/PodProgressStatus.swift

@@ -1,73 +0,0 @@
-//
-//  PodProgressStatus.swift
-//  OmniKit
-//
-//  Created by Pete Schwamb on 9/28/18.
-//  Copyright © 2018 Pete Schwamb. All rights reserved.
-//
-
-import Foundation
-
-public enum PodProgressStatus: UInt8, CustomStringConvertible, Equatable {
-    case initialized = 0
-    case memoryInitialized = 1
-    case reminderInitialized = 2
-    case pairingCompleted = 3
-    case priming = 4
-    case primingCompleted = 5
-    case basalInitialized = 6
-    case insertingCannula = 7
-    case aboveFiftyUnits = 8
-    case fiftyOrLessUnits = 9
-    case oneNotUsed = 10
-    case twoNotUsed = 11
-    case threeNotUsed = 12
-    case faultEventOccurred = 13        // fault event occurred (a "screamer")
-    case activationTimeExceeded = 14    // took > 2 hrs from progress 2 to 3 OR > 1 hr from 3 to 8
-    case inactive = 15                  // pod deactivated or a fatal packet state error
-    
-    public var readyForDelivery: Bool {
-        return self == .fiftyOrLessUnits || self == .aboveFiftyUnits
-    }
-    
-    public var unfinishedPairing: Bool {
-        return self.rawValue < PodProgressStatus.aboveFiftyUnits.rawValue
-    }
-
-    public var description: String {
-        switch self {
-        case .initialized:
-            return LocalizedString("Initialized", comment: "Pod initialized")
-        case .memoryInitialized:
-            return LocalizedString("Memory initialized", comment: "Pod memory initialized")
-        case .reminderInitialized:
-            return LocalizedString("Reminder initialized", comment: "Pod pairing reminder initialized")
-        case .pairingCompleted:
-            return LocalizedString("Paired completed", comment: "Pod status when pairing completed")
-        case .priming:
-            return LocalizedString("Priming", comment: "Pod status when priming")
-        case .primingCompleted:
-            return LocalizedString("Priming completed", comment: "Pod state when priming completed")
-        case .basalInitialized:
-            return LocalizedString("Basal initialized", comment: "Pod state when basal initialized")
-        case .insertingCannula:
-            return LocalizedString("Inserting cannula", comment: "Pod state when inserting cannula")
-        case .aboveFiftyUnits:
-            return LocalizedString("Normal", comment: "Pod state when running above fifty units")
-        case .fiftyOrLessUnits:
-            return LocalizedString("Low reservoir", comment: "Pod state when running with fifty or less units")
-        case .oneNotUsed:
-            return LocalizedString("oneNotUsed", comment: "Pod state oneNotUsed")
-        case .twoNotUsed:
-            return LocalizedString("twoNotUsed", comment: "Pod state twoNotUsed")
-        case .threeNotUsed:
-            return LocalizedString("threeNotUsed", comment: "Pod state threeNotUsed")
-        case .faultEventOccurred:
-            return LocalizedString("Fault event occurred", comment: "Pod state when fault event has occurred")
-        case .activationTimeExceeded:
-            return LocalizedString("Activation time exceeded", comment: "Pod state when activation not completed in the time allowed")
-        case .inactive:
-            return LocalizedString("Deactivated", comment: "Pod state when deactivated")
-        }
-    }
-}

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 1737
Dependecies/rileylink_ios/OmniKit/PumpManager/OmnipodPumpManager.swift


+ 0 - 220
Dependecies/rileylink_ios/OmniKit/PumpManager/OmnipodPumpManagerState.swift

@@ -1,220 +0,0 @@
-//
-//  OmnipodPumpManagerState.swift
-//  OmniKit
-//
-//  Created by Pete Schwamb on 8/4/18.
-//  Copyright © 2018 Pete Schwamb. All rights reserved.
-//
-
-import RileyLinkKit
-import RileyLinkBLEKit
-import LoopKit
-
-
-public struct OmnipodPumpManagerState: RawRepresentable, Equatable {
-    public typealias RawValue = PumpManager.RawStateValue
-    
-    public static let version = 2
-    
-    public var podState: PodState?
-
-    public var pairingAttemptAddress: UInt32?
-
-    public var timeZone: TimeZone
-    
-    public var basalSchedule: BasalSchedule
-    
-    public var rileyLinkConnectionManagerState: RileyLinkConnectionManagerState?
-
-    public var unstoredDoses: [UnfinalizedDose]
-
-    public var expirationReminderDate: Date?
-
-    public var confirmationBeeps: Bool
-
-    public var automaticBolusBeeps: Bool
-
-    // Temporal state not persisted
-
-    internal enum EngageablePumpState: Equatable {
-        case engaging
-        case disengaging
-        case stable
-    }
-
-    internal var suspendEngageState: EngageablePumpState = .stable
-
-    internal var bolusEngageState: EngageablePumpState = .stable
-
-    internal var tempBasalEngageState: EngageablePumpState = .stable
-
-    internal var lastPumpDataReportDate: Date?
-    
-    internal var insulinType: InsulinType
-
-    // MARK: -
-
-    public init(podState: PodState?, timeZone: TimeZone, basalSchedule: BasalSchedule, rileyLinkConnectionManagerState: RileyLinkConnectionManagerState?, insulinType: InsulinType) {
-        self.podState = podState
-        self.timeZone = timeZone
-        self.basalSchedule = basalSchedule
-        self.rileyLinkConnectionManagerState = rileyLinkConnectionManagerState
-        self.unstoredDoses = []
-        self.confirmationBeeps = false
-        self.automaticBolusBeeps = false
-        self.insulinType = insulinType
-    }
-    
-    public init?(rawValue: RawValue) {
-        
-        guard let version = rawValue["version"] as? Int else {
-            return nil
-        }
-        
-        let basalSchedule: BasalSchedule
-        
-        if version == 1 {
-            // migrate: basalSchedule moved from podState to oppm state
-            if let podStateRaw = rawValue["podState"] as? PodState.RawValue,
-                let rawBasalSchedule = podStateRaw["basalSchedule"] as? BasalSchedule.RawValue,
-                let migrateSchedule = BasalSchedule(rawValue: rawBasalSchedule)
-            {
-                basalSchedule = migrateSchedule
-            } else {
-                return nil
-            }
-        } else {
-            guard let rawBasalSchedule = rawValue["basalSchedule"] as? BasalSchedule.RawValue,
-                let schedule = BasalSchedule(rawValue: rawBasalSchedule) else
-            {
-                return nil
-            }
-            basalSchedule = schedule
-        }
-        
-        let podState: PodState?
-        if let podStateRaw = rawValue["podState"] as? PodState.RawValue {
-            podState = PodState(rawValue: podStateRaw)
-        } else {
-            podState = nil
-        }
-
-        let timeZone: TimeZone
-        if let timeZoneSeconds = rawValue["timeZone"] as? Int,
-            let tz = TimeZone(secondsFromGMT: timeZoneSeconds) {
-            timeZone = tz
-        } else {
-            timeZone = TimeZone.currentFixed
-        }
-        
-        let rileyLinkConnectionManagerState: RileyLinkConnectionManagerState?
-        if let rileyLinkConnectionManagerStateRaw = rawValue["rileyLinkConnectionManagerState"] as? RileyLinkConnectionManagerState.RawValue {
-            rileyLinkConnectionManagerState = RileyLinkConnectionManagerState(rawValue: rileyLinkConnectionManagerStateRaw)
-        } else {
-            rileyLinkConnectionManagerState = nil
-        }
-        
-        var insulinType: InsulinType?
-        if let rawInsulinType = rawValue["insulinType"] as? InsulinType.RawValue {
-            insulinType = InsulinType(rawValue: rawInsulinType)
-        }
-
-        self.init(
-            podState: podState,
-            timeZone: timeZone,
-            basalSchedule: basalSchedule,
-            rileyLinkConnectionManagerState: rileyLinkConnectionManagerState,
-            insulinType: insulinType ?? .novolog
-        )
-
-        if let expirationReminderDate = rawValue["expirationReminderDate"] as? Date {
-            self.expirationReminderDate = expirationReminderDate
-        } else if let expiresAt = podState?.expiresAt {
-            self.expirationReminderDate = expiresAt.addingTimeInterval(-Pod.expirationReminderAlertDefaultTimeBeforeExpiration)
-        }
-
-        if let rawUnstoredDoses = rawValue["unstoredDoses"] as? [UnfinalizedDose.RawValue] {
-            self.unstoredDoses = rawUnstoredDoses.compactMap( { UnfinalizedDose(rawValue: $0) } )
-        } else {
-            self.unstoredDoses = []
-        }
-
-        self.confirmationBeeps = rawValue["confirmationBeeps"] as? Bool ?? rawValue["bolusBeeps"] as? Bool ?? false
-        
-        self.automaticBolusBeeps = rawValue["automaticBolusBeeps"] as? Bool ?? false
-
-        if let pairingAttemptAddress = rawValue["pairingAttemptAddress"] as? UInt32 {
-            self.pairingAttemptAddress = pairingAttemptAddress
-        }
-    }
-    
-    public var rawValue: RawValue {
-        var value: [String : Any] = [
-            "version": OmnipodPumpManagerState.version,
-            "timeZone": timeZone.secondsFromGMT(),
-            "basalSchedule": basalSchedule.rawValue,
-            "unstoredDoses": unstoredDoses.map { $0.rawValue },
-            "confirmationBeeps": confirmationBeeps,
-            "automaticBolusBeeps": automaticBolusBeeps,
-            "insulinType": insulinType.rawValue,
-        ]
-        
-        if let podState = podState {
-            value["podState"] = podState.rawValue
-        }
-
-        if let expirationReminderDate = expirationReminderDate {
-            value["expirationReminderDate"] = expirationReminderDate
-        }
-        
-        if let rileyLinkConnectionManagerState = rileyLinkConnectionManagerState {
-            value["rileyLinkConnectionManagerState"] = rileyLinkConnectionManagerState.rawValue
-        }
-        
-        if let pairingAttemptAddress = pairingAttemptAddress {
-            value["pairingAttemptAddress"] = pairingAttemptAddress
-        }
-        
-        return value
-    }
-}
-
-extension OmnipodPumpManagerState {
-    var hasActivePod: Bool {
-        return podState?.isActive == true
-    }
-
-    var hasSetupPod: Bool {
-        return podState?.isSetupComplete == true
-    }
-
-    var isPumpDataStale: Bool {
-        let pumpStatusAgeTolerance = TimeInterval(minutes: 6)
-        let pumpDataAge = -(self.lastPumpDataReportDate ?? .distantPast).timeIntervalSinceNow
-        return pumpDataAge > pumpStatusAgeTolerance
-    }
-}
-
-
-extension OmnipodPumpManagerState: CustomDebugStringConvertible {
-    public var debugDescription: String {
-        return [
-            "## OmnipodPumpManagerState",
-            "* timeZone: \(timeZone)",
-            "* basalSchedule: \(String(describing: basalSchedule))",
-            "* expirationReminderDate: \(String(describing: expirationReminderDate))",
-            "* unstoredDoses: \(String(describing: unstoredDoses))",
-            "* suspendEngageState: \(String(describing: suspendEngageState))",
-            "* bolusEngageState: \(String(describing: bolusEngageState))",
-            "* tempBasalEngageState: \(String(describing: tempBasalEngageState))",
-            "* lastPumpDataReportDate: \(String(describing: lastPumpDataReportDate))",
-            "* isPumpDataStale: \(String(describing: isPumpDataStale))",
-            "* confirmationBeeps: \(String(describing: confirmationBeeps))",
-            "* automaticBolusBeeps: \(String(describing: automaticBolusBeeps))",
-            "* pairingAttemptAddress: \(String(describing: pairingAttemptAddress))",
-            "* insulinType: \(String(describing: insulinType))",
-            String(reflecting: podState),
-            String(reflecting: rileyLinkConnectionManagerState),
-        ].joined(separator: "\n")
-    }
-}

+ 0 - 469
Dependecies/rileylink_ios/OmniKit/PumpManager/PodComms.swift

@@ -1,469 +0,0 @@
-//
-//  PodComms.swift
-//  OmniKit
-//
-//  Created by Pete Schwamb on 10/7/17.
-//  Copyright © 2017 Pete Schwamb. All rights reserved.
-//
-
-import Foundation
-import RileyLinkBLEKit
-import LoopKit
-import os.log
-
-
-protocol PodCommsDelegate: class {
-    func podComms(_ podComms: PodComms, didChange podState: PodState)
-}
-
-class PodComms: CustomDebugStringConvertible {
-    
-    private let configuredDevices: Locked<Set<RileyLinkDevice>> = Locked(Set())
-    
-    weak var delegate: PodCommsDelegate?
-    
-    weak var messageLogger: MessageLogger?
-
-    public let log = OSLog(category: "PodComms")
-
-    private var startingPacketNumber = 0
-
-    // Only valid to access on the session serial queue
-    private var podState: PodState? {
-        didSet {
-            if let newValue = podState, newValue != oldValue {
-                //log.debug("Notifying delegate of new podState: %{public}@", String(reflecting: newValue))
-                delegate?.podComms(self, didChange: newValue)
-            }
-        }
-    }
-    
-    init(podState: PodState?) {
-        self.podState = podState
-        self.delegate = nil
-        self.messageLogger = nil
-    }
-    
-    var insulinType: InsulinType? {
-        get { podState?.insulinType }
-        set {
-            if let insulinType = newValue {
-                podState?.insulinType = insulinType
-            }
-        }
-    }
-    
-    /// Handles all the common work to send and verify the version response for the two pairing commands, AssignAddress and SetupPod.
-    ///  Has side effects of creating pod state, assigning startingPacketNumber, and updating pod state.
-    ///
-    /// - parameter address: Address being assigned to the pod
-    /// - parameter transport: PodMessageTransport used to send messages
-    /// - parameter message: Message to send; must be an AssignAddress or SetupPod
-    ///
-    /// - returns: The VersionResponse from the pod
-    ///
-    /// - Throws:
-    ///     - PodCommsError.noResponse
-    ///     - PodCommsError.podAckedInsteadOfReturningResponse
-    ///     - PodCommsError.unexpectedPacketType
-    ///     - PodCommsError.emptyResponse
-    ///     - PodCommsError.unexpectedResponse
-    ///     - PodCommsError.podChange
-    ///     - PodCommsError.rssiTooLow
-    ///     - PodCommsError.rssiTooHigh
-    ///     - PodCommsError.activationTimeExceeded
-    ///     - MessageError.invalidCrc
-    ///     - MessageError.invalidSequence
-    ///     - MessageError.invalidAddress
-    ///     - RileyLinkDeviceError
-    private func sendPairMessage(address: UInt32, transport: PodMessageTransport, message: Message, insulinType: InsulinType) throws -> VersionResponse {
-
-        defer {
-            log.debug("sendPairMessage saving current transport packet #%d", transport.packetNumber)
-            if self.podState != nil {
-                self.podState!.messageTransportState = MessageTransportState(packetNumber: transport.packetNumber, messageNumber: transport.messageNumber)
-            } else {
-                self.startingPacketNumber = transport.packetNumber
-            }
-        }
-
-        var didRetry = false
-        
-        var rssiRetries = 2
-        while true {
-            let response: Message
-            do {
-                response = try transport.sendMessage(message)
-            } catch let error {
-                if let podCommsError = error as? PodCommsError {
-                    switch podCommsError {
-                    // These errors can happen some times when the responses are not seen for a long
-                    // enough time. Automatically retrying using the already incremented packet # can
-                    // clear this condition without requiring any user interaction for a pairing failure.
-                    case .podAckedInsteadOfReturningResponse, .noResponse:
-                        if didRetry == false {
-                            didRetry = true
-                            log.debug("sendPairMessage to retry using updated packet #%d", transport.packetNumber)
-                            continue // the transport packet # is already advanced for the retry
-                        }
-                    default:
-                        break
-                    }
-                }
-                throw error
-            }
-
-            if let fault = response.fault {
-                log.error("Pod Fault: %{public}@", String(describing: fault))
-                if let podState = self.podState, podState.fault == nil {
-                    self.podState!.fault = fault
-                }
-                throw PodCommsError.podFault(fault: fault)
-            }
-
-            guard let config = response.messageBlocks[0] as? VersionResponse else {
-                log.error("sendPairMessage unexpected response: %{public}@", String(describing: response))
-                let responseType = response.messageBlocks[0].blockType
-                throw PodCommsError.unexpectedResponse(response: responseType)
-            }
-
-            guard config.address == address else {
-                log.error("sendPairMessage unexpected address return of %{public}@ instead of expected %{public}@",
-                  String(format: "04X", config.address), String(format: "%04X", address))
-                throw PodCommsError.invalidAddress(address: config.address, expectedAddress: address)
-            }
-
-            // If we previously had podState, verify that we are still dealing with the same pod
-            if let podState = self.podState, (podState.lot != config.lot || podState.tid != config.tid) {
-                // Have a new pod, could be a pod change w/o deactivation (or we're picking up some other pairing pod!)
-                log.error("Received pod response for [lot %u tid %u], expected [lot %u tid %u]", config.lot, config.tid, podState.lot, podState.tid)
-                throw PodCommsError.podChange
-            }
-
-            // Checking RSSI
-            let maxRssiAllowed = 59         // maximum RSSI limit allowed
-            let minRssiAllowed = 30         // minimum RSSI limit allowed
-            if let rssi = config.rssi, let gain = config.gain {
-                let rssiStr = String(format: "Receiver Low Gain: %d.\nReceived Signal Strength Indicator: %d", gain, rssi)
-                log.default("%s", rssiStr)
-                rssiRetries -= 1
-                if rssi < minRssiAllowed {
-                    log.default("RSSI value %d is less than minimum allowed value of %d, %d retries left", rssi, minRssiAllowed, rssiRetries)
-                    if rssiRetries > 0 {
-                        continue
-                    }
-                    throw PodCommsError.rssiTooLow
-                }
-                if rssi > maxRssiAllowed {
-                    log.default("RSSI value %d is more than maximum allowed value of %d, %d retries left", rssi, maxRssiAllowed, rssiRetries)
-                    if rssiRetries > 0 {
-                        continue
-                    }
-                    throw PodCommsError.rssiTooHigh
-                }
-            }
-
-            if self.podState == nil {
-                log.default("Creating PodState for address %{public}@ [lot %u tid %u], packet #%d, message #%d", String(format: "%04X", config.address), config.lot, config.tid, transport.packetNumber, transport.messageNumber)
-                self.podState = PodState(
-                    address: config.address,
-                    piVersion: String(describing: config.piVersion),
-                    pmVersion: String(describing: config.pmVersion),
-                    lot: config.lot,
-                    tid: config.tid,
-                    packetNumber: transport.packetNumber,
-                    messageNumber: transport.messageNumber,
-                    insulinType: insulinType
-                )
-                // podState setupProgress state should be addressAssigned
-            }
-
-            // Now that we have podState, check for an activation timeout condition that can be noted in setupProgress
-            guard config.podProgressStatus != .activationTimeExceeded else {
-                // The 2 hour window for the initial pairing has expired
-                self.podState?.setupProgress = .activationTimeout
-                throw PodCommsError.activationTimeExceeded
-            }
-
-            if config.podProgressStatus == .pairingCompleted {
-                log.info("Version Response %{public}@ indicates pairing is complete, moving pod to configured state", String(describing: config))
-                self.podState?.setupProgress = .podConfigured
-            }
-
-            return config
-        }
-    }
-
-    private func assignAddress(address: UInt32, commandSession: CommandSession, insulinType: InsulinType) throws {
-        commandSession.assertOnSessionQueue()
-
-        let packetNumber, messageNumber: Int
-        if let podState = self.podState {
-            packetNumber = podState.messageTransportState.packetNumber
-            messageNumber = podState.messageTransportState.messageNumber
-        } else {
-            packetNumber = self.startingPacketNumber
-            messageNumber = 0
-        }
-
-        log.debug("Attempting pairing with address %{public}@ using packet #%d", String(format: "%04X", address), packetNumber)
-        let messageTransportState = MessageTransportState(packetNumber: packetNumber, messageNumber: messageNumber)
-        let transport = PodMessageTransport(session: commandSession, address: 0xffffffff, ackAddress: address, state: messageTransportState)
-        transport.messageLogger = messageLogger
-        
-        // Create the Assign Address command message
-        let assignAddress = AssignAddressCommand(address: address)
-        let message = Message(address: 0xffffffff, messageBlocks: [assignAddress], sequenceNum: transport.messageNumber)
-
-        _ = try sendPairMessage(address: address, transport: transport, message: message, insulinType: insulinType)
-    }
-    
-    private func setupPod(podState: PodState, timeZone: TimeZone, commandSession: CommandSession, insulinType: InsulinType) throws {
-        commandSession.assertOnSessionQueue()
-        
-        let transport = PodMessageTransport(session: commandSession, address: 0xffffffff, ackAddress: podState.address, state: podState.messageTransportState)
-        transport.messageLogger = messageLogger
-        
-        let dateComponents = SetupPodCommand.dateComponents(date: Date(), timeZone: timeZone)
-        let setupPod = SetupPodCommand(address: podState.address, dateComponents: dateComponents, lot: podState.lot, tid: podState.tid)
-        
-        let message = Message(address: 0xffffffff, messageBlocks: [setupPod], sequenceNum: transport.messageNumber)
-        
-        let versionResponse: VersionResponse
-        do {
-            versionResponse = try sendPairMessage(address: podState.address, transport: transport, message: message, insulinType: insulinType)
-        } catch let error {
-            if case PodCommsError.podAckedInsteadOfReturningResponse = error {
-                log.default("SetupPod acked instead of returning response. Moving pod to configured state.")
-                self.podState?.setupProgress = .podConfigured
-                return
-            }
-            log.error("SetupPod returns error %{public}@", String(describing: error))
-            throw error
-        }
-
-        guard versionResponse.isSetupPodVersionResponse else {
-            log.error("SetupPod unexpected VersionResponse type: %{public}@", String(describing: versionResponse))
-            throw PodCommsError.invalidData
-        }
-    }
-    
-    func assignAddressAndSetupPod(
-        address: UInt32,
-        using deviceSelector: @escaping (_ completion: @escaping (_ device: RileyLinkDevice?) -> Void) -> Void,
-        timeZone: TimeZone,
-        messageLogger: MessageLogger?,
-        insulinType: InsulinType,
-        _ block: @escaping (_ result: SessionRunResult) -> Void)
-    {
-        deviceSelector { (device) in
-            guard let device = device else {
-                block(.failure(PodCommsError.noRileyLinkAvailable))
-                return
-            }
-
-            device.runSession(withName: "Pair Pod") { (commandSession) in
-                do {
-                    self.configureDevice(device, with: commandSession)
-                    
-                    if self.podState == nil {
-                        try self.assignAddress(address: address, commandSession: commandSession, insulinType: insulinType)
-                    }
-                    
-                    guard self.podState != nil else {
-                        block(.failure(PodCommsError.noPodPaired))
-                        return
-                    }
-
-                    if self.podState!.setupProgress != .podConfigured {
-                        try self.setupPod(podState: self.podState!, timeZone: timeZone, commandSession: commandSession, insulinType: insulinType)
-                    }
-
-                    guard self.podState!.setupProgress == .podConfigured else {
-                        self.log.error("Unexpected podStatus setupProgress value of %{public}@", String(describing: self.podState!.setupProgress))
-                        throw PodCommsError.invalidData
-                    }
-                    self.startingPacketNumber = 0
-
-                    // Run a session now for any post-pairing commands
-                    let transport = PodMessageTransport(session: commandSession, address: self.podState!.address, state: self.podState!.messageTransportState)
-                    transport.messageLogger = self.messageLogger
-                    let podSession = PodCommsSession(podState: self.podState!, transport: transport, delegate: self)
-
-                    block(.success(session: podSession))
-                } catch let error as PodCommsError {
-                    block(.failure(error))
-                } catch {
-                    block(.failure(PodCommsError.commsError(error: error)))
-                }
-            }
-        }
-    }
-    
-    enum SessionRunResult {
-        case success(session: PodCommsSession)
-        case failure(PodCommsError)
-    }
-    
-    func runSession(withName name: String, using deviceSelector: @escaping (_ completion: @escaping (_ device: RileyLinkDevice?) -> Void) -> Void, _ block: @escaping (_ result: SessionRunResult) -> Void) {
-
-        deviceSelector { (device) in
-            guard let device = device else {
-                block(.failure(PodCommsError.noRileyLinkAvailable))
-                return
-            }
-
-            device.runSession(withName: name) { (commandSession) in
-                guard self.podState != nil else {
-                    block(.failure(PodCommsError.noPodPaired))
-                    return
-                }
-
-                self.configureDevice(device, with: commandSession)
-                let transport = PodMessageTransport(session: commandSession, address: self.podState!.address, state: self.podState!.messageTransportState)
-                transport.messageLogger = self.messageLogger
-                let podSession = PodCommsSession(podState: self.podState!, transport: transport, delegate: self)
-                block(.success(session: podSession))
-            }
-        }
-    }
-    
-    // Must be called from within the RileyLinkDevice sessionQueue
-    private func configureDevice(_ device: RileyLinkDevice, with session: CommandSession) {
-        session.assertOnSessionQueue()
-
-        guard !self.configuredDevices.value.contains(device) else {
-            return
-        }
-        
-        do {
-            log.debug("configureRadio (omnipod)")
-            _ = try session.configureRadio()
-        } catch let error {
-            log.error("configure Radio failed with error: %{public}@", String(describing: error))
-            // Ignore the error and let the block run anyway
-            return
-        }
-        
-        NotificationCenter.default.post(name: .DeviceRadioConfigDidChange, object: device)
-        NotificationCenter.default.addObserver(self, selector: #selector(deviceRadioConfigDidChange(_:)), name: .DeviceRadioConfigDidChange, object: device)
-        NotificationCenter.default.addObserver(self, selector: #selector(deviceRadioConfigDidChange(_:)), name: .DeviceConnectionStateDidChange, object: device)
-        
-        log.debug("added device %{public}@ to configuredDevices", device.name ?? "unknown")
-        _ = configuredDevices.mutate { (value) in
-            value.insert(device)
-        }
-    }
-    
-    @objc private func deviceRadioConfigDidChange(_ note: Notification) {
-        guard let device = note.object as? RileyLinkDevice else {
-            return
-        }
-        log.debug("removing device %{public}@ from configuredDevices", device.name ?? "unknown")
-
-        NotificationCenter.default.removeObserver(self, name: .DeviceRadioConfigDidChange, object: device)
-        NotificationCenter.default.removeObserver(self, name: .DeviceConnectionStateDidChange, object: device)
-
-        _ = configuredDevices.mutate { (value) in
-            value.remove(device)
-        }
-    }
-    
-    // MARK: - CustomDebugStringConvertible
-    
-    var debugDescription: String {
-        return [
-            "## PodComms",
-            "podState: \(String(reflecting: podState))",
-            "configuredDevices: \(configuredDevices.value.map { $0.peripheralIdentifier.uuidString })",
-            "delegate: \(String(describing: delegate != nil))",
-            ""
-        ].joined(separator: "\n")
-    }
-
-}
-
-extension PodComms: PodCommsSessionDelegate {
-    func podCommsSession(_ podCommsSession: PodCommsSession, didChange state: PodState) {
-        podCommsSession.assertOnSessionQueue()
-        self.podState = state
-    }
-}
-
-
-private extension CommandSession {
-    
-    func configureRadio() throws {
-        
-        //        SYNC1     |0xDF00|0x54|Sync Word, High Byte
-        //        SYNC0     |0xDF01|0xC3|Sync Word, Low Byte
-        //        PKTLEN    |0xDF02|0x32|Packet Length
-        //        PKTCTRL1  |0xDF03|0x24|Packet Automation Control
-        //        PKTCTRL0  |0xDF04|0x00|Packet Automation Control
-        //        FSCTRL1   |0xDF07|0x06|Frequency Synthesizer Control
-        //        FREQ2     |0xDF09|0x12|Frequency Control Word, High Byte
-        //        FREQ1     |0xDF0A|0x14|Frequency Control Word, Middle Byte
-        //        FREQ0     |0xDF0B|0x5F|Frequency Control Word, Low Byte
-        //        MDMCFG4   |0xDF0C|0xCA|Modem configuration
-        //        MDMCFG3   |0xDF0D|0xBC|Modem Configuration
-        //        MDMCFG2   |0xDF0E|0x0A|Modem Configuration
-        //        MDMCFG1   |0xDF0F|0x13|Modem Configuration
-        //        MDMCFG0   |0xDF10|0x11|Modem Configuration
-        //        MCSM0     |0xDF14|0x18|Main Radio Control State Machine Configuration
-        //        FOCCFG    |0xDF15|0x17|Frequency Offset Compensation Configuration
-        //        AGCCTRL1  |0xDF18|0x70|AGC Control
-        //        FSCAL3    |0xDF1C|0xE9|Frequency Synthesizer Calibration
-        //        FSCAL2    |0xDF1D|0x2A|Frequency Synthesizer Calibration
-        //        FSCAL1    |0xDF1E|0x00|Frequency Synthesizer Calibration
-        //        FSCAL0    |0xDF1F|0x1F|Frequency Synthesizer Calibration
-        //        TEST1     |0xDF24|0x31|Various Test Settings
-        //        TEST0     |0xDF25|0x09|Various Test Settings
-        //        PA_TABLE0 |0xDF2E|0x60|PA Power Setting 0
-        //        VERSION   |0xDF37|0x04|Chip ID[7:0]
-        
-        try setSoftwareEncoding(.manchester)
-        try setPreamble(0x6665)
-        try setBaseFrequency(Measurement(value: 433.91, unit: .megahertz))
-        try updateRegister(.pktctrl1, value: 0x20)
-        try updateRegister(.pktctrl0, value: 0x00)
-        try updateRegister(.fsctrl1, value: 0x06)
-        try updateRegister(.mdmcfg4, value: 0xCA)
-        try updateRegister(.mdmcfg3, value: 0xBC)  // 0xBB for next lower bitrate
-        try updateRegister(.mdmcfg2, value: 0x06)
-        try updateRegister(.mdmcfg1, value: 0x70)
-        try updateRegister(.mdmcfg0, value: 0x11)
-        try updateRegister(.deviatn, value: 0x44)
-        try updateRegister(.mcsm0, value: 0x18)
-        try updateRegister(.foccfg, value: 0x17)
-        try updateRegister(.fscal3, value: 0xE9)
-        try updateRegister(.fscal2, value: 0x2A)
-        try updateRegister(.fscal1, value: 0x00)
-        try updateRegister(.fscal0, value: 0x1F)
-        
-        try updateRegister(.test1, value: 0x31)
-        try updateRegister(.test0, value: 0x09)
-        try updateRegister(.paTable0, value: 0x84)
-        try updateRegister(.sync1, value: 0xA5)
-        try updateRegister(.sync0, value: 0x5A)
-    }
-
-    // This is just a testing function for spoofing PDM packets, or other times when you need to generate a custom packet
-    private func sendPacket() throws {
-        let packetNumber = 19
-        let messageNumber = 0x24 >> 2
-        let address: UInt32 = 0x1f0b3554
-
-        let cmd = GetStatusCommand(podInfoType: .normal)
-
-        let message = Message(address: address, messageBlocks: [cmd], sequenceNum: messageNumber)
-
-        var dataRemaining = message.encoded()
-
-        let sendPacket = Packet(address: address, packetType: .pdm, sequenceNum: packetNumber, data: dataRemaining)
-        dataRemaining = dataRemaining.subdata(in: sendPacket.data.count..<dataRemaining.count)
-
-        let _ = try sendAndListen(sendPacket.encoded(), repeatCount: 0, timeout: .milliseconds(333), retryCount: 0, preambleExtension: .milliseconds(127))
-
-        throw PodCommsError.emptyResponse
-    }
-}

+ 0 - 742
Dependecies/rileylink_ios/OmniKit/PumpManager/PodCommsSession.swift

@@ -1,742 +0,0 @@
-//
-//  PodCommsSession.swift
-//  OmniKit
-//
-//  Created by Pete Schwamb on 10/13/17.
-//  Copyright © 2017 Pete Schwamb. All rights reserved.
-//
-
-import Foundation
-import RileyLinkBLEKit
-import LoopKit
-import os.log
-
-public enum PodCommsError: Error {
-    case noPodPaired
-    case invalidData
-    case noResponse
-    case emptyResponse
-    case podAckedInsteadOfReturningResponse
-    case unexpectedPacketType(packetType: PacketType)
-    case unexpectedResponse(response: MessageBlockType)
-    case unknownResponseType(rawType: UInt8)
-    case invalidAddress(address: UInt32, expectedAddress: UInt32)
-    case noRileyLinkAvailable
-    case unfinalizedBolus
-    case unfinalizedTempBasal
-    case nonceResyncFailed
-    case podSuspended
-    case podFault(fault: DetailedStatus)
-    case commsError(error: Error)
-    case rejectedMessage(errorCode: UInt8)
-    case podChange
-    case activationTimeExceeded
-    case rssiTooLow
-    case rssiTooHigh
-}
-
-extension PodCommsError: LocalizedError {
-    public var errorDescription: String? {
-        switch self {
-        case .noPodPaired:
-            return LocalizedString("No pod paired", comment: "Error message shown when no pod is paired")
-        case .invalidData:
-            return nil
-        case .noResponse:
-            return LocalizedString("No response from pod", comment: "Error message shown when no response from pod was received")
-        case .emptyResponse:
-            return LocalizedString("Empty response from pod", comment: "Error message shown when empty response from pod was received")
-        case .podAckedInsteadOfReturningResponse:
-            return LocalizedString("Pod sent ack instead of response", comment: "Error message shown when pod sends ack instead of response")
-        case .unexpectedPacketType:
-            return nil
-        case .unexpectedResponse:
-            return LocalizedString("Unexpected response from pod", comment: "Error message shown when empty response from pod was received")
-        case .unknownResponseType:
-            return nil
-        case .invalidAddress(address: let address, expectedAddress: let expectedAddress):
-            return String(format: LocalizedString("Invalid address 0x%x. Expected 0x%x", comment: "Error message for when unexpected address is received (1: received address) (2: expected address)"), address, expectedAddress)
-        case .noRileyLinkAvailable:
-            return LocalizedString("No RileyLink available", comment: "Error message shown when no response from pod was received")
-        case .unfinalizedBolus:
-            return LocalizedString("Bolus in progress", comment: "Error message shown when operation could not be completed due to existing bolus in progress")
-        case .unfinalizedTempBasal:
-            return LocalizedString("Temp basal in progress", comment: "Error message shown when temp basal could not be set due to existing temp basal in progress")
-        case .nonceResyncFailed:
-            return nil
-        case .podSuspended:
-            return LocalizedString("Pod is suspended", comment: "Error message action could not be performed because pod is suspended")
-        case .podFault(let fault):
-            let faultDescription = String(describing: fault.faultEventCode)
-            return String(format: LocalizedString("Pod Fault: %1$@", comment: "Format string for pod fault code"), faultDescription)
-        case .commsError(let error):
-            return error.localizedDescription
-        case .rejectedMessage(let errorCode):
-            return String(format: LocalizedString("Command error %1$u", comment: "Format string for invalid message error code (1: error code number)"), errorCode)
-        case .podChange:
-            return LocalizedString("Unexpected pod change", comment: "Format string for unexpected pod change")
-        case .activationTimeExceeded:
-            return LocalizedString("Activation time exceeded", comment: "Format string for activation time exceeded")
-        case .rssiTooLow: // occurs when RileyLink is too far from pod for reliable pairing, but can sometimes occur at other distances & positions
-            return LocalizedString("Poor signal strength", comment: "Format string for poor pod signal strength")
-        case .rssiTooHigh: // only occurs when RileyLink is too close to the pod for reliable pairing
-            return LocalizedString("Signal strength too high", comment: "Format string for pod signal strength too high")
-        }
-    }
-    
-//    public var failureReason: String? {
-//        return nil
-//    }
-    
-    public var recoverySuggestion: String? {
-        switch self {
-        case .noPodPaired:
-            return nil
-        case .invalidData:
-            return nil
-        case .noResponse:
-            return LocalizedString("Please try repositioning the pod or the RileyLink and try again", comment: "Recovery suggestion when no response is received from pod")
-        case .emptyResponse:
-            return nil
-        case .podAckedInsteadOfReturningResponse:
-            return LocalizedString("Try again", comment: "Recovery suggestion when ack received instead of response")
-        case .unexpectedPacketType:
-            return nil
-        case .unexpectedResponse:
-            return nil
-        case .unknownResponseType:
-            return nil
-        case .invalidAddress:
-            return LocalizedString("Crosstalk possible. Please move to a new location and try again", comment: "Recovery suggestion when unexpected address received")
-        case .noRileyLinkAvailable:
-            return LocalizedString("Make sure your RileyLink is nearby and powered on", comment: "Recovery suggestion when no RileyLink is available")
-        case .unfinalizedBolus:
-            return LocalizedString("Wait for existing bolus to finish, or cancel bolus", comment: "Recovery suggestion when operation could not be completed due to existing bolus in progress")
-        case .unfinalizedTempBasal:
-            return LocalizedString("Wait for existing temp basal to finish, or suspend to cancel", comment: "Recovery suggestion when operation could not be completed due to existing temp basal in progress")
-        case .nonceResyncFailed:
-            return nil
-        case .podSuspended:
-            return nil
-        case .podFault:
-            return nil
-        case .commsError:
-            return nil
-        case .rejectedMessage:
-            return nil
-        case .podChange:
-            return LocalizedString("Please bring only original pod in range or deactivate original pod", comment: "Recovery suggestion on unexpected pod change")
-        case .activationTimeExceeded:
-            return nil
-        case .rssiTooLow:
-            return LocalizedString("Please reposition the RileyLink relative to the pod", comment: "Recovery suggestion when pairing signal strength is too low")
-        case .rssiTooHigh:
-            return LocalizedString("Please reposition the RileyLink further from the pod", comment: "Recovery suggestion when pairing signal strength is too high")
-        }
-    }
-}
-
-public protocol PodCommsSessionDelegate: class {
-    func podCommsSession(_ podCommsSession: PodCommsSession, didChange state: PodState)
-}
-
-public class PodCommsSession {
-    private let useCancelNoneForStatus: Bool = false             // whether to always use a cancel none to get status
-    
-    public let log = OSLog(category: "PodCommsSession")
-    
-    private var podState: PodState {
-        didSet {
-            assertOnSessionQueue()
-            delegate.podCommsSession(self, didChange: podState)
-        }
-    }
-    
-    private unowned let delegate: PodCommsSessionDelegate
-    private var transport: MessageTransport
-
-    init(podState: PodState, transport: MessageTransport, delegate: PodCommsSessionDelegate) {
-        self.podState = podState
-        self.transport = transport
-        self.delegate = delegate
-        self.transport.delegate = self
-    }
-
-    // Handles updating PodState on first pod fault seen
-    private func handlePodFault(fault: DetailedStatus) {
-        if self.podState.fault == nil {
-            self.podState.fault = fault // save the first fault returned
-            handleCancelDosing(deliveryType: .all, bolusNotDelivered: fault.bolusNotDelivered)
-            podState.updateFromDetailedStatusResponse(fault)
-        }
-        log.error("Pod Fault: %@", String(describing: fault))
-    }
-
-    // Will throw either PodCommsError.podFault or PodCommsError.activationTimeExceeded
-    private func throwPodFault(fault: DetailedStatus) throws {
-        handlePodFault(fault: fault)
-        if fault.podProgressStatus == .activationTimeExceeded {
-            // avoids a confusing "No fault" error when activation time is exceeded
-            throw PodCommsError.activationTimeExceeded
-        }
-        throw PodCommsError.podFault(fault: fault)
-    }
-
-    /// Performs a message exchange, handling nonce resync, pod faults
-    ///
-    /// - Parameters:
-    ///   - messageBlocks: The message blocks to send
-    ///   - confirmationBeepType: If specified, type of confirmation beep to append as a separate beep message block
-    ///   - expectFollowOnMessage: If true, the pod will expect another message within 4 minutes, or will alarm with an 0x33 (51) fault.
-    /// - Returns: The received message response
-    /// - Throws:
-    ///     - PodCommsError.noResponse
-    ///     - PodCommsError.podFault
-    ///     - PodCommsError.unexpectedResponse
-    ///     - PodCommsError.rejectedMessage
-    ///     - PodCommsError.nonceResyncFailed
-    ///     - MessageError
-    ///     - RileyLinkDeviceError
-    func send<T: MessageBlock>(_ messageBlocks: [MessageBlock], confirmationBeepType: BeepConfigType? = nil, expectFollowOnMessage: Bool = false) throws -> T {
-        
-        var triesRemaining = 2  // Retries only happen for nonce resync
-        var blocksToSend = messageBlocks
-        
-        // If a confirmation beep type was specified & pod isn't faulted, append a beep config message block to emit the requested beep type
-        if let confirmationBeepType = confirmationBeepType, podState.isFaulted == false {
-            let confirmationBeepBlock = BeepConfigCommand(beepConfigType: confirmationBeepType, basalCompletionBeep: true, tempBasalCompletionBeep: false, bolusCompletionBeep: true)
-            blocksToSend += [confirmationBeepBlock]
-        }
-
-        if blocksToSend.contains(where: { $0 as? NonceResyncableMessageBlock != nil }) {
-            podState.advanceToNextNonce()
-        }
-        
-        let messageNumber = transport.messageNumber
-
-        var sentNonce: UInt32?
-
-        while (triesRemaining > 0) {
-            triesRemaining -= 1
-
-            for command in blocksToSend {
-                if let nonceBlock = command as? NonceResyncableMessageBlock {
-                    sentNonce = nonceBlock.nonce
-                    break // N.B. all nonce commands in single message should have the same value
-                }
-            }
-
-            let message = Message(address: podState.address, messageBlocks: blocksToSend, sequenceNum: messageNumber, expectFollowOnMessage: expectFollowOnMessage)
-
-            let response = try transport.sendMessage(message)
-            
-            // Simulate fault
-            //let podInfoResponse = try PodInfoResponse(encodedData: Data(hexadecimalString: "0216020d0000000000ab6a038403ff03860000285708030d0000")!)
-            //let response = Message(address: podState.address, messageBlocks: [podInfoResponse], sequenceNum: message.sequenceNum)
-
-            if let responseMessageBlock = response.messageBlocks[0] as? T {
-                log.info("POD Response: %@", String(describing: responseMessageBlock))
-                return responseMessageBlock
-            }
-
-            if let fault = response.fault {
-                try throwPodFault(fault: fault) // always throws
-            }
-
-            let responseType = response.messageBlocks[0].blockType
-            guard let errorResponse = response.messageBlocks[0] as? ErrorResponse else {
-                log.error("Unexpected response: %{public}@", String(describing: response.messageBlocks[0]))
-                throw PodCommsError.unexpectedResponse(response: responseType)
-            }
-
-            switch errorResponse.errorResponseType {
-            case .badNonce(let nonceResyncKey):
-                guard let sentNonce = sentNonce else {
-                    log.error("Unexpected bad nonce response: %{public}@", String(describing: response.messageBlocks[0]))
-                    throw PodCommsError.unexpectedResponse(response: responseType)
-                }
-                podState.resyncNonce(syncWord: nonceResyncKey, sentNonce: sentNonce, messageSequenceNum: message.sequenceNum)
-                log.info("resyncNonce(syncWord: 0x%02x, sentNonce: 0x%04x, messageSequenceNum: %d) -> 0x%04x", nonceResyncKey, sentNonce, message.sequenceNum, podState.currentNonce)
-                blocksToSend = blocksToSend.map({ (block) -> MessageBlock in
-                    if var resyncableBlock = block as? NonceResyncableMessageBlock {
-                        log.info("Replaced old nonce 0x%04x with resync nonce 0x%04x", resyncableBlock.nonce, podState.currentNonce)
-                        resyncableBlock.nonce = podState.currentNonce
-                        return resyncableBlock
-                    }
-                    return block
-                })
-                podState.advanceToNextNonce()
-                break
-            case .nonretryableError(let errorCode, let faultEventCode, let podProgress):
-                log.error("Command error: code %u, %{public}@, pod progress %{public}@", errorCode, String(describing: faultEventCode), String(describing: podProgress))
-                throw PodCommsError.rejectedMessage(errorCode: errorCode)
-            }
-        }
-        throw PodCommsError.nonceResyncFailed
-    }
-
-    // Returns time at which prime is expected to finish.
-    public func prime() throws -> TimeInterval {
-        //4c00 00c8 0102
-
-        let primeDuration = TimeInterval(seconds: 55)   // a bit more than (Pod.primeUnits / Pod.primeDeliveryRate)
-        
-        // Skip following alerts if we've already done them before
-        if podState.setupProgress != .startingPrime {
-            
-            // The following will set Tab5[$16] to 0 during pairing, which disables $6x faults.
-            let _: StatusResponse = try send([FaultConfigCommand(nonce: podState.currentNonce, tab5Sub16: 0, tab5Sub17: 0)])
-            let finishSetupReminder = PodAlert.finishSetupReminder
-            try configureAlerts([finishSetupReminder])
-        } else {
-            // We started prime, but didn't get confirmation somehow, so check status
-            let status: StatusResponse = try send([GetStatusCommand()])
-            podState.updateFromStatusResponse(status)
-            if status.podProgressStatus == .priming || status.podProgressStatus == .primingCompleted {
-                podState.setupProgress = .priming
-                return podState.primeFinishTime?.timeIntervalSinceNow ?? primeDuration
-            }
-        }
-
-        // Mark 2.6U delivery with 1 second between pulses for prime
-        
-        let primeFinishTime = Date() + primeDuration
-        podState.primeFinishTime = primeFinishTime
-        podState.setupProgress = .startingPrime
-
-        let timeBetweenPulses = TimeInterval(seconds: Pod.secondsPerPrimePulse)
-        let bolusSchedule = SetInsulinScheduleCommand.DeliverySchedule.bolus(units: Pod.primeUnits, timeBetweenPulses: timeBetweenPulses)
-        let scheduleCommand = SetInsulinScheduleCommand(nonce: podState.currentNonce, deliverySchedule: bolusSchedule)
-        let bolusExtraCommand = BolusExtraCommand(units: Pod.primeUnits, timeBetweenPulses: timeBetweenPulses)
-        let status: StatusResponse = try send([scheduleCommand, bolusExtraCommand])
-        podState.updateFromStatusResponse(status)
-        podState.setupProgress = .priming
-        return primeFinishTime.timeIntervalSinceNow
-    }
-    
-    public func programInitialBasalSchedule(_ basalSchedule: BasalSchedule, scheduleOffset: TimeInterval) throws {
-        if podState.setupProgress == .settingInitialBasalSchedule {
-            // We started basal schedule programming, but didn't get confirmation somehow, so check status
-            let status: StatusResponse = try send([GetStatusCommand()])
-            podState.updateFromStatusResponse(status)
-            if status.podProgressStatus == .basalInitialized {
-                podState.setupProgress = .initialBasalScheduleSet
-                return
-            }
-        }
-        
-        podState.setupProgress = .settingInitialBasalSchedule
-        // Set basal schedule
-        let _ = try setBasalSchedule(schedule: basalSchedule, scheduleOffset: scheduleOffset)
-        podState.setupProgress = .initialBasalScheduleSet
-        podState.finalizedDoses.append(UnfinalizedDose(resumeStartTime: Date(), scheduledCertainty: .certain, insulinType: podState.insulinType))
-    }
-
-    @discardableResult
-    private func configureAlerts(_ alerts: [PodAlert]) throws -> StatusResponse {
-        let configurations = alerts.map { $0.configuration }
-        let configureAlerts = ConfigureAlertsCommand(nonce: podState.currentNonce, configurations: configurations)
-        let status: StatusResponse = try send([configureAlerts])
-        for alert in alerts {
-            podState.registerConfiguredAlert(slot: alert.configuration.slot, alert: alert)
-        }
-        podState.updateFromStatusResponse(status)
-        return status
-    }
-
-    // emits the specified beep type and sets the completion beep flags, doesn't throw
-    public func beepConfig(beepConfigType: BeepConfigType, basalCompletionBeep: Bool, tempBasalCompletionBeep: Bool, bolusCompletionBeep: Bool) -> Result<StatusResponse, Error> {
-        if let fault = self.podState.fault {
-            log.info("Skip beep config with faulted pod")
-            return .failure(PodCommsError.podFault(fault: fault))
-        }
-        
-        let beepConfigCommand = BeepConfigCommand(beepConfigType: beepConfigType, basalCompletionBeep: basalCompletionBeep, tempBasalCompletionBeep: tempBasalCompletionBeep, bolusCompletionBeep: bolusCompletionBeep)
-        do {
-            let statusResponse: StatusResponse = try send([beepConfigCommand])
-            podState.updateFromStatusResponse(statusResponse)
-            return .success(statusResponse)
-        } catch let error {
-            return .failure(error)
-        }
-    }
-
-    private func markSetupProgressCompleted(statusResponse: StatusResponse) {
-        if (podState.setupProgress != .completed) {
-            podState.setupProgress = .completed
-            podState.setupUnitsDelivered = statusResponse.insulin // stash the current insulin delivered value as the baseline
-            log.info("Total setup units delivered: %@", String(describing: statusResponse.insulin))
-        }
-    }
-
-    public func insertCannula() throws -> TimeInterval {
-        let insertionWait: TimeInterval = .seconds(Pod.cannulaInsertionUnits / Pod.primeDeliveryRate)
-
-        guard let activatedAt = podState.activatedAt else {
-            throw PodCommsError.noPodPaired
-        }
-
-        if podState.setupProgress == .startingInsertCannula || podState.setupProgress == .cannulaInserting {
-            // We started cannula insertion, but didn't get confirmation somehow, so check status
-            let status: StatusResponse = try send([GetStatusCommand()])
-            if status.podProgressStatus == .insertingCannula {
-                podState.setupProgress = .cannulaInserting
-                podState.updateFromStatusResponse(status)
-                return insertionWait // Not sure when it started, wait full time to be sure
-            }
-            if status.podProgressStatus.readyForDelivery {
-                markSetupProgressCompleted(statusResponse: status)
-                podState.updateFromStatusResponse(status)
-                return TimeInterval(0) // Already done; no need to wait
-            }
-            podState.updateFromStatusResponse(status)
-        } else {
-            // Configure all the non-optional Pod Alarms
-            let expirationTime = activatedAt + Pod.nominalPodLife
-            let timeUntilExpirationAdvisory = expirationTime.timeIntervalSinceNow
-            let expirationAdvisoryAlarm = PodAlert.expirationAdvisoryAlarm(alarmTime: timeUntilExpirationAdvisory, duration: Pod.expirationAdvisoryWindow)
-            let endOfServiceTime = activatedAt + Pod.serviceDuration
-            let shutdownImminentAlarm = PodAlert.shutdownImminentAlarm((endOfServiceTime - Pod.endOfServiceImminentWindow).timeIntervalSinceNow)
-            try configureAlerts([expirationAdvisoryAlarm, shutdownImminentAlarm])
-        }
-        
-        // Mark 0.5U delivery with 1 second between pulses for cannula insertion
-
-        let timeBetweenPulses = TimeInterval(seconds: Pod.secondsPerPrimePulse)
-        let bolusSchedule = SetInsulinScheduleCommand.DeliverySchedule.bolus(units: Pod.cannulaInsertionUnits, timeBetweenPulses: timeBetweenPulses)
-        let bolusScheduleCommand = SetInsulinScheduleCommand(nonce: podState.currentNonce, deliverySchedule: bolusSchedule)
-        
-        podState.setupProgress = .startingInsertCannula
-        let bolusExtraCommand = BolusExtraCommand(units: Pod.cannulaInsertionUnits, timeBetweenPulses: timeBetweenPulses)
-        let status2: StatusResponse = try send([bolusScheduleCommand, bolusExtraCommand])
-        podState.updateFromStatusResponse(status2)
-        
-        podState.setupProgress = .cannulaInserting
-        return insertionWait
-    }
-
-    public func checkInsertionCompleted() throws {
-        if podState.setupProgress == .cannulaInserting {
-            let response: StatusResponse = try send([GetStatusCommand()])
-            if response.podProgressStatus.readyForDelivery {
-                markSetupProgressCompleted(statusResponse: response)
-            }
-            podState.updateFromStatusResponse(response)
-        }
-    }
-
-    // Throws SetBolusError
-    public enum DeliveryCommandResult {
-        case success(statusResponse: StatusResponse)
-        case certainFailure(error: PodCommsError)
-        case uncertainFailure(error: PodCommsError)
-    }
-
-    public enum CancelDeliveryResult {
-        case success(statusResponse: StatusResponse, canceledDose: UnfinalizedDose?)
-        case certainFailure(error: PodCommsError)
-        case uncertainFailure(error: PodCommsError)
-    }
-
-    
-    public func bolus(units: Double, automatic: Bool, acknowledgementBeep: Bool = false, completionBeep: Bool = false, programReminderInterval: TimeInterval = 0) -> DeliveryCommandResult {
-        
-        let timeBetweenPulses = TimeInterval(seconds: Pod.secondsPerBolusPulse)
-        let bolusSchedule = SetInsulinScheduleCommand.DeliverySchedule.bolus(units: units, timeBetweenPulses: timeBetweenPulses)
-        let bolusScheduleCommand = SetInsulinScheduleCommand(nonce: podState.currentNonce, deliverySchedule: bolusSchedule)
-        
-        guard podState.unfinalizedBolus == nil else {
-            return DeliveryCommandResult.certainFailure(error: .unfinalizedBolus)
-        }
-        
-        // Between bluetooth and the radio and firmware, about 1.2s on average passes before we start tracking
-        let commsOffset = TimeInterval(seconds: -1.5)
-        
-        let bolusExtraCommand = BolusExtraCommand(units: units, timeBetweenPulses: timeBetweenPulses, acknowledgementBeep: acknowledgementBeep, completionBeep: completionBeep, programReminderInterval: programReminderInterval)
-        do {
-            let statusResponse: StatusResponse = try send([bolusScheduleCommand, bolusExtraCommand])
-            podState.unfinalizedBolus = UnfinalizedDose(bolusAmount: units, startTime: Date().addingTimeInterval(commsOffset), scheduledCertainty: .certain, insulinType: podState.insulinType, automatic: automatic)
-            podState.updateFromStatusResponse(statusResponse)
-            return DeliveryCommandResult.success(statusResponse: statusResponse)
-        } catch PodCommsError.nonceResyncFailed {
-            return DeliveryCommandResult.certainFailure(error: PodCommsError.nonceResyncFailed)
-        } catch PodCommsError.rejectedMessage(let errorCode) {
-            return DeliveryCommandResult.certainFailure(error: PodCommsError.rejectedMessage(errorCode: errorCode))
-        } catch let error {
-            self.log.debug("Uncertain result bolusing")
-            // Attempt to verify bolus
-            let podCommsError = error as? PodCommsError ?? PodCommsError.commsError(error: error)
-            guard let status = try? getStatus() else {
-                self.log.debug("Status check failed; could not resolve bolus uncertainty")
-                podState.unfinalizedBolus = UnfinalizedDose(bolusAmount: units, startTime: Date(), scheduledCertainty: .uncertain, insulinType: podState.insulinType, automatic: automatic)
-                return DeliveryCommandResult.uncertainFailure(error: podCommsError)
-            }
-            if status.deliveryStatus.bolusing {
-                self.log.debug("getStatus resolved bolus uncertainty (succeeded)")
-                podState.unfinalizedBolus = UnfinalizedDose(bolusAmount: units, startTime: Date().addingTimeInterval(commsOffset), scheduledCertainty: .certain, insulinType: podState.insulinType, automatic: automatic)
-                return DeliveryCommandResult.success(statusResponse: status)
-            } else {
-                self.log.debug("getStatus resolved bolus uncertainty (failed)")
-                return DeliveryCommandResult.certainFailure(error: podCommsError)
-            }
-        }
-    }
-    
-    public func setTempBasal(rate: Double, duration: TimeInterval, acknowledgementBeep: Bool = false, completionBeep: Bool = false, programReminderInterval: TimeInterval = 0) -> DeliveryCommandResult {
-        
-        let tempBasalCommand = SetInsulinScheduleCommand(nonce: podState.currentNonce, tempBasalRate: rate, duration: duration)
-        let tempBasalExtraCommand = TempBasalExtraCommand(rate: rate, duration: duration, acknowledgementBeep: acknowledgementBeep, completionBeep: completionBeep, programReminderInterval: programReminderInterval)
-
-        guard podState.unfinalizedBolus?.isFinished != false else {
-            return DeliveryCommandResult.certainFailure(error: .unfinalizedBolus)
-        }
-
-        do {
-            let status: StatusResponse = try send([tempBasalCommand, tempBasalExtraCommand])
-            podState.unfinalizedTempBasal = UnfinalizedDose(tempBasalRate: rate, startTime: Date(), duration: duration, scheduledCertainty: .certain, insulinType: podState.insulinType)
-            podState.updateFromStatusResponse(status)
-            return DeliveryCommandResult.success(statusResponse: status)
-        } catch PodCommsError.nonceResyncFailed {
-            return DeliveryCommandResult.certainFailure(error: PodCommsError.nonceResyncFailed)
-        } catch PodCommsError.rejectedMessage(let errorCode) {
-            return DeliveryCommandResult.certainFailure(error: PodCommsError.rejectedMessage(errorCode: errorCode))
-        } catch let error {
-            podState.unfinalizedTempBasal = UnfinalizedDose(tempBasalRate: rate, startTime: Date(), duration: duration, scheduledCertainty: .uncertain, insulinType: podState.insulinType)
-            return DeliveryCommandResult.uncertainFailure(error: error as? PodCommsError ?? PodCommsError.commsError(error: error))
-        }
-    }
-
-    @discardableResult
-    private func handleCancelDosing(deliveryType: CancelDeliveryCommand.DeliveryType, bolusNotDelivered: Double) -> UnfinalizedDose? {
-        var canceledDose: UnfinalizedDose? = nil
-        let now = Date()
-
-        if deliveryType.contains(.basal) {
-            podState.unfinalizedSuspend = UnfinalizedDose(suspendStartTime: now, scheduledCertainty: .certain)
-            podState.suspendState = .suspended(now)
-        }
-
-        if let unfinalizedTempBasal = podState.unfinalizedTempBasal,
-            let finishTime = unfinalizedTempBasal.finishTime,
-            deliveryType.contains(.tempBasal),
-            finishTime > now
-        {
-            podState.unfinalizedTempBasal?.cancel(at: now)
-            if !deliveryType.contains(.basal) {
-                podState.suspendState = .resumed(now)
-            }
-            canceledDose = podState.unfinalizedTempBasal
-            log.info("Interrupted temp basal: %@", String(describing: canceledDose))
-        }
-
-        if let unfinalizedBolus = podState.unfinalizedBolus,
-            let finishTime = unfinalizedBolus.finishTime,
-            deliveryType.contains(.bolus),
-            finishTime > now
-        {
-            podState.unfinalizedBolus?.cancel(at: now, withRemaining: bolusNotDelivered)
-            canceledDose = podState.unfinalizedBolus
-            log.info("Interrupted bolus: %@", String(describing: canceledDose))
-        }
-
-        return canceledDose
-    }
-    
-    // Cancel beeping can be done implemented using beepType (for a single delivery type) or a separate confirmation beep message block (for cancel all).
-    // N.B., Using the built-in cancel delivery command beepType method when cancelling all insulin delivery will emit 3 different sets of cancel beeps!!!
-    public func cancelDelivery(deliveryType: CancelDeliveryCommand.DeliveryType, beepType: BeepType = .noBeep, confirmationBeepType: BeepConfigType? = nil) -> CancelDeliveryResult {
-
-        do {
-            let cancelDeliveryCommand = CancelDeliveryCommand(nonce: podState.currentNonce, deliveryType: deliveryType, beepType: beepType)
-            let status: StatusResponse = try send([cancelDeliveryCommand], confirmationBeepType: confirmationBeepType)
-
-            let canceledDose = handleCancelDosing(deliveryType: deliveryType, bolusNotDelivered: status.bolusNotDelivered)
-            podState.updateFromStatusResponse(status)
-
-            return CancelDeliveryResult.success(statusResponse: status, canceledDose: canceledDose)
-        } catch PodCommsError.nonceResyncFailed {
-            return CancelDeliveryResult.certainFailure(error: PodCommsError.nonceResyncFailed)
-        } catch PodCommsError.rejectedMessage(let errorCode) {
-            return CancelDeliveryResult.certainFailure(error: PodCommsError.rejectedMessage(errorCode: errorCode))
-        } catch let error {
-            podState.unfinalizedSuspend = UnfinalizedDose(suspendStartTime: Date(), scheduledCertainty: .uncertain)
-            return CancelDeliveryResult.uncertainFailure(error: error as? PodCommsError ?? PodCommsError.commsError(error: error))
-        }
-    }
-
-    public func testingCommands(confirmationBeepType: BeepConfigType? = nil) throws {
-        try cancelNone(confirmationBeepType: confirmationBeepType) // reads status & verifies nonce by doing a cancel none
-    }
-    
-    public func setTime(timeZone: TimeZone, basalSchedule: BasalSchedule, date: Date, acknowledgementBeep: Bool = false, completionBeep: Bool = false) throws -> StatusResponse {
-        let result = cancelDelivery(deliveryType: .all)
-        switch result {
-        case .certainFailure(let error):
-            throw error
-        case .uncertainFailure(let error):
-            throw error
-        case .success:
-            let scheduleOffset = timeZone.scheduleOffset(forDate: date)
-            let status = try setBasalSchedule(schedule: basalSchedule, scheduleOffset: scheduleOffset, acknowledgementBeep: acknowledgementBeep, completionBeep: completionBeep)
-            return status
-        }
-    }
-    
-    public func setBasalSchedule(schedule: BasalSchedule, scheduleOffset: TimeInterval, acknowledgementBeep: Bool = false, completionBeep: Bool = false, programReminderInterval: TimeInterval = 0) throws -> StatusResponse {
-
-        let basalScheduleCommand = SetInsulinScheduleCommand(nonce: podState.currentNonce, basalSchedule: schedule, scheduleOffset: scheduleOffset)
-        let basalExtraCommand = BasalScheduleExtraCommand.init(schedule: schedule, scheduleOffset: scheduleOffset, acknowledgementBeep: acknowledgementBeep, completionBeep: completionBeep, programReminderInterval: programReminderInterval)
-
-        do {
-            let status: StatusResponse = try send([basalScheduleCommand, basalExtraCommand])
-            let now = Date()
-            podState.suspendState = .resumed(now)
-            podState.unfinalizedResume = UnfinalizedDose(resumeStartTime: now, scheduledCertainty: .certain, insulinType: podState.insulinType)
-            podState.updateFromStatusResponse(status)
-            return status
-        } catch PodCommsError.nonceResyncFailed {
-            throw PodCommsError.nonceResyncFailed
-        } catch PodCommsError.rejectedMessage(let errorCode) {
-            throw PodCommsError.rejectedMessage(errorCode: errorCode)
-        } catch let error {
-            podState.unfinalizedResume = UnfinalizedDose(resumeStartTime: Date(), scheduledCertainty: .uncertain, insulinType: podState.insulinType)
-            throw error
-        }
-    }
-    
-    public func resumeBasal(schedule: BasalSchedule, scheduleOffset: TimeInterval, acknowledgementBeep: Bool = false, completionBeep: Bool = false, programReminderInterval: TimeInterval = 0) throws -> StatusResponse {
-        
-        let status = try setBasalSchedule(schedule: schedule, scheduleOffset: scheduleOffset, acknowledgementBeep: acknowledgementBeep, completionBeep: completionBeep, programReminderInterval: programReminderInterval)
-
-        podState.suspendState = .resumed(Date())
-
-        return status
-    }
-    
-    // use cancelDelivery with .none to get status as well as to validate & advance the nonce
-    // Throws PodCommsError
-    @discardableResult
-    public func cancelNone(confirmationBeepType: BeepConfigType? = nil) throws -> StatusResponse {
-        var statusResponse: StatusResponse
-
-        let cancelResult: CancelDeliveryResult = cancelDelivery(deliveryType: .none, confirmationBeepType: confirmationBeepType)
-        switch cancelResult {
-        case .certainFailure(let error):
-            throw error
-        case .uncertainFailure(let error):
-            throw error
-        case .success(let response, _):
-            statusResponse = response
-        }
-        podState.updateFromStatusResponse(statusResponse)
-        return statusResponse
-    }
-
-    // Throws PodCommsError
-    @discardableResult
-    public func getStatus(confirmationBeepType: BeepConfigType? = nil) throws -> StatusResponse {
-        if useCancelNoneForStatus {
-            return try cancelNone(confirmationBeepType: confirmationBeepType) // functional replacement for getStatus()
-        }
-        let statusResponse: StatusResponse = try send([GetStatusCommand()], confirmationBeepType: confirmationBeepType)
-        podState.updateFromStatusResponse(statusResponse)
-        return statusResponse
-    }
-    
-    @discardableResult
-    public func getDetailedStatus(confirmationBeepType: BeepConfigType? = nil) throws -> DetailedStatus {
-        let infoResponse: PodInfoResponse = try send([GetStatusCommand(podInfoType: .detailedStatus)], confirmationBeepType: confirmationBeepType)
-        
-        guard let detailedStatus = infoResponse.podInfo as? DetailedStatus else {
-            throw PodCommsError.unexpectedResponse(response: .podInfoResponse)
-        }
-        if detailedStatus.isFaulted && self.podState.fault == nil {
-            // just detected that the pod has faulted, handle setting the fault state but don't throw
-            handlePodFault(fault: detailedStatus)
-        } else {
-            podState.updateFromDetailedStatusResponse(detailedStatus)
-        }
-        return detailedStatus
-    }
-
-    public func finalizeFinishedDoses() {
-        podState.finalizeFinishedDoses()
-    }
-
-    @discardableResult
-    public func readPodInfo(podInfoResponseSubType: PodInfoResponseSubType, confirmationBeepType: BeepConfigType? = nil) throws -> PodInfoResponse {
-        let podInfoCommand = GetStatusCommand(podInfoType: podInfoResponseSubType)
-        let podInfoResponse: PodInfoResponse = try send([podInfoCommand], confirmationBeepType: confirmationBeepType)
-        return podInfoResponse
-    }
-
-    public func deactivatePod() throws {
-
-        // Don't try to cancel if the pod hasn't completed its setup as it will either receive no response
-        // (pod progress state <= 2) or creates a $31 pod fault (pod progress states 3 through 7).
-        if podState.setupProgress == .completed && podState.fault == nil && !podState.isSuspended {
-            let result = cancelDelivery(deliveryType: .all)
-            switch result {
-            case .certainFailure(let error):
-                throw error
-            case .uncertainFailure(let error):
-                throw error
-            default:
-                break
-            }
-        }
-
-        if podState.fault != nil {
-            // All the dosing cleanup from the fault should have already been
-            // handled in handlePodFault() when podState.fault was initialized.
-            do {
-                // read the most recent pulse log entries for later analysis, but don't throw on error
-                try readPodInfo(podInfoResponseSubType: .pulseLogRecent)
-            } catch let error {
-                log.error("Read pulse log failed: %@", String(describing: error))
-            }
-        }
-
-        let deactivatePod = DeactivatePodCommand(nonce: podState.currentNonce)
-
-        do {
-            let _: StatusResponse = try send([deactivatePod])
-        } catch let error as PodCommsError {
-            switch error {
-            case .podFault, .unexpectedResponse:
-                break
-            default:
-                throw error
-            }
-        }
-    }
-    
-    public func acknowledgeAlerts(alerts: AlertSet, confirmationBeepType: BeepConfigType? = nil) throws -> [AlertSlot: PodAlert] {
-        let cmd = AcknowledgeAlertCommand(nonce: podState.currentNonce, alerts: alerts)
-        let status: StatusResponse = try send([cmd], confirmationBeepType: confirmationBeepType)
-        podState.updateFromStatusResponse(status)
-        return podState.activeAlerts
-    }
-
-    func dosesForStorage(_ storageHandler: ([UnfinalizedDose]) -> Bool) {
-        assertOnSessionQueue()
-
-        let dosesToStore = podState.dosesToStore
-
-        if storageHandler(dosesToStore) {
-            log.info("Stored doses: %@", String(describing: dosesToStore))
-            self.podState.finalizedDoses.removeAll()
-        }
-    }
-
-    public func assertOnSessionQueue() {
-        transport.assertOnSessionQueue()
-    }
-}
-
-extension PodCommsSession: MessageTransportDelegate {
-    func messageTransport(_ messageTransport: MessageTransport, didUpdate state: MessageTransportState) {
-        messageTransport.assertOnSessionQueue()
-        podState.messageTransportState = state
-    }
-}

+ 0 - 607
Dependecies/rileylink_ios/OmniKit/PumpManager/PodState.swift

@@ -1,607 +0,0 @@
-//
-//  PodState.swift
-//  OmniKit
-//
-//  Created by Pete Schwamb on 10/13/17.
-//  Copyright © 2017 Pete Schwamb. All rights reserved.
-//
-
-import Foundation
-import LoopKit
-
-public enum SetupProgress: Int {
-    case addressAssigned = 0
-    case podConfigured
-    case startingPrime
-    case priming
-    case settingInitialBasalSchedule
-    case initialBasalScheduleSet
-    case startingInsertCannula
-    case cannulaInserting
-    case completed
-    case activationTimeout
-    
-    public var primingNeeded: Bool {
-        return self.rawValue < SetupProgress.priming.rawValue
-    }
-    
-    public var needsInitialBasalSchedule: Bool {
-        return self.rawValue < SetupProgress.initialBasalScheduleSet.rawValue
-    }
-
-    public var needsCannulaInsertion: Bool {
-        return self.rawValue < SetupProgress.completed.rawValue
-    }
-}
-
-// TODO: Mutating functions aren't guaranteed to synchronize read/write calls.
-// mutating funcs should be moved to something like this:
-// extension Locked where T == PodState {
-// }
-public struct PodState: RawRepresentable, Equatable, CustomDebugStringConvertible {
-    
-    public typealias RawValue = [String: Any]
-    
-    public let address: UInt32
-    fileprivate var nonceState: NonceState
-
-    public var activatedAt: Date?
-    public var expiresAt: Date?  // set based on StatusResponse timeActive and can change with Pod clock drift and/or system time change
-
-    public var setupUnitsDelivered: Double?
-
-    public let piVersion: String
-    public let pmVersion: String
-    public let lot: UInt32
-    public let tid: UInt32
-    var activeAlertSlots: AlertSet
-    public var lastInsulinMeasurements: PodInsulinMeasurements?
-
-    public var unfinalizedBolus: UnfinalizedDose?
-    public var unfinalizedTempBasal: UnfinalizedDose?
-    public var unfinalizedSuspend: UnfinalizedDose?
-    public var unfinalizedResume: UnfinalizedDose?
-
-    var finalizedDoses: [UnfinalizedDose]
-
-    public var dosesToStore: [UnfinalizedDose] {
-        return  finalizedDoses + [unfinalizedTempBasal, unfinalizedSuspend, unfinalizedBolus].compactMap {$0}
-    }
-
-    public var suspendState: SuspendState
-
-    public var isSuspended: Bool {
-        if case .suspended = suspendState {
-            return true
-        }
-        return false
-    }
-
-    public var fault: DetailedStatus?
-    public var messageTransportState: MessageTransportState
-    public var primeFinishTime: Date?
-    public var setupProgress: SetupProgress
-    public var configuredAlerts: [AlertSlot: PodAlert]
-
-    public var activeAlerts: [AlertSlot: PodAlert] {
-        var active = [AlertSlot: PodAlert]()
-        for slot in activeAlertSlots {
-            if let alert = configuredAlerts[slot] {
-                active[slot] = alert
-            }
-        }
-        return active
-    }
-    
-    public var insulinType: InsulinType
-    
-    public init(address: UInt32, piVersion: String, pmVersion: String, lot: UInt32, tid: UInt32, packetNumber: Int = 0, messageNumber: Int = 0, insulinType: InsulinType) {
-        self.address = address
-        self.nonceState = NonceState(lot: lot, tid: tid)
-        self.piVersion = piVersion
-        self.pmVersion = pmVersion
-        self.lot = lot
-        self.tid = tid
-        self.lastInsulinMeasurements = nil
-        self.finalizedDoses = []
-        self.suspendState = .resumed(Date())
-        self.fault = nil
-        self.activeAlertSlots = .none
-        self.messageTransportState = MessageTransportState(packetNumber: packetNumber, messageNumber: messageNumber)
-        self.primeFinishTime = nil
-        self.setupProgress = .addressAssigned
-        self.configuredAlerts = [.slot7: .waitingForPairingReminder]
-        self.insulinType = insulinType
-    }
-    
-    public var unfinishedPairing: Bool {
-        return setupProgress != .completed
-    }
-    
-    public var readyForCannulaInsertion: Bool {
-        guard let primeFinishTime = self.primeFinishTime else {
-            return false
-        }
-        return !setupProgress.primingNeeded && primeFinishTime.timeIntervalSinceNow < 0
-    }
-
-    public var isActive: Bool {
-        return setupProgress == .completed && fault == nil
-    }
-
-    // variation on isActive that doesn't care if Pod is faulted
-    public var isSetupComplete: Bool {
-        return setupProgress == .completed
-    }
-
-    public var isFaulted: Bool {
-        return fault != nil || setupProgress == .activationTimeout
-    }
-
-    public mutating func advanceToNextNonce() {
-        nonceState.advanceToNextNonce()
-    }
-    
-    public var currentNonce: UInt32 {
-        return nonceState.currentNonce
-    }
-    
-    public mutating func resyncNonce(syncWord: UInt16, sentNonce: UInt32, messageSequenceNum: Int) {
-        let sum = (sentNonce & 0xffff) + UInt32(crc16Table[messageSequenceNum]) + (lot & 0xffff) + (tid & 0xffff)
-        let seed = UInt16(sum & 0xffff) ^ syncWord
-        nonceState = NonceState(lot: lot, tid: tid, seed: seed)
-    }
-    
-    private mutating func updatePodTimes(timeActive: TimeInterval) -> Date {
-        let now = Date()
-        let activatedAtComputed = now - timeActive
-        if activatedAt == nil {
-            self.activatedAt = activatedAtComputed
-        }
-        let expiresAtComputed = activatedAtComputed + Pod.nominalPodLife
-        if expiresAt == nil {
-            self.expiresAt = expiresAtComputed
-        } else if expiresAtComputed < self.expiresAt! || expiresAtComputed > (self.expiresAt! + TimeInterval(minutes: 1)) {
-            // The computed expiresAt time is earlier than or more than a minute later than the current expiresAt time,
-            // so use the computed expiresAt time instead to handle Pod clock drift and/or system time changes issues.
-            // The more than a minute later test prevents oscillation of expiresAt based on the timing of the responses.
-            self.expiresAt = expiresAtComputed
-        }
-        return now
-    }
-
-    public mutating func updateFromStatusResponse(_ response: StatusResponse) {
-        if unfinalizedBolus == nil && response.deliveryStatus.bolusing && response.podProgressStatus.readyForDelivery {
-            // Create the unfinalizedBolus since we currently bolusing in a ready state (possible Loop restart)
-            unfinalizedBolus = UnfinalizedDose(bolusAmount: response.bolusNotDelivered, startTime: Date(), scheduledCertainty: .certain, insulinType: insulinType, automatic: nil)
-        }
-        let now = updatePodTimes(timeActive: response.timeActive)
-        updateDeliveryStatus(deliveryStatus: response.deliveryStatus)
-        lastInsulinMeasurements = PodInsulinMeasurements(insulinDelivered: response.insulin, reservoirLevel: response.reservoirLevel, setupUnitsDelivered: setupUnitsDelivered, validTime: now)
-        activeAlertSlots = response.alerts
-    }
-
-    public mutating func updateFromDetailedStatusResponse(_ response: DetailedStatus) {
-        let now = updatePodTimes(timeActive: response.timeActive)
-        updateDeliveryStatus(deliveryStatus: response.deliveryStatus)
-        lastInsulinMeasurements = PodInsulinMeasurements(insulinDelivered: response.totalInsulinDelivered, reservoirLevel: response.reservoirLevel, setupUnitsDelivered: setupUnitsDelivered, validTime: now)
-        activeAlertSlots = response.unacknowledgedAlerts
-    }
-
-    public mutating func registerConfiguredAlert(slot: AlertSlot, alert: PodAlert) {
-        configuredAlerts[slot] = alert
-    }
-
-    public mutating func finalizeFinishedDoses() {
-        if let bolus = unfinalizedBolus, bolus.isFinished {
-            finalizedDoses.append(bolus)
-            unfinalizedBolus = nil
-        }
-
-        if let tempBasal = unfinalizedTempBasal, tempBasal.isFinished {
-            finalizedDoses.append(tempBasal)
-            unfinalizedTempBasal = nil
-        }
-    }
-    
-    private mutating func updateDeliveryStatus(deliveryStatus: DeliveryStatus) {
-        finalizeFinishedDoses()
-
-        if let bolus = unfinalizedBolus, bolus.scheduledCertainty == .uncertain {
-            if deliveryStatus.bolusing {
-                // Bolus did schedule
-                unfinalizedBolus?.scheduledCertainty = .certain
-            } else {
-                // Bolus didn't happen
-                unfinalizedBolus = nil
-            }
-        }
-
-        if let tempBasal = unfinalizedTempBasal, tempBasal.scheduledCertainty == .uncertain {
-            if deliveryStatus.tempBasalRunning {
-                // Temp basal did schedule
-                unfinalizedTempBasal?.scheduledCertainty = .certain
-            } else {
-                // Temp basal didn't happen
-                unfinalizedTempBasal = nil
-            }
-        }
-
-        if let resume = unfinalizedResume, resume.scheduledCertainty == .uncertain {
-            if deliveryStatus != .suspended {
-                // Resume was enacted
-                unfinalizedResume?.scheduledCertainty = .certain
-            } else {
-                // Resume wasn't enacted
-                unfinalizedResume = nil
-            }
-        }
-
-        if let suspend = unfinalizedSuspend {
-            if suspend.scheduledCertainty == .uncertain {
-                if deliveryStatus == .suspended {
-                    // Suspend was enacted
-                    unfinalizedSuspend?.scheduledCertainty = .certain
-                } else {
-                    // Suspend wasn't enacted
-                    unfinalizedSuspend = nil
-                }
-            }
-
-            if let resume = unfinalizedResume, suspend.startTime < resume.startTime {
-                finalizedDoses.append(suspend)
-                finalizedDoses.append(resume)
-                unfinalizedSuspend = nil
-                unfinalizedResume = nil
-            }
-        }
-    }
-
-    // MARK: - RawRepresentable
-    public init?(rawValue: RawValue) {
-
-        guard
-            let address = rawValue["address"] as? UInt32,
-            let nonceStateRaw = rawValue["nonceState"] as? NonceState.RawValue,
-            let nonceState = NonceState(rawValue: nonceStateRaw),
-            let piVersion = rawValue["piVersion"] as? String,
-            let pmVersion = rawValue["pmVersion"] as? String,
-            let lot = rawValue["lot"] as? UInt32,
-            let tid = rawValue["tid"] as? UInt32
-            else {
-                return nil
-            }
-        
-        self.address = address
-        self.nonceState = nonceState
-        self.piVersion = piVersion
-        self.pmVersion = pmVersion
-        self.lot = lot
-        self.tid = tid
-
-
-        if let activatedAt = rawValue["activatedAt"] as? Date {
-            self.activatedAt = activatedAt
-            if let expiresAt = rawValue["expiresAt"] as? Date {
-                self.expiresAt = expiresAt
-            } else {
-                self.expiresAt = activatedAt + Pod.nominalPodLife
-            }
-        }
-
-        if let setupUnitsDelivered = rawValue["setupUnitsDelivered"] as? Double {
-            self.setupUnitsDelivered = setupUnitsDelivered
-        }
-
-        if let suspended = rawValue["suspended"] as? Bool {
-            // Migrate old value
-            if suspended {
-                suspendState = .suspended(Date())
-            } else {
-                suspendState = .resumed(Date())
-            }
-        } else if let rawSuspendState = rawValue["suspendState"] as? SuspendState.RawValue, let suspendState = SuspendState(rawValue: rawSuspendState) {
-            self.suspendState = suspendState
-        } else {
-            return nil
-        }
-
-        if let rawUnfinalizedBolus = rawValue["unfinalizedBolus"] as? UnfinalizedDose.RawValue
-        {
-            self.unfinalizedBolus = UnfinalizedDose(rawValue: rawUnfinalizedBolus)
-        }
-
-        if let rawUnfinalizedTempBasal = rawValue["unfinalizedTempBasal"] as? UnfinalizedDose.RawValue
-        {
-            self.unfinalizedTempBasal = UnfinalizedDose(rawValue: rawUnfinalizedTempBasal)
-        }
-
-        if let rawUnfinalizedSuspend = rawValue["unfinalizedSuspend"] as? UnfinalizedDose.RawValue
-        {
-            self.unfinalizedSuspend = UnfinalizedDose(rawValue: rawUnfinalizedSuspend)
-        }
-
-        if let rawUnfinalizedResume = rawValue["unfinalizedResume"] as? UnfinalizedDose.RawValue
-        {
-            self.unfinalizedResume = UnfinalizedDose(rawValue: rawUnfinalizedResume)
-        }
-
-        if let rawLastInsulinMeasurements = rawValue["lastInsulinMeasurements"] as? PodInsulinMeasurements.RawValue {
-            self.lastInsulinMeasurements = PodInsulinMeasurements(rawValue: rawLastInsulinMeasurements)
-        } else {
-            self.lastInsulinMeasurements = nil
-        }
-        
-        if let rawFinalizedDoses = rawValue["finalizedDoses"] as? [UnfinalizedDose.RawValue] {
-            self.finalizedDoses = rawFinalizedDoses.compactMap( { UnfinalizedDose(rawValue: $0) } )
-        } else {
-            self.finalizedDoses = []
-        }
-        
-        if let rawFault = rawValue["fault"] as? DetailedStatus.RawValue,
-           let fault = DetailedStatus(rawValue: rawFault),
-           fault.faultEventCode.faultType != .noFaults
-        {
-            self.fault = fault
-        } else {
-            self.fault = nil
-        }
-        
-        if let alarmsRawValue = rawValue["alerts"] as? UInt8 {
-            self.activeAlertSlots = AlertSet(rawValue: alarmsRawValue)
-        } else {
-            self.activeAlertSlots = .none
-        }
-        
-        if let setupProgressRaw = rawValue["setupProgress"] as? Int,
-            let setupProgress = SetupProgress(rawValue: setupProgressRaw)
-        {
-            self.setupProgress = setupProgress
-        } else {
-            // Migrate
-            self.setupProgress = .completed
-        }
-        
-        if let messageTransportStateRaw = rawValue["messageTransportState"] as? MessageTransportState.RawValue,
-            let messageTransportState = MessageTransportState(rawValue: messageTransportStateRaw)
-        {
-            self.messageTransportState = messageTransportState
-        } else {
-            self.messageTransportState = MessageTransportState(packetNumber: 0, messageNumber: 0)
-        }
-
-        if let rawConfiguredAlerts = rawValue["configuredAlerts"] as? [String: PodAlert.RawValue] {
-            var configuredAlerts = [AlertSlot: PodAlert]()
-            for (rawSlot, rawAlert) in rawConfiguredAlerts {
-                if let slotNum = UInt8(rawSlot), let slot = AlertSlot(rawValue: slotNum), let alert = PodAlert(rawValue: rawAlert) {
-                    configuredAlerts[slot] = alert
-                }
-            }
-            self.configuredAlerts = configuredAlerts
-        } else {
-            // Assume migration, and set up with alerts that are normally configured
-            self.configuredAlerts = [
-                .slot2: .shutdownImminentAlarm(0),
-                .slot3: .expirationAlert(0),
-                .slot4: .lowReservoirAlarm(0),
-                .slot7: .expirationAdvisoryAlarm(alarmTime: 0, duration: 0)
-            ]
-        }
-        
-        self.primeFinishTime = rawValue["primeFinishTime"] as? Date
-        
-        if let rawInsulinType = rawValue["insulinType"] as? InsulinType.RawValue, let insulinType = InsulinType(rawValue: rawInsulinType) {
-            self.insulinType = insulinType
-        } else {
-            insulinType = .humalog
-        }
-    }
-    
-    public var rawValue: RawValue {
-        var rawValue: RawValue = [
-            "address": address,
-            "nonceState": nonceState.rawValue,
-            "piVersion": piVersion,
-            "pmVersion": pmVersion,
-            "lot": lot,
-            "tid": tid,
-            "suspendState": suspendState.rawValue,
-            "finalizedDoses": finalizedDoses.map( { $0.rawValue }),
-            "alerts": activeAlertSlots.rawValue,
-            "messageTransportState": messageTransportState.rawValue,
-            "setupProgress": setupProgress.rawValue,
-            "insulinType": insulinType.rawValue
-            ]
-        
-        if let unfinalizedBolus = self.unfinalizedBolus {
-            rawValue["unfinalizedBolus"] = unfinalizedBolus.rawValue
-        }
-        
-        if let unfinalizedTempBasal = self.unfinalizedTempBasal {
-            rawValue["unfinalizedTempBasal"] = unfinalizedTempBasal.rawValue
-        }
-
-        if let unfinalizedSuspend = self.unfinalizedSuspend {
-            rawValue["unfinalizedSuspend"] = unfinalizedSuspend.rawValue
-        }
-
-        if let unfinalizedResume = self.unfinalizedResume {
-            rawValue["unfinalizedResume"] = unfinalizedResume.rawValue
-        }
-
-        if let lastInsulinMeasurements = self.lastInsulinMeasurements {
-            rawValue["lastInsulinMeasurements"] = lastInsulinMeasurements.rawValue
-        }
-        
-        if let fault = self.fault {
-            rawValue["fault"] = fault.rawValue
-        }
-
-        if let primeFinishTime = primeFinishTime {
-            rawValue["primeFinishTime"] = primeFinishTime
-        }
-
-        if let activatedAt = activatedAt {
-            rawValue["activatedAt"] = activatedAt
-        }
-
-        if let expiresAt = expiresAt {
-            rawValue["expiresAt"] = expiresAt
-        }
-
-        if let setupUnitsDelivered = setupUnitsDelivered {
-            rawValue["setupUnitsDelivered"] = setupUnitsDelivered
-        }
-
-        if configuredAlerts.count > 0 {
-            let rawConfiguredAlerts = Dictionary(uniqueKeysWithValues:
-                configuredAlerts.map { slot, alarm in (String(describing: slot.rawValue), alarm.rawValue) })
-            rawValue["configuredAlerts"] = rawConfiguredAlerts
-        }
-
-        return rawValue
-    }
-    
-    // MARK: - CustomDebugStringConvertible
-    
-    public var debugDescription: String {
-        return [
-            "### PodState",
-            "* address: \(String(format: "%04X", address))",
-            "* activatedAt: \(String(reflecting: activatedAt))",
-            "* expiresAt: \(String(reflecting: expiresAt))",
-            "* setupUnitsDelivered: \(String(reflecting: setupUnitsDelivered))",
-            "* piVersion: \(piVersion)",
-            "* pmVersion: \(pmVersion)",
-            "* lot: \(lot)",
-            "* tid: \(tid)",
-            "* suspendState: \(suspendState)",
-            "* unfinalizedBolus: \(String(describing: unfinalizedBolus))",
-            "* unfinalizedTempBasal: \(String(describing: unfinalizedTempBasal))",
-            "* unfinalizedSuspend: \(String(describing: unfinalizedSuspend))",
-            "* unfinalizedResume: \(String(describing: unfinalizedResume))",
-            "* finalizedDoses: \(String(describing: finalizedDoses))",
-            "* activeAlerts: \(String(describing: activeAlerts))",
-            "* messageTransportState: \(String(describing: messageTransportState))",
-            "* setupProgress: \(setupProgress)",
-            "* primeFinishTime: \(String(describing: primeFinishTime))",
-            "* configuredAlerts: \(String(describing: configuredAlerts))",
-            "* insulinType: \(String(describing: insulinType))",
-            "",
-            fault != nil ? String(reflecting: fault!) : "fault: nil",
-            "",
-        ].joined(separator: "\n")
-    }
-}
-
-fileprivate struct NonceState: RawRepresentable, Equatable {
-    public typealias RawValue = [String: Any]
-    
-    var table: [UInt32]
-    var idx: UInt8
-    
-    public init(lot: UInt32 = 0, tid: UInt32 = 0, seed: UInt16 = 0) {
-        table = Array(repeating: UInt32(0), count: 2 + 16)
-        table[0] = (lot & 0xFFFF) &+ (lot >> 16) &+ 0x55543DC3
-        table[1] = (tid & 0xFFFF) &+ (tid >> 16) &+ 0xAAAAE44E
-        
-        idx = 0
-        
-        table[0] += UInt32((seed & 0x00ff))
-        table[1] += UInt32((seed & 0xff00) >> 8)
-        
-        for i in 0..<16 {
-            table[2 + i] = generateEntry()
-        }
-        
-        idx = UInt8((table[0] + table[1]) & 0x0F)
-    }
-
-    private mutating func generateEntry() -> UInt32 {
-        table[0] = (table[0] >> 16) &+ ((table[0] & 0xFFFF) &* 0x5D7F)
-        table[1] = (table[1] >> 16) &+ ((table[1] & 0xFFFF) &* 0x8CA0)
-        return table[1] &+ ((table[0] & 0xFFFF) << 16)
-    }
-    
-    public mutating func advanceToNextNonce() {
-        let nonce = currentNonce
-        table[Int(2 + idx)] = generateEntry()
-        idx = UInt8(nonce & 0x0F)
-    }
-    
-    public var currentNonce: UInt32 {
-        return table[Int(2 + idx)]
-    }
-    
-    // RawRepresentable
-    public init?(rawValue: RawValue) {
-        guard
-            let table = rawValue["table"] as? [UInt32],
-            let idx = rawValue["idx"] as? UInt8
-            else {
-                return nil
-        }
-        self.table = table
-        self.idx = idx
-    }
-    
-    public var rawValue: RawValue {
-        let rawValue: RawValue = [
-            "table": table,
-            "idx": idx,
-        ]
-        
-        return rawValue
-    }
-}
-
-
-public enum SuspendState: Equatable, RawRepresentable {
-    public typealias RawValue = [String: Any]
-
-    private enum SuspendStateType: Int {
-        case suspend, resume
-    }
-
-    case suspended(Date)
-    case resumed(Date)
-
-    private var identifier: Int {
-        switch self {
-        case .suspended:
-            return 1
-        case .resumed:
-            return 2
-        }
-    }
-
-    public init?(rawValue: RawValue) {
-        guard let suspendStateType = rawValue["case"] as? SuspendStateType.RawValue,
-            let date = rawValue["date"] as? Date else {
-                return nil
-        }
-        switch SuspendStateType(rawValue: suspendStateType) {
-        case .suspend?:
-            self = .suspended(date)
-        case .resume?:
-            self = .resumed(date)
-        default:
-            return nil
-        }
-    }
-
-    public var rawValue: RawValue {
-        switch self {
-        case .suspended(let date):
-            return [
-                "case": SuspendStateType.suspend.rawValue,
-                "date": date
-            ]
-        case .resumed(let date):
-            return [
-                "case": SuspendStateType.resume.rawValue,
-                "date": date
-            ]
-        }
-    }
-}

+ 0 - 240
Dependecies/rileylink_ios/OmniKitTests/MessageTests.swift

@@ -1,240 +0,0 @@
-//
-//  MessageTests.swift
-//  OmniKitTests
-//
-//  Created by Pete Schwamb on 10/14/17.
-//  Copyright © 2017 Pete Schwamb. All rights reserved.
-//
-
-import XCTest
-@testable import OmniKit
-
-class MessageTests: XCTestCase {
-    
-    func testMessageData() {
-        // 2016-06-26T20:33:28.412197 ID1:1f01482a PTYPE:PDM SEQ:13 ID2:1f01482a B9:10 BLEN:3 BODY:0e0100802c CRC:88
-        
-        let msg = Message(address: 0x1f01482a, messageBlocks: [GetStatusCommand()], sequenceNum: 4)
-        
-        XCTAssertEqual("1f01482a10030e0100802c", msg.encoded().hexadecimalString)
-    }
-    
-    func testMessageDecoding() {
-        do {
-            let msg = try Message(encodedData: Data(hexadecimalString: "1f00ee84300a1d18003f1800004297ff8128")!)
-            
-            XCTAssertEqual(0x1f00ee84, msg.address)
-            XCTAssertEqual(12, msg.sequenceNum)
-            
-            let messageBlocks = msg.messageBlocks
-            
-            XCTAssertEqual(1, messageBlocks.count)
-            
-            let statusResponse = messageBlocks[0] as! StatusResponse
-            
-            XCTAssertEqual(nil, statusResponse.reservoirLevel)
-            XCTAssertEqual(TimeInterval(minutes: 4261), statusResponse.timeActive)
-
-            XCTAssertEqual(.scheduledBasal, statusResponse.deliveryStatus)
-            XCTAssertEqual(.aboveFiftyUnits, statusResponse.podProgressStatus)
-            XCTAssertEqual(6.3, statusResponse.insulin, accuracy: 0.01)
-            XCTAssertEqual(0, statusResponse.bolusNotDelivered)
-            XCTAssertEqual(3, statusResponse.podMessageCounter)
-            XCTAssert(statusResponse.alerts.isEmpty)
-
-            XCTAssertEqual("1f00ee84300a1d18003f1800004297ff8128", msg.encoded().hexadecimalString)
-        } catch (let error) {
-            XCTFail("message decoding threw error: \(error)")
-        }
-    }
-    
-    func testAssemblingMultiPacketMessage() {
-        do {
-            let packet1 = try Packet(encodedData: Data(hexadecimalString: "ffffffffe4ffffffff041d011b13881008340a5002070002070002030000a62b0004479420")!)
-            XCTAssertEqual(packet1.data.hexadecimalString, "ffffffff041d011b13881008340a5002070002070002030000a62b00044794")
-            XCTAssertEqual(packet1.packetType, .pod)
-
-            XCTAssertThrowsError(try Message(encodedData: packet1.data)) { error in
-                XCTAssertEqual(String(describing: error), "notEnoughData")
-            }
-            
-            let packet2 = try Packet(encodedData: Data(hexadecimalString: "ffffffff861f00ee878352ff")!)
-            XCTAssertEqual(packet2.address, 0xffffffff)
-            XCTAssertEqual(packet2.data.hexadecimalString, "1f00ee878352")
-            XCTAssertEqual(packet2.packetType, .con)
-            
-            let messageBody = packet1.data + packet2.data
-            XCTAssertEqual(messageBody.hexadecimalString, "ffffffff041d011b13881008340a5002070002070002030000a62b000447941f00ee878352")
-
-            let message = try Message(encodedData: messageBody)
-            XCTAssertEqual(message.messageBlocks.count, 1)
-
-        } catch (let error) {
-            XCTFail("message decoding threw error: \(error)")
-        }
-    }
-    
-    func testParsingVersionResponse() {
-        do {
-            let config = try VersionResponse(encodedData: Data(hexadecimalString: "011502070002070002020000a64000097c279c1f08ced2")!)
-            XCTAssertEqual(23, config.data.count)
-            XCTAssertEqual(0x1f08ced2, config.address)
-            XCTAssertEqual(42560, config.lot)
-            XCTAssertEqual(621607, config.tid)
-        } catch (let error) {
-            XCTFail("message decoding threw error: \(error)")
-        }
-    }
-    
-    func testParsingLongVersionResponse() {
-        do {
-            let message = try Message(encodedData: Data(hexadecimalString: "ffffffff041d011b13881008340a5002070002070002030000a62b000447941f00ee878352")!)
-            let config = message.messageBlocks[0] as! VersionResponse
-            XCTAssertEqual(29, config.data.count)
-            XCTAssertEqual(0x1f00ee87, config.address)
-            XCTAssertEqual(42539, config.lot)
-            XCTAssertEqual(280468, config.tid)
-            XCTAssertEqual("2.7.0", String(describing: config.piVersion))
-            XCTAssertEqual("2.7.0", String(describing: config.pmVersion))
-        } catch (let error) {
-            XCTFail("message decoding threw error: \(error)")
-        }
-    }
-
-    func testParsingConfigWithPairingExpired() {
-        do {
-            let message = try Message(encodedData: Data(hexadecimalString: "ffffffff04170115020700020700020e0000a5ad00053030971f08686301fd")!)
-            let config = message.messageBlocks[0] as! VersionResponse
-            XCTAssertEqual(.activationTimeExceeded, config.podProgressStatus)
-        } catch (let error) {
-            XCTFail("message decoding threw error: \(error)")
-        }
-    }
-
-    func testAssignAddressCommand() {
-        do {
-            // Encode
-            let encoded = AssignAddressCommand(address: 0x1f01482a)
-            XCTAssertEqual("07041f01482a", encoded.data.hexadecimalString)
-
-            // Decode
-            let decoded = try AssignAddressCommand(encodedData: Data(hexadecimalString: "07041f01482a")!)
-            XCTAssertEqual(0x1f01482a, decoded.address)
-        } catch (let error) {
-            XCTFail("message decoding threw error: \(error)")
-        }
-    }
-    
-    func testSetupPodCommand() {
-        do {
-            var components = DateComponents()
-            components.day = 12
-            components.month = 6
-            components.year = 2016
-            components.hour = 13
-            components.minute = 47
-
-            // Decode
-            let decoded = try SetupPodCommand(encodedData: Data(hexadecimalString: "03131f0218c31404060c100d2f0000a4be0004e4a1")!)
-            XCTAssertEqual(0x1f0218c3, decoded.address)
-            XCTAssertEqual(components, decoded.dateComponents)
-            XCTAssertEqual(0x0000a4be, decoded.lot)
-            XCTAssertEqual(0x0004e4a1, decoded.tid)
-
-            // Encode
-            let encoded = SetupPodCommand(address: 0x1f0218c3, dateComponents: components, lot: 0x0000a4be, tid: 0x0004e4a1)
-            XCTAssertEqual("03131f0218c31404060c100d2f0000a4be0004e4a1", encoded.data.hexadecimalString)            
-
-        } catch (let error) {
-            XCTFail("message decoding threw error: \(error)")
-        }
-    }
-    
-    func testInsertCannula() {
-//        2018-04-03T19:23:14.3d ID1:1f00ee85 PTYPE:PDM SEQ:17 ID2:1f00ee85 B9:38 BLEN:31 BODY:1a0e7e30bf16020065010050000a000a170d000064000186a0 CRC:33
-//        2018-04-03T19:23:14.3d ID1:1f00ee85 PTYPE:ACK SEQ:18 ID2:1f00ee85 CRC:89
-//        2018-04-03T19:23:14.3d ID1:1f00ee85 PTYPE:CON SEQ:19 CON:000000000000808c CRC:6f
-//        2018-04-03T19:23:14.3d ID1:1f00ee85 PTYPE:POD SEQ:20 ID2:1f00ee85 B9:3c BLEN:10 BODY:1d570016f00a00000bff8099 CRC:86
-//        2018-04-03T19:23:14.3d ID1:1f00ee85 PTYPE:ACK SEQ:21 ID2:1f00ee85 CRC:a0
-
-        do {
-            // Decode
-            let cmd = try SetInsulinScheduleCommand(encodedData: Data(hexadecimalString: "1a0ebed2e16b02010a0101a000340034")!)
-            XCTAssertEqual(0xbed2e16b, cmd.nonce)
-            
-            if case SetInsulinScheduleCommand.DeliverySchedule.bolus(let units, let timeBetweenPulses) = cmd.deliverySchedule {
-                XCTAssertEqual(2.6, units)
-                XCTAssertEqual(.seconds(1), timeBetweenPulses)
-            } else {
-                XCTFail("Expected ScheduleEntry.bolus type")
-            }
-        } catch (let error) {
-            XCTFail("message decoding threw error: \(error)")
-        }
-    }
-    
-    func testStatusResponseAlarmsParsing() {
-        // 1d 28 0082 00 0044 46eb ff
-        
-        do {
-            // Decode
-            let status = try StatusResponse(encodedData: Data(hexadecimalString: "1d28008200004446ebff")!)
-            XCTAssert(status.alerts.contains(.slot3))
-            XCTAssert(status.alerts.contains(.slot7))
-        } catch (let error) {
-            XCTFail("message decoding threw error: \(error)")
-        }
-    }
-    
-    func testConfigureAlertsCommand() {
-        // 79a4 10df 0502
-        // Pod expires 1 minute short of 3 days
-        let podSoftExpirationTime = TimeInterval(hours:72) - TimeInterval(minutes:1)
-        let alertConfig1 = AlertConfiguration(alertType: .slot7, active: true, autoOffModifier: false, duration: .hours(7), trigger: .timeUntilAlert(podSoftExpirationTime), beepRepeat: .every60Minutes, beepType: .bipBeepBipBeepBipBeepBipBeep)
-        XCTAssertEqual("79a410df0502", alertConfig1.data.hexadecimalString)
-
-        // 2800 1283 0602
-        let podHardExpirationTime = TimeInterval(hours:79) - TimeInterval(minutes:1)
-        let alertConfig2 = AlertConfiguration(alertType: .slot2, active: true, autoOffModifier: false, duration: .minutes(0), trigger: .timeUntilAlert(podHardExpirationTime), beepRepeat: .every15Minutes, beepType: .bipBeepBipBeepBipBeepBipBeep)
-        XCTAssertEqual("280012830602", alertConfig2.data.hexadecimalString)
-
-        // 020f 0000 0202
-        let alertConfig3 = AlertConfiguration(alertType: .slot0, active: false, autoOffModifier: true, duration: .minutes(15), trigger: .timeUntilAlert(0), beepRepeat: .every1MinuteFor15Minutes, beepType: .bipBeepBipBeepBipBeepBipBeep)
-        XCTAssertEqual("020f00000202", alertConfig3.data.hexadecimalString)
-        
-        let configureAlerts = ConfigureAlertsCommand(nonce: 0xfeb6268b, configurations:[alertConfig1, alertConfig2, alertConfig3])
-        XCTAssertEqual("1916feb6268b79a410df0502280012830602020f00000202", configureAlerts.data.hexadecimalString)
-        
-        do {
-            let decoded = try ConfigureAlertsCommand(encodedData: Data(hexadecimalString: "1916feb6268b79a410df0502280012830602020f00000202")!)
-            XCTAssertEqual(3, decoded.configurations.count)
-            
-            let config1 = decoded.configurations[0]
-            XCTAssertEqual(.slot7, config1.slot)
-            XCTAssertEqual(true, config1.active)
-            XCTAssertEqual(false, config1.autoOffModifier)
-            XCTAssertEqual(.hours(7), config1.duration)
-            if case AlertTrigger.timeUntilAlert(let duration) = config1.trigger {
-                XCTAssertEqual(podSoftExpirationTime, duration)
-            }
-            XCTAssertEqual(.every60Minutes, config1.beepRepeat)
-            XCTAssertEqual(.bipBeepBipBeepBipBeepBipBeep, config1.beepType)
-            
-            let cfg = try AlertConfiguration(encodedData: Data(hexadecimalString: "4c0000640102")!)
-            XCTAssertEqual(.slot4, cfg.slot)
-            XCTAssertEqual(true, cfg.active)
-            XCTAssertEqual(false, cfg.autoOffModifier)
-            XCTAssertEqual(0, cfg.duration)
-            if case AlertTrigger.unitsRemaining(let volume) = cfg.trigger {
-                XCTAssertEqual(10, volume)
-            }
-            XCTAssertEqual(.every1MinuteFor3MinutesAndRepeatEvery60Minutes, cfg.beepRepeat)
-            XCTAssertEqual(.bipBeepBipBeepBipBeepBipBeep, cfg.beepType)
-
-
-        } catch (let error) {
-            XCTFail("message decoding threw error: \(error)")
-        }
-    }
-}
-

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 475
Dependecies/rileylink_ios/OmniKitTests/PodInfoTests.swift


+ 0 - 77
Dependecies/rileylink_ios/OmniKitTests/StatusTests.swift

@@ -1,77 +0,0 @@
-//
-//  StatusTests.swift
-//  OmniKitTests
-//
-//  Created by Eelke Jager on 08/09/2018.
-//  Copyright © 2018 Pete Schwamb. All rights reserved.
-//
-import Foundation
-
-import XCTest
-@testable import OmniKit
-
-class StatusTests: XCTestCase {
-    
-    func testStatusRequestCommand() {
-        // 0e 01 00
-        do {
-            // Encode
-            let encoded = GetStatusCommand(podInfoType: .normal)
-            XCTAssertEqual("0e0100", encoded.data.hexadecimalString)
-            
-            // Decode
-            let decoded = try GetStatusCommand(encodedData: Data(hexadecimalString: "0e0100")!)
-            XCTAssertEqual(.normal, decoded.podInfoType)
-        } catch (let error) {
-            XCTFail("message decoding threw error: \(error)")
-        }
-    }
-
-    func testStatusResponse46UnitsLeft() {
-        /// 1d19050ec82c08376f9801dc
-        do {
-            // Decode
-            let decoded = try StatusResponse(encodedData: Data(hexadecimalString: "1d19050ec82c08376f9801dc")!)
-            XCTAssertEqual(TimeInterval(minutes: 3547), decoded.timeActive)
-            XCTAssertEqual(.scheduledBasal, decoded.deliveryStatus)
-            XCTAssertEqual(.fiftyOrLessUnits, decoded.podProgressStatus)
-            XCTAssertEqual(129.45, decoded.insulin, accuracy: 0.01)
-            XCTAssertEqual(46.00, decoded.reservoirLevel)
-            XCTAssertEqual(2.2, decoded.bolusNotDelivered)
-            XCTAssertEqual(9, decoded.podMessageCounter)
-            //XCTAssert(,decoded.alarms)
-        } catch (let error) {
-            XCTFail("message decoding threw error: \(error)")
-        }
-    }
-    
-    func testStatusRequestCommandConfiguredAlerts() {
-        // 0e 01 01
-        do {
-            // Encode
-            let encoded = GetStatusCommand(podInfoType: .configuredAlerts)
-            XCTAssertEqual("0e0101", encoded.data.hexadecimalString)
-                
-            // Decode
-            let decoded = try GetStatusCommand(encodedData: Data(hexadecimalString: "0e0101")!)
-            XCTAssertEqual(.configuredAlerts, decoded.podInfoType)
-        } catch (let error) {
-            XCTFail("message decoding threw error: \(error)")
-        }
-    }
-    
-    func testStatusRequestCommandFaultEvents() {
-        // 0e 01 02
-        do {
-            // Encode
-            let encoded = GetStatusCommand(podInfoType: .detailedStatus)
-            XCTAssertEqual("0e0102", encoded.data.hexadecimalString)
-            
-            // Decode
-            let decoded = try GetStatusCommand(encodedData: Data(hexadecimalString: "0e0102")!)
-            XCTAssertEqual(.detailedStatus, decoded.podInfoType)
-        } catch (let error) {
-            XCTFail("message decoding threw error: \(error)")
-        }
-    }
-}

+ 0 - 172
Dependecies/rileylink_ios/OmniKitUI/ViewControllers/CommandResponseViewController.swift

@@ -1,172 +0,0 @@
-//
-//  CommandResponseViewController.swift
-//  OmniKitUI
-//
-//  Created by Pete Schwamb on 8/28/18.
-//  Copyright © 2018 Pete Schwamb. All rights reserved.
-//
-
-import Foundation
-import LoopKitUI
-import OmniKit
-import RileyLinkBLEKit
-
-extension CommandResponseViewController {
-    typealias T = CommandResponseViewController
-    
-    // Returns an appropriately formatted error string or "Succeeded" if no error
-    private static func resultString(error: Error?) -> String {
-        guard let error = error else {
-            return LocalizedString("Succeeded", comment: "A message indicating a command succeeded")
-        }
-
-        let errorStrings: [String]
-        if let error = error as? LocalizedError {
-            errorStrings = [error.errorDescription, error.failureReason, error.recoverySuggestion].compactMap { $0 }
-        } else {
-            errorStrings = [error.localizedDescription].compactMap { $0 }
-        }
-        let errorText = errorStrings.joined(separator: ". ")
-
-        if errorText.isEmpty {
-            return String(describing: error)
-        }
-        return errorText + "."
-    }
-
-    static func changeTime(pumpManager: OmnipodPumpManager) -> T {
-        return T { (completionHandler) -> String in
-            pumpManager.setTime() { (error) in
-                DispatchQueue.main.async {
-                    completionHandler(resultString(error: error))
-                }
-            }
-            return LocalizedString("Changing time…", comment: "Progress message for changing pod time.")
-        }
-    }
-    
-    private static func podStatusString(status: DetailedStatus, configuredAlerts: [AlertSlot: PodAlert]) -> String {
-        var result, str: String
-
-        let formatter = DateComponentsFormatter()
-        formatter.unitsStyle = .full
-        formatter.allowedUnits = [.day, .hour, .minute]
-        if let timeStr = formatter.string(from: status.timeActive) {
-            str = timeStr
-        } else {
-            str = String(format: LocalizedString("%1$@ minutes", comment: "The format string for minutes (1: number of minutes string)"), String(describing: Int(status.timeActive / 60)))
-        }
-        result = String(format: LocalizedString("Pod Active: %1$@\n", comment: "The format string for Pod Active: (1: Pod active time string)"), str)
-
-        result += String(format: LocalizedString("Delivery Status: %1$@\n", comment: "The format string for Delivery Status: (1: delivery status string)"), String(describing: status.deliveryStatus))
-
-        result += String(format: LocalizedString("Pulse Count: %1$d\n", comment: "The format string for Pulse Count (1: pulse count)"), Int(status.totalInsulinDelivered / Pod.pulseSize))
-
-        result += String(format: LocalizedString("Reservoir Level: %1$@ U\n", comment: "The format string for Reservoir Level: (1: reservoir level string)"), status.reservoirLevel?.twoDecimals ?? "50+")
-
-        result += String(format: LocalizedString("Last Bolus Not Delivered: %1$@ U\n", comment: "The format string for Last Bolus Not Delivered: (1: bolus not delivered string)"), status.bolusNotDelivered.twoDecimals)
-
-        let alertsDescription = status.unacknowledgedAlerts.map { (slot) -> String in
-            if let podAlert = configuredAlerts[slot] {
-                return String(describing: podAlert)
-            } else {
-                return String(describing: slot)
-            }
-        }
-        let alertString: String
-        if status.unacknowledgedAlerts.isEmpty {
-            alertString = String(describing: status.unacknowledgedAlerts)
-        } else {
-            alertString = alertsDescription.joined(separator: ", ")
-        }
-        result += String(format: LocalizedString("Alerts: %1$@\n", comment: "The format string for Alerts: (1: the alerts string)"), alertString)
-
-        result += String(format: LocalizedString("RSSI: %1$@\n", comment: "The format string for RSSI: (1: RSSI value)"), String(describing: status.radioRSSI))
-
-        result += String(format: LocalizedString("Receiver Low Gain: %1$@\n", comment: "The format string for receiverLowGain: (1: receiverLowGain)"), String(describing: status.receiverLowGain))
-        
-        if status.faultEventCode.faultType != .noFaults {
-            result += "\n" // since we have a fault, report the additional fault related information in a separate section
-            result += String(format: LocalizedString("Fault: %1$@\n", comment: "The format string for a fault: (1: The fault description)"), status.faultEventCode.localizedDescription)
-            if let refStr = status.pdmRef {
-                result += refStr + "\n" // add the PDM style Ref code info as a separate line
-            }
-            if let previousPodProgressStatus = status.previousPodProgressStatus {
-                result += String(format: LocalizedString("Previous pod progress: %1$@\n", comment: "The format string for previous pod progress: (1: previous pod progress string)"), String(describing: previousPodProgressStatus))
-            }
-            if let faultEventTimeSinceActivation = status.faultEventTimeSinceActivation, let faultTimeStr = formatter.string(from: faultEventTimeSinceActivation) {
-                result += String(format: LocalizedString("Fault time: %1$@\n", comment: "The format string for fault time: (1: fault time string)"), faultTimeStr)
-            }
-        }
-
-        return result
-    }
-
-    static func readPodStatus(pumpManager: OmnipodPumpManager) -> T {
-        return T { (completionHandler) -> String in
-            pumpManager.readPodStatus() { (result) in
-                DispatchQueue.main.async {
-                    switch result {
-                    case .success(let status):
-                        let configuredAlerts = pumpManager.state.podState!.configuredAlerts
-                        completionHandler(podStatusString(status: status, configuredAlerts: configuredAlerts))
-                    case .failure(let error):
-                        completionHandler(resultString(error: error))
-                    }
-                }
-            }
-            return LocalizedString("Read Pod Status…", comment: "Progress message for reading Pod status.")
-        }
-    }
-
-    static func testingCommands(pumpManager: OmnipodPumpManager) -> T {
-        return T { (completionHandler) -> String in
-            pumpManager.testingCommands() { (error) in
-                DispatchQueue.main.async {
-                    completionHandler(resultString(error: error))
-                }
-            }
-            return LocalizedString("Testing Commands…", comment: "Progress message for testing commands.")
-        }
-    }
-
-    static func playTestBeeps(pumpManager: OmnipodPumpManager) -> T {
-        return T { (completionHandler) -> String in
-            pumpManager.playTestBeeps() { (error) in
-                let response: String
-                if let error = error {
-                    response = resultString(error: error)
-                } else {
-                    response = LocalizedString("Play test beeps command sent successfully.\n\nIf you did not hear any beeps from your pod, the piezo speaker in your pod may be broken or disabled.", comment: "Success message for play test beeps.")
-                }
-                DispatchQueue.main.async {
-                    completionHandler(response)
-                }
-            }
-            return LocalizedString("Play Test Beeps…", comment: "Progress message for play test beeps.")
-        }
-    }
-
-    static func readPulseLog(pumpManager: OmnipodPumpManager) -> T {
-        return T { (completionHandler) -> String in
-            pumpManager.readPulseLog() { (result) in
-                DispatchQueue.main.async {
-                    switch result {
-                    case .success(let pulseLogString):
-                        completionHandler(pulseLogString)
-                    case .failure(let error):
-                        completionHandler(resultString(error: error))
-                    }
-                }
-            }
-            return LocalizedString("Reading Pulse Log…", comment: "Progress message for reading pulse log.")
-        }
-    }
-}
-
-extension Double {
-    var twoDecimals: String {
-        return String(format: "%.2f", self)
-    }
-}
-

+ 0 - 253
Dependecies/rileylink_ios/OmniKitUI/ViewControllers/InsertCannulaSetupViewController.swift

@@ -1,253 +0,0 @@
-//
-//  InsertCannulaSetupViewController.swift
-//  OmniKitUI
-//
-//  Created by Pete Schwamb on 9/18/18.
-//  Copyright © 2018 Pete Schwamb. All rights reserved.
-//
-
-import UIKit
-import LoopKit
-import LoopKitUI
-import RileyLinkKit
-import OmniKit
-import SwiftUI
-
-class InsertCannulaSetupViewController: SetupTableViewController {
-    
-    var pumpManager: OmnipodPumpManager!
-    
-    // MARK: -
-    
-    @IBOutlet weak var activityIndicator: SetupIndicatorView!
-    
-    @IBOutlet weak var loadingLabel: UILabel!
-    
-    private var loadingText: String? {
-        didSet {
-            tableView.beginUpdates()
-            loadingLabel.text = loadingText
-            
-            let isHidden = (loadingText == nil)
-            loadingLabel.isHidden = isHidden
-            tableView.endUpdates()
-        }
-    }
-    
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        
-        continueState = .initial
-    }
-    
-    override func setEditing(_ editing: Bool, animated: Bool) {
-        super.setEditing(editing, animated: animated)
-    }
-    
-    // MARK: - UITableViewDelegate
-    
-    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        if case .startingInsertion = continueState {
-            return
-        }
-
-        tableView.deselectRow(at: indexPath, animated: true)
-    }
-    
-    // MARK: - Navigation
-    
-    private enum State {
-        case initial
-        case startingInsertion
-        case inserting(finishTime: CFTimeInterval)
-        case needsCheckInsertion
-        case fault
-        case ready
-    }
-    
-    private var continueState: State = .initial {
-        didSet {
-            switch continueState {
-            case .initial:
-                activityIndicator.state = .hidden
-                footerView.primaryButton.isEnabled = true
-                footerView.primaryButton.setInsertCannulaTitle()
-            case .startingInsertion:
-                activityIndicator.state = .indeterminantProgress
-                footerView.primaryButton.isEnabled = false
-                lastError = nil
-            case .inserting(let finishTime):
-                activityIndicator.state = .timedProgress(finishTime: CACurrentMediaTime() + finishTime)
-                footerView.primaryButton.isEnabled = false
-                lastError = nil
-            case .needsCheckInsertion:
-                activityIndicator.state = .hidden
-                footerView.primaryButton.isEnabled = true
-                footerView.primaryButton.setRecheckInsertionTitle()
-            case .fault:
-                activityIndicator.state = .hidden
-                footerView.primaryButton.isEnabled = true
-                footerView.primaryButton.setDeactivateTitle()
-            case .ready:
-                activityIndicator.state = .completed
-                footerView.primaryButton.isEnabled = true
-                footerView.primaryButton.resetTitle()
-                lastError = nil
-            }
-        }
-    }
-    
-    private var lastError: Error? {
-        didSet {
-            guard oldValue != nil || lastError != nil else {
-                return
-            }
-            
-            var errorText = lastError?.localizedDescription
-            
-            if let error = lastError as? LocalizedError {
-                let localizedText = [error.errorDescription, error.failureReason, error.recoverySuggestion].compactMap({ $0 }).joined(separator: ". ")
-                
-                if !localizedText.isEmpty {
-                    errorText = localizedText + "."
-                }
-            }
-            
-            // If we have an error but no error text, generate a string to describe the error
-            if let error = lastError, (errorText == nil || errorText!.isEmpty) {
-                errorText = String(describing: error)
-            }
-            loadingText = errorText
-            
-            // If we have an error, update the continue state depending on whether the cannula insertion was started
-            if let podCommsError = lastError as? PodCommsError {
-                switch podCommsError {
-                case .podFault, .activationTimeExceeded:
-                    continueState = .fault
-                default:
-                    continueState = initialOrNeedsCannulaInsertionCheck
-                }
-            } else if lastError != nil {
-                continueState = initialOrNeedsCannulaInsertionCheck
-            }
-        }
-    }
-
-    // .needsCheckInsertion (if cannula insertion has been started but its completion hasn't been verified) or else .initial
-    private var initialOrNeedsCannulaInsertionCheck: State {
-        if pumpManager.state.podState?.setupProgress == .cannulaInserting {
-            return .needsCheckInsertion
-        }
-        return .initial
-    }
-
-    // .ready (if pod setup has been verifed to be complete) or else .needsCheckInsertion
-    private var readyOrNeedsCannulaInsertionCheck: State {
-        if pumpManager.state.podState?.setupProgress == .completed {
-            return .ready
-        }
-        return .needsCheckInsertion
-    }
-
-    private func navigateToReplacePod() {
-        performSegue(withIdentifier: "ReplacePod", sender: nil)
-    }
-
-    override func continueButtonPressed(_ sender: Any) {
-        switch continueState {
-        case .initial:
-            continueState = .startingInsertion
-            insertCannula()
-        case .needsCheckInsertion:
-            checkCannulaInsertionFinished()
-            if pumpManager.state.podState?.setupProgress == .completed {
-                super.continueButtonPressed(sender)
-            }
-        case .ready:
-            super.continueButtonPressed(sender)
-        case .fault:
-            navigateToReplacePod()
-        case .startingInsertion, .inserting:
-            break
-        }
-    }
-    
-    override func cancelButtonPressed(_ sender: Any) {
-        let confirmVC = UIAlertController(pumpDeletionHandler: {
-            self.navigateToReplacePod()
-        })
-        present(confirmVC, animated: true) {}
-    }
-    
-    private func insertCannula() {
-        guard let podState = pumpManager.state.podState, podState.setupProgress.needsCannulaInsertion else {
-            self.continueState = readyOrNeedsCannulaInsertionCheck
-            return
-        }
-        pumpManager.insertCannula() { (result) in
-            DispatchQueue.main.async {
-                switch(result) {
-                case .success(let finishTime):
-                    self.continueState = .inserting(finishTime: finishTime)
-                    let delay = finishTime
-                    if delay > 0 {
-                        DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
-                            self.checkCannulaInsertionFinished() // now check if actually ready
-                        }
-                    } else {
-                        self.continueState = self.readyOrNeedsCannulaInsertionCheck
-                    }
-                case .failure(let error):
-                    self.lastError = error
-                }
-            }
-        }
-    }
-
-    private func checkCannulaInsertionFinished() {
-        activityIndicator.state = .indeterminantProgress
-        self.pumpManager.checkCannulaInsertionFinished() { (error) in
-            DispatchQueue.main.async {
-                if let error = error {
-                    self.lastError = error
-                }
-                self.continueState = self.readyOrNeedsCannulaInsertionCheck
-            }
-        }
-    }
-}
-
-private extension SetupButton {
-    func setInsertCannulaTitle() {
-        setTitle(LocalizedString("Insert Cannula", comment: "Button title to insert cannula during setup"), for: .normal)
-    }
-    func setRecheckInsertionTitle() {
-        setTitle(LocalizedString("Recheck Cannula Insertion", comment: "Button title to recheck cannula insertion during setup"), for: .normal)
-    }
-    func setDeactivateTitle() {
-        setTitle(LocalizedString("Deactivate", comment: "Button title to deactivate pod because of fault during setup"), for: .normal)
-    }
-
-}
-
-private extension UIAlertController {
-    convenience init(pumpDeletionHandler handler: @escaping () -> Void) {
-        self.init(
-            title: nil,
-            message: LocalizedString("Are you sure you want to shutdown this pod?", comment: "Confirmation message for shutting down a pod"),
-            preferredStyle: .actionSheet
-        )
-        
-        addAction(UIAlertAction(
-            title: LocalizedString("Deactivate Pod", comment: "Button title to deactivate pod"),
-            style: .destructive,
-            handler: { (_) in
-                handler()
-        }
-        ))
-        
-        let exit = LocalizedString("Continue", comment: "The title of the continue action in an action sheet")
-        addAction(UIAlertAction(title: exit, style: .default, handler: nil))
-    }
-}
-

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 999
Dependecies/rileylink_ios/OmniKitUI/ViewControllers/OmnipodSettingsViewController.swift


+ 0 - 270
Dependecies/rileylink_ios/OmniKitUI/ViewControllers/PairPodSetupViewController.swift

@@ -1,270 +0,0 @@
-//
-//  PairPodSetupViewController.swift
-//  OmniKitUI
-//
-//  Created by Pete Schwamb on 9/18/18.
-//  Copyright © 2018 Pete Schwamb. All rights reserved.
-//
-
-import UIKit
-import LoopKit
-import LoopKitUI
-import RileyLinkKit
-import OmniKit
-import os.log
-
-class PairPodSetupViewController: SetupTableViewController {
-    
-    var rileyLinkPumpManager: RileyLinkPumpManager!
-    
-    var previouslyEncounteredWeakComms: Bool = false
-    
-    var pumpManager: OmnipodPumpManager! {
-        didSet {
-            if oldValue == nil && pumpManager != nil {
-                pumpManagerWasSet()
-            }
-        }
-    }
-
-    private let log = OSLog(category: "PairPodSetupViewController")
-
-    // MARK: -
-    
-    @IBOutlet weak var activityIndicator: SetupIndicatorView!
-    
-    @IBOutlet weak var loadingLabel: UILabel!
-    
-    private var loadingText: String? {
-        didSet {
-            tableView.beginUpdates()
-            loadingLabel.text = loadingText
-            
-            let isHidden = (loadingText == nil)
-            loadingLabel.isHidden = isHidden
-            tableView.endUpdates()
-        }
-    }
-    
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        continueState = .initial
-    }
-    
-    private func pumpManagerWasSet() {
-        // Still priming?
-        let primeFinishesAt = pumpManager.state.podState?.primeFinishTime
-        let currentTime = Date()
-        if let finishTime = primeFinishesAt, finishTime > currentTime {
-            self.continueState = .pairing
-            let delay = finishTime.timeIntervalSince(currentTime)
-            DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
-                self.continueState = .ready
-            }
-        }
-    }
-    
-    // MARK: - UITableViewDelegate
-    
-    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        if case .pairing = continueState {
-            return
-        }
-        
-        tableView.deselectRow(at: indexPath, animated: true)
-    }
-    
-    // MARK: - State
-    
-    private enum State {
-        case initial
-        case pairing
-        case priming(finishTime: TimeInterval)
-        case fault
-        case ready
-    }
-    
-    private var continueState: State = .initial {
-        didSet {
-            log.default("Changed continueState from %{public}@ to %{public}@", String(describing: oldValue), String(describing: continueState))
-
-            switch continueState {
-            case .initial:
-                activityIndicator.state = .hidden
-                footerView.primaryButton.isEnabled = true
-                footerView.primaryButton.setPairTitle()
-            case .pairing:
-                activityIndicator.state = .indeterminantProgress
-                footerView.primaryButton.isEnabled = false
-                footerView.primaryButton.setPairTitle()
-                lastError = nil
-                loadingText = LocalizedString("Pairing…", comment: "The text of the loading label when pairing")
-            case .priming(let finishTime):
-                activityIndicator.state = .timedProgress(finishTime: CACurrentMediaTime() + finishTime)
-                footerView.primaryButton.isEnabled = false
-                footerView.primaryButton.setPairTitle()
-                lastError = nil
-                loadingText = LocalizedString("Priming…", comment: "The text of the loading label when priming")
-            case .fault:
-                activityIndicator.state = .hidden
-                footerView.primaryButton.isEnabled = true
-                footerView.primaryButton.setDeactivateTitle()
-            case .ready:
-                activityIndicator.state = .completed
-                footerView.primaryButton.isEnabled = true
-                footerView.primaryButton.resetTitle()
-                lastError = nil
-                loadingText = LocalizedString("Primed", comment: "The text of the loading label when pod is primed")
-            }
-        }
-    }
-    
-    private var lastError: Error? {
-        didSet {
-            guard oldValue != nil || lastError != nil else {
-                return
-            }
-            
-            var errorStrings: [String]
-            var errorText: String
-            
-            if let error = lastError as? LocalizedError {
-                errorStrings = [error.errorDescription, error.failureReason, error.recoverySuggestion].compactMap { $0 }
-            } else {
-                errorStrings = [lastError?.localizedDescription].compactMap { $0 }
-            }
-            
-            if let commsError = lastError as? PodCommsError, commsError.possibleWeakCommsCause {
-                if previouslyEncounteredWeakComms {
-                    errorStrings.append(LocalizedString("If the problem persists, move to a new area and try again", comment: "Additional pairing recovery suggestion on multiple pairing failures"))
-                } else {
-                    previouslyEncounteredWeakComms = true
-                }
-            }
-
-            errorText = errorStrings.joined(separator: ". ")
-            
-            if !errorText.isEmpty {
-                errorText += "."
-            } else if let error = lastError {
-                // We have an error but no error text, generate a string to describe the error
-                errorText = String(describing: error)
-            }
-            loadingText = errorText
-            
-            // If we have an error, update the continue state
-            if let podCommsError = lastError as? PodCommsError {
-                switch podCommsError {
-                case .podFault, .activationTimeExceeded:
-                    continueState = .fault
-                default:
-                    continueState = .initial
-                }
-            } else if lastError != nil {
-                continueState = .initial
-            }
-        }
-    }
-    
-    // MARK: - Navigation
-    
-    private func navigateToReplacePod() {
-        log.default("Navigating to ReplacePod screen")
-        performSegue(withIdentifier: "ReplacePod", sender: nil)
-    }
-
-    override func continueButtonPressed(_ sender: Any) {
-        switch continueState {
-        case .initial:
-            pair()
-        case .ready:
-            super.continueButtonPressed(sender)
-        case .fault:
-            navigateToReplacePod()
-        default:
-            break
-        }
-
-    }
-    
-    override func cancelButtonPressed(_ sender: Any) {
-        let podState = pumpManager.state.podState
-
-        if podState != nil {
-            let confirmVC = UIAlertController(pumpDeletionHandler: {
-                self.navigateToReplacePod()
-            })
-            self.present(confirmVC, animated: true) {}
-        } else {
-            super.cancelButtonPressed(sender)
-        }
-    }
-    
-    // MARK: -
-    
-    private func pair() {
-        self.continueState = .pairing
-
-        pumpManager.pairAndPrime() { (result) in
-            DispatchQueue.main.async {
-                switch result {
-                case .success(let finishTime):
-                    self.log.default("Pairing succeeded, finishing in %{public}@ sec", String(describing: finishTime))
-                    if finishTime > 0 {
-                        self.continueState = .priming(finishTime: finishTime)
-                        DispatchQueue.main.asyncAfter(deadline: .now() + finishTime) {
-                            self.continueState = .ready
-                        }
-                    } else {
-                        self.continueState = .ready
-                    }
-                case .failure(let error):
-                    self.log.default("Pairing failed with error: %{public}@", String(describing: error))
-                    self.lastError = error
-                }
-            }
-        }
-    }
-}
-
-private extension PodCommsError {
-    var possibleWeakCommsCause: Bool {
-        switch self {
-        case .invalidData, .noResponse, .invalidAddress, .rssiTooLow, .rssiTooHigh, .unexpectedPacketType:
-            return true
-        default:
-            return false
-        }
-    }
-}
-
-private extension SetupButton {
-    func setPairTitle() {
-        setTitle(LocalizedString("Pair", comment: "Button title to pair with pod during setup"), for: .normal)
-    }
-    
-    func setDeactivateTitle() {
-        setTitle(LocalizedString("Deactivate", comment: "Button title to deactivate pod because of fault during setup"), for: .normal)
-    }
-}
-
-private extension UIAlertController {
-    convenience init(pumpDeletionHandler handler: @escaping () -> Void) {
-        self.init(
-            title: nil,
-            message: LocalizedString("Are you sure you want to shutdown this pod?", comment: "Confirmation message for shutting down a pod"),
-            preferredStyle: .actionSheet
-        )
-        
-        addAction(UIAlertAction(
-            title: LocalizedString("Deactivate Pod", comment: "Button title to deactivate pod"),
-            style: .destructive,
-            handler: { (_) in
-                handler()
-        }
-        ))
-        
-        let exit = LocalizedString("Continue", comment: "The title of the continue action in an action sheet")
-        addAction(UIAlertAction(title: exit, style: .default, handler: nil))
-    }
-}

+ 0 - 237
Dependecies/rileylink_ios/OmniKitUI/ViewControllers/ReplacePodViewController.swift

@@ -1,237 +0,0 @@
-//
-//  ReplacePodViewController.swift
-//  OmniKitUI
-//
-//  Created by Pete Schwamb on 11/28/18.
-//  Copyright © 2018 Pete Schwamb. All rights reserved.
-//
-
-import UIKit
-import LoopKitUI
-import OmniKit
-
-
-class ReplacePodViewController: SetupTableViewController {
-
-    enum PodReplacementReason {
-        case normal
-        case activationTimeout
-        case fault(_ podFault: DetailedStatus)
-        case canceledPairingBeforeApplication
-        case canceledPairing
-    }
-
-    var replacementReason: PodReplacementReason = .normal {
-        didSet {
-            updateButtonTint()
-            switch replacementReason {
-            case .normal:
-                break // Text set in interface builder
-            case .activationTimeout:
-                instructionsLabel.text = LocalizedString("Activation time exceeded. The pod must be deactivated before pairing with a new one. Please deactivate and discard pod.", comment: "Instructions when deactivating pod that didn't complete activation in time.")
-            case .fault(let podFault):
-                var faultDescription = podFault.faultEventCode.localizedDescription
-                if let refString = podFault.pdmRef {
-                    faultDescription += String(format: " (%@)", refString)
-                }
-                instructionsLabel.text = String(format: LocalizedString("%1$@. Insulin delivery has stopped. Please deactivate and remove pod.", comment: "Format string providing instructions for replacing pod due to a fault. (1: The fault description)"), faultDescription)
-            case .canceledPairingBeforeApplication:
-                instructionsLabel.text = LocalizedString("Incompletely set up pod must be deactivated before pairing with a new one. Please deactivate and discard pod.", comment: "Instructions when deactivating pod that has been paired, but not attached.")
-            case .canceledPairing:
-                instructionsLabel.text = LocalizedString("Incompletely set up pod must be deactivated before pairing with a new one. Please deactivate and remove pod.", comment: "Instructions when deactivating pod that has been paired and possibly attached.")
-            }
-
-            tableView.reloadData()
-        }
-    }
-    
-    var pumpManager: OmnipodPumpManager! {
-        didSet {
-            let podState = pumpManager.state.podState
-
-            if let podFault = podState?.fault {
-                if podFault.podProgressStatus == .activationTimeExceeded {
-                    self.replacementReason = .activationTimeout
-                } else {
-                    self.replacementReason = .fault(podFault)
-                }
-            } else if podState?.setupProgress.primingNeeded == true {
-                self.replacementReason = .canceledPairingBeforeApplication
-            } else if podState?.setupProgress.needsCannulaInsertion == true {
-                self.replacementReason = .canceledPairing
-            } else {
-                self.replacementReason = .normal
-            }
-        }
-    }
-    
-    // MARK: -
-    
-    @IBOutlet weak var activityIndicator: SetupIndicatorView!
-    
-    @IBOutlet weak var loadingLabel: UILabel!
-
-    @IBOutlet weak var instructionsLabel: UILabel!
-
-
-    private var tryCount: Int = 0
-    
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        
-        continueState = .initial
-    }
-    
-    override func setEditing(_ editing: Bool, animated: Bool) {
-        super.setEditing(editing, animated: animated)
-    }
-    
-    // MARK: - UITableViewDelegate
-    
-    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        guard continueState != .deactivating else {
-            return
-        }
-        
-        tableView.deselectRow(at: indexPath, animated: true)
-    }
-
-    
-    // MARK: - Navigation
-    
-    private enum State {
-        case initial
-        case deactivating
-        case deactivationFailed
-        case continueAfterFailure
-        case ready
-    }
-    
-    private var continueState: State = .initial {
-        didSet {
-            updateButtonTint()
-            switch continueState {
-            case .initial:
-                activityIndicator.state = .hidden
-                footerView.primaryButton.isEnabled = true
-                footerView.primaryButton.setDeactivateTitle()
-            case .deactivating:
-                activityIndicator.state = .indeterminantProgress
-                footerView.primaryButton.isEnabled = false
-                lastError = nil
-            case .deactivationFailed:
-                activityIndicator.state = .hidden
-                footerView.primaryButton.isEnabled = true
-                footerView.primaryButton.setRetryTitle()
-            case .continueAfterFailure:
-                activityIndicator.state = .hidden
-                footerView.primaryButton.isEnabled = true
-                footerView.primaryButton.resetTitle()
-                tableView.beginUpdates()
-                loadingLabel.text = LocalizedString("Unable to deactivate pod. Please continue and pair a new one.", comment: "Instructions when pod cannot be deactivated")
-                loadingLabel.isHidden = false
-                tableView.endUpdates()
-            case .ready:
-                navigationItem.rightBarButtonItem = nil
-                activityIndicator.state = .completed
-                footerView.primaryButton.isEnabled = true
-                footerView.primaryButton.resetTitle()
-                footerView.primaryButton.tintColor = nil
-                lastError = nil
-            }
-        }
-    }
-    
-    private var lastError: Error? {
-        didSet {
-            guard oldValue != nil || lastError != nil else {
-                return
-            }
-            
-            var errorText = lastError?.localizedDescription
-            
-            if let error = lastError as? LocalizedError {
-                let localizedText = [error.errorDescription, error.failureReason, error.recoverySuggestion].compactMap({ $0 }).joined(separator: ". ")
-                
-                if !localizedText.isEmpty {
-                    errorText = localizedText + "."
-                }
-            }
-            
-            // If we have an error but no error text, generate a string to describe the error
-            if let error = lastError, (errorText == nil || errorText!.isEmpty) {
-                errorText = String(describing: error)
-            }
-
-            tableView.beginUpdates()
-            loadingLabel.text = errorText
-            
-            let isHidden = (errorText == nil)
-            loadingLabel.isHidden = isHidden
-            tableView.endUpdates()
-        }
-    }
-    
-    override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
-        return continueState == .ready || continueState == .continueAfterFailure
-    }
-    
-    override func continueButtonPressed(_ sender: Any) {
-        switch continueState {
-        case .ready, .continueAfterFailure:
-            super.continueButtonPressed(sender)
-        case .initial, .deactivationFailed:
-            continueState = .deactivating
-            deactivate()
-        case .deactivating:
-            break
-        }
-    }
-    
-    func deactivate() {
-        tryCount += 1
-
-        let continueAfterFailure = tryCount > 1
-        pumpManager.deactivatePod(forgetPodOnFail: continueAfterFailure) { (error) in
-            DispatchQueue.main.async {
-                if let error = error {
-                    if continueAfterFailure {
-                        self.continueState = .continueAfterFailure
-                    } else {
-                        self.lastError = error
-                        self.continueState = .deactivationFailed
-                    }
-                } else {
-                    self.continueState = .ready
-                }
-            }
-        }
-    }
-
-    override func cancelButtonPressed(_ sender: Any) {
-        self.dismiss(animated: true, completion: nil)
-    }
-
-    private func updateButtonTint() {
-        let buttonTint: UIColor?
-        if case .normal = replacementReason, case .initial = continueState {
-            buttonTint = .deleteColor
-        } else {
-            buttonTint = nil
-        }
-        footerView.primaryButton.tintColor = buttonTint
-    }
-
-}
-
-private extension SetupButton {
-    func setDeactivateTitle() {
-        setTitle(LocalizedString("Deactivate Pod", comment: "Button title for pod deactivation"), for: .normal)
-    }
-    
-    func setRetryTitle() {
-        setTitle(LocalizedString("Retry Pod Deactivation", comment: "Button title for retrying pod deactivation"), for: .normal)
-    }
-}
-
-

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 5954
Dependecies/rileylink_ios/RileyLink.xcodeproj/project.pbxproj


+ 0 - 305
Dependecies/rileylink_ios/RileyLinkBLEKit/CommandSession.swift

@@ -1,305 +0,0 @@
-//
-//  RileyLinkCmdSession.swift
-//  RileyLinkBLEKit
-//
-//  Created by Pete Schwamb on 10/8/17.
-//  Copyright © 2017 Pete Schwamb. All rights reserved.
-//
-
-import Foundation
-
-public enum RXFilterMode: UInt8 {
-    case wide   = 0x50  // 300KHz
-    case narrow = 0x90  // 150KHz
-}
-
-public enum SoftwareEncodingType: UInt8 {
-    case none       = 0x00
-    case manchester = 0x01
-    case fourbsixb  = 0x02
-}
-
-public enum CC111XRegister: UInt8 {
-    case sync1    = 0x00
-    case sync0    = 0x01
-    case pktlen   = 0x02
-    case pktctrl1 = 0x03
-    case pktctrl0 = 0x04
-    case fsctrl1  = 0x07
-    case freq2    = 0x09
-    case freq1    = 0x0a
-    case freq0    = 0x0b
-    case mdmcfg4  = 0x0c
-    case mdmcfg3  = 0x0d
-    case mdmcfg2  = 0x0e
-    case mdmcfg1  = 0x0f
-    case mdmcfg0  = 0x10
-    case deviatn  = 0x11
-    case mcsm0    = 0x14
-    case foccfg   = 0x15
-    case agcctrl2 = 0x17
-    case agcctrl1 = 0x18
-    case agcctrl0 = 0x19
-    case frend1   = 0x1a
-    case frend0   = 0x1b
-    case fscal3   = 0x1c
-    case fscal2   = 0x1d
-    case fscal1   = 0x1e
-    case fscal0   = 0x1f
-    case test1    = 0x24
-    case test0    = 0x25
-    case paTable0 = 0x2e
-}
-
-public struct RileyLinkStatistics {
-    public let uptime: TimeInterval
-    public let radioRxOverflowCount: UInt16
-    public let radioRxFifoOverflowCount: UInt16
-    public let packetRxCount: UInt16
-    public let packetTxCount: UInt16
-    public let crcFailureCount: UInt16
-    public let spiSyncFailureCount: UInt16
-    
-    public init(uptime: TimeInterval, radioRxOverflowCount: UInt16, radioRxFifoOverflowCount: UInt16, packetRxCount: UInt16, packetTxCount: UInt16, crcFailureCount: UInt16, spiSyncFailureCount: UInt16) {
-        self.uptime = uptime
-        self.radioRxOverflowCount = radioRxOverflowCount
-        self.radioRxFifoOverflowCount = radioRxFifoOverflowCount
-        self.packetRxCount = packetRxCount
-        self.packetTxCount = packetTxCount
-        self.crcFailureCount = crcFailureCount
-        self.spiSyncFailureCount = spiSyncFailureCount
-    }
-    
-}
-
-public struct CommandSession {
-    let manager: PeripheralManager
-    let responseType: PeripheralManager.ResponseType
-    public let firmwareVersion: RadioFirmwareVersion
-
-    /// Invokes a command expecting a response
-    ///
-    /// Unsuccessful responses are thrown as errors.
-    ///
-    /// - Parameters:
-    ///   - command: The command
-    ///   - timeout: The amount of time to wait for the pump to respond before throwing a timeout error. This should not include any expected BLE latency.
-    /// - Returns: The successful response
-    /// - Throws: RileyLinkDeviceError
-    private func writeCommand<C: Command>(_ command: C, timeout: TimeInterval) throws -> C.ResponseType {
-        let response = try manager.writeCommand(command,
-            timeout: timeout + PeripheralManager.expectedMaxBLELatency,
-            responseType: responseType
-        )
-
-        switch response.code {
-        case .rxTimeout:
-            throw RileyLinkDeviceError.responseTimeout
-        case .commandInterrupted:
-            throw RileyLinkDeviceError.responseTimeout
-        case .zeroData:
-            throw RileyLinkDeviceError.invalidResponse(Data())
-        case .invalidParam, .unknownCommand:
-            throw RileyLinkDeviceError.invalidInput(command.data.hexadecimalString)
-        case .success:
-            return response
-        }
-    }
-
-    /// Invokes a command expecting an RF packet response
-    ///
-    /// - Parameters:
-    ///   - command: The command
-    ///   - timeout: The amount of time to wait for the pump to respond before throwing a timeout error. This should not include any expected BLE latency.
-    /// - Returns: The successful packet response
-    /// - Throws: RileyLinkDeviceError
-    private func writeCommand<C: Command>(_ command: C, timeout: TimeInterval) throws -> RFPacket where C.ResponseType == PacketResponse {
-        let response: C.ResponseType = try writeCommand(command, timeout: timeout)
-
-        guard let packet = response.packet else {
-            throw RileyLinkDeviceError.invalidResponse(Data())
-        }
-        return packet
-    }
-
-    /// - Throws: RileyLinkDeviceError
-    public func updateRegister(_ address: CC111XRegister, value: UInt8) throws {
-        let command = UpdateRegister(address, value: value, firmwareVersion: firmwareVersion)
-        _ = try writeCommand(command, timeout: 0)
-    }
-    
-    /// - Throws: RileyLinkDeviceError
-    public func readRegister(_ address: CC111XRegister) throws -> UInt8 {
-        guard firmwareVersion.supportsReadRegister else {
-            throw RileyLinkDeviceError.unsupportedCommand(String(describing: RileyLinkCommand.readRegister))
-        }
-        
-        let command = ReadRegister(address, firmwareVersion: firmwareVersion)
-        let response: ReadRegisterResponse = try writeCommand(command, timeout: 0)
-        
-        guard response.code == .success else {
-            throw RileyLinkDeviceError.invalidInput("Unsupported register: \(String(describing: address))")
-        }
-
-        return response.value
-    }
-
-    
-    /// - Throws: RileyLinkDeviceError
-    public func enableCCLEDs() throws {
-        let enableBlue = SetLEDMode(.blue, mode: .auto)
-        _ = try writeCommand(enableBlue, timeout: 0)
-        let enableGreen = SetLEDMode(.green, mode: .auto)
-        _ = try writeCommand(enableGreen, timeout: 0)
-    }
-
-    private static let xtalFrequency = Measurement<UnitFrequency>(value: 24, unit: .megahertz)
-
-    /// - Throws: RileyLinkDeviceError
-    public func setBaseFrequency(_ frequency: Measurement<UnitFrequency>) throws {
-        let val = Int(
-            frequency.converted(to: .hertz).value /
-            (CommandSession.xtalFrequency / pow(2, 16)).converted(to: .hertz).value)
-
-        try updateRegister(.freq0, value: UInt8(val & 0xff))
-        try updateRegister(.freq1, value: UInt8((val >> 8) & 0xff))
-        try updateRegister(.freq2, value: UInt8((val >> 16) & 0xff))
-    }
-    
-    public func readBaseFrequency() throws -> Measurement<UnitFrequency> {
-        let freq0 = try readRegister(.freq0)
-        let freq1 = try readRegister(.freq1)
-        let freq2 = try readRegister(.freq2)
-
-        let value = Double(UInt32(freq0) + (UInt32(freq1) << 8) + (UInt32(freq2) << 16))
-
-        let frequency = value * (CommandSession.xtalFrequency / pow(2, 16)).converted(to: .hertz).value
-
-        return Measurement<UnitFrequency>(value: frequency, unit: .hertz).converted(to: .megahertz)
-    }
-
-    /// Sends data to the pump, listening for a reply
-    ///
-    /// - Parameters:
-    ///   - data: The data to send
-    ///   - repeatCount: The number of times to repeat the message before listening begins
-    ///   - timeout: The length of time to listen for a response before timing out
-    ///   - retryCount: The number of times to repeat the send & listen sequence
-    ///   - preambleExtension: If set, the length of time to continuously send preamble data. Overrides the register based preamble settings.
-    /// - Returns: The packet reply
-    /// - Throws: RileyLinkDeviceError
-    public func sendAndListen(_ data: Data, repeatCount: Int, timeout: TimeInterval, retryCount: Int, preambleExtension: TimeInterval?) throws -> RFPacket {
-        let delayBetweenPackets: TimeInterval = 0
-
-        let command = SendAndListen(
-            outgoing: data,
-            sendChannel: 0,
-            repeatCount: UInt8(clamping: repeatCount),
-            delayBetweenPacketsMS: UInt16(clamping: Int(delayBetweenPackets)),
-            listenChannel: 0,
-            timeoutMS: UInt32(clamping: Int(timeout.milliseconds)),
-            retryCount: UInt8(clamping: retryCount),
-            preambleExtensionMS: UInt16(clamping: Int(preambleExtension?.milliseconds ?? 0)),
-            firmwareVersion: firmwareVersion
-        )
-
-        // At least 17 ms between packets for radio to stop/start
-        let radioTimeBetweenPackets = TimeInterval(milliseconds: 17)
-        let timeBetweenPackets = delayBetweenPackets + radioTimeBetweenPackets
-
-        // 16384 = bitrate, 8 = bits per byte
-        let singlePacketSendTime: TimeInterval = (Double(data.count * 8) / 16_384)
-        let preambleTime = preambleExtension ?? 0
-        let totalRepeatSendTime: TimeInterval = (singlePacketSendTime + timeBetweenPackets + preambleTime) * Double(repeatCount+1)
-        let totalTimeout = (totalRepeatSendTime + timeout) * Double(retryCount + 1)
-        return try writeCommand(command, timeout: totalTimeout)
-    }
-    
-    /// Sends data to the pump, listening for a reply
-    ///
-    /// - Parameters:
-    ///   - data: The data to send
-    ///   - repeatCount: The number of times to repeat the message before listening begins
-    ///   - timeout: The length of time to listen for a response before timing out
-    ///   - retryCount: The number of times to repeat the send & listen sequence if no response is heard
-    /// - Returns: The packet reply
-    /// - Throws: RileyLinkDeviceError
-    public func sendAndListen(_ data: Data, repeatCount: Int, timeout: TimeInterval, retryCount: Int) throws -> RFPacket {
-        return try sendAndListen(data, repeatCount: repeatCount, timeout: timeout, retryCount: retryCount, preambleExtension: nil)
-    }
-
-
-    /// - Throws: RileyLinkDeviceError
-    public func listen(onChannel channel: Int, timeout: TimeInterval) throws -> RFPacket? {
-        let command = GetPacket(
-            listenChannel: 0,
-            timeoutMS: UInt32(clamping: Int(timeout.milliseconds))
-        )
-
-        return try writeCommand(command, timeout: timeout)
-    }
-
-    /// - Throws: RileyLinkDeviceError
-    public func send(_ data: Data, onChannel channel: Int, timeout: TimeInterval) throws {
-        let command = SendPacket(
-            outgoing: data,
-            sendChannel: UInt8(clamping: channel),
-            repeatCount: 0,
-            delayBetweenPacketsMS: 0,
-            preambleExtensionMS: 0,
-            firmwareVersion: firmwareVersion
-        )
-
-        _ = try writeCommand(command, timeout: timeout)
-    }
-    
-    /// - Throws: RileyLinkDeviceError
-    public func setSoftwareEncoding(_ swEncodingType: SoftwareEncodingType) throws {
-        guard firmwareVersion.supportsSoftwareEncoding else {
-            throw RileyLinkDeviceError.unsupportedCommand(String(describing: RileyLinkCommand.setSWEncoding))
-        }
-        
-        let command = SetSoftwareEncoding(swEncodingType)
-        
-        let response = try writeCommand(command, timeout: 0)
-        
-        guard response.code == .success else {
-            throw RileyLinkDeviceError.invalidInput(String(describing: swEncodingType))
-        }
-    }
-    
-    public func resetRadioConfig() throws {
-        guard firmwareVersion.supportsResetRadioConfig else {
-            return
-        }
-        
-        let command = ResetRadioConfig()
-        _ = try writeCommand(command, timeout: 0)
-    }
-    
-    public func getRileyLinkStatistics() throws -> RileyLinkStatistics {
-        guard firmwareVersion.supportsRileyLinkStatistics else {
-            throw RileyLinkDeviceError.unsupportedCommand(String(describing: RileyLinkCommand.getStatistics))
-        }
-        
-        let command = GetStatistics()
-        let response: GetStatisticsResponse = try writeCommand(command, timeout: 0)
-        
-        return response.statistics
-    }
-    
-    public func setPreamble(_ preambleValue: UInt16) throws {
-        guard firmwareVersion.supportsCustomPreamble else {
-            throw RileyLinkDeviceError.unsupportedCommand(String(describing: RileyLinkCommand.setPreamble))
-        }
-        
-        let command = SetPreamble(preambleValue)
-        
-        _ = try writeCommand(command, timeout: 0)
-    }
-
-    /// Asserts that the caller is currently on the session's queue
-    public func assertOnSessionQueue() {
-        dispatchPrecondition(condition: .onQueue(manager.queue))
-    }
-}

+ 0 - 434
Dependecies/rileylink_ios/RileyLinkBLEKit/PeripheralManager+RileyLink.swift

@@ -1,434 +0,0 @@
-//
-//  PeripheralManager+RileyLink.swift
-//  xDripG5
-//
-//  Copyright © 2017 LoopKit Authors. All rights reserved.
-//
-
-import CoreBluetooth
-import os.log
-
-
-protocol CBUUIDRawValue: RawRepresentable {}
-extension CBUUIDRawValue where RawValue == String {
-    var cbUUID: CBUUID {
-        return CBUUID(string: rawValue)
-    }
-}
-
-
-enum RileyLinkServiceUUID: String, CBUUIDRawValue {
-    case main = "0235733B-99C5-4197-B856-69219C2A3845"
-}
-
-enum MainServiceCharacteristicUUID: String, CBUUIDRawValue {
-    case data            = "C842E849-5028-42E2-867C-016ADADA9155"
-    case responseCount   = "6E6C7910-B89E-43A5-A0FE-50C5E2B81F4A"
-    case customName      = "D93B2AF0-1E28-11E4-8C21-0800200C9A66"
-    case timerTick       = "6E6C7910-B89E-43A5-78AF-50C5E2B86F7E"
-    case firmwareVersion = "30D99DC9-7C91-4295-A051-0A104D238CF2"
-    case ledMode         = "C6D84241-F1A7-4F9C-A25F-FCE16732F14E"
-}
-
-enum RileyLinkLEDMode: UInt8 {
-    case off  = 0x00
-    case on   = 0x01
-    case auto = 0x02
-}
-
-
-extension PeripheralManager.Configuration {
-    static var rileyLink: PeripheralManager.Configuration {
-        return PeripheralManager.Configuration(
-            serviceCharacteristics: [
-                RileyLinkServiceUUID.main.cbUUID: [
-                    MainServiceCharacteristicUUID.data.cbUUID,
-                    MainServiceCharacteristicUUID.responseCount.cbUUID,
-                    MainServiceCharacteristicUUID.customName.cbUUID,
-                    MainServiceCharacteristicUUID.timerTick.cbUUID,
-                    MainServiceCharacteristicUUID.firmwareVersion.cbUUID,
-                    MainServiceCharacteristicUUID.ledMode.cbUUID
-                ]
-            ],
-            notifyingCharacteristics: [
-                RileyLinkServiceUUID.main.cbUUID: [
-                    MainServiceCharacteristicUUID.responseCount.cbUUID
-                    // TODO: Should timer tick default to on?
-                ]
-            ],
-            valueUpdateMacros: [
-                // When the responseCount changes, the data characteristic should be read.
-                MainServiceCharacteristicUUID.responseCount.cbUUID: { (manager: PeripheralManager) in
-                    guard let dataCharacteristic = manager.peripheral.getCharacteristicWithUUID(.data)
-                    else {
-                        return
-                    }
-
-                    manager.peripheral.readValue(for: dataCharacteristic)
-                }
-            ]
-        )
-    }
-}
-
-
-fileprivate extension CBPeripheral {
-    func getCharacteristicWithUUID(_ uuid: MainServiceCharacteristicUUID, serviceUUID: RileyLinkServiceUUID = .main) -> CBCharacteristic? {
-        guard let service = services?.itemWithUUID(serviceUUID.cbUUID) else {
-            return nil
-        }
-
-        return service.characteristics?.itemWithUUID(uuid.cbUUID)
-    }
-}
-
-
-extension CBCentralManager {
-    func scanForPeripherals(withOptions options: [String: Any]? = nil) {
-        scanForPeripherals(withServices: [RileyLinkServiceUUID.main.cbUUID], options: options)
-    }
-}
-
-
-extension Command {
-    /// Encodes a command's data by validating and prepending its length
-    ///
-    /// - Returns: Writable command data
-    /// - Throws: RileyLinkDeviceError.writeSizeLimitExceeded if the command data is too long
-    fileprivate func writableData() throws -> Data {
-        var data = self.data
-
-        guard data.count <= 220 else {
-            throw RileyLinkDeviceError.writeSizeLimitExceeded(maxLength: 220)
-        }
-
-        data.insert(UInt8(clamping: data.count), at: 0)
-        return data
-    }
-}
-
-
-private let log = OSLog(category: "PeripheralManager+RileyLink")
-
-
-extension PeripheralManager {
-    static let expectedMaxBLELatency: TimeInterval = 2
-
-    var timerTickEnabled: Bool {
-        return peripheral.getCharacteristicWithUUID(.timerTick)?.isNotifying ?? false
-    }
-
-    func setTimerTickEnabled(_ enabled: Bool, timeout: TimeInterval = expectedMaxBLELatency, completion: ((_ error: RileyLinkDeviceError?) -> Void)? = nil) {
-        perform { (manager) in
-            do {
-                guard let characteristic = manager.peripheral.getCharacteristicWithUUID(.timerTick) else {
-                    throw PeripheralManagerError.unknownCharacteristic
-                }
-
-                try manager.setNotifyValue(enabled, for: characteristic, timeout: timeout)
-                completion?(nil)
-            } catch let error as PeripheralManagerError {
-                completion?(.peripheralManagerError(error))
-            } catch {
-                assertionFailure()
-            }
-        }
-    }
-
-    func setLEDMode(mode: RileyLinkLEDMode) {
-        perform { (manager) in
-            do {
-                guard let characteristic = manager.peripheral.getCharacteristicWithUUID(.ledMode) else {
-                    throw PeripheralManagerError.unknownCharacteristic
-                }
-                let value = Data([mode.rawValue])
-                try manager.writeValue(value, for: characteristic, type: .withResponse, timeout: PeripheralManager.expectedMaxBLELatency)
-            } catch (let error) {
-                assertionFailure(String(describing: error))
-            }
-        }
-    }
-
-    
-
-    func startIdleListening(idleTimeout: TimeInterval, channel: UInt8, timeout: TimeInterval = expectedMaxBLELatency, completion: @escaping (_ error: RileyLinkDeviceError?) -> Void) {
-        perform { (manager) in
-            let command = GetPacket(listenChannel: channel, timeoutMS: UInt32(clamping: Int(idleTimeout.milliseconds)))
-
-            do {
-                try manager.writeCommandWithoutResponse(command, timeout: timeout)
-                completion(nil)
-            } catch let error as RileyLinkDeviceError {
-                completion(error)
-            } catch {
-                assertionFailure()
-            }
-        }
-    }
-
-    func setCustomName(_ name: String, timeout: TimeInterval = expectedMaxBLELatency, completion: ((_ error: RileyLinkDeviceError?) -> Void)? = nil) {
-        guard let value = name.data(using: .utf8) else {
-            completion?(.invalidInput(name))
-            return
-        }
-
-        perform { (manager) in
-            do {
-                guard let characteristic = manager.peripheral.getCharacteristicWithUUID(.customName) else {
-                    throw PeripheralManagerError.unknownCharacteristic
-                }
-
-                try manager.writeValue(value, for: characteristic, type: .withResponse, timeout: timeout)
-                completion?(nil)
-            } catch let error as PeripheralManagerError {
-                completion?(.peripheralManagerError(error))
-            } catch {
-                assertionFailure()
-            }
-        }
-    }
-}
-
-
-
-// MARK: - Synchronous commands
-extension PeripheralManager {
-    enum ResponseType {
-        case single
-        case buffered
-    }
-
-    /// Invokes a command expecting a response
-    ///
-    /// - Parameters:
-    ///   - command: The command
-    ///   - timeout: The amount of time to wait for the peripheral to respond before throwing a timeout error
-    ///   - responseType: The BLE response value framing method
-    /// - Returns: The received response
-    /// - Throws:
-    ///     - RileyLinkDeviceError.invalidResponse
-    ///     - RileyLinkDeviceError.peripheralManagerError
-    ///     - RileyLinkDeviceError.writeSizeLimitExceeded
-    func writeCommand<C: Command>(_ command: C, timeout: TimeInterval, responseType: ResponseType) throws -> C.ResponseType {
-        guard let characteristic = peripheral.getCharacteristicWithUUID(.data) else {
-            throw RileyLinkDeviceError.peripheralManagerError(.unknownCharacteristic)
-        }
-
-        let value = try command.writableData()
-
-
-        switch responseType {
-        case .single:
-            log.debug("RL Send (single): %@", value.hexadecimalString)
-            return try writeCommand(value,
-                for: characteristic,
-                timeout: timeout
-            )
-        case .buffered:
-            log.debug("RL Send (buffered): %@", value.hexadecimalString)
-            return try writeLegacyCommand(value,
-                for: characteristic,
-                timeout: timeout,
-                endOfResponseMarker: 0x00
-            )
-        }
-    }
-
-    /// Invokes a command without waiting for its response
-    ///
-    /// - Parameters:
-    ///   - command: The command
-    ///   - timeout: The amount of time to wait for the peripheral to confirm the write before throwing a timeout error
-    /// - Throws:
-    ///     - RileyLinkDeviceError.invalidResponse
-    ///     - RileyLinkDeviceError.peripheralManagerError
-    ///     - RileyLinkDeviceError.writeSizeLimitExceeded
-    fileprivate func writeCommandWithoutResponse<C: Command>(_ command: C, timeout: TimeInterval) throws {
-        guard let characteristic = peripheral.getCharacteristicWithUUID(.data) else {
-            throw RileyLinkDeviceError.peripheralManagerError(.unknownCharacteristic)
-        }
-
-        let value = try command.writableData()
-
-        log.debug("RL Send (no response expected): %@", value.hexadecimalString)
-
-        do {
-            try writeValue(value, for: characteristic, type: .withResponse, timeout: timeout)
-        } catch let error as PeripheralManagerError {
-            throw RileyLinkDeviceError.peripheralManagerError(error)
-        }
-    }
-    
-    /// - Throws:
-    ///     - RileyLinkDeviceError.invalidResponse
-    ///     - RileyLinkDeviceError.peripheralManagerError
-    func readRadioFirmwareVersion(timeout: TimeInterval, responseType: ResponseType) throws -> String {
-        let response = try writeCommand(GetVersion(), timeout: timeout, responseType: responseType)
-        return response.version
-    }
-
-    /// - Throws:
-    ///     - RileyLinkDeviceError.invalidResponse
-    ///     - RileyLinkDeviceError.peripheralManagerError
-    func readBluetoothFirmwareVersion(timeout: TimeInterval) throws -> String {
-        guard let characteristic = peripheral.getCharacteristicWithUUID(.firmwareVersion) else {
-            throw RileyLinkDeviceError.peripheralManagerError(.unknownCharacteristic)
-        }
-
-        do {
-            guard let data = try readValue(for: characteristic, timeout: timeout) else {
-                // TODO: This is an "unknown value" issue, not a timeout
-                throw RileyLinkDeviceError.peripheralManagerError(.timeout)
-            }
-
-            guard let version = String(bytes: data, encoding: .utf8) else {
-                throw RileyLinkDeviceError.invalidResponse(data)
-            }
-
-            return version
-        } catch let error as PeripheralManagerError {
-            throw RileyLinkDeviceError.peripheralManagerError(error)
-        }
-    }
-}
-
-
-// MARK: - Lower-level helper operations
-extension PeripheralManager {
-
-    /// Writes command data expecting a single response
-    ///
-    /// - Parameters:
-    ///   - data: The command data
-    ///   - characteristic: The peripheral characteristic to write
-    ///   - type: The type of characteristic write
-    ///   - timeout: The amount of time to wait for the peripheral to respond before throwing a timeout error
-    /// - Returns: The recieved response
-    /// - Throws:
-    ///     - RileyLinkDeviceError.invalidResponse
-    ///     - RileyLinkDeviceError.peripheralManagerError
-    private func writeCommand<R: Response>(_ data: Data,
-        for characteristic: CBCharacteristic,
-        type: CBCharacteristicWriteType = .withResponse,
-        timeout: TimeInterval
-    ) throws -> R
-    {
-        var capturedResponse: R?
-
-        do {
-            try runCommand(timeout: timeout) {
-                if case .withResponse = type {
-                    addCondition(.write(characteristic: characteristic))
-                }
-
-                addCondition(.valueUpdate(characteristic: characteristic, matching: { value in
-                    guard let value = value, value.count > 0 else {
-                        log.debug("Empty response from RileyLink. Continuing to listen for command response.")
-                        return false
-                    }
-                    
-                    log.debug("RL Recv(single): %@", value.hexadecimalString)
-
-                    guard let code = ResponseCode(rawValue: value[0]) else {
-                        let unknownCode = value[0..<1].hexadecimalString
-                        log.error("Unknown response code from RileyLink: %{public}@. Continuing to listen for command response.", unknownCode)
-                        return false
-                    }
-
-                    switch code {
-                    case .commandInterrupted:
-                        // This is expected in cases where an "Idle" GetPacket command is running
-                        log.debug("Idle command interrupted. Continuing to listen for command response.")
-                        return false
-                    default:
-                        guard let response = R(data: value) else {
-                            log.error("Unable to parse response.")
-                            // We don't recognize the contents. Keep listening.
-                            return false
-                        }
-                        log.debug("RileyLink response: %{public}@", String(describing: response))
-                        capturedResponse = response
-                        return true
-                    }
-                }))
-
-                peripheral.writeValue(data, for: characteristic, type: type)
-            }
-        } catch let error as PeripheralManagerError {
-            throw RileyLinkDeviceError.peripheralManagerError(error)
-        }
-
-        guard let response = capturedResponse else {
-            throw RileyLinkDeviceError.invalidResponse(characteristic.value ?? Data())
-        }
-
-        return response
-    }
-
-    /// Writes command data expecting a bufferred response
-    ///
-    /// - Parameters:
-    ///   - data: The command data
-    ///   - characteristic: The peripheral characteristic to write
-    ///   - type: The type of characteristic write
-    ///   - timeout: The amount of time to wait for the peripheral to respond before throwing a timeout error
-    ///   - endOfResponseMarker: The marker delimiting the end of a response in the buffer
-    /// - Returns: The received response. In the event of multiple responses in the buffer, the first parsable response is returned.
-    /// - Throws:
-    ///     - RileyLinkDeviceError.invalidResponse
-    ///     - RileyLinkDeviceError.peripheralManagerError
-    private func writeLegacyCommand<R: Response>(_ data: Data,
-        for characteristic: CBCharacteristic,
-        type: CBCharacteristicWriteType = .withResponse,
-        timeout: TimeInterval,
-        endOfResponseMarker: UInt8
-    ) throws -> R
-    {
-        var capturedResponse: R?
-        var buffer = ResponseBuffer<R>(endMarker: endOfResponseMarker)
-
-        do {
-            try runCommand(timeout: timeout) {
-                if case .withResponse = type {
-                    addCondition(.write(characteristic: characteristic))
-                }
-
-                addCondition(.valueUpdate(characteristic: characteristic, matching: { value in
-                    guard let value = value else {
-                        return false
-                    }
-
-                    log.debug("RL Recv(buffered): %@", value.hexadecimalString)
-                    buffer.append(value)
-
-                    for response in buffer.responses {
-                        switch response.code {
-                        case .rxTimeout, .zeroData, .invalidParam, .unknownCommand:
-                            log.debug("RileyLink response: %{public}@", String(describing: response))
-                            capturedResponse = response
-                            return true
-                        case .commandInterrupted:
-                            // This is expected in cases where an "Idle" GetPacket command is running
-                            log.debug("RileyLink response: %{public}@", String(describing: response))
-                        case .success:
-                            capturedResponse = response
-                            return true
-                        }
-                    }
-
-                    return false
-                }))
-
-                peripheral.writeValue(data, for: characteristic, type: type)
-            }
-        } catch let error as PeripheralManagerError {
-            throw RileyLinkDeviceError.peripheralManagerError(error)
-        }
-
-        guard let response = capturedResponse else {
-            throw RileyLinkDeviceError.invalidResponse(characteristic.value ?? Data())
-        }
-
-        return response
-    }
-}

+ 0 - 474
Dependecies/rileylink_ios/RileyLinkBLEKit/PeripheralManager.swift

@@ -1,474 +0,0 @@
-//
-//  PeripheralManager.swift
-//  xDripG5
-//
-//  Copyright © 2017 LoopKit Authors. All rights reserved.
-//
-
-import CoreBluetooth
-import Foundation
-import os.log
-
-
-class PeripheralManager: NSObject {
-
-    private let log = OSLog(category: "PeripheralManager")
-
-    ///
-    /// This is mutable, because CBPeripheral instances can seemingly become invalid, and need to be periodically re-fetched from CBCentralManager
-    var peripheral: CBPeripheral {
-        didSet {
-            guard oldValue !== peripheral else {
-                return
-            }
-
-            log.error("Replacing peripheral reference %{public}@ -> %{public}@", oldValue, peripheral)
-
-            oldValue.delegate = nil
-            peripheral.delegate = self
-
-            queue.sync {
-                self.needsConfiguration = true
-            }
-        }
-    }
-    
-    /// The dispatch queue used to serialize operations on the peripheral
-    let queue: DispatchQueue
-
-    /// The condition used to signal command completion
-    private let commandLock = NSCondition()
-
-    /// The required conditions for the operation to complete
-    private var commandConditions = [CommandCondition]()
-
-    /// Any error surfaced during the active operation
-    private var commandError: Error?
-
-    private(set) weak var central: CBCentralManager?
-    
-    let configuration: Configuration
-
-    // Confined to `queue`
-    private var needsConfiguration = true
-
-    weak var delegate: PeripheralManagerDelegate? {
-        didSet {
-            queue.sync {
-                needsConfiguration = true
-            }
-        }
-    }
-
-    // Called from RileyLinkDeviceManager.managerQueue
-    init(peripheral: CBPeripheral, configuration: Configuration, centralManager: CBCentralManager, queue: DispatchQueue) {
-        self.peripheral = peripheral
-        self.central = centralManager
-        self.configuration = configuration
-        self.queue = queue
-
-        super.init()
-
-        peripheral.delegate = self
-
-        assertConfiguration()
-    }
-}
-
-
-// MARK: - Nested types
-extension PeripheralManager {
-    struct Configuration {
-        var serviceCharacteristics: [CBUUID: [CBUUID]] = [:]
-        var notifyingCharacteristics: [CBUUID: [CBUUID]] = [:]
-        var valueUpdateMacros: [CBUUID: (_ manager: PeripheralManager) -> Void] = [:]
-    }
-
-    enum CommandCondition {
-        case notificationStateUpdate(characteristic: CBCharacteristic, enabled: Bool)
-        case valueUpdate(characteristic: CBCharacteristic, matching: ((Data?) -> Bool)?)
-        case write(characteristic: CBCharacteristic)
-        case discoverServices
-        case discoverCharacteristicsForService(serviceUUID: CBUUID)
-    }
-}
-
-protocol PeripheralManagerDelegate: class {
-    func peripheralManager(_ manager: PeripheralManager, didUpdateValueFor characteristic: CBCharacteristic)
-
-    func peripheralManager(_ manager: PeripheralManager, didReadRSSI RSSI: NSNumber, error: Error?)
-
-    func peripheralManagerDidUpdateName(_ manager: PeripheralManager)
-
-    func completeConfiguration(for manager: PeripheralManager) throws
-}
-
-
-// MARK: - Operation sequence management
-extension PeripheralManager {
-    func configureAndRun(_ block: @escaping (_ manager: PeripheralManager) -> Void) -> (() -> Void) {
-        return {
-            // TODO: Accessing self might be a race on initialization
-            if !self.needsConfiguration && self.peripheral.services == nil {
-                self.log.error("Configured peripheral has no services. Reconfiguring…")
-            }
-            
-            if self.needsConfiguration || self.peripheral.services == nil {
-                do {
-                    try self.applyConfiguration()
-                    self.log.default("Peripheral configuration completed")
-                } catch let error {
-                    self.log.error("Error applying peripheral configuration: %@", String(describing: error))
-                    // Will retry
-                }
-
-                do {
-                    if let delegate = self.delegate {
-                        try delegate.completeConfiguration(for: self)
-                        self.log.default("Delegate configuration completed")
-                        self.needsConfiguration = false
-                    } else {
-                        self.log.error("No delegate set for configuration")
-                    }
-                } catch let error {
-                    self.log.error("Error applying delegate configuration: %@", String(describing: error))
-                    // Will retry
-                }
-            }
-
-            block(self)
-        }
-    }
-
-    func perform(_ block: @escaping (_ manager: PeripheralManager) -> Void) {
-        queue.async(execute: configureAndRun(block))
-    }
-
-    private func assertConfiguration() {
-        perform { (_) in
-            // Intentionally empty to trigger configuration if necessary
-        }
-    }
-
-    private func applyConfiguration(discoveryTimeout: TimeInterval = 2) throws {
-        try discoverServices(configuration.serviceCharacteristics.keys.map { $0 }, timeout: discoveryTimeout)
-
-        for service in peripheral.services ?? [] {
-            guard let characteristics = configuration.serviceCharacteristics[service.uuid] else {
-                // Not all services may have characteristics
-                continue
-            }
-
-            try discoverCharacteristics(characteristics, for: service, timeout: discoveryTimeout)
-        }
-
-        for (serviceUUID, characteristicUUIDs) in configuration.notifyingCharacteristics {
-            guard let service = peripheral.services?.itemWithUUID(serviceUUID) else {
-                throw PeripheralManagerError.unknownCharacteristic
-            }
-
-            for characteristicUUID in characteristicUUIDs {
-                guard let characteristic = service.characteristics?.itemWithUUID(characteristicUUID) else {
-                    throw PeripheralManagerError.unknownCharacteristic
-                }
-
-                guard !characteristic.isNotifying else {
-                    continue
-                }
-
-                try setNotifyValue(true, for: characteristic, timeout: discoveryTimeout)
-            }
-        }
-    }
-}
-
-
-// MARK: - Synchronous Commands
-extension PeripheralManager {
-    /// - Throws: PeripheralManagerError
-    func runCommand(timeout: TimeInterval, command: () -> Void) throws {
-        // Prelude
-        dispatchPrecondition(condition: .onQueue(queue))
-        guard central?.state == .poweredOn && peripheral.state == .connected else {
-            throw PeripheralManagerError.notReady
-        }
-
-        commandLock.lock()
-
-        defer {
-            commandLock.unlock()
-        }
-
-        guard commandConditions.isEmpty else {
-            throw PeripheralManagerError.notReady
-        }
-
-        // Run
-        command()
-
-        guard !commandConditions.isEmpty else {
-            // If the command didn't add any conditions, then finish immediately
-            return
-        }
-
-        // Postlude
-        let signaled = commandLock.wait(until: Date(timeIntervalSinceNow: timeout))
-
-        defer {
-            commandError = nil
-            commandConditions = []
-        }
-
-        guard signaled else {
-            throw PeripheralManagerError.timeout
-        }
-
-        if let error = commandError {
-            throw PeripheralManagerError.cbPeripheralError(error)
-        }
-    }
-
-    /// It's illegal to call this without first acquiring the commandLock
-    ///
-    /// - Parameter condition: The condition to add
-    func addCondition(_ condition: CommandCondition) {
-        dispatchPrecondition(condition: .onQueue(queue))
-        commandConditions.append(condition)
-    }
-
-    func discoverServices(_ serviceUUIDs: [CBUUID], timeout: TimeInterval) throws {
-        let servicesToDiscover = peripheral.servicesToDiscover(from: serviceUUIDs)
-
-        guard servicesToDiscover.count > 0 else {
-            return
-        }
-
-        try runCommand(timeout: timeout) {
-            addCondition(.discoverServices)
-
-            peripheral.discoverServices(serviceUUIDs)
-        }
-    }
-
-    func discoverCharacteristics(_ characteristicUUIDs: [CBUUID], for service: CBService, timeout: TimeInterval) throws {
-        let characteristicsToDiscover = peripheral.characteristicsToDiscover(from: characteristicUUIDs, for: service)
-
-        guard characteristicsToDiscover.count > 0 else {
-            return
-        }
-
-        try runCommand(timeout: timeout) {
-            addCondition(.discoverCharacteristicsForService(serviceUUID: service.uuid))
-
-            peripheral.discoverCharacteristics(characteristicsToDiscover, for: service)
-        }
-    }
-
-    /// - Throws: PeripheralManagerError
-    func setNotifyValue(_ enabled: Bool, for characteristic: CBCharacteristic, timeout: TimeInterval) throws {
-        try runCommand(timeout: timeout) {
-            addCondition(.notificationStateUpdate(characteristic: characteristic, enabled: enabled))
-
-            peripheral.setNotifyValue(enabled, for: characteristic)
-        }
-    }
-
-    /// - Throws: PeripheralManagerError
-    func readValue(for characteristic: CBCharacteristic, timeout: TimeInterval) throws -> Data? {
-        try runCommand(timeout: timeout) {
-            addCondition(.valueUpdate(characteristic: characteristic, matching: nil))
-
-            peripheral.readValue(for: characteristic)
-        }
-
-        return characteristic.value
-    }
-
-    /// - Throws: PeripheralManagerError
-    func wait(for characteristic: CBCharacteristic, timeout: TimeInterval) throws -> Data {
-        try runCommand(timeout: timeout) {
-            addCondition(.valueUpdate(characteristic: characteristic, matching: nil))
-        }
-
-        guard let value = characteristic.value else {
-            throw PeripheralManagerError.timeout
-        }
-
-        return value
-    }
-
-    /// - Throws: PeripheralManagerError
-    func writeValue(_ value: Data, for characteristic: CBCharacteristic, type: CBCharacteristicWriteType, timeout: TimeInterval) throws {
-        try runCommand(timeout: timeout) {
-            if case .withResponse = type {
-                addCondition(.write(characteristic: characteristic))
-            }
-
-            peripheral.writeValue(value, for: characteristic, type: type)
-        }
-    }
-}
-
-
-// MARK: - Delegate methods executed on the central's queue
-extension PeripheralManager: CBPeripheralDelegate {
-
-    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
-        commandLock.lock()
-
-        if let index = commandConditions.firstIndex(where: { (condition) -> Bool in
-            if case .discoverServices = condition {
-                return true
-            } else {
-                return false
-            }
-        }) {
-            commandConditions.remove(at: index)
-            commandError = error
-
-            if commandConditions.isEmpty {
-                commandLock.broadcast()
-            }
-        }
-
-        commandLock.unlock()
-    }
-
-    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
-        commandLock.lock()
-
-        if let index = commandConditions.firstIndex(where: { (condition) -> Bool in
-            if case .discoverCharacteristicsForService(serviceUUID: service.uuid) = condition {
-                return true
-            } else {
-                return false
-            }
-        }) {
-            commandConditions.remove(at: index)
-            commandError = error
-
-            if commandConditions.isEmpty {
-                commandLock.broadcast()
-            }
-        }
-
-        commandLock.unlock()
-    }
-
-    func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
-        commandLock.lock()
-
-        if let index = commandConditions.firstIndex(where: { (condition) -> Bool in
-            if case .notificationStateUpdate(characteristic: characteristic, enabled: characteristic.isNotifying) = condition {
-                return true
-            } else {
-                return false
-            }
-        }) {
-            commandConditions.remove(at: index)
-            commandError = error
-
-            if commandConditions.isEmpty {
-                commandLock.broadcast()
-            }
-        }
-
-        commandLock.unlock()
-    }
-
-    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
-        commandLock.lock()
-
-        if let index = commandConditions.firstIndex(where: { (condition) -> Bool in
-            if case .write(characteristic: characteristic) = condition {
-                return true
-            } else {
-                return false
-            }
-        }) {
-            commandConditions.remove(at: index)
-            commandError = error
-
-            if commandConditions.isEmpty {
-                commandLock.broadcast()
-            }
-        }
-
-        commandLock.unlock()
-    }
-
-    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
-        commandLock.lock()
-
-        var notifyDelegate = false
-
-        if let index = commandConditions.firstIndex(where: { (condition) -> Bool in
-            if case .valueUpdate(characteristic: characteristic, matching: let matching) = condition {
-                return matching?(characteristic.value) ?? true
-            } else {
-                return false
-            }
-        }) {
-            commandConditions.remove(at: index)
-            commandError = error
-
-            if commandConditions.isEmpty {
-                commandLock.broadcast()
-            }
-        } else if let macro = configuration.valueUpdateMacros[characteristic.uuid] {
-            macro(self)
-        } else if commandConditions.isEmpty {
-            notifyDelegate = true // execute after the unlock
-        }
-
-        commandLock.unlock()
-
-        if notifyDelegate {
-            // If we weren't expecting this notification, pass it along to the delegate
-            delegate?.peripheralManager(self, didUpdateValueFor: characteristic)
-        }
-    }
-
-    func peripheral(_ peripheral: CBPeripheral, didReadRSSI RSSI: NSNumber, error: Error?) {
-        delegate?.peripheralManager(self, didReadRSSI: RSSI, error: error)
-    }
-
-    func peripheralDidUpdateName(_ peripheral: CBPeripheral) {
-        delegate?.peripheralManagerDidUpdateName(self)
-    }
-}
-
-
-extension PeripheralManager: CBCentralManagerDelegate {
-    func centralManagerDidUpdateState(_ central: CBCentralManager) {
-        switch central.state {
-        case .poweredOn:
-            assertConfiguration()
-        default:
-            break
-        }
-    }
-
-    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
-        switch peripheral.state {
-        case .connected:
-            assertConfiguration()
-        default:
-            break
-        }
-    }
-}
-
-
-extension PeripheralManager {
-    public override var debugDescription: String {
-        var items = [
-            "## PeripheralManager",
-            "peripheral: \(peripheral)",
-        ]
-        queue.sync {
-            items.append("needsConfiguration: \(needsConfiguration)")
-        }
-        return items.joined(separator: "\n")
-    }
-}

+ 0 - 54
Dependecies/rileylink_ios/RileyLinkBLEKit/PeripheralManagerError.swift

@@ -1,54 +0,0 @@
-//
-//  PeripheralManagerError.swift
-//  RileyLinkBLEKit
-//
-//  Copyright © 2017 Pete Schwamb. All rights reserved.
-//
-
-import CoreBluetooth
-
-
-public enum PeripheralManagerError: Error {
-    case cbPeripheralError(Error)
-    case notReady
-    case timeout
-    case unknownCharacteristic
-}
-
-
-extension PeripheralManagerError: LocalizedError {
-    public var errorDescription: String? {
-        switch self {
-        case .cbPeripheralError(let error):
-            return error.localizedDescription
-        case .notReady:
-            return LocalizedString("RileyLink is not connected", comment: "Not ready error description")
-        case .timeout:
-            return LocalizedString("RileyLink did not respond in time", comment: "Timeout error description")
-        case .unknownCharacteristic:
-            return LocalizedString("Unknown characteristic", comment: "Error description")
-        }
-    }
-
-    public var failureReason: String? {
-        switch self {
-        case .cbPeripheralError(let error as NSError):
-            return error.localizedFailureReason
-        case .unknownCharacteristic:
-            return LocalizedString("The RileyLink was temporarily disconnected", comment: "Failure reason: unknown peripheral characteristic")
-        default:
-            return nil
-        }
-    }
-
-    public var recoverySuggestion: String? {
-        switch self {
-        case .cbPeripheralError(let error as NSError):
-            return error.localizedRecoverySuggestion
-        case .unknownCharacteristic:
-            return LocalizedString("Make sure the device is nearby, and the issue should resolve automatically", comment: "Recovery suggestion for unknown peripheral characteristic")
-        default:
-            return nil
-        }
-    }
-}

+ 0 - 99
Dependecies/rileylink_ios/RileyLinkBLEKit/RileyLinkConnectionManager.swift

@@ -1,99 +0,0 @@
-//
-//  RileyLinkConnectionManager.swift
-//  RileyLinkBLEKit
-//
-//  Created by Pete Schwamb on 8/16/18.
-//  Copyright © 2018 Pete Schwamb. All rights reserved.
-//
-
-import Foundation
-
-public protocol RileyLinkConnectionManagerDelegate : class {
-    func rileyLinkConnectionManager(_ rileyLinkConnectionManager: RileyLinkConnectionManager, didChange state: RileyLinkConnectionManagerState)
-}
-
-public class RileyLinkConnectionManager {
-    
-    public typealias RawStateValue = [String : Any]
-
-    /// The current, serializable state of the manager
-    public var rawState: RawStateValue {
-        return state.rawValue
-    }
-    
-    public private(set) var state: RileyLinkConnectionManagerState {
-        didSet {
-            delegate?.rileyLinkConnectionManager(self, didChange: state)
-        }
-    }
-
-    public var deviceProvider: RileyLinkDeviceProvider {
-        return rileyLinkDeviceManager
-    }
-    
-    public weak var delegate: RileyLinkConnectionManagerDelegate?
-    
-    private let rileyLinkDeviceManager: RileyLinkDeviceManager
-    
-    private var autoConnectIDs: Set<String> {
-        get {
-            return state.autoConnectIDs
-        }
-        set {
-            state.autoConnectIDs = newValue
-        }
-    }
-    
-    public init(state: RileyLinkConnectionManagerState) {
-        self.rileyLinkDeviceManager = RileyLinkDeviceManager(autoConnectIDs: state.autoConnectIDs)
-        self.state = state
-    }
-    
-    public init(autoConnectIDs: Set<String>) {
-        self.rileyLinkDeviceManager = RileyLinkDeviceManager(autoConnectIDs: autoConnectIDs)
-        self.state = RileyLinkConnectionManagerState(autoConnectIDs: autoConnectIDs)
-    }
-    
-    public convenience init?(rawValue: RawStateValue) {
-        if let state = RileyLinkConnectionManagerState(rawValue: rawValue) {
-            self.init(state: state)
-        } else {
-            return nil
-        }
-    }
-    
-    public var connectingCount: Int {
-        return self.autoConnectIDs.count
-    }
-    
-    public func shouldConnect(to deviceID: String) -> Bool {
-        return self.autoConnectIDs.contains(deviceID)
-    }
-    
-    public func connect(_ device: RileyLinkDevice) {
-        autoConnectIDs.insert(device.peripheralIdentifier.uuidString)
-        rileyLinkDeviceManager.connect(device)
-    }
-    
-    public func disconnect(_ device: RileyLinkDevice) {
-        autoConnectIDs.remove(device.peripheralIdentifier.uuidString)
-        rileyLinkDeviceManager.disconnect(device)
-    }
-
-    public func setScanningEnabled(_ enabled: Bool) {
-        rileyLinkDeviceManager.setScanningEnabled(enabled)
-    }
-}
-
-public protocol RileyLinkDeviceProvider: class {
-    func getDevices(_ completion: @escaping (_ devices: [RileyLinkDevice]) -> Void)
-    var idleListeningEnabled: Bool { get }
-    var timerTickEnabled: Bool { get set }
-    func deprioritize(_ device: RileyLinkDevice, completion: (() -> Void)?)
-    func assertIdleListening(forcingRestart: Bool)
-    var idleListeningState: RileyLinkDevice.IdleListeningState { get set }
-
-    var debugDescription: String { get }
-}
-
-extension RileyLinkDeviceManager: RileyLinkDeviceProvider {}

+ 0 - 426
Dependecies/rileylink_ios/RileyLinkBLEKit/RileyLinkDevice.swift

@@ -1,426 +0,0 @@
-//
-//  RileyLinkDevice.swift
-//  RileyLinkBLEKit
-//
-//  Copyright © 2017 Pete Schwamb. All rights reserved.
-//
-
-import CoreBluetooth
-import os.log
-
-
-/// TODO: Should we be tracking the most recent "pump" RSSI?
-public class RileyLinkDevice {
-    let manager: PeripheralManager
-
-    private let log = OSLog(category: "RileyLinkDevice")
-
-    // Confined to `manager.queue`
-    private var bleFirmwareVersion: BLEFirmwareVersion?
-
-    // Confined to `manager.queue`
-    private var radioFirmwareVersion: RadioFirmwareVersion?
-
-    // Confined to `lock`
-    private var idleListeningState: IdleListeningState = .disabled
-
-    // Confined to `lock`
-    private var lastIdle: Date?
-    
-    // Confined to `lock`
-    // TODO: Tidy up this state/preference machine
-    private var isIdleListeningPending = false
-
-    // Confined to `lock`
-    private var isTimerTickEnabled = true
-
-    /// Serializes access to device state
-    private var lock = os_unfair_lock()
-
-    /// The queue used to serialize sessions and observe when they've drained
-    private let sessionQueue: OperationQueue = {
-        let queue = OperationQueue()
-        queue.name = "com.rileylink.RileyLinkBLEKit.RileyLinkDevice.sessionQueue"
-        queue.maxConcurrentOperationCount = 1
-
-        return queue
-    }()
-
-    private var sessionQueueOperationCountObserver: NSKeyValueObservation!
-
-    init(peripheralManager: PeripheralManager) {
-        self.manager = peripheralManager
-        sessionQueue.underlyingQueue = peripheralManager.queue
-
-        peripheralManager.delegate = self
-
-        sessionQueueOperationCountObserver = sessionQueue.observe(\.operationCount, options: [.new]) { [weak self] (queue, change) in
-            if let newValue = change.newValue, newValue == 0 {
-                self?.log.debug("Session queue operation count is now empty")
-                self?.assertIdleListening(forceRestart: true)
-            }
-        }
-    }
-}
-
-
-// MARK: - Peripheral operations. Thread-safe.
-extension RileyLinkDevice {
-    public var name: String? {
-        return manager.peripheral.name
-    }
-
-    public var deviceURI: String {
-        return "rileylink://\(name ?? peripheralIdentifier.uuidString)"
-    }
-
-    public var peripheralIdentifier: UUID {
-        return manager.peripheral.identifier
-    }
-
-    public var peripheralState: CBPeripheralState {
-        return manager.peripheral.state
-    }
-
-    public func readRSSI() {
-        guard case .connected = manager.peripheral.state, case .poweredOn? = manager.central?.state else {
-            return
-        }
-        manager.peripheral.readRSSI()
-    }
-
-    public func setCustomName(_ name: String) {
-        manager.setCustomName(name)
-    }
-    
-    public func enableBLELEDs() {
-        manager.setLEDMode(mode: .on)
-    }
-
-    /// Asserts that the caller is currently on the session queue
-    public func assertOnSessionQueue() {
-        dispatchPrecondition(condition: .onQueue(manager.queue))
-    }
-
-    /// Schedules a closure to execute on the session queue after a specified time
-    ///
-    /// - Parameters:
-    ///   - deadline: The time after which to execute
-    ///   - execute: The closure to execute
-    public func sessionQueueAsyncAfter(deadline: DispatchTime, execute: @escaping () -> Void) {
-        manager.queue.asyncAfter(deadline: deadline, execute: execute)
-    }
-}
-
-
-extension RileyLinkDevice: Equatable, Hashable {
-    public static func ==(lhs: RileyLinkDevice, rhs: RileyLinkDevice) -> Bool {
-        return lhs === rhs
-    }
-
-    public func hash(into hasher: inout Hasher) {
-        hasher.combine(peripheralIdentifier)
-    }
-}
-
-
-// MARK: - Status management
-extension RileyLinkDevice {
-    public struct Status {
-        public let lastIdle: Date?
-
-        public let name: String?
-
-        public let bleFirmwareVersion: BLEFirmwareVersion?
-
-        public let radioFirmwareVersion: RadioFirmwareVersion?
-    }
-
-    public func getStatus(_ completion: @escaping (_ status: Status) -> Void) {
-        os_unfair_lock_lock(&lock)
-        let lastIdle = self.lastIdle
-        os_unfair_lock_unlock(&lock)
-
-        self.manager.queue.async {
-            completion(Status(
-                lastIdle: lastIdle,
-                name: self.name,
-                bleFirmwareVersion: self.bleFirmwareVersion,
-                radioFirmwareVersion: self.radioFirmwareVersion
-            ))
-        }
-    }
-}
-
-
-// MARK: - Command session management
-extension RileyLinkDevice {
-    public func runSession(withName name: String, _ block: @escaping (_ session: CommandSession) -> Void) {
-        sessionQueue.addOperation(manager.configureAndRun({ [weak self] (manager) in
-            self?.log.default("======================== %{public}@ ===========================", name)
-            let bleFirmwareVersion = self?.bleFirmwareVersion
-            let radioFirmwareVersion = self?.radioFirmwareVersion
-
-            if bleFirmwareVersion == nil || radioFirmwareVersion == nil {
-                self?.log.error("Running session with incomplete configuration: bleFirmwareVersion %{public}@, radioFirmwareVersion: %{public}@", String(describing: bleFirmwareVersion), String(describing: radioFirmwareVersion))
-            }
-
-            block(CommandSession(manager: manager, responseType: bleFirmwareVersion?.responseType ?? .buffered, firmwareVersion: radioFirmwareVersion ?? .unknown))
-            self?.log.default("------------------------ %{public}@ ---------------------------", name)
-        }))
-    }
-}
-
-
-// MARK: - Idle management
-extension RileyLinkDevice {
-    public enum IdleListeningState {
-        case enabled(timeout: TimeInterval, channel: UInt8)
-        case disabled
-    }
-
-    func setIdleListeningState(_ state: IdleListeningState) {
-        os_unfair_lock_lock(&lock)
-        let oldValue = idleListeningState
-        idleListeningState = state
-        os_unfair_lock_unlock(&lock)
-
-        switch (oldValue, state) {
-        case (.disabled, .enabled):
-            assertIdleListening(forceRestart: true)
-        case (.enabled, .enabled):
-            assertIdleListening(forceRestart: false)
-        default:
-            break
-        }
-    }
-
-    public func assertIdleListening(forceRestart: Bool = false) {
-        os_unfair_lock_lock(&lock)
-        guard case .enabled(timeout: let timeout, channel: let channel) = self.idleListeningState else {
-            os_unfair_lock_unlock(&lock)
-            return
-        }
-
-        guard case .connected = self.manager.peripheral.state, case .poweredOn? = self.manager.central?.state else {
-            os_unfair_lock_unlock(&lock)
-            return
-        }
-
-        guard forceRestart || (self.lastIdle ?? .distantPast).timeIntervalSinceNow < -timeout else {
-            os_unfair_lock_unlock(&lock)
-            return
-        }
-
-        guard !self.isIdleListeningPending else {
-            os_unfair_lock_unlock(&lock)
-            return
-        }
-
-        self.isIdleListeningPending = true
-        os_unfair_lock_unlock(&lock)
-        self.log.debug("Enqueuing idle listening")
-
-        self.manager.startIdleListening(idleTimeout: timeout, channel: channel) { (error) in
-            os_unfair_lock_lock(&self.lock)
-            self.isIdleListeningPending = false
-
-            if let error = error {
-                self.log.error("Unable to start idle listening: %@", String(describing: error))
-                os_unfair_lock_unlock(&self.lock)
-            } else {
-                self.lastIdle = Date()
-                os_unfair_lock_unlock(&self.lock)
-                NotificationCenter.default.post(name: .DeviceDidStartIdle, object: self)
-            }
-        }
-    }
-}
-
-
-// MARK: - Timer tick management
-extension RileyLinkDevice {
-    func setTimerTickEnabled(_ enabled: Bool) {
-        os_unfair_lock_lock(&lock)
-        self.isTimerTickEnabled = enabled
-        os_unfair_lock_unlock(&lock)
-        self.assertTimerTick()
-    }
-
-    func assertTimerTick() {
-        os_unfair_lock_lock(&self.lock)
-        let isTimerTickEnabled = self.isTimerTickEnabled
-        os_unfair_lock_unlock(&self.lock)
-
-        if isTimerTickEnabled != self.manager.timerTickEnabled {
-            self.manager.setTimerTickEnabled(isTimerTickEnabled)
-        }
-    }
-}
-
-
-// MARK: - CBCentralManagerDelegate Proxying
-extension RileyLinkDevice {
-    func centralManagerDidUpdateState(_ central: CBCentralManager) {
-        if case .poweredOn = central.state {
-            assertIdleListening(forceRestart: false)
-            assertTimerTick()
-        }
-
-        manager.centralManagerDidUpdateState(central)
-    }
-
-    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
-        log.debug("didConnect %@", peripheral)
-        if case .connected = peripheral.state {
-            assertIdleListening(forceRestart: false)
-            assertTimerTick()
-        }
-
-        manager.centralManager(central, didConnect: peripheral)
-
-        NotificationCenter.default.post(name: .DeviceConnectionStateDidChange, object: self)
-    }
-
-    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
-        log.debug("didDisconnectPeripheral %@", peripheral)
-        NotificationCenter.default.post(name: .DeviceConnectionStateDidChange, object: self)
-    }
-
-    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
-        log.debug("didFailToConnect %@", peripheral)
-        NotificationCenter.default.post(name: .DeviceConnectionStateDidChange, object: self)
-    }
-}
-
-
-extension RileyLinkDevice: PeripheralManagerDelegate {
-    // This is called from the central's queue
-    func peripheralManager(_ manager: PeripheralManager, didUpdateValueFor characteristic: CBCharacteristic) {
-        log.debug("Did UpdateValueFor %@", characteristic)
-        switch MainServiceCharacteristicUUID(rawValue: characteristic.uuid.uuidString) {
-        case .data?:
-            guard let value = characteristic.value, value.count > 0 else {
-                return
-            }
-
-            self.manager.queue.async {
-                if let responseType = self.bleFirmwareVersion?.responseType {
-                    let response: PacketResponse?
-
-                    switch responseType {
-                    case .buffered:
-                        var buffer =  ResponseBuffer<PacketResponse>(endMarker: 0x00)
-                        buffer.append(value)
-                        response = buffer.responses.last
-                    case .single:
-                        response = PacketResponse(data: value)
-                    }
-
-                    if let response = response {
-                        switch response.code {
-                        case .rxTimeout, .commandInterrupted, .zeroData, .invalidParam, .unknownCommand:
-                            self.log.debug("Idle error received: %@", String(describing: response.code))
-                        case .success:
-                            if let packet = response.packet {
-                                self.log.debug("Idle packet received: %@", value.hexadecimalString)
-                                NotificationCenter.default.post(
-                                    name: .DevicePacketReceived,
-                                    object: self,
-                                    userInfo: [RileyLinkDevice.notificationPacketKey: packet]
-                                )
-                            }
-                        }
-                    } else {
-                        self.log.error("Unknown idle response: %@", value.hexadecimalString)
-                    }
-                } else {
-                    self.log.error("Skipping parsing characteristic value update due to missing BLE firmware version")
-                }
-
-                self.assertIdleListening(forceRestart: true)
-            }
-        case .responseCount?:
-            // PeripheralManager.Configuration.valueUpdateMacros is responsible for handling this response.
-            break
-        case .timerTick?:
-            NotificationCenter.default.post(name: .DeviceTimerDidTick, object: self)
-
-            assertIdleListening(forceRestart: false)
-        case .customName?, .firmwareVersion?, .ledMode?, .none:
-            break
-        }
-    }
-
-    func peripheralManager(_ manager: PeripheralManager, didReadRSSI RSSI: NSNumber, error: Error?) {
-        NotificationCenter.default.post(
-            name: .DeviceRSSIDidChange,
-            object: self,
-            userInfo: [RileyLinkDevice.notificationRSSIKey: RSSI]
-        )
-    }
-
-    func peripheralManagerDidUpdateName(_ manager: PeripheralManager) {
-        NotificationCenter.default.post(
-            name: .DeviceNameDidChange,
-            object: self,
-            userInfo: nil
-        )
-    }
-
-    func completeConfiguration(for manager: PeripheralManager) throws {
-        // Read bluetooth version to determine compatibility
-        log.default("Reading firmware versions for PeripheralManager configuration")
-        let bleVersionString = try manager.readBluetoothFirmwareVersion(timeout: 1)
-        bleFirmwareVersion = BLEFirmwareVersion(versionString: bleVersionString)
-
-        let radioVersionString = try manager.readRadioFirmwareVersion(timeout: 1, responseType: bleFirmwareVersion?.responseType ?? .buffered)
-        radioFirmwareVersion = RadioFirmwareVersion(versionString: radioVersionString)
-    }
-}
-
-
-extension RileyLinkDevice: CustomDebugStringConvertible {
-    public var debugDescription: String {
-        os_unfair_lock_lock(&lock)
-        let lastIdle = self.lastIdle
-        let isIdleListeningPending = self.isIdleListeningPending
-        let isTimerTickEnabled = self.isTimerTickEnabled
-        os_unfair_lock_unlock(&lock)
-
-        return [
-            "## RileyLinkDevice",
-            "* name: \(name ?? "")",
-            "* lastIdle: \(lastIdle ?? .distantPast)",
-            "* isIdleListeningPending: \(isIdleListeningPending)",
-            "* isTimerTickEnabled: \(isTimerTickEnabled)",
-            "* isTimerTickNotifying: \(manager.timerTickEnabled)",
-            "* radioFirmware: \(String(describing: radioFirmwareVersion))",
-            "* bleFirmware: \(String(describing: bleFirmwareVersion))",
-            "* peripheralManager: \(manager)",
-            "* sessionQueue.operationCount: \(sessionQueue.operationCount)"
-        ].joined(separator: "\n")
-    }
-}
-
-
-extension RileyLinkDevice {
-    public static let notificationPacketKey = "com.rileylink.RileyLinkBLEKit.RileyLinkDevice.NotificationPacket"
-
-    public static let notificationRSSIKey = "com.rileylink.RileyLinkBLEKit.RileyLinkDevice.NotificationRSSI"
-}
-
-
-extension Notification.Name {
-    public static let DeviceConnectionStateDidChange = Notification.Name(rawValue: "com.rileylink.RileyLinkBLEKit.ConnectionStateDidChange")
-
-    public static let DeviceDidStartIdle = Notification.Name(rawValue: "com.rileylink.RileyLinkBLEKit.DidStartIdle")
-
-    public static let DeviceNameDidChange = Notification.Name(rawValue: "com.rileylink.RileyLinkBLEKit.NameDidChange")
-
-    public static let DevicePacketReceived = Notification.Name(rawValue: "com.rileylink.RileyLinkBLEKit.PacketReceived")
-
-    public static let DeviceRSSIDidChange = Notification.Name(rawValue: "com.rileylink.RileyLinkBLEKit.RSSIDidChange")
-
-    public static let DeviceTimerDidTick = Notification.Name(rawValue: "com.rileylink.RileyLinkBLEKit.TimerTickDidChange")
-}

+ 0 - 54
Dependecies/rileylink_ios/RileyLinkBLEKit/RileyLinkDeviceError.swift

@@ -1,54 +0,0 @@
-//
-//  RileyLinkDeviceError.swift
-//  RileyLinkBLEKit
-//
-//  Copyright © 2018 Pete Schwamb. All rights reserved.
-//
-
-
-public enum RileyLinkDeviceError: Error {
-    case peripheralManagerError(PeripheralManagerError)
-    case invalidInput(String)
-    case writeSizeLimitExceeded(maxLength: Int)
-    case invalidResponse(Data)
-    case responseTimeout
-    case unsupportedCommand(String)
-}
-
-
-extension RileyLinkDeviceError: LocalizedError {
-    public var errorDescription: String? {
-        switch self {
-        case .peripheralManagerError(let error):
-            return error.errorDescription
-        case .invalidInput(let input):
-            return String(format: LocalizedString("Input %@ is invalid", comment: "Invalid input error description (1: input)"), String(describing: input))
-        case .invalidResponse(let response):
-            return String(format: LocalizedString("Response %@ is invalid", comment: "Invalid response error description (1: response)"), String(describing: response))
-        case .writeSizeLimitExceeded(let maxLength):
-            return String(format: LocalizedString("Data exceeded maximum size of %@ bytes", comment: "Write size limit exceeded error description (1: size limit)"), NumberFormatter.localizedString(from: NSNumber(value: maxLength), number: .none))
-        case .responseTimeout:
-            return LocalizedString("Pump did not respond in time", comment: "Response timeout error description")
-        case .unsupportedCommand(let command):
-            return String(format: LocalizedString("RileyLink firmware does not support the %@ command", comment: "Unsupported command error description"), String(describing: command))
-        }
-    }
-
-    public var failureReason: String? {
-        switch self {
-        case .peripheralManagerError(let error):
-            return error.failureReason
-        default:
-            return nil
-        }
-    }
-
-    public var recoverySuggestion: String? {
-        switch self {
-        case .peripheralManagerError(let error):
-            return error.recoverySuggestion
-        default:
-            return nil
-        }
-    }
-}

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 1136
Dependecies/rileylink_ios/RileyLinkKit/PumpOpsSession.swift


+ 0 - 30
Dependecies/rileylink_ios/RileyLinkKit/RileyLinkDevice.swift

@@ -1,30 +0,0 @@
-//
-//  RileyLinkDevice.swift
-//  RileyLinkKit
-//
-//  Copyright © 2017 Pete Schwamb. All rights reserved.
-//
-
-import RileyLinkBLEKit
-
-
-extension RileyLinkDevice.Status {
-    public var firmwareDescription: String {
-        let versions = [radioFirmwareVersion, bleFirmwareVersion].compactMap { (version: CustomStringConvertible?) -> String? in
-            if let version = version {
-                return String(describing: version)
-            } else {
-                return nil
-            }
-        }
-
-        return versions.joined(separator: " / ")
-    }
-}
-
-
-extension Notification.Name {
-    public static let DeviceRadioConfigDidChange = Notification.Name(rawValue: "com.rileylink.RileyLinkKit.DeviceRadioConfigDidChange")
-
-    public static let DeviceStateDidChange = Notification.Name(rawValue: "com.rileylink.RileyLinkKit.DeviceStateDidChange")
-}

+ 0 - 107
Dependecies/rileylink_ios/RileyLinkKit/RileyLinkPumpManager.swift

@@ -1,107 +0,0 @@
-//
-//  RileyLinkPumpManager.swift
-//  Loop
-//
-//  Copyright © 2018 LoopKit Authors. All rights reserved.
-//
-
-import LoopKit
-import RileyLinkBLEKit
-
-open class RileyLinkPumpManager {
-    
-    public init(rileyLinkDeviceProvider: RileyLinkDeviceProvider,
-                rileyLinkConnectionManager: RileyLinkConnectionManager? = nil) {
-        
-        self.rileyLinkDeviceProvider = rileyLinkDeviceProvider
-        self.rileyLinkConnectionManager = rileyLinkConnectionManager
-        self.rileyLinkConnectionManagerState = rileyLinkConnectionManager?.state
-        
-        // Listen for device notifications
-        NotificationCenter.default.addObserver(self, selector: #selector(receivedRileyLinkPacketNotification(_:)), name: .DevicePacketReceived, object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(receivedRileyLinkTimerTickNotification(_:)), name: .DeviceTimerDidTick, object: nil)
-    }
-    
-    /// Manages all the RileyLinks - access to management is optional
-    public let rileyLinkConnectionManager: RileyLinkConnectionManager?
-
-    // TODO: Not thread-safe
-    open var rileyLinkConnectionManagerState: RileyLinkConnectionManagerState?
-    
-    /// Access to rileylink devices
-    public let rileyLinkDeviceProvider: RileyLinkDeviceProvider
-
-    // TODO: Put this on each RileyLinkDevice?
-    private var lastTimerTick = Locked(Date.distantPast)
-
-    /// Called when one of the connected devices receives a packet outside of a session
-    ///
-    /// - Parameters:
-    ///   - device: The device
-    ///   - packet: The received packet
-    open func device(_ device: RileyLinkDevice, didReceivePacket packet: RFPacket) { }
-
-    open func deviceTimerDidTick(_ device: RileyLinkDevice) { }
-
-    // MARK: - CustomDebugStringConvertible
-    
-    open var debugDescription: String {
-        return [
-            "## RileyLinkPumpManager",
-            "rileyLinkConnectionManager: \(String(reflecting: rileyLinkConnectionManager))",
-            "lastTimerTick: \(String(describing: lastTimerTick.value))",
-            "",
-            String(reflecting: rileyLinkDeviceProvider),
-        ].joined(separator: "\n")
-    }
-}
-
-// MARK: - RileyLink Updates
-extension RileyLinkPumpManager {
-
-    /**
-     Called when a new idle message is received by the RileyLink.
-
-     Only MySentryPumpStatus messages are handled.
-
-     - parameter note: The notification object
-     */
-    @objc private func receivedRileyLinkPacketNotification(_ note: Notification) {
-        guard let device = note.object as? RileyLinkDevice,
-            let packet = note.userInfo?[RileyLinkDevice.notificationPacketKey] as? RFPacket
-        else {
-            return
-        }
-
-        device.assertOnSessionQueue()
-
-        self.device(device, didReceivePacket: packet)
-    }
-
-    @objc private func receivedRileyLinkTimerTickNotification(_ note: Notification) {
-        guard let device = note.object as? RileyLinkDevice else {
-            return
-        }
-
-        self.lastTimerTick.value = Date()
-        self.deviceTimerDidTick(device)
-    }
-    
-    open func connectToRileyLink(_ device: RileyLinkDevice) {
-        rileyLinkConnectionManager?.connect(device)
-    }
-
-    open func disconnectFromRileyLink(_ device: RileyLinkDevice) {
-        rileyLinkConnectionManager?.disconnect(device)
-    }
-    
-}
-
-// MARK: - RileyLinkConnectionManagerDelegate
-extension RileyLinkPumpManager: RileyLinkConnectionManagerDelegate {
-    public func rileyLinkConnectionManager(_ rileyLinkConnectionManager: RileyLinkConnectionManager, didChange state: RileyLinkConnectionManagerState) {
-        self.rileyLinkConnectionManagerState = state
-    }
-}
-
-

+ 0 - 41
Dependecies/rileylink_ios/RileyLinkKitUI/Base.lproj/Localizable.strings

@@ -1,41 +0,0 @@
-/* The title of the section describing commands */
-"Commands" = "Commands";
-
-/* The connected state */
-"Connected" = "Connected";
-
-/* The in-progress connecting state */
-"Connecting" = "Connecting";
-
-/* The title of the cell showing BLE connection state */
-"Connection State" = "Connection State";
-
-/* The title of the section describing the device */
-"Device" = "Device";
-
-/* The title of the devices table section in RileyLink settings */
-"Devices" = "Devices";
-
-/* The disconnected state */
-"Disconnected" = "Disconnected";
-
-/* The in-progress disconnecting state */
-"Disconnecting" = "Disconnecting";
-
-/* The title of the cell showing firmware version */
-"Firmware" = "Firmware";
-
-/* The title of the cell showing current rileylink frequency */
-"Frequency" = "Frequency";
-
-/* The title of the cell showing device name */
-"Name" = "Name";
-
-/* RileyLink setup description */
-"RileyLink allows for communication with the pump over Bluetooth Low Energy." = "RileyLink allows for communication with the pump over Bluetooth Low Energy.";
-
-/* The title of the cell showing BLE signal strength (RSSI) */
-"Signal Strength" = "Signal Strength";
-
-/* The title of the cell showing uptime */
-"Uptime" = "Uptime";

+ 0 - 413
Dependecies/rileylink_ios/RileyLinkKitUI/RileyLinkDeviceTableViewController.swift

@@ -1,413 +0,0 @@
-//
-//  RileyLinkDeviceTableViewController.swift
-//  Naterade
-//
-//  Created by Nathan Racklyeft on 3/5/16.
-//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
-//
-
-import UIKit
-import LoopKitUI
-import RileyLinkBLEKit
-import RileyLinkKit
-import os.log
-
-let CellIdentifier = "Cell"
-
-public class RileyLinkDeviceTableViewController: UITableViewController {
-
-    private let log = OSLog(category: "RileyLinkDeviceTableViewController")
-
-    public let device: RileyLinkDevice
-
-    private var bleRSSI: Int?
-
-    private var firmwareVersion: String? {
-        didSet {
-            guard isViewLoaded else {
-                return
-            }
-            
-            cellForRow(.version)?.detailTextLabel?.text = firmwareVersion
-        }
-    }
-    
-    private var uptime: TimeInterval? {
-        didSet {
-            guard isViewLoaded else {
-                return
-            }
-            
-            cellForRow(.uptime)?.setDetailAge(uptime)
-        }
-    }
-    
-    private var frequency: Measurement<UnitFrequency>? {
-        didSet {
-            guard isViewLoaded else {
-                return
-            }
-            
-            cellForRow(.frequency)?.setDetailFrequency(frequency, formatter: frequencyFormatter)
-        }
-    }
-
-    var rssiFetchTimer: Timer? {
-        willSet {
-            rssiFetchTimer?.invalidate()
-        }
-    }
-    
-    private lazy var frequencyFormatter: MeasurementFormatter = {
-        let formatter = MeasurementFormatter()
-        
-        formatter.numberFormatter = decimalFormatter
-        
-        return formatter
-    }()
-
-
-    private var appeared = false
-
-    public init(device: RileyLinkDevice) {
-        self.device = device
-
-        super.init(style: .grouped)
-
-        updateDeviceStatus()
-    }
-
-    required public init?(coder aDecoder: NSCoder) {
-        fatalError("init(coder:) has not been implemented")
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-
-        title = device.name
-
-        self.observe()
-    }
-    
-    @objc func updateRSSI() {
-        device.readRSSI()
-    }
-
-    func updateDeviceStatus() {
-        device.getStatus { (status) in
-            DispatchQueue.main.async {
-                self.firmwareVersion = status.firmwareDescription
-            }
-        }
-    }
-    
-    func updateUptime() {
-        device.runSession(withName: "Get stats for uptime") { (session) in
-            do {
-                let statistics = try session.getRileyLinkStatistics()
-                DispatchQueue.main.async {
-                    self.uptime = statistics.uptime
-                }
-            } catch let error {
-                self.log.error("Failed to get stats for uptime: %{public}@", String(describing: error))
-            }
-        }
-    }
-    
-    func updateFrequency() {
-
-        device.runSession(withName: "Get base frequency") { (session) in
-            do {
-                let frequency = try session.readBaseFrequency()
-                DispatchQueue.main.async {
-                    self.frequency = frequency
-                }
-            } catch let error {
-                self.log.error("Failed to get base frequency: %{public}@", String(describing: error))
-            }
-        }
-        
-    }
-
-    // References to registered notification center observers
-    private var notificationObservers: [Any] = []
-    
-    deinit {
-        for observer in notificationObservers {
-            NotificationCenter.default.removeObserver(observer)
-        }
-    }
-
-    private func observe() {
-        let center = NotificationCenter.default
-        let mainQueue = OperationQueue.main
-        
-        notificationObservers = [
-            center.addObserver(forName: .DeviceNameDidChange, object: device, queue: mainQueue) { [weak self] (note) -> Void in
-                if let cell = self?.cellForRow(.customName) {
-                    cell.detailTextLabel?.text = self?.device.name
-                }
-
-                self?.title = self?.device.name
-            },
-            center.addObserver(forName: .DeviceConnectionStateDidChange, object: device, queue: mainQueue) { [weak self] (note) -> Void in
-                if let cell = self?.cellForRow(.connection) {
-                    cell.detailTextLabel?.text = self?.device.peripheralState.description
-                }
-            },
-            center.addObserver(forName: .DeviceRSSIDidChange, object: device, queue: mainQueue) { [weak self] (note) -> Void in
-                self?.bleRSSI = note.userInfo?[RileyLinkDevice.notificationRSSIKey] as? Int
-
-                if let cell = self?.cellForRow(.rssi), let formatter = self?.integerFormatter {
-                    cell.setDetailRSSI(self?.bleRSSI, formatter: formatter)
-                }
-            },
-            center.addObserver(forName: .DeviceDidStartIdle, object: device, queue: mainQueue) { [weak self] (note) in
-                self?.updateDeviceStatus()
-            },
-        ]
-    }
-    
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-
-        if appeared {
-            tableView.reloadData()
-        }
-        
-        rssiFetchTimer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(updateRSSI), userInfo: nil, repeats: true)
-        
-        appeared = true
-        
-        updateRSSI()
-        
-        updateFrequency()
-
-        updateUptime()
-        
-    }
-    
-    public override func viewWillDisappear(_ animated: Bool) {
-        super.viewWillDisappear(animated)
-        rssiFetchTimer = nil
-    }
-
-
-    // MARK: - Formatters
-
-    private lazy var dateFormatter: DateFormatter = {
-        let dateFormatter = DateFormatter()
-
-        dateFormatter.dateStyle = .none
-        dateFormatter.timeStyle = .medium
-
-        return dateFormatter
-    }()
-    
-    private lazy var integerFormatter = NumberFormatter()
-
-    private lazy var measurementFormatter: MeasurementFormatter = {
-        let formatter = MeasurementFormatter()
-
-        formatter.numberFormatter = decimalFormatter
-
-        return formatter
-    }()
-
-    private lazy var decimalFormatter: NumberFormatter = {
-        let decimalFormatter = NumberFormatter()
-
-        decimalFormatter.numberStyle = .decimal
-        decimalFormatter.minimumSignificantDigits = 5
-
-        return decimalFormatter
-    }()
-
-    // MARK: - Table view data source
-
-    private enum Section: Int, CaseCountable {
-        case device
-        case commands
-    }
-
-    private enum DeviceRow: Int, CaseCountable {
-        case customName
-        case version
-        case rssi
-        case connection
-        case uptime
-        case frequency
-    }
-
-    private func cellForRow(_ row: DeviceRow) -> UITableViewCell? {
-        return tableView.cellForRow(at: IndexPath(row: row.rawValue, section: Section.device.rawValue))
-    }
-
-    public override func numberOfSections(in tableView: UITableView) -> Int {
-        return Section.count
-    }
-
-    public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-        switch Section(rawValue: section)! {
-        case .device:
-            return DeviceRow.count
-        case .commands:
-            return 0
-        }
-    }
-
-    public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        let cell: UITableViewCell
-
-        if let reusableCell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier) {
-            cell = reusableCell
-        } else {
-            cell = UITableViewCell(style: .value1, reuseIdentifier: CellIdentifier)
-        }
-
-        cell.accessoryType = .none
-
-        switch Section(rawValue: indexPath.section)! {
-        case .device:
-            switch DeviceRow(rawValue: indexPath.row)! {
-            case .customName:
-                cell.textLabel?.text = LocalizedString("Name", comment: "The title of the cell showing device name")
-                cell.detailTextLabel?.text = device.name
-                cell.accessoryType = .disclosureIndicator
-            case .version:
-                cell.textLabel?.text = LocalizedString("Firmware", comment: "The title of the cell showing firmware version")
-                cell.detailTextLabel?.text = firmwareVersion
-            case .connection:
-                cell.textLabel?.text = LocalizedString("Connection State", comment: "The title of the cell showing BLE connection state")
-                cell.detailTextLabel?.text = device.peripheralState.description
-            case .rssi:
-                cell.textLabel?.text = LocalizedString("Signal Strength", comment: "The title of the cell showing BLE signal strength (RSSI)")
-                cell.setDetailRSSI(bleRSSI, formatter: integerFormatter)
-            case .uptime:
-                cell.textLabel?.text = LocalizedString("Uptime", comment: "The title of the cell showing uptime")
-                cell.setDetailAge(uptime)
-            case .frequency:
-                cell.textLabel?.text = LocalizedString("Frequency", comment: "The title of the cell showing current rileylink frequency")
-                cell.setDetailFrequency(frequency, formatter: frequencyFormatter)
-            }
-        case .commands:
-            cell.accessoryType = .disclosureIndicator
-            cell.detailTextLabel?.text = nil
-        }
-
-        return cell
-    }
-
-    public override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
-        switch Section(rawValue: section)! {
-        case .device:
-            return LocalizedString("Device", comment: "The title of the section describing the device")
-        case .commands:
-            return LocalizedString("Commands", comment: "The title of the section describing commands")
-        }
-    }
-
-    // MARK: - UITableViewDelegate
-
-    public override func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
-        switch Section(rawValue: indexPath.section)! {
-        case .device:
-            switch DeviceRow(rawValue: indexPath.row)! {
-            case .customName:
-                return true
-            default:
-                return false
-            }
-        case .commands:
-            return device.peripheralState == .connected
-        }
-    }
-
-    public override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        switch Section(rawValue: indexPath.section)! {
-        case .device:
-            switch DeviceRow(rawValue: indexPath.row)! {
-            case .customName:
-                let vc = TextFieldTableViewController()
-                if let cell = tableView.cellForRow(at: indexPath) {
-                    vc.title = cell.textLabel?.text
-                    vc.value = device.name
-                    vc.delegate = self
-                    vc.keyboardType = .default
-                }
-
-                show(vc, sender: indexPath)
-            default:
-                break
-            }
-        case .commands:
-            break
-        }
-    }
-}
-
-
-extension RileyLinkDeviceTableViewController: TextFieldTableViewControllerDelegate {
-    public func textFieldTableViewControllerDidReturn(_ controller: TextFieldTableViewController) {
-        _ = navigationController?.popViewController(animated: true)
-    }
-
-    public func textFieldTableViewControllerDidEndEditing(_ controller: TextFieldTableViewController) {
-        if let indexPath = tableView.indexPathForSelectedRow {
-            switch Section(rawValue: indexPath.section)! {
-            case .device:
-                switch DeviceRow(rawValue: indexPath.row)! {
-                case .customName:
-                    device.setCustomName(controller.value!)
-                default:
-                    break
-                }
-            default:
-                break
-            }
-        }
-    }
-}
-
-private extension TimeInterval {
-    func format(using units: NSCalendar.Unit) -> String? {
-        let formatter = DateComponentsFormatter()
-        formatter.allowedUnits = units
-        formatter.unitsStyle = .full
-        formatter.zeroFormattingBehavior = .dropLeading
-        formatter.maximumUnitCount = 2
-        
-        return formatter.string(from: self)
-    }
-}
-
-private extension UITableViewCell {
-    func setDetailDate(_ date: Date?, formatter: DateFormatter) {
-        if let date = date {
-            detailTextLabel?.text = formatter.string(from: date)
-        } else {
-            detailTextLabel?.text = "-"
-        }
-    }
-
-    func setDetailRSSI(_ decibles: Int?, formatter: NumberFormatter) {
-        detailTextLabel?.text = formatter.decibleString(from: decibles) ?? "-"
-    }
-    
-    func setDetailAge(_ age: TimeInterval?) {
-        if let age = age {
-            detailTextLabel?.text = age.format(using: [.day, .hour, .minute])
-        } else {
-            detailTextLabel?.text = ""
-        }
-    }
-    
-    func setDetailFrequency(_ frequency: Measurement<UnitFrequency>?, formatter: MeasurementFormatter) {
-        if let frequency = frequency {
-            detailTextLabel?.text = formatter.string(from: frequency)
-        } else {
-            detailTextLabel?.text = ""
-        }
-    }
-
-}

+ 0 - 41
Dependecies/rileylink_ios/RileyLinkKitUI/da.lproj/Localizable.strings

@@ -1,41 +0,0 @@
-/* The title of the section describing commands */
-"Commands" = "Kommandoer";
-
-/* The connected state */
-"Connected" = "Tilsluttet";
-
-/* The in-progress connecting state */
-"Connecting" = "Tilslutter";
-
-/* The title of the cell showing BLE connection state */
-"Connection State" = "Tilslutningstilstand";
-
-/* The title of the section describing the device */
-"Device" = "Enhed";
-
-/* The title of the devices table section in RileyLink settings */
-"Devices" = "Enheder";
-
-/* The disconnected state */
-"Disconnected" = "Frakoblet";
-
-/* The in-progress disconnecting state */
-"Disconnecting" = "Frakobler";
-
-/* The title of the cell showing firmware version */
-"Firmware" = "Firmware";
-
-/* The title of the cell showing current rileylink frequency */
-"Frequency" = "Frekvens";
-
-/* The title of the cell showing device name */
-"Name" = "Navn";
-
-/* RileyLink setup description */
-"RileyLink allows for communication with the pump over Bluetooth Low Energy." = "RileyLink tillader kommunikation med pumpen vha Bluetooth Lav Energi.";
-
-/* The title of the cell showing BLE signal strength (RSSI) */
-"Signal Strength" = "Signal Styrke";
-
-/* The title of the cell showing uptime */
-"Uptime" = "Oppetid";

+ 0 - 41
Dependecies/rileylink_ios/RileyLinkKitUI/de.lproj/Localizable.strings

@@ -1,41 +0,0 @@
-/* The title of the section describing commands */
-"Commands" = "Befehle";
-
-/* The connected state */
-"Connected" = "Verbunden";
-
-/* The in-progress connecting state */
-"Connecting" = "Verbinden";
-
-/* The title of the cell showing BLE connection state */
-"Connection State" = "Verbindungsstatus";
-
-/* The title of the section describing the device */
-"Device" = "Gerät";
-
-/* The title of the devices table section in RileyLink settings */
-"Devices" = "Geräte";
-
-/* The disconnected state */
-"Disconnected" = "Getrennt";
-
-/* The in-progress disconnecting state */
-"Disconnecting" = "trennen";
-
-/* The title of the cell showing firmware version */
-"Firmware" = "Firmware";
-
-/* The title of the cell showing current rileylink frequency */
-"Frequency" = "Frequency";
-
-/* The title of the cell showing device name */
-"Name" = "Nombre";
-
-/* RileyLink setup description */
-"RileyLink allows for communication with the pump over Bluetooth Low Energy." = "RileyLink ermöglicht Kommunikation zur Pumpe über Bluetooth Low Energy.";
-
-/* The title of the cell showing BLE signal strength (RSSI) */
-"Signal Strength" = "Signalstärke";
-
-/* The title of the cell showing uptime */
-"Uptime" = "Uptime";

+ 0 - 41
Dependecies/rileylink_ios/RileyLinkKitUI/es.lproj/Localizable.strings

@@ -1,41 +0,0 @@
-/* The title of the section describing commands */
-"Commands" = "Comandos";
-
-/* The connected state */
-"Connected" = "Conectado";
-
-/* The in-progress connecting state */
-"Connecting" = "Conectando";
-
-/* The title of the cell showing BLE connection state */
-"Connection State" = "Estado de Conexión";
-
-/* The title of the section describing the device */
-"Device" = "Dispositivo";
-
-/* The title of the devices table section in RileyLink settings */
-"Devices" = "Dispositivos";
-
-/* The disconnected state */
-"Disconnected" = "Desconectado";
-
-/* The in-progress disconnecting state */
-"Disconnecting" = "Desconectando";
-
-/* The title of the cell showing firmware version */
-"Firmware" = "Firmware";
-
-/* The title of the cell showing current rileylink frequency */
-"Frequency" = "Frequencia";
-
-/* The title of the cell showing device name */
-"Name" = "Nombre";
-
-/* RileyLink setup description */
-"RileyLink allows for communication with the pump over Bluetooth Low Energy." = "RileyLink permite la comunicación con la microinfusora a través del uso de Bluetooth de baja energía.";
-
-/* The title of the cell showing BLE signal strength (RSSI) */
-"Signal Strength" = "Intensidad de señal";
-
-/* The title of the cell showing uptime */
-"Uptime" = "Uptime";

+ 0 - 42
Dependecies/rileylink_ios/RileyLinkKitUI/fi.lproj/Localizable.strings

@@ -1,42 +0,0 @@
-/* The title of the section describing commands */
-"Commands" = "Komennot";
-
-/* The connected state */
-"Connected" = "Yhdistetty";
-
-/* The in-progress connecting state */
-"Connecting" = "Yhdistetään";
-
-/* The title of the cell showing BLE connection state */
-"Connection State" = "Yhteyden tila";
-
-/* The title of the section describing the device */
-"Device" = "Laite";
-
-/* The title of the devices table section in RileyLink settings */
-"Devices" = "Laitteet";
-
-/* The disconnected state */
-"Disconnected" = "Ei yhteydessä";
-
-/* The in-progress disconnecting state */
-"Disconnecting" = "Katkaistaan";
-
-/* The title of the cell showing firmware version */
-"Firmware" = "Laiteohjelmisto";
-
-/* The title of the cell showing current rileylink frequency */
-"Frequency" = "Taajuus";
-
-/* The title of the cell showing device name */
-"Name" = "Nimi";
-
-/* RileyLink setup description */
-"RileyLink allows for communication with the pump over Bluetooth Low Energy." = "RileyLink mahdollistaa tiedonsiirron pumpun kanssa Bluetooth Low Energy -yhteyden kautta.";
-
-/* The title of the cell showing BLE signal strength (RSSI) */
-"Signal Strength" = "Signaalin vahvuus";
-
-/* The title of the cell showing uptime */
-"Uptime" = "Päällä";
-

+ 0 - 41
Dependecies/rileylink_ios/RileyLinkKitUI/fr.lproj/Localizable.strings

@@ -1,41 +0,0 @@
-/* The title of the section describing commands */
-"Commands" = "Commandes";
-
-/* The connected state */
-"Connected" = "Connecté";
-
-/* The in-progress connecting state */
-"Connecting" = "De liaison";
-
-/* The title of the cell showing BLE connection state */
-"Connection State" = "Etat de connexion";
-
-/* The title of the section describing the device */
-"Device" = "Dispositif";
-
-/* The title of the devices table section in RileyLink settings */
-"Devices" = "Dispositifs";
-
-/* The disconnected state */
-"Disconnected" = "Débranché";
-
-/* The in-progress disconnecting state */
-"Disconnecting" = "Se déconnecter";
-
-/* The title of the cell showing firmware version */
-"Firmware" = "Firmware";
-
-/* The title of the cell showing current rileylink frequency */
-"Frequency" = "Frequency";
-
-/* The title of the cell showing device name */
-"Name" = "Nom";
-
-/* RileyLink setup description */
-"RileyLink allows for communication with the pump over Bluetooth Low Energy." = "RileyLink permet la communication avec la pompe via Bluetooth Low Energy.";
-
-/* The title of the cell showing BLE signal strength (RSSI) */
-"Signal Strength" = "Force du signal";
-
-/* The title of the cell showing uptime */
-"Uptime" = "Uptime";

+ 0 - 41
Dependecies/rileylink_ios/RileyLinkKitUI/it.lproj/Localizable.strings

@@ -1,41 +0,0 @@
-/* The title of the section describing commands */
-"Commands" = "Comandi";
-
-/* The connected state */
-"Connected" = "Collegato";
-
-/* The in-progress connecting state */
-"Connecting" = "In collegamento";
-
-/* The title of the cell showing BLE connection state */
-"Connection State" = "Stato Connessione";
-
-/* The title of the section describing the device */
-"Device" = "Dispositivo";
-
-/* The title of the devices table section in RileyLink settings */
-"Devices" = "Dispositivi";
-
-/* The disconnected state */
-"Disconnected" = "Disconnesso";
-
-/* The in-progress disconnecting state */
-"Disconnecting" = "Disconnessione";
-
-/* The title of the cell showing firmware version */
-"Firmware" = "Firmware";
-
-/* The title of the cell showing current rileylink frequency */
-"Frequency" = "Frequency";
-
-/* The title of the cell showing device name */
-"Name" = "Nome";
-
-/* RileyLink setup description */
-"RileyLink allows for communication with the pump over Bluetooth Low Energy." = "RileyLink consente la comunicazione con il microinfusore tramite Bluetooth Low Energy.";
-
-/* The title of the cell showing BLE signal strength (RSSI) */
-"Signal Strength" = "Potenza Segnale";
-
-/* The title of the cell showing uptime */
-"Uptime" = "Uptime";

+ 0 - 41
Dependecies/rileylink_ios/RileyLinkKitUI/nb.lproj/Localizable.strings

@@ -1,41 +0,0 @@
-/* The title of the section describing commands */
-"Commands" = "Kommandoer";
-
-/* The connected state */
-"Connected" = "Tilkoblet";
-
-/* The in-progress connecting state */
-"Connecting" = "Kobler til";
-
-/* The title of the cell showing BLE connection state */
-"Connection State" = "Tilkoblingsstatus";
-
-/* The title of the section describing the device */
-"Device" = "Enhet";
-
-/* The title of the devices table section in RileyLink settings */
-"Devices" = "Enheter";
-
-/* The disconnected state */
-"Disconnected" = "Frakoblet";
-
-/* The in-progress disconnecting state */
-"Disconnecting" = "Kobler fra";
-
-/* The title of the cell showing firmware version */
-"Firmware" = "Fastvare";
-
-/* The title of the cell showing current rileylink frequency */
-"Frequency" = "Frekvens";
-
-/* The title of the cell showing device name */
-"Name" = "Navn";
-
-/* RileyLink setup description */
-"RileyLink allows for communication with the pump over Bluetooth Low Energy." = "RileyLink tillater kommunikasjon med pumpen over Bluetooth Low Energy.";
-
-/* The title of the cell showing BLE signal strength (RSSI) */
-"Signal Strength" = "Signalstyrke";
-
-/* The title of the cell showing uptime */
-"Uptime" = "Oppetid";

+ 0 - 41
Dependecies/rileylink_ios/RileyLinkKitUI/nl.lproj/Localizable.strings

@@ -1,41 +0,0 @@
-/* The title of the section describing commands */
-"Commands" = "Commando's";
-
-/* The connected state */
-"Connected" = "Verbonden";
-
-/* The in-progress connecting state */
-"Connecting" = "Verbinden";
-
-/* The title of the cell showing BLE connection state */
-"Connection State" = "Verbindingsstatus";
-
-/* The title of the section describing the device */
-"Device" = "Apparaat";
-
-/* The title of the devices table section in RileyLink settings */
-"Devices" = "Apparaten";
-
-/* The disconnected state */
-"Disconnected" = "Ontkoppeld";
-
-/* The in-progress disconnecting state */
-"Disconnecting" = "Ontkoppelen";
-
-/* The title of the cell showing firmware version */
-"Firmware" = "Firmware";
-
-/* The title of the cell showing current rileylink frequency */
-"Frequency" = "Frequency";
-
-/* The title of the cell showing device name */
-"Name" = "Naam";
-
-/* RileyLink setup description */
-"RileyLink allows for communication with the pump over Bluetooth Low Energy." = "RileyLink staat verbinding met de pomp toe via Bluetooth Low Energy (BLE of Bluetooth Smart).";
-
-/* The title of the cell showing BLE signal strength (RSSI) */
-"Signal Strength" = "Signaalsterkte";
-
-/* The title of the cell showing uptime */
-"Uptime" = "Uptime";

+ 0 - 41
Dependecies/rileylink_ios/RileyLinkKitUI/pl.lproj/Localizable.strings

@@ -1,41 +0,0 @@
-/* The title of the section describing commands */
-"Commands" = "Komendy";
-
-/* The connected state */
-"Connected" = "Połączony";
-
-/* The in-progress connecting state */
-"Connecting" = "Łączenie";
-
-/* The title of the cell showing BLE connection state */
-"Connection State" = "Status połączenia";
-
-/* The title of the section describing the device */
-"Device" = "Urządzenie";
-
-/* The title of the devices table section in RileyLink settings */
-"Devices" = "Urządzenia";
-
-/* The disconnected state */
-"Disconnected" = "Rozłączony";
-
-/* The in-progress disconnecting state */
-"Disconnecting" = "Rozłączanie";
-
-/* The title of the cell showing firmware version */
-"Firmware" = "Oprogramowanie";
-
-/* The title of the cell showing current rileylink frequency */
-"Frequency" = "Frequency";
-
-/* The title of the cell showing device name */
-"Name" = "Nazwa";
-
-/* RileyLink setup description */
-"RileyLink allows for communication with the pump over Bluetooth Low Energy." = "RileyLink będzie łączył się z pompą poprzez Bluetooth Low Energy.";
-
-/* The title of the cell showing BLE signal strength (RSSI) */
-"Signal Strength" = "Siła sygnału";
-
-/* The title of the cell showing uptime */
-"Uptime" = "Uptime";

+ 0 - 42
Dependecies/rileylink_ios/RileyLinkKitUI/pt-BR.lproj/Localizable.strings

@@ -1,42 +0,0 @@
-/* The title of the section describing commands */
-"Commands" = "Comandos";
-
-/* The connected state */
-"Connected" = "Conectado";
-
-/* The in-progress connecting state */
-"Connecting" = "Conectando";
-
-/* The title of the cell showing BLE connection state */
-"Connection State" = "Estado da Conexão";
-
-/* The title of the section describing the device */
-"Device" = "Dispositivo";
-
-/* The title of the devices table section in RileyLink settings */
-"Devices" = "Dispositivos";
-
-/* The disconnected state */
-"Disconnected" = "Desconectado";
-
-/* The in-progress disconnecting state */
-"Disconnecting" = "Desconectando";
-
-/* The title of the cell showing firmware version */
-"Firmware" = "Firmware";
-
-/* The title of the cell showing current rileylink frequency */
-"Frequency" = "Frequência";
-
-/* The title of the cell showing device name */
-"Name" = "Nome";
-
-/* RileyLink setup description */
-"RileyLink allows for communication with the pump over Bluetooth Low Energy." = "O RileyLink permite a comunicação com a bomba por Bluetooth de Baixa Energia.";
-
-/* The title of the cell showing BLE signal strength (RSSI) */
-"Signal Strength" = "Potência do Sinal";
-
-/* The title of the cell showing uptime */
-"Uptime" = "Tempo de Atividade";
-

+ 0 - 41
Dependecies/rileylink_ios/RileyLinkKitUI/ru.lproj/Localizable.strings

@@ -1,41 +0,0 @@
-/* The title of the section describing commands */
-"Commands" = "Команды";
-
-/* The connected state */
-"Connected" = "Соединение установлено";
-
-/* The in-progress connecting state */
-"Connecting" = "Соединяется";
-
-/* The title of the cell showing BLE connection state */
-"Connection State" = "Состояние соединения";
-
-/* The title of the section describing the device */
-"Device" = "устройство";
-
-/* The title of the devices table section in RileyLink settings */
-"Devices" = "устройства";
-
-/* The disconnected state */
-"Disconnected" = "Разъединено";
-
-/* The in-progress disconnecting state */
-"Disconnecting" = "Разъединяется";
-
-/* The title of the cell showing firmware version */
-"Firmware" = "Прошивка";
-
-/* The title of the cell showing current rileylink frequency */
-"Frequency" = "Frequency";
-
-/* The title of the cell showing device name */
-"Name" = "Название";
-
-/* RileyLink setup description */
-"RileyLink allows for communication with the pump over Bluetooth Low Energy." = "RileyLink позволяет вести коммуникацию с помпой через Bluetooth Low Energy.";
-
-/* The title of the cell showing BLE signal strength (RSSI) */
-"Signal Strength" = "Уровень сигнала";
-
-/* The title of the cell showing uptime */
-"Uptime" = "Uptime";

+ 0 - 41
Dependecies/rileylink_ios/RileyLinkKitUI/sv.lproj/Localizable.strings

@@ -1,41 +0,0 @@
-/* The title of the section describing commands */
-"Commands" = "Kommandon";
-
-/* The connected state */
-"Connected" = "Ansluten";
-
-/* The in-progress connecting state */
-"Connecting" = "Ansluter";
-
-/* The title of the cell showing BLE connection state */
-"Connection State" = "Anslutningsstatus";
-
-/* The title of the section describing the device */
-"Device" = "Enhet";
-
-/* The title of the devices table section in RileyLink settings */
-"Devices" = "Enheter";
-
-/* The disconnected state */
-"Disconnected" = "Frånkopplad";
-
-/* The in-progress disconnecting state */
-"Disconnecting" = "Kopplar från";
-
-/* The title of the cell showing firmware version */
-"Firmware" = "Firmware";
-
-/* The title of the cell showing current rileylink frequency */
-"Frequency" = "Frekvens";
-
-/* The title of the cell showing device name */
-"Name" = "Namn";
-
-/* RileyLink setup description */
-"RileyLink allows for communication with the pump over Bluetooth Low Energy." = "RileyLink kommunicerar med pumpen via Bluetooth lågenergianslutning.";
-
-/* The title of the cell showing BLE signal strength (RSSI) */
-"Signal Strength" = "Signalstyrka";
-
-/* The title of the cell showing uptime */
-"Uptime" = "Körs sedan";

+ 0 - 41
Dependecies/rileylink_ios/RileyLinkKitUI/zh-Hans.lproj/Localizable.strings

@@ -1,41 +0,0 @@
-/* The title of the section describing commands */
-"Commands" = "命令";
-
-/* The connected state */
-"Connected" = "已连接";
-
-/* The in-progress connecting state */
-"Connecting" = "正在连接";
-
-/* The title of the cell showing BLE connection state */
-"Connection State" = "连接状态";
-
-/* The title of the section describing the device */
-"Device" = "设备";
-
-/* The title of the devices table section in RileyLink settings */
-"Devices" = "设备";
-
-/* The disconnected state */
-"Disconnected" = "已断开连接";
-
-/* The in-progress disconnecting state */
-"Disconnecting" = "断开";
-
-/* The title of the cell showing firmware version */
-"Firmware" = "固件";
-
-/* The title of the cell showing current rileylink frequency */
-"Frequency" = "Frequency";
-
-/* The title of the cell showing device name */
-"Name" = "设备名称";
-
-/* RileyLink setup description */
-"RileyLink allows for communication with the pump over Bluetooth Low Energy." = "允许RileyLink通过低功耗蓝牙与泵连接通信";
-
-/* The title of the cell showing BLE signal strength (RSSI) */
-"Signal Strength" = "信号强度";
-
-/* The title of the cell showing uptime */
-"Uptime" = "Uptime";

+ 36 - 0
Dependencies/CGMBLEKit/.gitignore

@@ -0,0 +1,36 @@
+# OS X
+.DS_Store
+
+# Xcode
+build/
+*.pbxuser
+!default.pbxuser
+*.mode1v3
+!default.mode1v3
+*.mode2v3
+!default.mode2v3
+*.perspectivev3
+!default.perspectivev3
+xcuserdata
+*.xccheckout
+profile
+*.moved-aside
+DerivedData
+*.hmap
+*.ipa
+
+# Bundler
+.bundle
+
+Carthage
+# We recommend against adding the Pods directory to your .gitignore. However
+# you should judge for yourself, the pros and cons are mentioned at:
+# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
+#
+# Note: if you ignore the Pods directory, make sure to uncomment
+# `pod install` in .travis.yml
+#
+
+Pods/
+Carthage/
+.gitmodules

+ 657 - 0
Dependencies/CGMBLEKit/CGMBLEKit.xcodeproj/project.pbxproj

@@ -0,0 +1,657 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 48;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		38569354270C657B0002C50D /* TransmitterManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4325E9EC210EAEF500969CE5 /* TransmitterManager.swift */; };
+		38569356270C6B1A0002C50D /* WeakSynchronizedSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38569355270C6B1A0002C50D /* WeakSynchronizedSet.swift */; };
+		43026D3F2131C5C600A332E2 /* LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43026D3E2131C5C600A332E2 /* LocalizedString.swift */; };
+		43026D482131C99500A332E2 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 43026D462131C99500A332E2 /* Localizable.strings */; };
+		430D64C51CB7846A00FCA750 /* NSData+CRC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 430D64C41CB7846A00FCA750 /* NSData+CRC.swift */; };
+		431CE7631F8EEF6D00255374 /* CBPeripheral.swift in Sources */ = {isa = PBXBuildFile; fileRef = 431CE7621F8EEF6D00255374 /* CBPeripheral.swift */; };
+		431CE7671F91D0B300255374 /* PeripheralManager+G5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 431CE7661F91D0B300255374 /* PeripheralManager+G5.swift */; };
+		4323115F1EFC870300B95E62 /* OSLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4323115E1EFC870300B95E62 /* OSLog.swift */; };
+		433BC81B205CB64A000B1200 /* GlucoseBackfillMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 433BC81A205CB64A000B1200 /* GlucoseBackfillMessage.swift */; };
+		434B288320649D3C000EE07B /* ResetMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 434B288220649D3C000EE07B /* ResetMessage.swift */; };
+		435535D41FB2C1B000CE5A23 /* PeripheralManagerError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 435535D31FB2C1B000CE5A23 /* PeripheralManagerError.swift */; };
+		4379CFD2210EB0F700AADC79 /* TimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4379CFD1210EB0F700AADC79 /* TimeInterval.swift */; };
+		4379CFD4210EB14900AADC79 /* Glucose+SensorDisplayable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4379CFD3210EB14900AADC79 /* Glucose+SensorDisplayable.swift */; };
+		4379CFD6210EB19F00AADC79 /* Locked.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4379CFD5210EB19F00AADC79 /* Locked.swift */; };
+		43846AC61D8F896C00799272 /* CalibrationDataRxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43846AC51D8F896C00799272 /* CalibrationDataRxMessage.swift */; };
+		43880F981D9E19FC009061A8 /* TransmitterVersionRxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43880F971D9E19FC009061A8 /* TransmitterVersionRxMessage.swift */; };
+		43CABDF71C3506F100005705 /* CGMBLEKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CABDF61C3506F100005705 /* CGMBLEKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		43CABE121C350B2800005705 /* BluetoothManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CABE0E1C350B2800005705 /* BluetoothManager.swift */; };
+		43CABE131C350B2800005705 /* BluetoothServices.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CABE0F1C350B2800005705 /* BluetoothServices.swift */; };
+		43CABE151C350B2800005705 /* Transmitter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CABE111C350B2800005705 /* Transmitter.swift */; };
+		43CABE231C350B3D00005705 /* AuthRequestRxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CABE171C350B3D00005705 /* AuthRequestRxMessage.swift */; };
+		43CABE241C350B3D00005705 /* AuthChallengeTxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CABE181C350B3D00005705 /* AuthChallengeTxMessage.swift */; };
+		43CABE251C350B3D00005705 /* AuthRequestTxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CABE191C350B3D00005705 /* AuthRequestTxMessage.swift */; };
+		43CABE261C350B3D00005705 /* AuthChallengeRxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CABE1A1C350B3D00005705 /* AuthChallengeRxMessage.swift */; };
+		43CABE271C350B3D00005705 /* BondRequestTxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CABE1B1C350B3D00005705 /* BondRequestTxMessage.swift */; };
+		43CABE281C350B3D00005705 /* DisconnectTxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CABE1C1C350B3D00005705 /* DisconnectTxMessage.swift */; };
+		43CABE291C350B3D00005705 /* GlucoseRxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CABE1D1C350B3D00005705 /* GlucoseRxMessage.swift */; };
+		43CABE2A1C350B3D00005705 /* GlucoseTxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CABE1E1C350B3D00005705 /* GlucoseTxMessage.swift */; };
+		43CABE2B1C350B3D00005705 /* KeepAliveTxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CABE1F1C350B3D00005705 /* KeepAliveTxMessage.swift */; };
+		43CABE2C1C350B3D00005705 /* TransmitterMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CABE201C350B3D00005705 /* TransmitterMessage.swift */; };
+		43CABE2D1C350B3D00005705 /* TransmitterTimeRxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CABE211C350B3D00005705 /* TransmitterTimeRxMessage.swift */; };
+		43CABE2E1C350B3D00005705 /* TransmitterTimeTxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CABE221C350B3D00005705 /* TransmitterTimeTxMessage.swift */; };
+		43CE7CC81CA73AEB003CC1B0 /* FirmwareVersionTxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CE7CC71CA73AEB003CC1B0 /* FirmwareVersionTxMessage.swift */; };
+		43CE7CCA1CA73B94003CC1B0 /* TransmitterVersionTxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CE7CC91CA73B94003CC1B0 /* TransmitterVersionTxMessage.swift */; };
+		43CE7CCC1CA73BCC003CC1B0 /* BatteryStatusTxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CE7CCB1CA73BCC003CC1B0 /* BatteryStatusTxMessage.swift */; };
+		43CE7CCE1CA73C22003CC1B0 /* SessionStartTxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CE7CCD1CA73C22003CC1B0 /* SessionStartTxMessage.swift */; };
+		43CE7CD01CA73C57003CC1B0 /* SessionStopTxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CE7CCF1CA73C57003CC1B0 /* SessionStopTxMessage.swift */; };
+		43CE7CD21CA73CBC003CC1B0 /* CalibrateGlucoseTxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CE7CD11CA73CBC003CC1B0 /* CalibrateGlucoseTxMessage.swift */; };
+		43CE7CD41CA73CE8003CC1B0 /* GlucoseHistoryTxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CE7CD31CA73CE8003CC1B0 /* GlucoseHistoryTxMessage.swift */; };
+		43CE7CDC1CA77468003CC1B0 /* TransmitterStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CE7CDB1CA77468003CC1B0 /* TransmitterStatus.swift */; };
+		43D140CF2047AA940032346D /* Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43DC87BF1C8B509B005BC30D /* Data.swift */; };
+		43D140D12047BD930032346D /* Opcode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43D140D02047BD930032346D /* Opcode.swift */; };
+		43E3978B1D5668BD0028E321 /* CalibrationState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43E3978A1D5668BD0028E321 /* CalibrationState.swift */; };
+		43E3978F1D566B170028E321 /* Glucose.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43E3978E1D566B170028E321 /* Glucose.swift */; };
+		43E397931D56950C0028E321 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43E397921D56950C0028E321 /* HKUnit.swift */; };
+		43E4B1F21F8AF9790038823E /* PeripheralManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43E4B1F11F8AF9790038823E /* PeripheralManager.swift */; };
+		43EEA7111D14DC0800CBBDA0 /* AESCrypt.h in Headers */ = {isa = PBXBuildFile; fileRef = 43EEA70F1D14DC0800CBBDA0 /* AESCrypt.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		43EEA7121D14DC0800CBBDA0 /* AESCrypt.m in Sources */ = {isa = PBXBuildFile; fileRef = 43EEA7101D14DC0800CBBDA0 /* AESCrypt.m */; };
+		43F82BCE1D035D5C006F5DD7 /* SessionStartRxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F82BCD1D035D5C006F5DD7 /* SessionStartRxMessage.swift */; };
+		43F82BD01D035D68006F5DD7 /* SessionStopRxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F82BCF1D035D68006F5DD7 /* SessionStopRxMessage.swift */; };
+		A9D99F48225EE99300073DF6 /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A9D99F47225EE99300073DF6 /* HealthKit.framework */; };
+		E752B4102063C31B0063027D /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = E752B40F2063C31B0063027D /* Command.swift */; };
+		E75DB6AE20419B5D00FBE04E /* CalibrateGlucoseRxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E75DB6AD20419B5D00FBE04E /* CalibrateGlucoseRxMessage.swift */; };
+		E76FD69C205C75780056DA5B /* Calibration.swift in Sources */ = {isa = PBXBuildFile; fileRef = E76FD69B205C75780056DA5B /* Calibration.swift */; };
+		E76FD69E205C7A200056DA5B /* CalibrationDataTxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E76FD69D205C7A200056DA5B /* CalibrationDataTxMessage.swift */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		38569355270C6B1A0002C50D /* WeakSynchronizedSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WeakSynchronizedSet.swift; path = ../../LoopKit/LoopKit/WeakSynchronizedSet.swift; sourceTree = "<group>"; };
+		43026D3E2131C5C600A332E2 /* LocalizedString.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalizedString.swift; sourceTree = "<group>"; };
+		43026D472131C99500A332E2 /* base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = base; path = Base.lproj/Localizable.strings; sourceTree = "<group>"; };
+		43026D492131CA8C00A332E2 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
+		43026D4A2131CA8F00A332E2 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
+		43026D4B2131CA9000A332E2 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
+		43026D4C2131CA9100A332E2 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
+		43026D4D2131CA9200A332E2 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = "<group>"; };
+		43026D4E2131CA9200A332E2 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Localizable.strings; sourceTree = "<group>"; };
+		43026D4F2131CA9300A332E2 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = "<group>"; };
+		43026D502131CA9400A332E2 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
+		43026D512131CA9500A332E2 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
+		430D64C41CB7846A00FCA750 /* NSData+CRC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSData+CRC.swift"; sourceTree = "<group>"; };
+		431CE7621F8EEF6D00255374 /* CBPeripheral.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CBPeripheral.swift; sourceTree = "<group>"; };
+		431CE7661F91D0B300255374 /* PeripheralManager+G5.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PeripheralManager+G5.swift"; sourceTree = "<group>"; };
+		4323115E1EFC870300B95E62 /* OSLog.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OSLog.swift; sourceTree = "<group>"; };
+		4325E9EC210EAEF500969CE5 /* TransmitterManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransmitterManager.swift; sourceTree = "<group>"; };
+		4325E9EE210EAF3F00969CE5 /* ShareClientUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = ShareClientUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		433BC81A205CB64A000B1200 /* GlucoseBackfillMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseBackfillMessage.swift; sourceTree = "<group>"; };
+		434B288220649D3C000EE07B /* ResetMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResetMessage.swift; sourceTree = "<group>"; };
+		435535D31FB2C1B000CE5A23 /* PeripheralManagerError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeripheralManagerError.swift; sourceTree = "<group>"; };
+		4379CFD1210EB0F700AADC79 /* TimeInterval.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimeInterval.swift; sourceTree = "<group>"; };
+		4379CFD3210EB14900AADC79 /* Glucose+SensorDisplayable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Glucose+SensorDisplayable.swift"; sourceTree = "<group>"; };
+		4379CFD5210EB19F00AADC79 /* Locked.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Locked.swift; sourceTree = "<group>"; };
+		43846AC51D8F896C00799272 /* CalibrationDataRxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CalibrationDataRxMessage.swift; sourceTree = "<group>"; };
+		43880F971D9E19FC009061A8 /* TransmitterVersionRxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransmitterVersionRxMessage.swift; sourceTree = "<group>"; };
+		43A8EC49210D09BE00A81379 /* LoopKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LoopKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		43A8EC62210D4D1900A81379 /* LoopKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LoopKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		43A8EC70210E629300A81379 /* ShareClient.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = ShareClient.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		43CABDF31C3506F100005705 /* CGMBLEKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CGMBLEKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		43CABDF61C3506F100005705 /* CGMBLEKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CGMBLEKit.h; sourceTree = "<group>"; };
+		43CABDF81C3506F100005705 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		43CABE0E1C350B2800005705 /* BluetoothManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BluetoothManager.swift; sourceTree = "<group>"; };
+		43CABE0F1C350B2800005705 /* BluetoothServices.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BluetoothServices.swift; sourceTree = "<group>"; };
+		43CABE111C350B2800005705 /* Transmitter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Transmitter.swift; sourceTree = "<group>"; };
+		43CABE171C350B3D00005705 /* AuthRequestRxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthRequestRxMessage.swift; sourceTree = "<group>"; };
+		43CABE181C350B3D00005705 /* AuthChallengeTxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthChallengeTxMessage.swift; sourceTree = "<group>"; };
+		43CABE191C350B3D00005705 /* AuthRequestTxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthRequestTxMessage.swift; sourceTree = "<group>"; };
+		43CABE1A1C350B3D00005705 /* AuthChallengeRxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthChallengeRxMessage.swift; sourceTree = "<group>"; };
+		43CABE1B1C350B3D00005705 /* BondRequestTxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BondRequestTxMessage.swift; sourceTree = "<group>"; };
+		43CABE1C1C350B3D00005705 /* DisconnectTxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisconnectTxMessage.swift; sourceTree = "<group>"; };
+		43CABE1D1C350B3D00005705 /* GlucoseRxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlucoseRxMessage.swift; sourceTree = "<group>"; };
+		43CABE1E1C350B3D00005705 /* GlucoseTxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlucoseTxMessage.swift; sourceTree = "<group>"; };
+		43CABE1F1C350B3D00005705 /* KeepAliveTxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeepAliveTxMessage.swift; sourceTree = "<group>"; };
+		43CABE201C350B3D00005705 /* TransmitterMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransmitterMessage.swift; sourceTree = "<group>"; };
+		43CABE211C350B3D00005705 /* TransmitterTimeRxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransmitterTimeRxMessage.swift; sourceTree = "<group>"; };
+		43CABE221C350B3D00005705 /* TransmitterTimeTxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransmitterTimeTxMessage.swift; sourceTree = "<group>"; };
+		43CE7CC71CA73AEB003CC1B0 /* FirmwareVersionTxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirmwareVersionTxMessage.swift; sourceTree = "<group>"; };
+		43CE7CC91CA73B94003CC1B0 /* TransmitterVersionTxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransmitterVersionTxMessage.swift; sourceTree = "<group>"; };
+		43CE7CCB1CA73BCC003CC1B0 /* BatteryStatusTxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BatteryStatusTxMessage.swift; sourceTree = "<group>"; };
+		43CE7CCD1CA73C22003CC1B0 /* SessionStartTxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SessionStartTxMessage.swift; sourceTree = "<group>"; };
+		43CE7CCF1CA73C57003CC1B0 /* SessionStopTxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SessionStopTxMessage.swift; sourceTree = "<group>"; };
+		43CE7CD11CA73CBC003CC1B0 /* CalibrateGlucoseTxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CalibrateGlucoseTxMessage.swift; sourceTree = "<group>"; };
+		43CE7CD31CA73CE8003CC1B0 /* GlucoseHistoryTxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlucoseHistoryTxMessage.swift; sourceTree = "<group>"; };
+		43CE7CDB1CA77468003CC1B0 /* TransmitterStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransmitterStatus.swift; sourceTree = "<group>"; };
+		43D140D02047BD930032346D /* Opcode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Opcode.swift; sourceTree = "<group>"; };
+		43DC87BF1C8B509B005BC30D /* Data.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Data.swift; sourceTree = "<group>"; };
+		43E3978A1D5668BD0028E321 /* CalibrationState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CalibrationState.swift; sourceTree = "<group>"; };
+		43E3978E1D566B170028E321 /* Glucose.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Glucose.swift; sourceTree = "<group>"; };
+		43E397921D56950C0028E321 /* HKUnit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = "<group>"; };
+		43E4B1F11F8AF9790038823E /* PeripheralManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeripheralManager.swift; sourceTree = "<group>"; };
+		43EEA70F1D14DC0800CBBDA0 /* AESCrypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AESCrypt.h; sourceTree = "<group>"; };
+		43EEA7101D14DC0800CBBDA0 /* AESCrypt.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AESCrypt.m; sourceTree = "<group>"; };
+		43F82BCD1D035D5C006F5DD7 /* SessionStartRxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SessionStartRxMessage.swift; sourceTree = "<group>"; };
+		43F82BCF1D035D68006F5DD7 /* SessionStopRxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SessionStopRxMessage.swift; sourceTree = "<group>"; };
+		7D9BF0D32336EE51005DCFD6 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Localizable.strings; sourceTree = "<group>"; };
+		7D9BF0D92336EE5E005DCFD6 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = "<group>"; };
+		7D9BF0DF2336EE6E005DCFD6 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Localizable.strings; sourceTree = "<group>"; };
+		7D9BF0E52336EE77005DCFD6 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Localizable.strings; sourceTree = "<group>"; };
+		7D9BF0EB2336EE80005DCFD6 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = "<group>"; };
+		7D9BF0F12336EE89005DCFD6 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Localizable.strings; sourceTree = "<group>"; };
+		7D9BF11F2336FD7C005DCFD6 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/Localizable.strings; sourceTree = "<group>"; };
+		A9AD3821225EEEFB0058C179 /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS5.1.sdk/System/Library/Frameworks/HealthKit.framework; sourceTree = DEVELOPER_DIR; };
+		A9D99F47225EE99300073DF6 /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = System/Library/Frameworks/HealthKit.framework; sourceTree = SDKROOT; };
+		B4D40D4623A42A1700D7ECB5 /* LoopKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LoopKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		E752B40F2063C31B0063027D /* Command.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Command.swift; sourceTree = "<group>"; };
+		E75DB6AD20419B5D00FBE04E /* CalibrateGlucoseRxMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalibrateGlucoseRxMessage.swift; sourceTree = "<group>"; };
+		E76FD69B205C75780056DA5B /* Calibration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Calibration.swift; sourceTree = "<group>"; };
+		E76FD69D205C7A200056DA5B /* CalibrationDataTxMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalibrationDataTxMessage.swift; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		43CABDEF1C3506F100005705 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				A9D99F48225EE99300073DF6 /* HealthKit.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		437AFF172038EDF9008C4892 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				B4D40D4623A42A1700D7ECB5 /* LoopKit.framework */,
+				A9D99F47225EE99300073DF6 /* HealthKit.framework */,
+				A9AD3821225EEEFB0058C179 /* HealthKit.framework */,
+				43A8EC62210D4D1900A81379 /* LoopKit.framework */,
+				43A8EC49210D09BE00A81379 /* LoopKitUI.framework */,
+				43A8EC70210E629300A81379 /* ShareClient.framework */,
+				4325E9EE210EAF3F00969CE5 /* ShareClientUI.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		43CABDE91C3506F100005705 = {
+			isa = PBXGroup;
+			children = (
+				43CABDF51C3506F100005705 /* CGMBLEKit */,
+				43D140CD2047AA530032346D /* Common */,
+				43CABDF41C3506F100005705 /* Products */,
+				437AFF172038EDF9008C4892 /* Frameworks */,
+			);
+			sourceTree = "<group>";
+		};
+		43CABDF41C3506F100005705 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				43CABDF31C3506F100005705 /* CGMBLEKit.framework */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		43CABDF51C3506F100005705 /* CGMBLEKit */ = {
+			isa = PBXGroup;
+			children = (
+				43EEA70F1D14DC0800CBBDA0 /* AESCrypt.h */,
+				43EEA7101D14DC0800CBBDA0 /* AESCrypt.m */,
+				43CABE0E1C350B2800005705 /* BluetoothManager.swift */,
+				43CABE0F1C350B2800005705 /* BluetoothServices.swift */,
+				431CE7621F8EEF6D00255374 /* CBPeripheral.swift */,
+				E76FD69B205C75780056DA5B /* Calibration.swift */,
+				43E3978A1D5668BD0028E321 /* CalibrationState.swift */,
+				E752B40F2063C31B0063027D /* Command.swift */,
+				43E3978E1D566B170028E321 /* Glucose.swift */,
+				4379CFD3210EB14900AADC79 /* Glucose+SensorDisplayable.swift */,
+				43CABDF81C3506F100005705 /* Info.plist */,
+				43026D462131C99500A332E2 /* Localizable.strings */,
+				430D64C41CB7846A00FCA750 /* NSData+CRC.swift */,
+				4323115E1EFC870300B95E62 /* OSLog.swift */,
+				43D140D02047BD930032346D /* Opcode.swift */,
+				43E4B1F11F8AF9790038823E /* PeripheralManager.swift */,
+				435535D31FB2C1B000CE5A23 /* PeripheralManagerError.swift */,
+				431CE7661F91D0B300255374 /* PeripheralManager+G5.swift */,
+				43CABE111C350B2800005705 /* Transmitter.swift */,
+				4325E9EC210EAEF500969CE5 /* TransmitterManager.swift */,
+				43CE7CDB1CA77468003CC1B0 /* TransmitterStatus.swift */,
+				43CABDF61C3506F100005705 /* CGMBLEKit.h */,
+				43CABE161C350B2E00005705 /* Messages */,
+			);
+			path = CGMBLEKit;
+			sourceTree = "<group>";
+		};
+		43CABE161C350B2E00005705 /* Messages */ = {
+			isa = PBXGroup;
+			children = (
+				43CABE191C350B3D00005705 /* AuthRequestTxMessage.swift */,
+				43CABE171C350B3D00005705 /* AuthRequestRxMessage.swift */,
+				43CABE181C350B3D00005705 /* AuthChallengeTxMessage.swift */,
+				43CABE1A1C350B3D00005705 /* AuthChallengeRxMessage.swift */,
+				43CE7CCB1CA73BCC003CC1B0 /* BatteryStatusTxMessage.swift */,
+				43CABE1B1C350B3D00005705 /* BondRequestTxMessage.swift */,
+				43CE7CD11CA73CBC003CC1B0 /* CalibrateGlucoseTxMessage.swift */,
+				E75DB6AD20419B5D00FBE04E /* CalibrateGlucoseRxMessage.swift */,
+				E76FD69D205C7A200056DA5B /* CalibrationDataTxMessage.swift */,
+				43846AC51D8F896C00799272 /* CalibrationDataRxMessage.swift */,
+				43CABE1C1C350B3D00005705 /* DisconnectTxMessage.swift */,
+				43CE7CC71CA73AEB003CC1B0 /* FirmwareVersionTxMessage.swift */,
+				433BC81A205CB64A000B1200 /* GlucoseBackfillMessage.swift */,
+				43CE7CD31CA73CE8003CC1B0 /* GlucoseHistoryTxMessage.swift */,
+				43CABE1D1C350B3D00005705 /* GlucoseRxMessage.swift */,
+				43CABE1E1C350B3D00005705 /* GlucoseTxMessage.swift */,
+				43CABE1F1C350B3D00005705 /* KeepAliveTxMessage.swift */,
+				434B288220649D3C000EE07B /* ResetMessage.swift */,
+				43F82BCD1D035D5C006F5DD7 /* SessionStartRxMessage.swift */,
+				43CE7CCD1CA73C22003CC1B0 /* SessionStartTxMessage.swift */,
+				43F82BCF1D035D68006F5DD7 /* SessionStopRxMessage.swift */,
+				43CE7CCF1CA73C57003CC1B0 /* SessionStopTxMessage.swift */,
+				43CABE201C350B3D00005705 /* TransmitterMessage.swift */,
+				43CABE211C350B3D00005705 /* TransmitterTimeRxMessage.swift */,
+				43CABE221C350B3D00005705 /* TransmitterTimeTxMessage.swift */,
+				43CE7CC91CA73B94003CC1B0 /* TransmitterVersionTxMessage.swift */,
+				43880F971D9E19FC009061A8 /* TransmitterVersionRxMessage.swift */,
+			);
+			path = Messages;
+			sourceTree = "<group>";
+		};
+		43D140CD2047AA530032346D /* Common */ = {
+			isa = PBXGroup;
+			children = (
+				38569355270C6B1A0002C50D /* WeakSynchronizedSet.swift */,
+				43DC87BF1C8B509B005BC30D /* Data.swift */,
+				43E397921D56950C0028E321 /* HKUnit.swift */,
+				43026D3E2131C5C600A332E2 /* LocalizedString.swift */,
+				4379CFD5210EB19F00AADC79 /* Locked.swift */,
+				4379CFD1210EB0F700AADC79 /* TimeInterval.swift */,
+			);
+			path = Common;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		43CABDF01C3506F100005705 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				43CABDF71C3506F100005705 /* CGMBLEKit.h in Headers */,
+				43EEA7111D14DC0800CBBDA0 /* AESCrypt.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		43CABDF21C3506F100005705 /* CGMBLEKit */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 43CABE071C3506F100005705 /* Build configuration list for PBXNativeTarget "CGMBLEKit" */;
+			buildPhases = (
+				43CABDEE1C3506F100005705 /* Sources */,
+				43CABDEF1C3506F100005705 /* Frameworks */,
+				43CABDF01C3506F100005705 /* Headers */,
+				43CABDF11C3506F100005705 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = CGMBLEKit;
+			productName = xDripG5;
+			productReference = 43CABDF31C3506F100005705 /* CGMBLEKit.framework */;
+			productType = "com.apple.product-type.framework";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		43CABDEA1C3506F100005705 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastSwiftUpdateCheck = 0930;
+				LastUpgradeCheck = 1300;
+				ORGANIZATIONNAME = "LoopKit Authors";
+				TargetAttributes = {
+					43CABDF21C3506F100005705 = {
+						CreatedOnToolsVersion = 7.2;
+						LastSwiftMigration = 1020;
+					};
+				};
+			};
+			buildConfigurationList = 43CABDED1C3506F100005705 /* Build configuration list for PBXProject "CGMBLEKit" */;
+			compatibilityVersion = "Xcode 8.0";
+			developmentRegion = en;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+				base,
+				"zh-Hans",
+				nl,
+				fr,
+				de,
+				it,
+				nb,
+				pl,
+				ru,
+				es,
+				ja,
+				"pt-BR",
+				fi,
+				vi,
+				sv,
+				da,
+				ro,
+			);
+			mainGroup = 43CABDE91C3506F100005705;
+			productRefGroup = 43CABDF41C3506F100005705 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				43CABDF21C3506F100005705 /* CGMBLEKit */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		43CABDF11C3506F100005705 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				43026D482131C99500A332E2 /* Localizable.strings in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		43CABDEE1C3506F100005705 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				43026D3F2131C5C600A332E2 /* LocalizedString.swift in Sources */,
+				43CE7CCA1CA73B94003CC1B0 /* TransmitterVersionTxMessage.swift in Sources */,
+				E76FD69C205C75780056DA5B /* Calibration.swift in Sources */,
+				43E3978B1D5668BD0028E321 /* CalibrationState.swift in Sources */,
+				431CE7631F8EEF6D00255374 /* CBPeripheral.swift in Sources */,
+				E76FD69E205C7A200056DA5B /* CalibrationDataTxMessage.swift in Sources */,
+				38569356270C6B1A0002C50D /* WeakSynchronizedSet.swift in Sources */,
+				43CABE2D1C350B3D00005705 /* TransmitterTimeRxMessage.swift in Sources */,
+				43CABE291C350B3D00005705 /* GlucoseRxMessage.swift in Sources */,
+				43CE7CDC1CA77468003CC1B0 /* TransmitterStatus.swift in Sources */,
+				43CABE271C350B3D00005705 /* BondRequestTxMessage.swift in Sources */,
+				4323115F1EFC870300B95E62 /* OSLog.swift in Sources */,
+				43E4B1F21F8AF9790038823E /* PeripheralManager.swift in Sources */,
+				43CABE231C350B3D00005705 /* AuthRequestRxMessage.swift in Sources */,
+				43CABE261C350B3D00005705 /* AuthChallengeRxMessage.swift in Sources */,
+				43CE7CD41CA73CE8003CC1B0 /* GlucoseHistoryTxMessage.swift in Sources */,
+				43E397931D56950C0028E321 /* HKUnit.swift in Sources */,
+				43846AC61D8F896C00799272 /* CalibrationDataRxMessage.swift in Sources */,
+				43CE7CD01CA73C57003CC1B0 /* SessionStopTxMessage.swift in Sources */,
+				431CE7671F91D0B300255374 /* PeripheralManager+G5.swift in Sources */,
+				43CABE2A1C350B3D00005705 /* GlucoseTxMessage.swift in Sources */,
+				434B288320649D3C000EE07B /* ResetMessage.swift in Sources */,
+				43CE7CC81CA73AEB003CC1B0 /* FirmwareVersionTxMessage.swift in Sources */,
+				43D140D12047BD930032346D /* Opcode.swift in Sources */,
+				43CE7CCC1CA73BCC003CC1B0 /* BatteryStatusTxMessage.swift in Sources */,
+				4379CFD6210EB19F00AADC79 /* Locked.swift in Sources */,
+				43EEA7121D14DC0800CBBDA0 /* AESCrypt.m in Sources */,
+				43CE7CCE1CA73C22003CC1B0 /* SessionStartTxMessage.swift in Sources */,
+				433BC81B205CB64A000B1200 /* GlucoseBackfillMessage.swift in Sources */,
+				43CABE2E1C350B3D00005705 /* TransmitterTimeTxMessage.swift in Sources */,
+				4379CFD4210EB14900AADC79 /* Glucose+SensorDisplayable.swift in Sources */,
+				43880F981D9E19FC009061A8 /* TransmitterVersionRxMessage.swift in Sources */,
+				43CABE2C1C350B3D00005705 /* TransmitterMessage.swift in Sources */,
+				E75DB6AE20419B5D00FBE04E /* CalibrateGlucoseRxMessage.swift in Sources */,
+				43CABE131C350B2800005705 /* BluetoothServices.swift in Sources */,
+				43E3978F1D566B170028E321 /* Glucose.swift in Sources */,
+				43CABE151C350B2800005705 /* Transmitter.swift in Sources */,
+				43CABE281C350B3D00005705 /* DisconnectTxMessage.swift in Sources */,
+				43CABE121C350B2800005705 /* BluetoothManager.swift in Sources */,
+				43CABE2B1C350B3D00005705 /* KeepAliveTxMessage.swift in Sources */,
+				E752B4102063C31B0063027D /* Command.swift in Sources */,
+				43CABE241C350B3D00005705 /* AuthChallengeTxMessage.swift in Sources */,
+				4379CFD2210EB0F700AADC79 /* TimeInterval.swift in Sources */,
+				43CE7CD21CA73CBC003CC1B0 /* CalibrateGlucoseTxMessage.swift in Sources */,
+				38569354270C657B0002C50D /* TransmitterManager.swift in Sources */,
+				43F82BD01D035D68006F5DD7 /* SessionStopRxMessage.swift in Sources */,
+				43F82BCE1D035D5C006F5DD7 /* SessionStartRxMessage.swift in Sources */,
+				435535D41FB2C1B000CE5A23 /* PeripheralManagerError.swift in Sources */,
+				43D140CF2047AA940032346D /* Data.swift in Sources */,
+				43CABE251C350B3D00005705 /* AuthRequestTxMessage.swift in Sources */,
+				430D64C51CB7846A00FCA750 /* NSData+CRC.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+		43026D462131C99500A332E2 /* Localizable.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				43026D472131C99500A332E2 /* base */,
+				43026D492131CA8C00A332E2 /* zh-Hans */,
+				43026D4A2131CA8F00A332E2 /* nl */,
+				43026D4B2131CA9000A332E2 /* fr */,
+				43026D4C2131CA9100A332E2 /* de */,
+				43026D4D2131CA9200A332E2 /* it */,
+				43026D4E2131CA9200A332E2 /* nb */,
+				43026D4F2131CA9300A332E2 /* pl */,
+				43026D502131CA9400A332E2 /* ru */,
+				43026D512131CA9500A332E2 /* es */,
+				7D9BF0D32336EE51005DCFD6 /* ja */,
+				7D9BF0D92336EE5E005DCFD6 /* pt-BR */,
+				7D9BF0DF2336EE6E005DCFD6 /* fi */,
+				7D9BF0E52336EE77005DCFD6 /* vi */,
+				7D9BF0EB2336EE80005DCFD6 /* sv */,
+				7D9BF0F12336EE89005DCFD6 /* da */,
+				7D9BF11F2336FD7C005DCFD6 /* ro */,
+			);
+			name = Localizable.strings;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		43CABE051C3506F100005705 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				CURRENT_PROJECT_VERSION = 21;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
+				LOCALIZED_STRING_MACRO_NAMES = (
+					NSLocalizedString,
+					CFLocalizedString,
+					LocalizedString,
+				);
+				MTL_ENABLE_DEBUG_INFO = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = iphoneos;
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+				SWIFT_VERSION = 5.0;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				VERSIONING_SYSTEM = "apple-generic";
+				VERSION_INFO_PREFIX = "";
+				WATCHOS_DEPLOYMENT_TARGET = 4.0;
+			};
+			name = Debug;
+		};
+		43CABE061C3506F100005705 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				CURRENT_PROJECT_VERSION = 21;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
+				LOCALIZED_STRING_MACRO_NAMES = (
+					NSLocalizedString,
+					CFLocalizedString,
+					LocalizedString,
+				);
+				MTL_ENABLE_DEBUG_INFO = NO;
+				SDKROOT = iphoneos;
+				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+				SWIFT_VERSION = 5.0;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				VALIDATE_PRODUCT = YES;
+				VERSIONING_SYSTEM = "apple-generic";
+				VERSION_INFO_PREFIX = "";
+				WATCHOS_DEPLOYMENT_TARGET = 4.0;
+			};
+			name = Release;
+		};
+		43CABE081C3506F100005705 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				APPLICATION_EXTENSION_API_ONLY = YES;
+				CLANG_ENABLE_MODULES = YES;
+				CODE_SIGN_IDENTITY = "";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
+				DEFINES_MODULE = YES;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 21;
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
+				INFOPLIST_FILE = CGMBLEKit/Info.plist;
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = ru.artpancreas.cgmblekit;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SKIP_INSTALL = YES;
+				SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
+				SUPPORTS_MACCATALYST = NO;
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Debug;
+		};
+		43CABE091C3506F100005705 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				APPLICATION_EXTENSION_API_ONLY = YES;
+				CLANG_ENABLE_MODULES = YES;
+				CODE_SIGN_IDENTITY = "";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
+				DEFINES_MODULE = YES;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 21;
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
+				INFOPLIST_FILE = CGMBLEKit/Info.plist;
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = ru.artpancreas.cgmblekit;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SKIP_INSTALL = YES;
+				SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
+				SUPPORTS_MACCATALYST = NO;
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		43CABDED1C3506F100005705 /* Build configuration list for PBXProject "CGMBLEKit" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				43CABE051C3506F100005705 /* Debug */,
+				43CABE061C3506F100005705 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		43CABE071C3506F100005705 /* Build configuration list for PBXNativeTarget "CGMBLEKit" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				43CABE081C3506F100005705 /* Debug */,
+				43CABE091C3506F100005705 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 43CABDEA1C3506F100005705 /* Project object */;
+}

+ 7 - 0
Dependencies/CGMBLEKit/CGMBLEKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:">
+   </FileRef>
+</Workspace>

Dependecies/LoopKit/LoopKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist → Dependencies/CGMBLEKit/CGMBLEKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist


Dependecies/LoopKit/LoopKit.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings → Dependencies/CGMBLEKit/CGMBLEKit.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings


+ 67 - 0
Dependencies/CGMBLEKit/CGMBLEKit.xcodeproj/xcshareddata/xcschemes/CGMBLEKit.xcscheme

@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1300"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "43CABDF21C3506F100005705"
+               BuildableName = "CGMBLEKit.framework"
+               BlueprintName = "CGMBLEKit"
+               ReferencedContainer = "container:CGMBLEKit.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "43CABDF21C3506F100005705"
+            BuildableName = "CGMBLEKit.framework"
+            BlueprintName = "CGMBLEKit"
+            ReferencedContainer = "container:CGMBLEKit.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 19 - 0
Dependencies/CGMBLEKit/CGMBLEKit/AESCrypt.h

@@ -0,0 +1,19 @@
+//
+//  AESCrypt.h
+//  xDripG5
+//
+//  Created by Nate Racklyeft on 6/17/16.
+//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface AESCrypt : NSObject
+
+NS_ASSUME_NONNULL_BEGIN
+
++ (nullable NSData *)encryptData:(NSData *)data usingKey:(NSData *)key error:(NSError **)error;
+
+NS_ASSUME_NONNULL_END
+
+@end

+ 33 - 0
Dependencies/CGMBLEKit/CGMBLEKit/AESCrypt.m

@@ -0,0 +1,33 @@
+//
+//  AESCrypt.m
+//  xDripG5
+//
+//  Created by Nate Racklyeft on 6/17/16.
+//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
+//
+
+#import "AESCrypt.h"
+#import <CommonCrypto/CommonCryptor.h>
+
+@implementation AESCrypt
+
++ (NSData *)encryptData:(NSData *)data usingKey:(NSData *)key error:(NSError * _Nullable __autoreleasing *)error
+{
+    NSMutableData *dataOut = [NSMutableData dataWithLength: data.length + kCCBlockSizeAES128];
+
+    CCCryptorStatus status = CCCrypt(kCCEncrypt,
+                                     kCCAlgorithmAES,
+                                     kCCOptionECBMode,
+                                     key.bytes,
+                                     key.length,
+                                     NULL,
+                                     data.bytes,
+                                     data.length,
+                                     dataOut.mutableBytes,
+                                     dataOut.length,
+                                     NULL);
+
+    return status == kCCSuccess ? dataOut : nil;
+}
+
+@end

+ 39 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Base.lproj/Localizable.strings

@@ -0,0 +1,39 @@
+/* CGM display title */
+"Dexcom G5" = "Dexcom G5";
+
+/* CGM display title */
+"Dexcom G6" = "Dexcom G6";
+
+/* Error description for unreliable state */
+"Glucose data is unavailable" = "Glucose data is unavailable";
+
+/* Describes a low battery */
+"Low Battery" = "Low Battery";
+
+/* Describes a functioning transmitter */
+"OK" = "OK";
+
+/* Timeout error description */
+"Peripheral did not respond in time" = "Peripheral did not respond in time";
+
+/* Not ready error description */
+"Peripheral isnʼt connected" = "Peripheral isnʼt connected";
+
+/* The description of sensor calibration state when sensor calibration is ok. */
+"Sensor calibration is OK" = "Sensor calibration is OK";
+
+/* The description of sensor calibration state when raw value is unknown. (1: missing data details) */
+"Sensor is in unknown state %1$d" = "Sensor is in unknown state %1$d";
+
+/* The description of sensor calibration state when sensor sensor is stopped. */
+"Sensor is stopped" = "Sensor is stopped";
+
+/* The description of sensor calibration state when sensor sensor is warming up. */
+"Sensor is warming up" = "Sensor is warming up";
+
+/* The description of sensor calibration state when sensor needs calibration. */
+"Sensor needs calibration" = "Sensor needs calibration";
+
+/* Error description */
+"Unknown characteristic" = "Unknown characteristic";
+

+ 350 - 0
Dependencies/CGMBLEKit/CGMBLEKit/BluetoothManager.swift

@@ -0,0 +1,350 @@
+//
+//  BluetoothManager.swift
+//  xDripG5
+//
+//  Created by Nathan Racklyeft on 10/1/15.
+//  Copyright © 2015 Nathan Racklyeft. All rights reserved.
+//
+
+import CoreBluetooth
+import Foundation
+import os.log
+
+
+protocol BluetoothManagerDelegate: AnyObject {
+
+    /**
+     Tells the delegate that the bluetooth manager has finished connecting to and discovering all required services of its peripheral, or that it failed to do so
+
+     - parameter manager: The bluetooth manager
+     - parameter peripheralManager: The peripheral manager
+     - parameter error:   An error describing why bluetooth setup failed
+     */
+    func bluetoothManager(_ manager: BluetoothManager, peripheralManager: PeripheralManager, isReadyWithError error: Error?)
+
+    /**
+     Asks the delegate whether the discovered or restored peripheral should be connected
+
+     - parameter manager:    The bluetooth manager
+     - parameter peripheral: The found peripheral
+
+     - returns: True if the peripheral should connect
+     */
+    func bluetoothManager(_ manager: BluetoothManager, shouldConnectPeripheral peripheral: CBPeripheral) -> Bool
+
+    /// Informs the delegate that the bluetooth manager received new data in the control characteristic
+    ///
+    /// - Parameters:
+    ///   - manager: The bluetooth manager
+    ///   - peripheralManager: The peripheral manager
+    ///   - response: The data received on the control characteristic
+    func bluetoothManager(_ manager: BluetoothManager, peripheralManager: PeripheralManager, didReceiveControlResponse response: Data)
+
+    /// Informs the delegate that the bluetooth manager received new data in the backfill characteristic
+    ///
+    /// - Parameters:
+    ///   - manager: The bluetooth manager
+    ///   - response: The data received on the backfill characteristic
+    func bluetoothManager(_ manager: BluetoothManager, didReceiveBackfillResponse response: Data)
+
+    /// Informs the delegate that the bluetooth manager received new data in the authentication characteristic
+    ///
+    /// - Parameters:
+    ///   - manager: The bluetooth manager
+    ///   - peripheralManager: The peripheral manager
+    ///   - response: The data received on the authentication characteristic
+    func bluetoothManager(_ manager: BluetoothManager, peripheralManager: PeripheralManager, didReceiveAuthenticationResponse response: Data)
+}
+
+
+class BluetoothManager: NSObject {
+
+    var stayConnected: Bool {
+        get {
+            return lockedStayConnected.value
+        }
+        set {
+            lockedStayConnected.value = newValue
+        }
+    }
+    private let lockedStayConnected: Locked<Bool> = Locked(true)
+
+    weak var delegate: BluetoothManagerDelegate?
+
+    private let log = OSLog(category: "BluetoothManager")
+
+    /// Isolated to `managerQueue`
+    private var manager: CBCentralManager! = nil
+
+    /// Isolated to `managerQueue`
+    private var peripheral: CBPeripheral? {
+        get {
+            return peripheralManager?.peripheral
+        }
+        set {
+            guard let peripheral = newValue else {
+                peripheralManager = nil
+                return
+            }
+
+            if let peripheralManager = peripheralManager {
+                peripheralManager.peripheral = peripheral
+            } else {
+                peripheralManager = PeripheralManager(
+                    peripheral: peripheral,
+                    configuration: .dexcomG5,
+                    centralManager: manager
+                )
+            }
+        }
+    }
+
+    var peripheralIdentifier: UUID? {
+        get {
+            return lockedPeripheralIdentifier.value
+        }
+        set {
+            lockedPeripheralIdentifier.value = newValue
+        }
+    }
+    private let lockedPeripheralIdentifier: Locked<UUID?> = Locked(nil)
+
+    /// Isolated to `managerQueue`
+    private var peripheralManager: PeripheralManager? {
+        didSet {
+            oldValue?.delegate = nil
+            peripheralManager?.delegate = self
+
+            peripheralIdentifier = peripheralManager?.peripheral.identifier
+        }
+    }
+
+    // MARK: - Synchronization
+
+    private let managerQueue = DispatchQueue(label: "com.loudnate.CGMBLEKit.bluetoothManagerQueue", qos: .unspecified)
+
+    override init() {
+        super.init()
+
+        managerQueue.sync {
+            self.manager = CBCentralManager(delegate: self, queue: managerQueue, options: [CBCentralManagerOptionRestoreIdentifierKey: "com.loudnate.CGMBLEKit"])
+        }
+    }
+
+    // MARK: - Actions
+
+    func scanForPeripheral() {
+        dispatchPrecondition(condition: .notOnQueue(managerQueue))
+
+        managerQueue.sync {
+            self.managerQueue_scanForPeripheral()
+        }
+    }
+
+    func disconnect() {
+        dispatchPrecondition(condition: .notOnQueue(managerQueue))
+
+        managerQueue.sync {
+            if manager.isScanning {
+                manager.stopScan()
+            }
+
+            if let peripheral = peripheral {
+                manager.cancelPeripheralConnection(peripheral)
+            }
+        }
+    }
+
+    private func managerQueue_scanForPeripheral() {
+        dispatchPrecondition(condition: .onQueue(managerQueue))
+
+        guard manager.state == .poweredOn else {
+            return
+        }
+
+        let currentState = peripheral?.state ?? .disconnected
+        guard currentState != .connected else {
+            return
+        }
+
+        if let peripheralID = peripheralIdentifier, let peripheral = manager.retrievePeripherals(withIdentifiers: [peripheralID]).first {
+            log.debug("Re-connecting to known peripheral %{public}@", peripheral.identifier.uuidString)
+            self.peripheral = peripheral
+            self.manager.connect(peripheral)
+        } else if let peripheral = manager.retrieveConnectedPeripherals(withServices: [
+                TransmitterServiceUUID.advertisement.cbUUID,
+                TransmitterServiceUUID.cgmService.cbUUID
+            ]).first,
+            delegate == nil || delegate!.bluetoothManager(self, shouldConnectPeripheral: peripheral)
+        {
+            log.debug("Found system-connected peripheral: %{public}@", peripheral.identifier.uuidString)
+            self.peripheral = peripheral
+            self.manager.connect(peripheral)
+        } else {
+            log.debug("Scanning for peripherals")
+            manager.scanForPeripherals(withServices: [
+                    TransmitterServiceUUID.advertisement.cbUUID
+                ],
+                options: nil
+            )
+        }
+    }
+
+    /**
+    
+     Persistent connections don't seem to work with the transmitter shutoff: The OS won't re-wake the
+     app unless it's scanning.
+     
+     The sleep gives the transmitter time to shut down, but keeps the app running.
+
+     */
+    fileprivate func scanAfterDelay() {
+        DispatchQueue.global(qos: .utility).async {
+            Thread.sleep(forTimeInterval: 2)
+
+            self.scanForPeripheral()
+        }
+    }
+
+    // MARK: - Accessors
+
+    var isScanning: Bool {
+        dispatchPrecondition(condition: .notOnQueue(managerQueue))
+
+        var isScanning = false
+        managerQueue.sync {
+            isScanning = manager.isScanning
+        }
+        return isScanning
+    }
+
+    override var debugDescription: String {
+        return [
+            "## BluetoothManager",
+            peripheralManager.map(String.init(reflecting:)) ?? "No peripheral",
+        ].joined(separator: "\n")
+    }
+}
+
+
+extension BluetoothManager: CBCentralManagerDelegate {
+    func centralManagerDidUpdateState(_ central: CBCentralManager) {
+        dispatchPrecondition(condition: .onQueue(managerQueue))
+
+        peripheralManager?.centralManagerDidUpdateState(central)
+        log.default("%{public}@: %{public}@", #function, String(describing: central.state.rawValue))
+
+        switch central.state {
+        case .poweredOn:
+            managerQueue_scanForPeripheral()
+        case .resetting, .poweredOff, .unauthorized, .unknown, .unsupported:
+            fallthrough
+        @unknown default:
+            if central.isScanning {
+                central.stopScan()
+            }
+        }
+    }
+
+    func centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any]) {
+        dispatchPrecondition(condition: .onQueue(managerQueue))
+
+        if let peripherals = dict[CBCentralManagerRestoredStatePeripheralsKey] as? [CBPeripheral] {
+            for peripheral in peripherals {
+                if delegate == nil || delegate!.bluetoothManager(self, shouldConnectPeripheral: peripheral) {
+                    log.default("Restoring peripheral from state: %{public}@", peripheral.identifier.uuidString)
+                    self.peripheral = peripheral
+                }
+            }
+        }
+    }
+
+    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
+        dispatchPrecondition(condition: .onQueue(managerQueue))
+
+        log.info("%{public}@: %{public}@", #function, peripheral)
+        if delegate == nil || delegate!.bluetoothManager(self, shouldConnectPeripheral: peripheral) {
+            self.peripheral = peripheral
+
+            central.connect(peripheral, options: nil)
+
+            central.stopScan()
+        }
+    }
+
+    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
+        dispatchPrecondition(condition: .onQueue(managerQueue))
+
+        log.default("%{public}@: %{public}@", #function, peripheral)
+        if central.isScanning {
+            central.stopScan()
+        }
+
+        peripheralManager?.centralManager(central, didConnect: peripheral)
+
+        if case .poweredOn = manager.state, case .connected = peripheral.state, let peripheralManager = peripheralManager {
+            self.delegate?.bluetoothManager(self, peripheralManager: peripheralManager, isReadyWithError: nil)
+        }
+    }
+
+    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
+        dispatchPrecondition(condition: .onQueue(managerQueue))
+        log.default("%{public}@: %{public}@", #function, peripheral)
+        // Ignore errors indicating the peripheral disconnected remotely, as that's expected behavior
+        if let error = error as NSError?, CBError(_nsError: error).code != .peripheralDisconnected {
+            log.error("%{public}@: %{public}@", #function, error)
+            if let peripheralManager = peripheralManager {
+                self.delegate?.bluetoothManager(self, peripheralManager: peripheralManager, isReadyWithError: error)
+            }
+        }
+
+        if stayConnected {
+            scanAfterDelay()
+        }
+    }
+
+    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
+        dispatchPrecondition(condition: .onQueue(managerQueue))
+
+        log.error("%{public}@: %{public}@", #function, String(describing: error))
+        if let error = error, let peripheralManager = peripheralManager {
+            self.delegate?.bluetoothManager(self, peripheralManager: peripheralManager, isReadyWithError: error)
+        }
+
+        if stayConnected {
+            scanAfterDelay()
+        }
+    }
+}
+
+
+extension BluetoothManager: PeripheralManagerDelegate {
+    func peripheralManager(_ manager: PeripheralManager, didReadRSSI RSSI: NSNumber, error: Error?) {
+        
+    }
+
+    func peripheralManagerDidUpdateName(_ manager: PeripheralManager) {
+
+    }
+
+    func completeConfiguration(for manager: PeripheralManager) throws {
+
+    }
+
+    func peripheralManager(_ manager: PeripheralManager, didUpdateValueFor characteristic: CBCharacteristic) {
+        guard let value = characteristic.value else {
+            return
+        }
+
+        switch CGMServiceCharacteristicUUID(rawValue: characteristic.uuid.uuidString.uppercased()) {
+        case .none, .communication?:
+            return
+        case .control?:
+            self.delegate?.bluetoothManager(self, peripheralManager: manager, didReceiveControlResponse: value)
+        case .backfill?:
+            self.delegate?.bluetoothManager(self, didReceiveBackfillResponse: value)
+        case .authentication?:
+            self.delegate?.bluetoothManager(self, peripheralManager: manager, didReceiveAuthenticationResponse: value)
+        }
+    }
+}

+ 87 - 0
Dependencies/CGMBLEKit/CGMBLEKit/BluetoothServices.swift

@@ -0,0 +1,87 @@
+//
+//  BluetoothServices.swift
+//  xDripG5
+//
+//  Created by Nathan Racklyeft on 10/16/15.
+//  Copyright © 2015 Nathan Racklyeft. All rights reserved.
+//
+
+import CoreBluetooth
+
+/*
+G5 BLE attributes, retrieved using LightBlue on 2015-10-01
+
+These are the G4 details, for reference:
+https://github.com/StephenBlackWasAlreadyTaken/xDrip/blob/af20e32652d19aa40becc1a39f6276cad187fdce/app/src/main/java/com/eveningoutpost/dexdrip/UtilityModels/DexShareAttributes.java
+*/
+
+protocol CBUUIDRawValue: RawRepresentable {}
+extension CBUUIDRawValue where RawValue == String {
+    var cbUUID: CBUUID {
+        return CBUUID(string: rawValue)
+    }
+}
+
+
+enum TransmitterServiceUUID: String, CBUUIDRawValue {
+    case deviceInfo = "180A"
+    case advertisement = "FEBC"
+    case cgmService = "F8083532-849E-531C-C594-30F1F86A4EA5"
+
+    case serviceB = "F8084532-849E-531C-C594-30F1F86A4EA5"
+}
+
+
+enum DeviceInfoCharacteristicUUID: String, CBUUIDRawValue {
+    // Read
+    // "DexcomUN"
+    case manufacturerNameString = "2A29"
+}
+
+
+enum CGMServiceCharacteristicUUID: String, CBUUIDRawValue {
+
+    // Read/Notify
+    case communication = "F8083533-849E-531C-C594-30F1F86A4EA5"
+
+    // Write/Indicate
+    case control = "F8083534-849E-531C-C594-30F1F86A4EA5"
+
+    // Write/Indicate
+    case authentication = "F8083535-849E-531C-C594-30F1F86A4EA5"
+
+    // Read/Write/Notify
+    case backfill = "F8083536-849E-531C-C594-30F1F86A4EA5"
+
+//    // Unknown attribute present on older G6 transmitters
+//    case unknown1 = "F8083537-849E-531C-C594-30F1F86A4EA5"
+//
+//    // Updated G6 characteristic (read/notify)
+//    case unknown2 = "F8083538-849E-531C-C594-30F1F86A4EA5"
+}
+
+
+enum ServiceBCharacteristicUUID: String, CBUUIDRawValue {
+    // Write/Indicate
+    case characteristicE = "F8084533-849E-531C-C594-30F1F86A4EA5"
+    // Read/Write/Notify
+    case characteristicF = "F8084534-849E-531C-C594-30F1F86A4EA5"
+}
+
+
+extension PeripheralManager.Configuration {
+    static var dexcomG5: PeripheralManager.Configuration {
+        return PeripheralManager.Configuration(
+            serviceCharacteristics: [
+                TransmitterServiceUUID.cgmService.cbUUID: [
+                    CGMServiceCharacteristicUUID.communication.cbUUID,
+                    CGMServiceCharacteristicUUID.authentication.cbUUID,
+                    CGMServiceCharacteristicUUID.control.cbUUID,
+                    CGMServiceCharacteristicUUID.backfill.cbUUID,
+                ]
+            ],
+            notifyingCharacteristics: [:],
+            valueUpdateMacros: [:]
+        )
+    }
+}

+ 45 - 0
Dependencies/CGMBLEKit/CGMBLEKit/CBPeripheral.swift

@@ -0,0 +1,45 @@
+//
+//  CBPeripheral.swift
+//  xDripG5
+//
+//  Copyright © 2017 LoopKit Authors. All rights reserved.
+//
+
+import CoreBluetooth
+
+
+// MARK: - Discovery helpers.
+extension CBPeripheral {
+    func servicesToDiscover(from serviceUUIDs: [CBUUID]) -> [CBUUID] {
+        let knownServiceUUIDs = services?.compactMap({ $0.uuid }) ?? []
+        return serviceUUIDs.filter({ !knownServiceUUIDs.contains($0) })
+    }
+
+    func characteristicsToDiscover(from characteristicUUIDs: [CBUUID], for service: CBService) -> [CBUUID] {
+        let knownCharacteristicUUIDs = service.characteristics?.compactMap({ $0.uuid }) ?? []
+        return characteristicUUIDs.filter({ !knownCharacteristicUUIDs.contains($0) })
+    }
+}
+
+
+extension Collection where Element: CBAttribute {
+    func itemWithUUID(_ uuid: CBUUID) -> Element? {
+        for attribute in self {
+            if attribute.uuid == uuid {
+                return attribute
+            }
+        }
+
+        return nil
+    }
+
+    func itemWithUUIDString(_ uuidString: String) -> Element? {
+        for attribute in self {
+            if attribute.uuid.uuidString == uuidString {
+                return attribute
+            }
+        }
+
+        return nil
+    }
+}

+ 17 - 0
Dependencies/CGMBLEKit/CGMBLEKit/CGMBLEKit.h

@@ -0,0 +1,17 @@
+//
+//  CGMBLEKit.h
+//  xDripG5
+//
+//  Created by Nathan Racklyeft on 12/30/15.
+//  Copyright © 2015 Nathan Racklyeft. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <CGMBLEKit/AESCrypt.h>
+
+//! Project version number for CGMBLEKIt.
+FOUNDATION_EXPORT double CGMBLEKitVersionNumber;
+
+//! Project version string for CGMBLEKit.
+FOUNDATION_EXPORT const unsigned char CGMBLEKitVersionString[];
+

+ 27 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Calibration.swift

@@ -0,0 +1,27 @@
+//
+//  Calibration.swift
+//  xDripG5
+//
+//  Created by Paul Dickens on 17/03/2018.
+//  Copyright © 2018 LoopKit Authors. All rights reserved.
+//
+
+import Foundation
+import HealthKit
+
+
+public struct Calibration {
+    init?(calibrationMessage: CalibrationDataRxMessage, activationDate: Date) {
+        guard calibrationMessage.glucose > 0 else {
+            return nil
+        }
+
+        let unit = HKUnit.milligramsPerDeciliter
+
+        glucose = HKQuantity(unit: unit, doubleValue: Double(calibrationMessage.glucose))
+        date = activationDate.addingTimeInterval(TimeInterval(calibrationMessage.timestamp))
+    }
+
+    public let glucose: HKQuantity
+    public let date: Date
+}

+ 106 - 0
Dependencies/CGMBLEKit/CGMBLEKit/CalibrationState.swift

@@ -0,0 +1,106 @@
+//
+//  CalibrationState.swift
+//  xDripG5
+//
+//  Created by Nate Racklyeft on 8/6/16.
+//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
+//
+
+import Foundation
+
+
+public enum CalibrationState: RawRepresentable {
+    public typealias RawValue = UInt8
+
+    public enum State: RawValue {
+        case stopped = 1
+        case warmup = 2
+
+        case needFirstInitialCalibration = 4
+        case needSecondInitialCalibration = 5
+        case ok = 6
+        case needCalibration7 = 7
+        case calibrationError8 = 8
+        case calibrationError9 = 9
+        case calibrationError10 = 10
+        case sensorFailure11 = 11
+        case sensorFailure12 = 12
+        case calibrationError13 = 13
+        case needCalibration14 = 14
+        case sessionFailure15 = 15
+        case sessionFailure16 = 16
+        case sessionFailure17 = 17
+        case questionMarks = 18
+    }
+
+    case known(State)
+    case unknown(RawValue)
+
+    public init(rawValue: RawValue) {
+        guard let state = State(rawValue: rawValue) else {
+            self = .unknown(rawValue)
+            return
+        }
+
+        self = .known(state)
+    }
+
+    public var rawValue: RawValue {
+        switch self {
+        case .known(let state):
+            return state.rawValue
+        case .unknown(let rawValue):
+            return rawValue
+        }
+    }
+
+    public var hasReliableGlucose: Bool {
+        guard case .known(let state) = self else {
+            return false
+        }
+
+        switch state {
+        case .stopped,
+             .warmup,
+             .needFirstInitialCalibration,
+             .needSecondInitialCalibration,
+             .calibrationError8,
+             .calibrationError9,
+             .calibrationError10,
+             .sensorFailure11,
+             .sensorFailure12,
+             .calibrationError13,
+             .sessionFailure15,
+             .sessionFailure16,
+             .sessionFailure17,
+             .questionMarks:
+            return false
+        case .ok, .needCalibration7, .needCalibration14:
+            return true
+        }
+    }
+}
+
+extension CalibrationState: Equatable {
+    public static func ==(lhs: CalibrationState, rhs: CalibrationState) -> Bool {
+        switch (lhs, rhs) {
+        case (.known(let lhs), .known(let rhs)):
+            return lhs == rhs
+        case (.unknown(let lhs), .unknown(let rhs)):
+            return lhs == rhs
+        default:
+            return false
+        }
+    }
+}
+
+extension CalibrationState: CustomStringConvertible {
+    public var description: String {
+        switch self {
+        case .known(let state):
+            return String(describing: state)
+        case .unknown(let value):
+            return ".unknown(\(value))"
+        }
+    }
+}

+ 79 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Command.swift

@@ -0,0 +1,79 @@
+//
+//  Command.swift
+//  xDripG5
+//
+//  Created by Paul Dickens on 22/03/2018.
+//  Copyright © 2018 LoopKit Authors. All rights reserved.
+//
+
+import Foundation
+import HealthKit
+
+
+public enum Command: RawRepresentable {
+    public typealias RawValue = [String: Any]
+
+    case startSensor(at: Date)
+    case stopSensor(at: Date)
+    case calibrateSensor(to: HKQuantity, at: Date)
+    case resetTransmitter
+
+    public init?(rawValue: RawValue) {
+        guard let action = rawValue["action"] as? Action.RawValue else {
+            return nil
+        }
+
+        let date = rawValue["date"] as? Date
+
+        switch Action(rawValue: action) {
+        case .startSensor?:
+            guard let date = date else {
+                return nil
+            }
+            self = .startSensor(at: date)
+        case .stopSensor?:
+            guard let date = date else {
+                return nil
+            }
+            self = .stopSensor(at: date)
+        case .calibrateSensor?:
+            guard let date = date, let glucose = rawValue["glucose"] as? HKQuantity else {
+                return nil
+            }
+            self = .calibrateSensor(to: glucose, at: date)
+        case .resetTransmitter?:
+            self = .resetTransmitter
+        case .none:
+            return nil
+        }
+    }
+
+    private enum Action: Int {
+        case startSensor, stopSensor, calibrateSensor, resetTransmitter
+    }
+
+    public var rawValue: RawValue {
+        switch self {
+        case .startSensor(let date):
+            return [
+                "action": Action.startSensor.rawValue,
+                "date": date
+            ]
+        case .stopSensor(let date):
+            return [
+                "action": Action.stopSensor.rawValue,
+                "date": date
+            ]
+        case .calibrateSensor(let glucose, let date):
+            return [
+                "action": Action.calibrateSensor.rawValue,
+                "date": date,
+                "glucose": glucose
+            ]
+        case .resetTransmitter:
+            return [
+                "action": Action.resetTransmitter.rawValue
+            ]
+        }
+    }
+}

+ 67 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Glucose+SensorDisplayable.swift

@@ -0,0 +1,67 @@
+//
+//  GlucoseRxMessage.swift
+//  Loop
+//
+//  Created by Nathan Racklyeft on 5/30/16.
+//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
+//
+
+import Foundation
+
+
+extension Glucose {
+    public var isStateValid: Bool {
+        return state == .known(.ok) && status == .ok
+    }
+
+    public var stateDescription: String {
+        var messages = [String]()
+
+        switch state {
+        case .known(.ok):
+            break  // Suppress the "OK" message
+        default:
+            messages.append(state.localizedDescription)
+        }
+
+        switch self.status {
+        case .ok:
+            if messages.isEmpty {
+                messages.append(status.localizedDescription)
+            } else {
+                break  // Suppress the "OK" message
+            }
+        case .lowBattery, .unknown:
+            messages.append(status.localizedDescription)
+        }
+
+        return messages.joined(separator: ". ")
+    }
+
+//    public var trendType: GlucoseTrend? {
+//        guard trend < Int(Int8.max) else {
+//            return nil
+//        }
+//
+//        switch trend {
+//        case let x where x <= -30:
+//            return .downDownDown
+//        case let x where x <= -20:
+//            return .downDown
+//        case let x where x <= -10:
+//            return .down
+//        case let x where x < 10:
+//            return .flat
+//        case let x where x < 20:
+//            return .up
+//        case let x where x < 30:
+//            return .upUp
+//        default:
+//            return .upUpUp
+//        }
+//    }
+
+    public var isLocal: Bool {
+        return true
+    }
+}

+ 105 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Glucose.swift

@@ -0,0 +1,105 @@
+//
+//  Glucose.swift
+//  xDripG5
+//
+//  Created by Nate Racklyeft on 8/6/16.
+//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
+//
+
+import Foundation
+import HealthKit
+
+
+public struct Glucose {
+    let glucoseMessage: GlucoseSubMessage
+    let timeMessage: TransmitterTimeRxMessage
+
+    init(
+        transmitterID: String,
+        glucoseMessage: GlucoseRxMessage,
+        timeMessage: TransmitterTimeRxMessage,
+        calibrationMessage: CalibrationDataRxMessage? = nil,
+        activationDate: Date
+    ) {
+        self.init(
+            transmitterID: transmitterID,
+            status: glucoseMessage.status,
+            glucoseMessage: glucoseMessage.glucose,
+            timeMessage: timeMessage,
+            calibrationMessage: calibrationMessage,
+            activationDate: activationDate
+        )
+    }
+
+    init(
+        transmitterID: String,
+        status: UInt8,
+        glucoseMessage: GlucoseSubMessage,
+        timeMessage: TransmitterTimeRxMessage,
+        calibrationMessage: CalibrationDataRxMessage? = nil,
+        activationDate: Date
+    ) {
+        self.transmitterID = transmitterID
+        self.glucoseMessage = glucoseMessage
+        self.timeMessage = timeMessage
+        self.status = TransmitterStatus(rawValue: status)
+        self.activationDate = activationDate
+
+        sessionStartDate = activationDate.addingTimeInterval(TimeInterval(timeMessage.sessionStartTime))
+        readDate = activationDate.addingTimeInterval(TimeInterval(glucoseMessage.timestamp))
+        lastCalibration = calibrationMessage != nil ? Calibration(calibrationMessage: calibrationMessage!, activationDate: activationDate) : nil
+    }
+
+    // MARK: - Transmitter Info
+    public let transmitterID: String
+    public let status: TransmitterStatus
+    public let activationDate: Date
+    public let sessionStartDate: Date
+
+    // MARK: - Glucose Info
+    public let lastCalibration: Calibration?
+    public let readDate: Date
+
+    public var isDisplayOnly: Bool {
+        return glucoseMessage.glucoseIsDisplayOnly
+    }
+
+    public var glucose: HKQuantity? {
+        guard state.hasReliableGlucose && glucoseMessage.glucose >= 39 else { 
+            return nil
+        }
+
+        let unit = HKUnit.milligramsPerDeciliter
+
+        return HKQuantity(unit: unit, doubleValue: Double(glucoseMessage.glucose))
+    }
+
+    public var state: CalibrationState {
+        return CalibrationState(rawValue: glucoseMessage.state)
+    }
+
+    public var trend: Int {
+        return Int(glucoseMessage.trend)
+    }
+
+    public var trendRate: HKQuantity? {
+        guard glucoseMessage.trend < Int8.max && glucoseMessage.trend > Int8.min else {
+            return nil
+        }
+
+        let unit = HKUnit.milligramsPerDeciliterPerMinute
+        return HKQuantity(unit: unit, doubleValue: Double(glucoseMessage.trend) / 10)
+    }
+
+    // An identifier for this reading thatʼs consistent between backfill/live data
+    public var syncIdentifier: String {
+        return "\(transmitterID) \(glucoseMessage.timestamp)"
+    }
+}
+
+
+extension Glucose: Equatable {
+    public static func ==(lhs: Glucose, rhs: Glucose) -> Bool {
+        return lhs.glucoseMessage == rhs.glucoseMessage && lhs.syncIdentifier == rhs.syncIdentifier
+    }
+}

+ 26 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Info.plist

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>FMWK</string>
+	<key>CFBundleShortVersionString</key>
+	<string>3.2</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>$(CURRENT_PROJECT_VERSION)</string>
+	<key>NSPrincipalClass</key>
+	<string></string>
+</dict>
+</plist>

+ 28 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/AuthChallengeRxMessage.swift

@@ -0,0 +1,28 @@
+//
+//  AuthChallengeRxMessage.swift
+//  xDrip5
+//
+//  Created by Nathan Racklyeft on 11/22/15.
+//  Copyright © 2015 Nathan Racklyeft. All rights reserved.
+//
+
+import Foundation
+
+
+struct AuthChallengeRxMessage: TransmitterRxMessage {
+    let isAuthenticated: Bool
+    let isBonded: Bool
+
+    init?(data: Data) {
+        guard data.count >= 3 else {
+            return nil
+        }
+
+        guard data.starts(with: .authChallengeRx) else {
+            return nil
+        }
+
+        isAuthenticated = data[1] == 0x1
+        isBonded = data[2] == 0x1
+    }
+}

+ 20 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/AuthChallengeTxMessage.swift

@@ -0,0 +1,20 @@
+//
+//  AuthChallengeTxMessage.swift
+//  xDrip5
+//
+//  Created by Nathan Racklyeft on 11/22/15.
+//  Copyright © 2015 Nathan Racklyeft. All rights reserved.
+//
+
+import Foundation
+
+
+struct AuthChallengeTxMessage: TransmitterTxMessage {
+    let challengeHash: Data
+
+    var data: Data {
+        var data = Data(for: .authChallengeTx)
+        data.append(challengeHash)
+        return data
+    }
+}

+ 28 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/AuthRequestRxMessage.swift

@@ -0,0 +1,28 @@
+//
+//  AuthRequestRxMessage.swift
+//  xDrip5
+//
+//  Created by Nathan Racklyeft on 11/22/15.
+//  Copyright © 2015 Nathan Racklyeft. All rights reserved.
+//
+
+import Foundation
+
+
+struct AuthRequestRxMessage: TransmitterRxMessage {
+    let tokenHash: Data
+    let challenge: Data
+
+    init?(data: Data) {
+        guard data.count >= 17 else {
+            return nil
+        }
+
+        guard data.starts(with: .authRequestRx) else {
+            return nil
+        }
+
+        tokenHash = data.subdata(in: 1..<9)
+        challenge = data.subdata(in: 9..<17)
+    }
+}

+ 29 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/AuthRequestTxMessage.swift

@@ -0,0 +1,29 @@
+//
+//  AuthRequestTxMessage.swift
+//  xDrip5
+//
+//  Created by Nathan Racklyeft on 11/22/15.
+//  Copyright © 2015 Nathan Racklyeft. All rights reserved.
+//
+
+import Foundation
+
+
+struct AuthRequestTxMessage: TransmitterTxMessage {
+    let singleUseToken: Data
+    let endByte: UInt8 = 0x2
+
+    init() {
+        let uuid = UUID().uuid
+
+        singleUseToken = Data([uuid.0, uuid.1, uuid.2, uuid.3,
+                               uuid.4, uuid.5, uuid.6, uuid.7])
+    }
+
+    var data: Data {
+        var data = Data(for: .authRequestTx)
+        data.append(singleUseToken)
+        data.append(endByte)
+        return data
+    }
+}

+ 16 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/BatteryStatusTxMessage.swift

@@ -0,0 +1,16 @@
+//
+//  BatteryStatusTxMessage.swift
+//  xDripG5
+//
+//  Created by Nathan Racklyeft on 3/26/16.
+//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
+//
+
+import Foundation
+
+
+struct BatteryStatusTxMessage {
+    let opcode: Opcode = .batteryStatusTx
+
+    // Response: 23003c012f01cd021f247bae
+}

+ 17 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/BondRequestTxMessage.swift

@@ -0,0 +1,17 @@
+//
+//  BondRequestTxMessage.swift
+//  xDrip5
+//
+//  Created by Nathan Racklyeft on 11/23/15.
+//  Copyright © 2015 Nathan Racklyeft. All rights reserved.
+//
+
+import Foundation
+
+
+/// Initiates a bond with the central
+struct BondRequestTxMessage: TransmitterTxMessage {
+    var data: Data {
+        return Data(for: .bondRequest)
+    }
+}

+ 22 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/CalibrateGlucoseRxMessage.swift

@@ -0,0 +1,22 @@
+//
+//  CalibrateGlucoseRxMessage.swift
+//  xDripG5
+//
+//  Created by Paul Dickens on 25/02/2018.
+//  Copyright © 2018 LoopKit Authors. All rights reserved.
+//
+
+import Foundation
+
+
+public struct CalibrateGlucoseRxMessage: TransmitterRxMessage {
+    init?(data: Data) {
+        guard data.count == 5 && data.isCRCValid else {
+            return nil
+        }
+
+        guard data.starts(with: .calibrateGlucoseRx) else {
+            return nil
+        }
+    }
+}

+ 24 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/CalibrateGlucoseTxMessage.swift

@@ -0,0 +1,24 @@
+//
+//  CalibrateGlucoseTxMessage.swift
+//  xDripG5
+//
+//  Created by Nathan Racklyeft on 3/26/16.
+//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
+//
+
+import Foundation
+
+
+struct CalibrateGlucoseTxMessage: RespondableMessage {
+    typealias Response = CalibrateGlucoseRxMessage
+
+    let time: UInt32
+    let glucose: UInt16
+
+    var data: Data {
+        var data = Data(for: .calibrateGlucoseTx)
+        data.append(glucose)
+        data.append(time)
+        return data.appendingCRC()
+    }
+}

+ 28 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/CalibrationDataRxMessage.swift

@@ -0,0 +1,28 @@
+//
+//  CalibrationDataRxMessage.swift
+//  Pods
+//
+//  Created by Nate Racklyeft on 9/18/16.
+//
+//
+
+import Foundation
+
+
+struct CalibrationDataRxMessage: TransmitterRxMessage {
+    let glucose: UInt16
+    let timestamp: UInt32
+
+    init?(data: Data) {
+        guard data.count == 19 && data.isCRCValid else {
+            return nil
+        }
+
+        guard data.starts(with: .calibrationDataRx) else {
+            return nil
+        }
+
+        glucose = data[11..<13].toInt() & 0xfff
+        timestamp = data[13..<17].toInt()
+    }
+}

+ 18 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/CalibrationDataTxMessage.swift

@@ -0,0 +1,18 @@
+//
+//  CalibrationDataTxMessage.swift
+//  xDripG5
+//
+//  Created by Paul Dickens on 17/03/2018.
+//  Copyright © 2018 LoopKit Authors. All rights reserved.
+//
+
+import Foundation
+
+
+struct CalibrationDataTxMessage: RespondableMessage {
+    typealias Response = CalibrationDataRxMessage
+
+    var data: Data {
+        return Data(for: .calibrationDataTx).appendingCRC()
+    }
+}

+ 16 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/DisconnectTxMessage.swift

@@ -0,0 +1,16 @@
+//
+//  DisconnectTxMessage.swift
+//  xDrip5
+//
+//  Created by Nathan Racklyeft on 11/23/15.
+//  Copyright © 2015 Nathan Racklyeft. All rights reserved.
+//
+
+import Foundation
+
+
+struct DisconnectTxMessage: TransmitterTxMessage {
+    var data: Data {
+        return Data(for: .disconnectTx)
+    }
+}

+ 14 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/FirmwareVersionTxMessage.swift

@@ -0,0 +1,14 @@
+//
+//  FirmwareVersionTxMessage.swift
+//  xDripG5
+//
+//  Created by Nathan Racklyeft on 3/26/16.
+//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
+//
+
+import Foundation
+
+
+struct FirmwareVersionTxMessage {
+    let opcode: Opcode = .firmwareVersionTx
+}

+ 122 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/GlucoseBackfillMessage.swift

@@ -0,0 +1,122 @@
+//
+//  GlucoseBackfillMessage.swift
+//  xDripG5
+//
+//  Copyright © 2018 LoopKit Authors. All rights reserved.
+//
+
+import Foundation
+
+// 50 05 02 00 b7ff5200 66045300 00000000 0000 7138
+
+struct GlucoseBackfillTxMessage: RespondableMessage {
+    typealias Response = GlucoseBackfillRxMessage
+
+    let byte1: UInt8
+    let byte2: UInt8
+    let identifier: UInt8
+
+    let startTime: UInt32
+    let endTime: UInt32
+
+    let length: UInt32 = 0
+    let backfillCRC: UInt16 = 0
+
+    var data: Data {
+        var data = Data(for: .glucoseBackfillTx)
+        data.append(contentsOf: [byte1, byte2, identifier])
+        data.append(startTime)
+        data.append(endTime)
+        data.append(length)
+        data.append(backfillCRC)
+
+        return data.appendingCRC()
+    }
+}
+
+// 51 00 01 00 b7ff5200 66045300 32000000 e6cb 9805
+
+struct GlucoseBackfillRxMessage: TransmitterRxMessage {
+    let status: UInt8
+    let backfillStatus: UInt8
+    let identifier: UInt8
+    let startTime: UInt32
+    let endTime: UInt32
+    let bufferLength: UInt32
+    let bufferCRC: UInt16
+
+    init?(data: Data) {
+        guard data.count == 20,
+            data.isCRCValid,
+            data.starts(with: .glucoseBackfillRx)
+        else {
+            return nil
+        }
+
+        status = data[1]
+        backfillStatus = data[2]
+        identifier = data[3]
+        startTime = data[4..<8].toInt()
+        endTime = data[8..<12].toInt()
+        bufferLength = data[12..<16].toInt()
+        bufferCRC = data[16..<18].toInt()
+    }
+}
+
+// 0100bc460000b7ff52008b0006eee30053008500
+// 020006eb0f025300800006ee3a0353007e0006f5
+// 030066045300790006f8
+
+struct GlucoseBackfillFrameBuffer {
+    let identifier: UInt8
+    private var frames: [Data] = []
+
+    init(identifier: UInt8) {
+        self.identifier = identifier
+    }
+
+    mutating func append(_ frame: Data) {
+        // Byte 0 is the frame index
+        // Byte 1 is the identifier
+        guard frame.count > 2,
+            frame[0] == frames.count + 1,
+            frame[1] == identifier else {
+            return
+        }
+
+        frames.append(frame)
+    }
+
+    var count: Int {
+        return frames.reduce(0, { $0 + $1.count })
+    }
+
+    var crc16: UInt16 {
+        return frames.reduce(into: Data(), { $0.append($1) }).crc16
+    }
+
+    var glucose: [GlucoseSubMessage] {
+        // Drop the first 2 bytes from each frame
+        let data = frames.reduce(into: Data(), { $0.append($1.dropFirst(2)) })
+
+        // Drop the first 4 bytes from the combined message
+        // Byte 0: ??
+        // Byte 1: ??
+        // Byte 2: ?? (only seen 0 so far)
+        // Byte 3: ?? (only seen 0 so far)
+        let glucoseData = data.dropFirst(4)
+
+        return stride(
+            from: glucoseData.startIndex,
+            to: glucoseData.endIndex,
+            by: GlucoseSubMessage.size
+        ).compactMap {
+            let range = $0..<$0.advanced(by: GlucoseSubMessage.size)
+            guard glucoseData.endIndex >= range.endIndex else {
+                return nil
+            }
+
+            return GlucoseSubMessage(data: glucoseData[range])
+        }
+    }
+}

+ 14 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/GlucoseHistoryTxMessage.swift

@@ -0,0 +1,14 @@
+//
+//  GlucoseHistoryTxMessage.swift
+//  xDripG5
+//
+//  Created by Nathan Racklyeft on 3/26/16.
+//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
+//
+
+import Foundation
+
+
+struct GlucoseHistoryTxMessage {
+    let opcode: Opcode = .glucoseHistoryTx
+}

+ 88 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/GlucoseRxMessage.swift

@@ -0,0 +1,88 @@
+//
+//  GlucoseRxMessage.swift
+//  xDrip5
+//
+//  Created by Nathan Racklyeft on 11/23/15.
+//  Copyright © 2015 Nathan Racklyeft. All rights reserved.
+//
+
+import Foundation
+
+
+public struct GlucoseSubMessage: TransmitterRxMessage {
+    static let size = 8
+
+    public let timestamp: UInt32
+    public let glucoseIsDisplayOnly: Bool
+    public let glucose: UInt16
+    public let state: UInt8
+    public let trend: Int8
+
+    init?(data: Data) {
+        guard data.count >= GlucoseSubMessage.size else {
+            return nil
+        }
+
+        var start = data.startIndex
+        var end = start.advanced(by: 4)
+        timestamp = data[start..<end].toInt()
+
+        start = end
+        end = start.advanced(by: 2)
+        let glucoseBytes = data[start..<end].to(UInt16.self)
+        glucoseIsDisplayOnly = (glucoseBytes & 0xf000) > 0
+        glucose = glucoseBytes & 0xfff
+
+        start = end
+        end = start.advanced(by: 1)
+        state = data[start]
+
+        start = end
+        end = start.advanced(by: 1)
+        trend = Int8(bitPattern: data[start])
+    }
+}
+
+
+public struct GlucoseRxMessage: TransmitterRxMessage {
+    public let status: UInt8
+    public let sequence: UInt32
+    public let glucose: GlucoseSubMessage
+
+    init?(data: Data) {
+        guard data.count >= 16 && data.isCRCValid else {
+            return nil
+        }
+
+        guard data.starts(with: .glucoseRx) || data.starts(with: .glucoseG6Rx) else {
+            return nil
+        }
+
+        status = data[1]
+        sequence = data[2..<6].toInt()
+
+        guard let glucose = GlucoseSubMessage(data: data[6...]) else {
+            return nil
+        }
+        self.glucose = glucose
+    }
+}
+
+extension GlucoseSubMessage: Equatable {
+    public static func ==(lhs: GlucoseSubMessage, rhs: GlucoseSubMessage) -> Bool {
+        return lhs.timestamp == rhs.timestamp &&
+            lhs.glucoseIsDisplayOnly == rhs.glucoseIsDisplayOnly &&
+            lhs.glucose == rhs.glucose &&
+            lhs.state == rhs.state &&
+            lhs.trend == rhs.trend
+    }
+}
+
+
+extension GlucoseRxMessage: Equatable {
+    public static func ==(lhs: GlucoseRxMessage, rhs: GlucoseRxMessage) -> Bool {
+        return lhs.status == rhs.status &&
+            lhs.sequence == rhs.sequence &&
+            lhs.glucose == rhs.glucose
+    }
+}

+ 18 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/GlucoseTxMessage.swift

@@ -0,0 +1,18 @@
+//
+//  GlucoseTxMessage.swift
+//  xDrip5
+//
+//  Created by Nathan Racklyeft on 11/23/15.
+//  Copyright © 2015 Nathan Racklyeft. All rights reserved.
+//
+
+import Foundation
+
+
+struct GlucoseTxMessage: RespondableMessage {
+    typealias Response = GlucoseRxMessage
+
+    var data: Data {
+        return Data(for: .glucoseTx).appendingCRC()
+    }
+}

+ 20 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/KeepAliveTxMessage.swift

@@ -0,0 +1,20 @@
+//
+//  KeepAliveTxMessage.swift
+//  xDrip5
+//
+//  Created by Nathan Racklyeft on 11/23/15.
+//  Copyright © 2015 Nathan Racklyeft. All rights reserved.
+//
+
+import Foundation
+
+
+struct KeepAliveTxMessage: TransmitterTxMessage {
+    let time: UInt8
+
+    var data: Data {
+        var data = Data(for: .keepAlive)
+        data.append(time)
+        return data
+    }
+}

+ 30 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/ResetMessage.swift

@@ -0,0 +1,30 @@
+//
+//  ResetMessage.swift
+//  xDripG5
+//
+//  Copyright © 2018 LoopKit Authors. All rights reserved.
+//
+
+import Foundation
+
+
+struct ResetTxMessage: RespondableMessage {
+    typealias Response = ResetRxMessage
+
+    var data: Data {
+        return Data(for: .resetTx).appendingCRC()
+    }
+}
+
+
+struct ResetRxMessage: TransmitterRxMessage {
+    let status: UInt8
+
+    init?(data: Data) {
+        guard data.count >= 2, data.starts(with: .resetRx) else {
+            return nil
+        }
+
+        status = data[1]
+    }
+}

+ 37 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/SessionStartRxMessage.swift

@@ -0,0 +1,37 @@
+//
+//  SessionStartRxMessage.swift
+//  xDripG5
+//
+//  Created by Nathan Racklyeft on 6/4/16.
+//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
+//
+
+import Foundation
+
+
+struct SessionStartRxMessage: TransmitterRxMessage {
+    let status: UInt8
+    let received: UInt8
+
+    // I've only seen examples of these 2 values matching
+    let requestedStartTime: UInt32
+    let sessionStartTime: UInt32
+
+    let transmitterTime: UInt32
+
+    init?(data: Data) {
+        guard data.count == 17 && data.isCRCValid else {
+            return nil
+        }
+
+        guard data.starts(with: .sessionStartRx) else {
+            return nil
+        }
+
+        status = data[1]
+        received = data[2]
+        requestedStartTime = data[3..<7].toInt()
+        sessionStartTime = data[7..<11].toInt()
+        transmitterTime = data[11..<15].toInt()
+    }
+}

+ 27 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/SessionStartTxMessage.swift

@@ -0,0 +1,27 @@
+//
+//  SessionStartTxMessage.swift
+//  xDripG5
+//
+//  Created by Nathan Racklyeft on 3/26/16.
+//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
+//
+
+import Foundation
+
+
+struct SessionStartTxMessage: RespondableMessage {
+    typealias Response = SessionStartRxMessage
+
+    /// Time since activation in Dex seconds
+    let startTime: UInt32
+
+    /// Time in seconds since Unix Epoch
+    let secondsSince1970: UInt32
+
+    var data: Data {
+        var data = Data(for: .sessionStartTx)
+        data.append(startTime)
+        data.append(secondsSince1970)
+        return data.appendingCRC()
+    }
+}

+ 0 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Messages/SessionStopRxMessage.swift


Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov