diff --git a/MinimedKit/Info.plist b/MinimedKit/Info.plist
index 425ef70fb..5d7827c27 100644
--- a/MinimedKit/Info.plist
+++ b/MinimedKit/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- 0.7.1
+ 0.8.0
CFBundleSignature
????
CFBundleVersion
diff --git a/MinimedKit/MessageType.swift b/MinimedKit/MessageType.swift
index a4df84169..7d4915860 100644
--- a/MinimedKit/MessageType.swift
+++ b/MinimedKit/MessageType.swift
@@ -28,6 +28,7 @@ public enum MessageType: UInt8 {
case GetPumpModel = 0x8d
case ReadTempBasal = 0x98
case ReadSettings = 0xc0
+ case ReadPumpStatus = 0xce
var bodyType: MessageBody.Type {
switch self {
@@ -59,6 +60,8 @@ public enum MessageType: UInt8 {
return GetBatteryCarelinkMessageBody.self
case .ReadRemainingInsulin:
return ReadRemainingInsulinMessageBody.self
+ case .ReadPumpStatus:
+ return ReadPumpStatusMessageBody.self
default:
return UnknownMessageBody.self
}
diff --git a/MinimedKit/Messages/GetBatteryCarelinkMessageBody.swift b/MinimedKit/Messages/GetBatteryCarelinkMessageBody.swift
index 681633019..a8dd6f8ff 100644
--- a/MinimedKit/Messages/GetBatteryCarelinkMessageBody.swift
+++ b/MinimedKit/Messages/GetBatteryCarelinkMessageBody.swift
@@ -8,25 +8,37 @@
import Foundation
+public enum BatteryStatus {
+ case Low
+ case Normal
+ case Unknown(rawVal: UInt8)
+
+ init(statusByte: UInt8) {
+ switch statusByte {
+ case 1:
+ self = .Low
+ case 0:
+ self = .Normal
+ default:
+ self = .Unknown(rawVal: statusByte)
+ }
+ }
+}
+
public class GetBatteryCarelinkMessageBody: CarelinkLongMessageBody {
- public let status: String
+ public let status: BatteryStatus
public let volts: Double
public required init?(rxData: NSData) {
guard rxData.length == self.dynamicType.length else {
- status = ""
volts = 0
+ status = .Unknown(rawVal: 0)
super.init(rxData: rxData)
return nil
}
volts = Double(Int(rxData[2] as UInt8) << 8 + Int(rxData[3] as UInt8)) / 100.0
-
- if rxData[1] as UInt8 > 0 {
- status = "Low"
- } else {
- status = "Normal"
- }
+ status = BatteryStatus(statusByte: rxData[1] as UInt8)
super.init(rxData: rxData)
}
diff --git a/MinimedKit/Messages/ReadPumpStatusMessageBody.swift b/MinimedKit/Messages/ReadPumpStatusMessageBody.swift
new file mode 100644
index 000000000..7ab72f975
--- /dev/null
+++ b/MinimedKit/Messages/ReadPumpStatusMessageBody.swift
@@ -0,0 +1,27 @@
+//
+// ReadPumpStatusMessageBody.swift
+// RileyLink
+//
+// Created by Pete Schwamb on 7/31/16.
+// Copyright © 2016 Pete Schwamb. All rights reserved.
+//
+
+import Foundation
+
+public class ReadPumpStatusMessageBody: CarelinkLongMessageBody {
+
+ public let bolusing: Bool
+ public let suspended: Bool
+
+ public required init?(rxData: NSData) {
+ guard rxData.length == self.dynamicType.length else {
+ return nil
+ }
+
+ bolusing = (rxData[2] as UInt8) > 0
+ suspended = (rxData[3] as UInt8) > 0
+
+ super.init(rxData: rxData)
+ }
+
+}
diff --git a/MinimedKit/Messages/ReadRemainingInsulinMessageBody.swift b/MinimedKit/Messages/ReadRemainingInsulinMessageBody.swift
index 35af7dff3..f5ec46ae6 100644
--- a/MinimedKit/Messages/ReadRemainingInsulinMessageBody.swift
+++ b/MinimedKit/Messages/ReadRemainingInsulinMessageBody.swift
@@ -6,7 +6,7 @@
// Copyright © 2016 Pete Schwamb. All rights reserved.
//
-import UIKit
+import Foundation
public class ReadRemainingInsulinMessageBody: CarelinkLongMessageBody {
diff --git a/MinimedKit/PumpEventType.swift b/MinimedKit/PumpEventType.swift
index 722b72c48..5c7579d96 100644
--- a/MinimedKit/PumpEventType.swift
+++ b/MinimedKit/PumpEventType.swift
@@ -69,7 +69,7 @@ public enum PumpEventType: UInt8 {
case DeleteOtherDeviceID = 0x82
case ChangeCaptureEventEnable = 0x83
- var eventType: PumpEvent.Type {
+ public var eventType: PumpEvent.Type {
switch self {
case .BolusNormal:
return BolusNormalPumpEvent.self
diff --git a/MinimedKit/PumpEvents/ChangeTimePumpEvent.swift b/MinimedKit/PumpEvents/ChangeTimePumpEvent.swift
index 8126dbf5a..99ebb210a 100644
--- a/MinimedKit/PumpEvents/ChangeTimePumpEvent.swift
+++ b/MinimedKit/PumpEvents/ChangeTimePumpEvent.swift
@@ -30,7 +30,7 @@ public struct ChangeTimePumpEvent: TimestampedPumpEvent {
oldTimestamp = NSDateComponents(pumpEventData: availableData, offset: 2)
timestamp = NSDateComponents(pumpEventData: availableData, offset: 9)
}
-
+
public var dictionaryRepresentation: [String: AnyObject] {
return [
"_type": "ChangeTime",
diff --git a/MinimedKit/PumpEvents/PumpAlarmPumpEvent.swift b/MinimedKit/PumpEvents/PumpAlarmPumpEvent.swift
index b4d47f5e7..72b87b9fd 100644
--- a/MinimedKit/PumpEvents/PumpAlarmPumpEvent.swift
+++ b/MinimedKit/PumpEvents/PumpAlarmPumpEvent.swift
@@ -8,12 +8,41 @@
import Foundation
+public enum PumpAlarmType {
+ case BatteryOutLimitExceeded
+ case NoDelivery
+ case BatteryDepleted
+ case DeviceReset
+ case ReprogramError
+ case EmptyReservoir
+ case UnknownType(rawType: UInt8)
+
+ init(rawType: UInt8) {
+ switch rawType {
+ case 3:
+ self = .BatteryOutLimitExceeded
+ case 4:
+ self = .NoDelivery
+ case 5:
+ self = .BatteryDepleted
+ case 16:
+ self = .DeviceReset
+ case 61:
+ self = .ReprogramError
+ case 62:
+ self = .EmptyReservoir
+ default:
+ self = .UnknownType(rawType: rawType)
+ }
+ }
+}
+
public struct PumpAlarmPumpEvent: TimestampedPumpEvent {
public let length: Int
public let rawData: NSData
public let timestamp: NSDateComponents
- let rawType: Int
-
+ public let alarmType: PumpAlarmType
+
public init?(availableData: NSData, pumpModel: PumpModel) {
length = 9
@@ -23,14 +52,16 @@ public struct PumpAlarmPumpEvent: TimestampedPumpEvent {
rawData = availableData[0..CFBundlePackageType
BNDL
CFBundleShortVersionString
- 0.7.1
+ 0.8.0
CFBundleSignature
????
CFBundleVersion
diff --git a/NightscoutUploadKit/DeviceStatus/BatteryStatus.swift b/NightscoutUploadKit/DeviceStatus/BatteryStatus.swift
new file mode 100644
index 000000000..3cfda095f
--- /dev/null
+++ b/NightscoutUploadKit/DeviceStatus/BatteryStatus.swift
@@ -0,0 +1,43 @@
+//
+// BatteryStatus.swift
+// RileyLink
+//
+// Created by Pete Schwamb on 7/28/16.
+// Copyright © 2016 Pete Schwamb. All rights reserved.
+//
+
+import Foundation
+
+public enum BatteryIndicator: String {
+ case Low = "low"
+ case Normal = "normal"
+}
+
+public struct BatteryStatus {
+ let percent: Int?
+ let voltage: Double?
+ let status: BatteryIndicator?
+
+ public init(percent: Int? = nil, voltage: Double? = nil, status: BatteryIndicator? = nil) {
+ self.percent = percent
+ self.voltage = voltage
+ self.status = status
+ }
+
+ public var dictionaryRepresentation: [String: AnyObject] {
+ var rval = [String: AnyObject]()
+
+ if let percent = percent {
+ rval["percent"] = percent
+ }
+ if let voltage = voltage {
+ rval["voltage"] = voltage
+ }
+
+ if let status = status {
+ rval["status"] = status.rawValue
+ }
+
+ return rval
+ }
+}
\ No newline at end of file
diff --git a/NightscoutUploadKit/DeviceStatus/COBStatus.swift b/NightscoutUploadKit/DeviceStatus/COBStatus.swift
new file mode 100644
index 000000000..496b9c99d
--- /dev/null
+++ b/NightscoutUploadKit/DeviceStatus/COBStatus.swift
@@ -0,0 +1,30 @@
+//
+// COBStatus.swift
+// RileyLink
+//
+// Created by Pete Schwamb on 8/2/16.
+// Copyright © 2016 Pete Schwamb. All rights reserved.
+//
+
+import Foundation
+
+public struct COBStatus {
+ let cob: Double
+ let timestamp: NSDate
+
+ public init(cob: Double, timestamp: NSDate) {
+ self.cob = cob // grams
+ self.timestamp = timestamp
+ }
+
+ public var dictionaryRepresentation: [String: AnyObject] {
+
+ var rval = [String: AnyObject]()
+
+ rval["timestamp"] = TimeFormat.timestampStrFromDate(timestamp)
+ rval["cob"] = cob
+
+ return rval
+ }
+
+}
\ No newline at end of file
diff --git a/NightscoutUploadKit/DeviceStatus/DeviceStatus.swift b/NightscoutUploadKit/DeviceStatus/DeviceStatus.swift
new file mode 100644
index 000000000..a0c8fc66b
--- /dev/null
+++ b/NightscoutUploadKit/DeviceStatus/DeviceStatus.swift
@@ -0,0 +1,48 @@
+//
+// DeviceStatus.swift
+// RileyLink
+//
+// Created by Pete Schwamb on 7/26/16.
+// Copyright © 2016 Pete Schwamb. All rights reserved.
+//
+
+import Foundation
+
+public struct DeviceStatus {
+ let device: String
+ let timestamp: NSDate
+ let pumpStatus: PumpStatus?
+ let uploaderStatus: UploaderStatus?
+ let loopStatus: LoopStatus?
+
+ public init(device: String, timestamp: NSDate, pumpStatus: PumpStatus? = nil, uploaderStatus: UploaderStatus? = nil, loopStatus: LoopStatus? = nil) {
+ self.device = device
+ self.timestamp = timestamp
+ self.pumpStatus = pumpStatus
+ self.uploaderStatus = uploaderStatus
+ self.loopStatus = loopStatus
+ }
+
+ public var dictionaryRepresentation: [String: AnyObject] {
+ var rval = [String: AnyObject]()
+
+ rval["device"] = device
+ rval["created_at"] = TimeFormat.timestampStrFromDate(timestamp)
+
+ if let pump = pumpStatus {
+ rval["pump"] = pump.dictionaryRepresentation
+ }
+
+ if let uploader = uploaderStatus {
+ rval["uploader"] = uploader.dictionaryRepresentation
+ }
+
+ if let loop = loopStatus {
+ // Would like to change this to avoid confusion about whether or not this was uploaded from Loop or openaps
+ rval["openaps"] = loop.dictionaryRepresentation
+ }
+
+ return rval
+ }
+}
+
diff --git a/NightscoutUploadKit/DeviceStatus/IOBStatus.swift b/NightscoutUploadKit/DeviceStatus/IOBStatus.swift
new file mode 100644
index 000000000..8e42dee32
--- /dev/null
+++ b/NightscoutUploadKit/DeviceStatus/IOBStatus.swift
@@ -0,0 +1,38 @@
+//
+// IOBStatus.swift
+// RileyLink
+//
+// Created by Pete Schwamb on 7/28/16.
+// Copyright © 2016 Pete Schwamb. All rights reserved.
+//
+
+import Foundation
+
+public struct IOBStatus {
+ let timestamp: NSDate
+ let iob: Double? // basal iob + bolus iob: can be negative
+ let basalIOB: Double? // does not include bolus iob
+
+ public init(timestamp: NSDate, iob: Double? = nil, basalIOB: Double? = nil) {
+ self.timestamp = timestamp
+ self.iob = iob
+ self.basalIOB = basalIOB
+ }
+
+ public var dictionaryRepresentation: [String: AnyObject] {
+
+ var rval = [String: AnyObject]()
+
+ rval["timestamp"] = TimeFormat.timestampStrFromDate(timestamp)
+
+ if let iob = iob {
+ rval["iob"] = iob
+ }
+
+ if let basalIOB = basalIOB {
+ rval["basaliob"] = basalIOB
+ }
+
+ return rval
+ }
+}
\ No newline at end of file
diff --git a/NightscoutUploadKit/DeviceStatus/LoopEnacted.swift b/NightscoutUploadKit/DeviceStatus/LoopEnacted.swift
new file mode 100644
index 000000000..606c902fc
--- /dev/null
+++ b/NightscoutUploadKit/DeviceStatus/LoopEnacted.swift
@@ -0,0 +1,32 @@
+//
+// LoopEnacted.swift
+// RileyLink
+//
+// Created by Pete Schwamb on 7/28/16.
+// Copyright © 2016 Pete Schwamb. All rights reserved.
+//
+
+import Foundation
+
+public struct LoopEnacted {
+ let rate: Double
+ let duration: NSTimeInterval
+ let timestamp: NSDate
+ let received: Bool
+
+ public init(rate: Double, duration: NSTimeInterval, timestamp: NSDate, received: Bool) {
+ self.rate = rate
+ self.duration = duration
+ self.timestamp = timestamp
+ self.received = received
+ }
+
+ public var dictionaryRepresentation: [String: AnyObject] {
+ return [
+ "rate": rate,
+ "duration": duration / 60.0,
+ "timestamp": TimeFormat.timestampStrFromDate(timestamp),
+ "recieved": received // [sic]
+ ]
+ }
+}
\ No newline at end of file
diff --git a/NightscoutUploadKit/DeviceStatus/LoopStatus.swift b/NightscoutUploadKit/DeviceStatus/LoopStatus.swift
new file mode 100644
index 000000000..f97e20de0
--- /dev/null
+++ b/NightscoutUploadKit/DeviceStatus/LoopStatus.swift
@@ -0,0 +1,57 @@
+//
+// LoopStatus.swift
+// RileyLink
+//
+// Created by Pete Schwamb on 7/26/16.
+// Copyright © 2016 Pete Schwamb. All rights reserved.
+//
+
+import Foundation
+
+public struct LoopStatus {
+ let name: String
+ let timestamp: NSDate
+
+ let iob: IOBStatus?
+ let cob: COBStatus?
+ let suggested: LoopSuggested?
+ let enacted: LoopEnacted?
+
+ let failureReason: String?
+
+ public init(name: String, timestamp: NSDate, glucose: Int? = nil, iob: IOBStatus? = nil, cob: COBStatus? = nil, suggested: LoopSuggested? = nil, enacted: LoopEnacted?, failureReason: String? = nil) {
+ self.name = name
+ self.timestamp = timestamp
+ self.suggested = suggested
+ self.enacted = enacted
+ self.iob = iob
+ self.cob = cob
+ self.failureReason = failureReason
+ }
+
+ public var dictionaryRepresentation: [String: AnyObject] {
+ var rval = [String: AnyObject]()
+
+ rval["name"] = name
+ rval["timestamp"] = TimeFormat.timestampStrFromDate(timestamp)
+
+ if let suggested = suggested {
+ rval["suggested"] = suggested.dictionaryRepresentation
+ }
+
+ if let enacted = enacted {
+ rval["enacted"] = enacted.dictionaryRepresentation
+ }
+
+ if let iob = iob {
+ rval["iob"] = iob.dictionaryRepresentation
+ }
+
+ if let cob = cob {
+ rval["cob"] = cob.dictionaryRepresentation
+ }
+
+ return rval
+ }
+}
+
diff --git a/NightscoutUploadKit/DeviceStatus/LoopSuggested.swift b/NightscoutUploadKit/DeviceStatus/LoopSuggested.swift
new file mode 100644
index 000000000..45ab81313
--- /dev/null
+++ b/NightscoutUploadKit/DeviceStatus/LoopSuggested.swift
@@ -0,0 +1,66 @@
+//
+// LoopSuggested.swift
+// RileyLink
+//
+// Created by Pete Schwamb on 7/28/16.
+// Copyright © 2016 Pete Schwamb. All rights reserved.
+//
+
+import Foundation
+
+public struct LoopSuggested {
+ let timestamp: NSDate
+ let rate: Double
+ let duration: NSTimeInterval
+ let eventualBG: Int
+ let bg: Int
+ let reason: String?
+ let tick: Int?
+ let correction: Double?
+
+ public init(timestamp: NSDate, rate: Double, duration: NSTimeInterval, eventualBG: Int, bg: Int, reason: String? = nil, tick: Int? = nil, correction: Double? = nil) {
+ self.timestamp = timestamp
+ self.rate = rate
+ self.duration = duration
+ self.eventualBG = eventualBG
+ self.bg = bg
+ self.reason = reason
+ self.tick = tick
+ self.correction = correction
+ }
+
+ public var dictionaryRepresentation: [String: AnyObject] {
+
+ var rval = [String: AnyObject]()
+
+ rval["timestamp"] = TimeFormat.timestampStrFromDate(timestamp)
+
+ if let tick = tick {
+ let tickStr: String
+ if tick > 0 {
+ tickStr = "+\(tick)"
+ } else if tick < 0 {
+ tickStr = "-\(tick)"
+ } else {
+ tickStr = "0"
+ }
+ rval["tick"] = tickStr
+ }
+
+ rval["rate"] = rate
+ rval["duration"] = duration / 60.0
+ rval["bg"] = bg
+ rval["eventualBG"] = eventualBG
+
+ if let reason = reason {
+ rval["reason"] = reason
+ }
+
+ if let correction = correction {
+ rval["correction"] = correction
+ }
+
+
+ return rval
+ }
+}
diff --git a/NightscoutUploadKit/DeviceStatus/PumpStatus.swift b/NightscoutUploadKit/DeviceStatus/PumpStatus.swift
new file mode 100644
index 000000000..3c6c27a2c
--- /dev/null
+++ b/NightscoutUploadKit/DeviceStatus/PumpStatus.swift
@@ -0,0 +1,50 @@
+//
+// PumpStatus.swift
+// RileyLink
+//
+// Created by Pete Schwamb on 7/26/16.
+// Copyright © 2016 Pete Schwamb. All rights reserved.
+//
+
+import Foundation
+
+public struct PumpStatus {
+ let clock: NSDate
+ let pumpID: String
+ let iob: IOBStatus?
+ let battery: BatteryStatus?
+ let suspended: Bool?
+ let bolusing: Bool?
+ let reservoir: Double?
+
+ public init(clock: NSDate, pumpID: String, iob: IOBStatus? = nil, battery: BatteryStatus? = nil, suspended: Bool? = nil, bolusing: Bool? = nil, reservoir: Double? = nil) {
+ self.clock = clock
+ self.pumpID = pumpID
+ self.iob = iob
+ self.battery = battery
+ self.suspended = suspended
+ self.bolusing = bolusing
+ self.reservoir = reservoir
+ }
+
+ public var dictionaryRepresentation: [String: AnyObject] {
+ var rval = [String: AnyObject]()
+
+ rval["clock"] = TimeFormat.timestampStrFromDate(clock)
+ rval["pumpID"] = pumpID
+
+ if let battery = battery {
+ rval["battery"] = battery.dictionaryRepresentation
+ }
+
+ if let reservoir = reservoir {
+ rval["reservoir"] = reservoir
+ }
+
+ if let iob = iob {
+ rval["iob"] = iob.dictionaryRepresentation
+ }
+
+ return rval
+ }
+}
\ No newline at end of file
diff --git a/NightscoutUploadKit/DeviceStatus/UploaderStatus.swift b/NightscoutUploadKit/DeviceStatus/UploaderStatus.swift
new file mode 100644
index 000000000..a591f566d
--- /dev/null
+++ b/NightscoutUploadKit/DeviceStatus/UploaderStatus.swift
@@ -0,0 +1,35 @@
+//
+// UploaderStatus.swift
+// RileyLink
+//
+// Created by Pete Schwamb on 7/26/16.
+// Copyright © 2016 Pete Schwamb. All rights reserved.
+//
+
+import Foundation
+
+public struct UploaderStatus {
+
+ public let battery: Int?
+ public let name: String
+ public let timestamp: NSDate
+
+ public init(name: String, timestamp: NSDate, battery: Int? = nil) {
+ self.name = name
+ self.timestamp = timestamp
+ self.battery = battery
+ }
+
+ public var dictionaryRepresentation: [String: AnyObject] {
+ var rval = [String: AnyObject]()
+
+ rval["name"] = name
+ rval["timestamp"] = TimeFormat.timestampStrFromDate(timestamp)
+
+ if let battery = battery {
+ rval["battery"] = battery
+ }
+
+ return rval
+ }
+}
\ No newline at end of file
diff --git a/NightscoutUploadKit/Info.plist b/NightscoutUploadKit/Info.plist
index 425ef70fb..5d7827c27 100644
--- a/NightscoutUploadKit/Info.plist
+++ b/NightscoutUploadKit/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- 0.7.1
+ 0.8.0
CFBundleSignature
????
CFBundleVersion
diff --git a/NightscoutUploadKit/NightscoutUploader.swift b/NightscoutUploadKit/NightscoutUploader.swift
index 1d3daf196..0c5471f12 100644
--- a/NightscoutUploadKit/NightscoutUploader.swift
+++ b/NightscoutUploadKit/NightscoutUploader.swift
@@ -64,7 +64,14 @@ public class NightscoutUploader {
}
// MARK: - Processing data from pump
-
+
+ /**
+ Enqueues pump history events for upload, with automatic retry management.
+
+ - parameter events: An array of timestamped history events. Only types with known Nightscout mappings will be uploaded.
+ - parameter source: The device identifier to display in Nightscout
+ - parameter pumpModel: The pump model info associated with the events
+ */
public func processPumpEvents(events: [TimestampedHistoryEvent], source: String, pumpModel: PumpModel) {
// Find valid event times
@@ -98,6 +105,27 @@ public class NightscoutUploader {
}
self.flushAll()
}
+
+ /**
+ Attempts to upload pump history events.
+
+ This method will not retry if the network task failed.
+
+ - parameter pumpEvents: An array of timestamped history events. Only types with known Nightscout mappings will be uploaded.
+ - parameter source: The device identifier to display in Nightscout
+ - parameter pumpModel: The pump model info associated with the events
+ - parameter completionHandler: A closure to execute when the task completes. It has a single argument for any error that might have occurred during the upload.
+ */
+ public func upload(pumpEvents: [TimestampedHistoryEvent], forSource source: String, from pumpModel: PumpModel, completionHandler: (ErrorType?) -> Void) {
+ let treatments = NightscoutPumpEvents.translate(pumpEvents, eventSource: source).map { $0.dictionaryRepresentation }
+
+ uploadToNS(treatments, endpoint: defaultNightscoutTreatmentPath, completion: completionHandler)
+ }
+
+ public func uploadDeviceStatus(status: DeviceStatus) {
+ deviceStatuses.append(status.dictionaryRepresentation)
+ flushAll()
+ }
// Entries [ { sgv: 375,
// date: 1432421525000,
@@ -107,10 +135,9 @@ public class NightscoutUploader {
// device: 'share2',
// type: 'sgv' } ]
- public func handlePumpStatus(status: MySentryPumpStatusMessageBody, device: String) {
+ public func uploadSGVFromMySentryPumpStatus(status: MySentryPumpStatusMessageBody, device: String) {
var recordSGV = true
-
let glucose: Int = {
switch status.glucose {
case .Active(glucose: let glucose):
@@ -127,52 +154,7 @@ public class NightscoutUploader {
}
}()
- // Create deviceStatus record from this mysentry packet
-
- var nsStatus = [String: AnyObject]()
-
- nsStatus["device"] = device
- nsStatus["created_at"] = TimeFormat.timestampStrFromDate(NSDate())
-
- // TODO: use battery monitoring to post updates if we're not hearing from pump?
-
- let uploaderDevice = UIDevice.currentDevice()
-
- if uploaderDevice.batteryMonitoringEnabled {
- nsStatus["uploader"] = ["battery":uploaderDevice.batteryLevel * 100]
- }
-
- guard let pumpDate = status.pumpDateComponents.date else {
- self.errorHandler?(error: UploadError.MissingTimezone, context: "Unable to get status.pumpDateComponents.date")
- return
- }
-
- let pumpDateStr = TimeFormat.timestampStrFromDate(pumpDate)
-
- nsStatus["pump"] = [
- "clock": pumpDateStr,
- "iob": [
- "timestamp": pumpDateStr,
- "bolusiob": status.iob,
- ],
- "reservoir": status.reservoirRemainingUnits,
- "battery": [
- "percent": status.batteryRemainingPercent
- ]
- ]
-
- switch status.glucose {
- case .Active(glucose: _):
- nsStatus["sensor"] = [
- "sensorAge": status.sensorAgeHours,
- "sensorRemaining": status.sensorRemainingHours,
- ]
- default:
- nsStatus["sensorNotActive"] = true
- }
- deviceStatuses.append(nsStatus)
-
-
+
// Create SGV entry from this mysentry packet
if (recordSGV) {
var entry: [String: AnyObject] = [
@@ -252,18 +234,15 @@ public class NightscoutUploader {
let uploadURL = siteURL.URLByAppendingPathComponent(endpoint)
let request = NSMutableURLRequest(URL: uploadURL)
+ request.HTTPMethod = "POST"
+ request.setValue("application/json", forHTTPHeaderField: "Content-Type")
+ request.setValue("application/json", forHTTPHeaderField: "Accept")
+ request.setValue(APISecret.SHA1, forHTTPHeaderField: "api-secret")
+
do {
-
- let sendData = try NSJSONSerialization.dataWithJSONObject(json, options: NSJSONWritingOptions.PrettyPrinted)
- request.HTTPMethod = "POST"
-
- request.setValue("application/json", forHTTPHeaderField:"Content-Type")
- request.setValue("application/json", forHTTPHeaderField:"Accept")
- request.setValue(APISecret.SHA1, forHTTPHeaderField:"api-secret")
- request.HTTPBody = sendData
-
- let task = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data, response, error) in
-
+ let sendData = try NSJSONSerialization.dataWithJSONObject(json, options: [])
+
+ let task = NSURLSession.sharedSession().uploadTaskWithRequest(request, fromData: sendData) { (data, response, error) in
if let error = error {
completion(error)
return
@@ -275,7 +254,7 @@ public class NightscoutUploader {
} else {
completion(nil)
}
- })
+ }
task.resume()
} catch let error as NSError {
completion(error)
diff --git a/NightscoutUploadKit/BGCheckNightscoutTreatment.swift b/NightscoutUploadKit/Treatments/BGCheckNightscoutTreatment.swift
similarity index 100%
rename from NightscoutUploadKit/BGCheckNightscoutTreatment.swift
rename to NightscoutUploadKit/Treatments/BGCheckNightscoutTreatment.swift
diff --git a/NightscoutUploadKit/BolusNightscoutTreatment.swift b/NightscoutUploadKit/Treatments/BolusNightscoutTreatment.swift
similarity index 100%
rename from NightscoutUploadKit/BolusNightscoutTreatment.swift
rename to NightscoutUploadKit/Treatments/BolusNightscoutTreatment.swift
diff --git a/NightscoutUploadKit/MealBolusNightscoutTreatment.swift b/NightscoutUploadKit/Treatments/MealBolusNightscoutTreatment.swift
similarity index 100%
rename from NightscoutUploadKit/MealBolusNightscoutTreatment.swift
rename to NightscoutUploadKit/Treatments/MealBolusNightscoutTreatment.swift
diff --git a/NightscoutUploadKit/NightscoutTreatment.swift b/NightscoutUploadKit/Treatments/NightscoutTreatment.swift
similarity index 100%
rename from NightscoutUploadKit/NightscoutTreatment.swift
rename to NightscoutUploadKit/Treatments/NightscoutTreatment.swift
diff --git a/NightscoutUploadKit/TempBasalNightscoutTreatment.swift b/NightscoutUploadKit/Treatments/TempBasalNightscoutTreatment.swift
similarity index 100%
rename from NightscoutUploadKit/TempBasalNightscoutTreatment.swift
rename to NightscoutUploadKit/Treatments/TempBasalNightscoutTreatment.swift
diff --git a/NightscoutUploadKitTests/Info.plist b/NightscoutUploadKitTests/Info.plist
index 8d8ed6042..dc2ece127 100644
--- a/NightscoutUploadKitTests/Info.plist
+++ b/NightscoutUploadKitTests/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
BNDL
CFBundleShortVersionString
- 0.7.1
+ 0.8.0
CFBundleSignature
????
CFBundleVersion
diff --git a/RileyLink.xcodeproj/project.pbxproj b/RileyLink.xcodeproj/project.pbxproj
index 7ce5e3968..75f5b6963 100644
--- a/RileyLink.xcodeproj/project.pbxproj
+++ b/RileyLink.xcodeproj/project.pbxproj
@@ -151,6 +151,9 @@
C1711A5C1C953F3000CB25BD /* GetBatteryCarelinkMessageBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1711A5B1C953F3000CB25BD /* GetBatteryCarelinkMessageBody.swift */; };
C1711A5E1C977BD000CB25BD /* GetHistoryPageCarelinkMessageBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1711A5D1C977BD000CB25BD /* GetHistoryPageCarelinkMessageBody.swift */; };
C174F26B19EB824D00398C72 /* ISO8601DateFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = C174F26A19EB824D00398C72 /* ISO8601DateFormatter.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
+ C178845D1D4EF3D800405663 /* ReadPumpStatusMessageBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = C178845C1D4EF3D800405663 /* ReadPumpStatusMessageBody.swift */; };
+ C178845F1D5166BE00405663 /* COBStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = C178845E1D5166BE00405663 /* COBStatus.swift */; };
+ C17884611D519F1E00405663 /* BatteryIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C17884601D519F1E00405663 /* BatteryIndicator.swift */; };
C1842BBB1C8E184300DB42AC /* PumpModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1842BBA1C8E184300DB42AC /* PumpModel.swift */; };
C1842BBD1C8E7C6E00DB42AC /* PumpEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1842BBC1C8E7C6E00DB42AC /* PumpEvent.swift */; };
C1842BBF1C8E855A00DB42AC /* PumpEventType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1842BBE1C8E855A00DB42AC /* PumpEventType.swift */; };
@@ -205,8 +208,21 @@
C1842C231C8FA45100DB42AC /* ChangeAlarmClockEnablePumpEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1842BF91C8FA45100DB42AC /* ChangeAlarmClockEnablePumpEvent.swift */; };
C1842C241C8FA45100DB42AC /* BatteryPumpEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1842BFA1C8FA45100DB42AC /* BatteryPumpEvent.swift */; };
C1842C251C8FA45100DB42AC /* AlarmSensorPumpEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1842BFB1C8FA45100DB42AC /* AlarmSensorPumpEvent.swift */; };
+ C1A492631D4A5A19008964FF /* IOBStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1A492621D4A5A19008964FF /* IOBStatus.swift */; };
+ C1A492651D4A5DEB008964FF /* BatteryStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1A492641D4A5DEB008964FF /* BatteryStatus.swift */; };
+ C1A492671D4A65D9008964FF /* LoopSuggested.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1A492661D4A65D9008964FF /* LoopSuggested.swift */; };
+ C1A492691D4A66C0008964FF /* LoopEnacted.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1A492681D4A66C0008964FF /* LoopEnacted.swift */; };
C1AA39941AB6804000BC9E33 /* UIAlertView+Blocks.m in Sources */ = {isa = PBXBuildFile; fileRef = C1AA39931AB6804000BC9E33 /* UIAlertView+Blocks.m */; };
C1AACC6B1CECD5F500C07049 /* RileyLinkListTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1AACC6A1CECD5F500C07049 /* RileyLinkListTableViewController.swift */; };
+ C1AF21E21D4838C90088C41D /* DeviceStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1AF21E11D4838C90088C41D /* DeviceStatus.swift */; };
+ C1AF21E41D4865320088C41D /* LoopStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1AF21E31D4865320088C41D /* LoopStatus.swift */; };
+ C1AF21E61D48667F0088C41D /* UploaderStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1AF21E51D48667F0088C41D /* UploaderStatus.swift */; };
+ C1AF21E81D4866960088C41D /* PumpStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1AF21E71D4866960088C41D /* PumpStatus.swift */; };
+ C1AF21F01D4901220088C41D /* BolusNightscoutTreatment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1AF21EB1D4901220088C41D /* BolusNightscoutTreatment.swift */; };
+ C1AF21F11D4901220088C41D /* NightscoutTreatment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1AF21EC1D4901220088C41D /* NightscoutTreatment.swift */; };
+ C1AF21F21D4901220088C41D /* BGCheckNightscoutTreatment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1AF21ED1D4901220088C41D /* BGCheckNightscoutTreatment.swift */; };
+ C1AF21F31D4901220088C41D /* MealBolusNightscoutTreatment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1AF21EE1D4901220088C41D /* MealBolusNightscoutTreatment.swift */; };
+ C1AF21F41D4901220088C41D /* TempBasalNightscoutTreatment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1AF21EF1D4901220088C41D /* TempBasalNightscoutTreatment.swift */; };
C1B3830E1CD0665D00CE7782 /* NightscoutUploadKit.h in Headers */ = {isa = PBXBuildFile; fileRef = C1B3830D1CD0665D00CE7782 /* NightscoutUploadKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
C1B383151CD0665D00CE7782 /* NightscoutUploadKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1B3830B1CD0665D00CE7782 /* NightscoutUploadKit.framework */; };
C1B3831C1CD0665D00CE7782 /* NightscoutUploadKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1B3831B1CD0665D00CE7782 /* NightscoutUploadKitTests.swift */; };
@@ -214,11 +230,6 @@
C1B383211CD0665D00CE7782 /* NightscoutUploadKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C1B3830B1CD0665D00CE7782 /* NightscoutUploadKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
C1B383281CD0668600CE7782 /* NightscoutUploader.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1842C281C908A3C00DB42AC /* NightscoutUploader.swift */; };
C1B383291CD0668600CE7782 /* NightscoutPumpEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1842C2A1C90DFB600DB42AC /* NightscoutPumpEvents.swift */; };
- C1B3832A1CD0668600CE7782 /* NightscoutTreatment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1842C2E1C90F6D900DB42AC /* NightscoutTreatment.swift */; };
- C1B3832B1CD0668600CE7782 /* BGCheckNightscoutTreatment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1842C301C91D56400DB42AC /* BGCheckNightscoutTreatment.swift */; };
- C1B3832C1CD0668600CE7782 /* MealBolusNightscoutTreatment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1842C321C91DAFA00DB42AC /* MealBolusNightscoutTreatment.swift */; };
- C1B3832D1CD0668600CE7782 /* BolusNightscoutTreatment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C19F94AA1C91DF6E00018F7D /* BolusNightscoutTreatment.swift */; };
- C1B3832E1CD0668600CE7782 /* TempBasalNightscoutTreatment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12FB2751CC5893C00879B80 /* TempBasalNightscoutTreatment.swift */; };
C1B383301CD0680800CE7782 /* MinimedKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C10D9BC11C8269D500378342 /* MinimedKit.framework */; };
C1B383311CD068C300CE7782 /* RileyLinkBLEKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 430D64CB1CB855AB00FCA750 /* RileyLinkBLEKit.framework */; };
C1B383361CD1BA8100CE7782 /* DeviceDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1B383351CD1BA8100CE7782 /* DeviceDataManager.swift */; };
@@ -473,7 +484,6 @@
C12EA25D198B436900309FA4 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
C12EA25F198B436900309FA4 /* RileyLinkTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RileyLinkTests.m; sourceTree = ""; };
C12EA269198B442100309FA4 /* Storyboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Storyboard.storyboard; sourceTree = ""; };
- C12FB2751CC5893C00879B80 /* TempBasalNightscoutTreatment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TempBasalNightscoutTreatment.swift; sourceTree = ""; };
C139AC221BFD84B500B0518F /* RuntimeUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RuntimeUtils.h; sourceTree = ""; };
C139AC231BFD84B500B0518F /* RuntimeUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RuntimeUtils.m; sourceTree = ""; };
C14303151C97C98000A40450 /* PumpAckMessageBody.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PumpAckMessageBody.swift; sourceTree = ""; };
@@ -513,6 +523,9 @@
C1711A5D1C977BD000CB25BD /* GetHistoryPageCarelinkMessageBody.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GetHistoryPageCarelinkMessageBody.swift; sourceTree = ""; };
C174F26919EB824D00398C72 /* ISO8601DateFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ISO8601DateFormatter.h; sourceTree = ""; };
C174F26A19EB824D00398C72 /* ISO8601DateFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ISO8601DateFormatter.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
+ C178845C1D4EF3D800405663 /* ReadPumpStatusMessageBody.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReadPumpStatusMessageBody.swift; sourceTree = ""; };
+ C178845E1D5166BE00405663 /* COBStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = COBStatus.swift; sourceTree = ""; };
+ C17884601D519F1E00405663 /* BatteryIndicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BatteryIndicator.swift; sourceTree = ""; };
C1842BBA1C8E184300DB42AC /* PumpModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PumpModel.swift; sourceTree = ""; };
C1842BBC1C8E7C6E00DB42AC /* PumpEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PumpEvent.swift; sourceTree = ""; };
C1842BBE1C8E855A00DB42AC /* PumpEventType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = PumpEventType.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
@@ -569,13 +582,22 @@
C1842BFB1C8FA45100DB42AC /* AlarmSensorPumpEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = AlarmSensorPumpEvent.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
C1842C281C908A3C00DB42AC /* NightscoutUploader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NightscoutUploader.swift; sourceTree = ""; };
C1842C2A1C90DFB600DB42AC /* NightscoutPumpEvents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NightscoutPumpEvents.swift; sourceTree = ""; };
- C1842C2E1C90F6D900DB42AC /* NightscoutTreatment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NightscoutTreatment.swift; sourceTree = ""; };
- C1842C301C91D56400DB42AC /* BGCheckNightscoutTreatment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BGCheckNightscoutTreatment.swift; sourceTree = ""; };
- C1842C321C91DAFA00DB42AC /* MealBolusNightscoutTreatment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = MealBolusNightscoutTreatment.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
- C19F94AA1C91DF6E00018F7D /* BolusNightscoutTreatment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BolusNightscoutTreatment.swift; sourceTree = ""; };
+ C1A492621D4A5A19008964FF /* IOBStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IOBStatus.swift; sourceTree = ""; };
+ C1A492641D4A5DEB008964FF /* BatteryStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BatteryStatus.swift; sourceTree = ""; };
+ C1A492661D4A65D9008964FF /* LoopSuggested.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoopSuggested.swift; sourceTree = ""; };
+ C1A492681D4A66C0008964FF /* LoopEnacted.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoopEnacted.swift; sourceTree = ""; };
C1AA39921AB6804000BC9E33 /* UIAlertView+Blocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIAlertView+Blocks.h"; sourceTree = ""; };
C1AA39931AB6804000BC9E33 /* UIAlertView+Blocks.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIAlertView+Blocks.m"; sourceTree = ""; };
C1AACC6A1CECD5F500C07049 /* RileyLinkListTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RileyLinkListTableViewController.swift; sourceTree = ""; };
+ C1AF21E11D4838C90088C41D /* DeviceStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceStatus.swift; sourceTree = ""; };
+ C1AF21E31D4865320088C41D /* LoopStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoopStatus.swift; sourceTree = ""; };
+ C1AF21E51D48667F0088C41D /* UploaderStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UploaderStatus.swift; sourceTree = ""; };
+ C1AF21E71D4866960088C41D /* PumpStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PumpStatus.swift; sourceTree = ""; };
+ C1AF21EB1D4901220088C41D /* BolusNightscoutTreatment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BolusNightscoutTreatment.swift; sourceTree = ""; };
+ C1AF21EC1D4901220088C41D /* NightscoutTreatment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NightscoutTreatment.swift; sourceTree = ""; };
+ C1AF21ED1D4901220088C41D /* BGCheckNightscoutTreatment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BGCheckNightscoutTreatment.swift; sourceTree = ""; };
+ C1AF21EE1D4901220088C41D /* MealBolusNightscoutTreatment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MealBolusNightscoutTreatment.swift; sourceTree = ""; };
+ C1AF21EF1D4901220088C41D /* TempBasalNightscoutTreatment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TempBasalNightscoutTreatment.swift; sourceTree = ""; };
C1B3830B1CD0665D00CE7782 /* NightscoutUploadKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = NightscoutUploadKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
C1B3830D1CD0665D00CE7782 /* NightscoutUploadKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NightscoutUploadKit.h; sourceTree = ""; };
C1B3830F1CD0665D00CE7782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
@@ -1090,22 +1112,48 @@
C14FFC5A1D3D74F90049CF85 /* NibLoadable.swift */,
C14FFC601D3D75470049CF85 /* UIColor.swift */,
C14FFC6C1D3D85A40049CF85 /* NSTimeInterval.swift */,
+ C17884601D519F1E00405663 /* BatteryIndicator.swift */,
);
name = Extensions;
sourceTree = "";
};
+ C1AF21E91D4900300088C41D /* DeviceStatus */ = {
+ isa = PBXGroup;
+ children = (
+ C1AF21E11D4838C90088C41D /* DeviceStatus.swift */,
+ C1AF21E51D48667F0088C41D /* UploaderStatus.swift */,
+ C1AF21E71D4866960088C41D /* PumpStatus.swift */,
+ C1A492621D4A5A19008964FF /* IOBStatus.swift */,
+ C178845E1D5166BE00405663 /* COBStatus.swift */,
+ C1A492641D4A5DEB008964FF /* BatteryStatus.swift */,
+ C1AF21E31D4865320088C41D /* LoopStatus.swift */,
+ C1A492661D4A65D9008964FF /* LoopSuggested.swift */,
+ C1A492681D4A66C0008964FF /* LoopEnacted.swift */,
+ );
+ path = DeviceStatus;
+ sourceTree = "";
+ };
+ C1AF21EA1D4900880088C41D /* Treatments */ = {
+ isa = PBXGroup;
+ children = (
+ C1AF21EB1D4901220088C41D /* BolusNightscoutTreatment.swift */,
+ C1AF21EC1D4901220088C41D /* NightscoutTreatment.swift */,
+ C1AF21ED1D4901220088C41D /* BGCheckNightscoutTreatment.swift */,
+ C1AF21EE1D4901220088C41D /* MealBolusNightscoutTreatment.swift */,
+ C1AF21EF1D4901220088C41D /* TempBasalNightscoutTreatment.swift */,
+ );
+ path = Treatments;
+ sourceTree = "";
+ };
C1B3830C1CD0665D00CE7782 /* NightscoutUploadKit */ = {
isa = PBXGroup;
children = (
+ C1AF21EA1D4900880088C41D /* Treatments */,
+ C1AF21E91D4900300088C41D /* DeviceStatus */,
C1B3830D1CD0665D00CE7782 /* NightscoutUploadKit.h */,
C1B3830F1CD0665D00CE7782 /* Info.plist */,
- C1842C301C91D56400DB42AC /* BGCheckNightscoutTreatment.swift */,
- C19F94AA1C91DF6E00018F7D /* BolusNightscoutTreatment.swift */,
- C1842C321C91DAFA00DB42AC /* MealBolusNightscoutTreatment.swift */,
- C1842C2A1C90DFB600DB42AC /* NightscoutPumpEvents.swift */,
- C1842C2E1C90F6D900DB42AC /* NightscoutTreatment.swift */,
C1842C281C908A3C00DB42AC /* NightscoutUploader.swift */,
- C12FB2751CC5893C00879B80 /* TempBasalNightscoutTreatment.swift */,
+ C1842C2A1C90DFB600DB42AC /* NightscoutPumpEvents.swift */,
43B0ADC81D1268B300AAD278 /* TimeFormat.swift */,
C1B4A94D1D1C423D003B8985 /* NSUserDefaults.swift */,
);
@@ -1182,6 +1230,7 @@
43CA932C1CB8CFA1000026B5 /* ReadTempBasalCarelinkMessageBody.swift */,
43CA932D1CB8CFA1000026B5 /* ReadTimeCarelinkMessageBody.swift */,
C1EAD6C41C826B92006DBA60 /* UnknownMessageBody.swift */,
+ C178845C1D4EF3D800405663 /* ReadPumpStatusMessageBody.swift */,
);
path = Messages;
sourceTree = "";
@@ -1365,6 +1414,7 @@
C12EA234198B436800309FA4 /* Frameworks */,
C12EA235198B436800309FA4 /* Resources */,
C10D9BB81C82614F00378342 /* Embed Frameworks */,
+ C1AF21F51D4BC0C30088C41D /* ShellScript */,
);
buildRules = (
);
@@ -1589,6 +1639,23 @@
};
/* End PBXResourcesBuildPhase section */
+/* Begin PBXShellScriptBuildPhase section */
+ C1AF21F51D4BC0C30088C41D /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(SRCROOT)/Carthage/Build/iOS/Crypto.framework",
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "/usr/local/bin/carthage copy-frameworks";
+ };
+/* End PBXShellScriptBuildPhase section */
+
/* Begin PBXSourcesBuildPhase section */
430D64C61CB855AB00FCA750 /* Sources */ = {
isa = PBXSourcesBuildPhase;
@@ -1672,6 +1739,7 @@
C1842C041C8FA45100DB42AC /* DeleteOtherDeviceIDPumpEvent.swift in Sources */,
C1842C0B1C8FA45100DB42AC /* ChangeTimePumpEvent.swift in Sources */,
C1842C0D1C8FA45100DB42AC /* TempBasalPumpEvent.swift in Sources */,
+ C178845D1D4EF3D800405663 /* ReadPumpStatusMessageBody.swift in Sources */,
43B0ADCB1D126B1100AAD278 /* SelectBasalProfilePumpEvent.swift in Sources */,
C1842C0C1C8FA45100DB42AC /* ChangeTimeFormatPumpEvent.swift in Sources */,
C10AB08D1C855613000F102E /* FindDeviceMessageBody.swift in Sources */,
@@ -1809,6 +1877,7 @@
C14FFC551D3D72A50049CF85 /* UIViewController.swift in Sources */,
434FF1DE1CF268F3000DB779 /* RileyLinkDeviceTableViewCell.swift in Sources */,
C14FFC651D3D7E250049CF85 /* RemoteDataManager.swift in Sources */,
+ C17884611D519F1E00405663 /* BatteryIndicator.swift in Sources */,
C1AA39941AB6804000BC9E33 /* UIAlertView+Blocks.m in Sources */,
C1EF58881B3F93FE001C8C80 /* Config.m in Sources */,
C126164B1B685F93001FAD87 /* RileyLink.xcdatamodeld in Sources */,
@@ -1838,17 +1907,26 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- C1B3832E1CD0668600CE7782 /* TempBasalNightscoutTreatment.swift in Sources */,
- C1B3832B1CD0668600CE7782 /* BGCheckNightscoutTreatment.swift in Sources */,
C1B383291CD0668600CE7782 /* NightscoutPumpEvents.swift in Sources */,
43B0ADCC1D126E3000AAD278 /* NSDateFormatter.swift in Sources */,
+ C1AF21E81D4866960088C41D /* PumpStatus.swift in Sources */,
C1B4A94E1D1C423D003B8985 /* NSUserDefaults.swift in Sources */,
- C1B3832D1CD0668600CE7782 /* BolusNightscoutTreatment.swift in Sources */,
+ C1AF21F01D4901220088C41D /* BolusNightscoutTreatment.swift in Sources */,
+ C1AF21F21D4901220088C41D /* BGCheckNightscoutTreatment.swift in Sources */,
+ C1AF21E61D48667F0088C41D /* UploaderStatus.swift in Sources */,
+ C1AF21F31D4901220088C41D /* MealBolusNightscoutTreatment.swift in Sources */,
+ C1A492691D4A66C0008964FF /* LoopEnacted.swift in Sources */,
+ C1A492651D4A5DEB008964FF /* BatteryStatus.swift in Sources */,
+ C1A492631D4A5A19008964FF /* IOBStatus.swift in Sources */,
43D657461D0CF38F00216E20 /* NSTimeInterval.swift in Sources */,
- C1B3832C1CD0668600CE7782 /* MealBolusNightscoutTreatment.swift in Sources */,
+ C1AF21E41D4865320088C41D /* LoopStatus.swift in Sources */,
+ C1AF21F11D4901220088C41D /* NightscoutTreatment.swift in Sources */,
+ C1A492671D4A65D9008964FF /* LoopSuggested.swift in Sources */,
+ C178845F1D5166BE00405663 /* COBStatus.swift in Sources */,
43B0ADC91D1268B300AAD278 /* TimeFormat.swift in Sources */,
+ C1AF21E21D4838C90088C41D /* DeviceStatus.swift in Sources */,
C1B383281CD0668600CE7782 /* NightscoutUploader.swift in Sources */,
- C1B3832A1CD0668600CE7782 /* NightscoutTreatment.swift in Sources */,
+ C1AF21F41D4901220088C41D /* TempBasalNightscoutTreatment.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1943,11 +2021,11 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- CURRENT_PROJECT_VERSION = 10;
+ CURRENT_PROJECT_VERSION = 11;
DEBUG_INFORMATION_FORMAT = dwarf;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 10;
+ DYLIB_CURRENT_VERSION = 11;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_NO_COMMON_BLOCKS = YES;
@@ -1971,11 +2049,11 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 10;
+ CURRENT_PROJECT_VERSION = 11;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 10;
+ DYLIB_CURRENT_VERSION = 11;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_NO_COMMON_BLOCKS = YES;
@@ -2034,11 +2112,11 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- CURRENT_PROJECT_VERSION = 10;
+ CURRENT_PROJECT_VERSION = 11;
DEBUG_INFORMATION_FORMAT = dwarf;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 10;
+ DYLIB_CURRENT_VERSION = 11;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_NO_COMMON_BLOCKS = YES;
@@ -2064,11 +2142,11 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 10;
+ CURRENT_PROJECT_VERSION = 11;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 10;
+ DYLIB_CURRENT_VERSION = 11;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_NO_COMMON_BLOCKS = YES;
@@ -2127,11 +2205,11 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- CURRENT_PROJECT_VERSION = 10;
+ CURRENT_PROJECT_VERSION = 11;
DEBUG_INFORMATION_FORMAT = dwarf;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 10;
+ DYLIB_CURRENT_VERSION = 11;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_NO_COMMON_BLOCKS = YES;
@@ -2156,11 +2234,11 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 10;
+ CURRENT_PROJECT_VERSION = 11;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 10;
+ DYLIB_CURRENT_VERSION = 11;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_NO_COMMON_BLOCKS = YES;
@@ -2229,7 +2307,7 @@
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 10;
+ CURRENT_PROJECT_VERSION = 11;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
@@ -2271,7 +2349,7 @@
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
- CURRENT_PROJECT_VERSION = 10;
+ CURRENT_PROJECT_VERSION = 11;
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@@ -2376,11 +2454,11 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- CURRENT_PROJECT_VERSION = 10;
+ CURRENT_PROJECT_VERSION = 11;
DEBUG_INFORMATION_FORMAT = dwarf;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 10;
+ DYLIB_CURRENT_VERSION = 11;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = (
@@ -2409,11 +2487,11 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 10;
+ CURRENT_PROJECT_VERSION = 11;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 10;
+ DYLIB_CURRENT_VERSION = 11;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = (
diff --git a/RileyLink/BatteryIndicator.swift b/RileyLink/BatteryIndicator.swift
new file mode 100644
index 000000000..9c14117e6
--- /dev/null
+++ b/RileyLink/BatteryIndicator.swift
@@ -0,0 +1,23 @@
+//
+// BatteryIndicator.swift
+// RileyLink
+//
+// Created by Pete Schwamb on 8/2/16.
+// Copyright © 2016 Pete Schwamb. All rights reserved.
+//
+
+import NightscoutUploadKit
+import MinimedKit
+
+extension BatteryIndicator {
+ init?(batteryStatus: MinimedKit.BatteryStatus) {
+ switch batteryStatus {
+ case .Low:
+ self = .Low
+ case .Normal:
+ self = .Normal
+ default:
+ return nil
+ }
+ }
+}
\ No newline at end of file
diff --git a/RileyLink/Config.h b/RileyLink/Config.h
index a56d92aeb..dd3b89aa9 100644
--- a/RileyLink/Config.h
+++ b/RileyLink/Config.h
@@ -17,6 +17,7 @@
@property (nonatomic, nullable, strong) NSURL *nightscoutURL;
@property (nonatomic, nullable, strong) NSString *nightscoutAPISecret;
@property (nonatomic, nullable, strong) NSString *pumpID;
+@property (nonatomic, nullable, strong) NSString *pumpModelNumber;
@property (nonatomic, nullable, strong) NSTimeZone *pumpTimeZone;
@property (nonatomic, nullable, strong) NSSet *autoConnectIds;
@property (nonatomic, assign) BOOL uploadEnabled;
diff --git a/RileyLink/Config.m b/RileyLink/Config.m
index 4f7922d5c..6f7dd85f0 100644
--- a/RileyLink/Config.m
+++ b/RileyLink/Config.m
@@ -64,6 +64,15 @@ - (NSString*) pumpID {
return [_defaults stringForKey:@"pumpID"];
}
+- (void) setPumpModelNumber:(NSString *)pumpModelNumber {
+ [_defaults setValue:pumpModelNumber forKey:@"pumpModelNumber"];
+}
+
+- (NSString*) pumpModelNumber {
+ return [_defaults stringForKey:@"pumpModelNumber"];
+}
+
+
- (void) setPumpTimeZone:(NSTimeZone *)pumpTimeZone {
if (pumpTimeZone) {
diff --git a/RileyLink/DeviceDataManager.swift b/RileyLink/DeviceDataManager.swift
index c501daf00..54e927037 100644
--- a/RileyLink/DeviceDataManager.swift
+++ b/RileyLink/DeviceDataManager.swift
@@ -29,45 +29,87 @@ class DeviceDataManager {
}
}
- var latestPumpStatus: MySentryPumpStatusMessageBody?
+ var latestPumpStatusDate: NSDate?
- var pumpTimeZone: NSTimeZone? = Config.sharedInstance().pumpTimeZone {
+ var latestPumpStatusFromMySentry: MySentryPumpStatusMessageBody? {
didSet {
- Config.sharedInstance().pumpTimeZone = pumpTimeZone
-
- if let pumpTimeZone = pumpTimeZone {
-
- if let pumpState = rileyLinkManager.pumpState {
- pumpState.timeZone = pumpTimeZone
- }
+ if let update = latestPumpStatusFromMySentry, let timeZone = pumpState?.timeZone {
+ let pumpClock = update.pumpDateComponents
+ pumpClock.timeZone = timeZone
+ latestPumpStatusDate = pumpClock.date
}
}
}
-
- var pumpID: String? = Config.sharedInstance().pumpID {
+
+
+ var latestPolledPumpStatus: RileyLinkKit.PumpStatus? {
didSet {
- if pumpID?.characters.count != 6 {
- pumpID = nil
+ if let update = latestPolledPumpStatus, let timeZone = pumpState?.timeZone {
+ let pumpClock = update.clock
+ pumpClock.timeZone = timeZone
+ latestPumpStatusDate = pumpClock.date
+ }
+ }
+ }
+
+ var pumpID: String? {
+ get {
+ return pumpState?.pumpID
+ }
+ set {
+ guard newValue?.characters.count == 6 && newValue != pumpState?.pumpID else {
+ return
}
- if let pumpID = pumpID {
+ if let pumpID = newValue {
let pumpState = PumpState(pumpID: pumpID)
- if let timeZone = pumpTimeZone {
+ if let timeZone = self.pumpState?.timeZone {
pumpState.timeZone = timeZone
}
- rileyLinkManager.pumpState = pumpState
+ self.pumpState = pumpState
} else {
- rileyLinkManager.pumpState = nil
+ self.pumpState = nil
}
-
+
remoteDataManager.nightscoutUploader?.reset()
Config.sharedInstance().pumpID = pumpID
}
}
+ var pumpState: PumpState? {
+ didSet {
+ rileyLinkManager.pumpState = pumpState
+
+ if let oldValue = oldValue {
+ NSNotificationCenter.defaultCenter().removeObserver(self, name: PumpState.ValuesDidChangeNotification, object: oldValue)
+ }
+
+ if let pumpState = pumpState {
+ NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(pumpStateValuesDidChange(_:)), name: PumpState.ValuesDidChangeNotification, object: pumpState)
+ }
+ }
+ }
+
+ @objc private func pumpStateValuesDidChange(note: NSNotification) {
+ switch note.userInfo?[PumpState.PropertyKey] as? String {
+ case "timeZone"?:
+ Config.sharedInstance().pumpTimeZone = pumpState?.timeZone
+ case "pumpModel"?:
+ if let sentrySupported = pumpState?.pumpModel?.larger {
+ rileyLinkManager.idleListeningEnabled = sentrySupported
+ rileyLinkManager.timerTickEnabled = !sentrySupported
+ }
+ Config.sharedInstance().pumpModelNumber = pumpState?.pumpModel?.rawValue
+ case "lastHistoryDump"?, "awakeUntil"?:
+ break
+ default:
+ break
+ }
+ }
+
var lastHistoryAttempt: NSDate? = nil
var lastRileyLinkHeardFrom: RileyLinkDevice? = nil
@@ -89,7 +131,7 @@ class DeviceDataManager {
}
}
- func receivedRileyLinkManagerNotification(note: NSNotification) {
+ @objc private func receivedRileyLinkManagerNotification(note: NSNotification) {
NSNotificationCenter.defaultCenter().postNotificationName(note.name, object: self, userInfo: note.userInfo)
}
@@ -100,29 +142,24 @@ class DeviceDataManager {
return self.rileyLinkManager.firstConnectedDevice
}
- func receivedRileyLinkPacketNotification(note: NSNotification) {
+ /**
+ 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: NSNotification) {
if let
device = note.object as? RileyLinkDevice,
data = note.userInfo?[RileyLinkDevice.IdleMessageDataKey] as? NSData,
message = PumpMessage(rxData: data)
{
- lastRileyLinkHeardFrom = device
switch message.packetType {
case .MySentry:
switch message.messageBody {
case let body as MySentryPumpStatusMessageBody:
- updatePumpStatus(body, fromDevice: device)
- case is MySentryAlertMessageBody:
- break
- // TODO: de-dupe
- // logger?.addMessage(body.dictionaryRepresentation, toCollection: "sentryAlert")
- case is MySentryAlertClearedMessageBody:
- break
- // TODO: de-dupe
- // logger?.addMessage(body.dictionaryRepresentation, toCollection: "sentryAlert")
- case is UnknownMessageBody:
- break
- //logger?.addMessage(body.dictionaryRepresentation, toCollection: "sentryOther")
+ pumpStatusUpdateReceived(body, fromDevice: device)
default:
break
}
@@ -132,6 +169,11 @@ class DeviceDataManager {
}
}
+ @objc private func receivedRileyLinkTimerTickNotification(note: NSNotification) {
+ self.assertCurrentPumpData()
+ }
+
+
func connectToRileyLink(device: RileyLinkDevice) {
connectedPeripheralIDs.insert(device.peripheral.identifier.UUIDString)
@@ -144,24 +186,141 @@ class DeviceDataManager {
rileyLinkManager.disconnectDevice(device)
}
- private func updatePumpStatus(status: MySentryPumpStatusMessageBody, fromDevice device: RileyLinkDevice) {
- status.pumpDateComponents.timeZone = pumpTimeZone
- status.glucoseDateComponents?.timeZone = pumpTimeZone
-
- if status != latestPumpStatus {
- latestPumpStatus = status
+ private func pumpStatusUpdateReceived(status: MySentryPumpStatusMessageBody, fromDevice device: RileyLinkDevice) {
+ status.pumpDateComponents.timeZone = pumpState?.timeZone
+ status.glucoseDateComponents?.timeZone = pumpState?.timeZone
+
+ // Avoid duplicates
+ if status != latestPumpStatusFromMySentry {
+ latestPumpStatusFromMySentry = status
+
+ // Sentry packets are sent in groups of 3, 5s apart. Wait 11s to avoid conflicting comms.
+ let delay = dispatch_time(DISPATCH_TIME_NOW, Int64(11 * NSEC_PER_SEC))
+ dispatch_after(delay, dispatch_get_main_queue()) {
+ self.getPumpHistory(device)
+ }
if status.batteryRemainingPercent == 0 {
//NotificationManager.sendPumpBatteryLowNotification()
}
- if Config.sharedInstance().uploadEnabled {
- remoteDataManager.nightscoutUploader?.handlePumpStatus(status, device: device.deviceURI)
+
+ guard Config.sharedInstance().uploadEnabled, let pumpID = pumpID else {
+ return
}
- // Sentry packets are sent in groups of 3, 5s apart. Wait 11s to avoid conflicting comms.
- let delay = dispatch_time(DISPATCH_TIME_NOW, Int64(11 * NSEC_PER_SEC))
- dispatch_after(delay, dispatch_get_main_queue()) {
- self.getPumpHistory(device)
+ // Gather PumpStatus from MySentry packet
+ let pumpStatus: NightscoutUploadKit.PumpStatus?
+ if let pumpDate = status.pumpDateComponents.date {
+
+ let batteryStatus = BatteryStatus(percent: status.batteryRemainingPercent)
+ let iobStatus = IOBStatus(timestamp: pumpDate, iob: status.iob)
+
+ pumpStatus = NightscoutUploadKit.PumpStatus(clock: pumpDate, pumpID: pumpID, iob: iobStatus, battery: batteryStatus, reservoir: status.reservoirRemainingUnits)
+ } else {
+ pumpStatus = nil
+ print("Could not interpret pump clock: \(status.pumpDateComponents)")
+ }
+
+ // Trigger device status upload, even if something is wrong with pumpStatus
+ self.uploadDeviceStatus(pumpStatus)
+
+ // Send SGVs
+ remoteDataManager.nightscoutUploader?.uploadSGVFromMySentryPumpStatus(status, device: device.deviceURI)
+ }
+ }
+
+ private func uploadDeviceStatus(pumpStatus: NightscoutUploadKit.PumpStatus? /*, loopStatus: LoopStatus */) {
+
+ guard let uploader = remoteDataManager.nightscoutUploader else {
+ return
+ }
+
+ // Gather UploaderStatus
+ let uploaderDevice = UIDevice.currentDevice()
+
+ let battery: Int?
+ if uploaderDevice.batteryMonitoringEnabled {
+ battery = Int(uploaderDevice.batteryLevel * 100)
+ } else {
+ battery = nil
+ }
+ let uploaderStatus = UploaderStatus(name: uploaderDevice.name, timestamp: NSDate(), battery: battery)
+
+
+ // Mock out some loop data for testing
+ // let loopTime = NSDate()
+ // let iob = IOBStatus(iob: 3.0, basaliob: 1.2, timestamp: NSDate())
+ // let loopSuggested = LoopSuggested(timestamp: loopTime, rate: 1.2, duration: NSTimeInterval(30*60), correction: 0, eventualBG: 200, reason: "Test Reason", bg: 205, tick: 5)
+ // let loopEnacted = LoopEnacted(rate: 1.2, duration: NSTimeInterval(30*60), timestamp: loopTime, received: true)
+ // let loopStatus = LoopStatus(name: "TestLoopName", timestamp: NSDate(), iob: iob, suggested: loopSuggested, enacted: loopEnacted, failureReason: nil)
+
+ // Build DeviceStatus
+ let deviceStatus = DeviceStatus(device: uploaderDevice.name, timestamp: NSDate(), pumpStatus: pumpStatus, uploaderStatus: uploaderStatus)
+
+ uploader.uploadDeviceStatus(deviceStatus)
+ }
+
+ /**
+ Ensures pump data is current by either waking and polling, or ensuring we're listening to sentry packets.
+ */
+ private func assertCurrentPumpData() {
+ guard let device = rileyLinkManager.firstConnectedDevice else {
+ return
+ }
+
+ device.assertIdleListening()
+
+ // How long should we wait before we poll for new pump data?
+ let pumpStatusAgeTolerance = rileyLinkManager.idleListeningEnabled ? NSTimeInterval(minutes: 11) : NSTimeInterval(minutes: 4)
+
+ // If we don't yet have pump status, or it's old, poll for it.
+ if latestPumpStatusDate == nil || latestPumpStatusDate!.timeIntervalSinceNow <= -pumpStatusAgeTolerance {
+ guard let device = rileyLinkManager.firstConnectedDevice else {
+ return
+ }
+
+ guard let ops = device.ops else {
+ self.troubleshootPumpCommsWithDevice(device)
+ return
+ }
+
+ ops.readPumpStatus({ (result) in
+ switch result {
+ case .Success(let status):
+ self.latestPolledPumpStatus = status
+ let battery = BatteryStatus(voltage: status.batteryVolts, status: BatteryIndicator(batteryStatus: status.batteryStatus))
+ status.clock.timeZone = ops.pumpState.timeZone
+ guard let date = status.clock.date else {
+ print("Could not interpret clock")
+ return
+ }
+ let nsPumpStatus = NightscoutUploadKit.PumpStatus(clock: date, pumpID: ops.pumpState.pumpID, iob: nil, battery: battery, suspended: status.suspended, bolusing: status.bolusing, reservoir: status.reservoir)
+ self.uploadDeviceStatus(nsPumpStatus)
+ case .Failure:
+ self.troubleshootPumpCommsWithDevice(device)
+ }
+ })
+ }
+ }
+
+ /**
+ Attempts to fix an extended communication failure between a RileyLink device and the pump
+
+ - parameter device: The RileyLink device
+ */
+ private func troubleshootPumpCommsWithDevice(device: RileyLinkDevice) {
+
+ // How long we should wait before we re-tune the RileyLink
+ let tuneTolerance = NSTimeInterval(minutes: 14)
+
+ if device.lastTuned?.timeIntervalSinceNow <= -tuneTolerance {
+ device.tunePumpWithResultHandler { (result) in
+ switch result {
+ case .Success(let scanResult):
+ print("Device auto-tuned to \(scanResult.bestFrequency) MHz")
+ case .Failure(let error):
+ print("Device auto-tune failed with error: \(error)")
+ }
}
}
}
@@ -194,7 +353,6 @@ class DeviceDataManager {
private func handleNewHistoryEvents(events: [TimestampedHistoryEvent], pumpModel: PumpModel, device: RileyLinkDevice) {
// TODO: get insulin doses from history
- // TODO: upload events to Nightscout
if Config.sharedInstance().uploadEnabled {
remoteDataManager.nightscoutUploader?.processPumpEvents(events, source: device.deviceURI, pumpModel: pumpModel)
}
@@ -206,46 +364,45 @@ class DeviceDataManager {
init() {
- let pumpState: PumpState?
+ let pumpID = Config.sharedInstance().pumpID
+
+ var idleListeningEnabled = true
if let pumpID = pumpID {
- pumpState = PumpState(pumpID: pumpID)
+ let pumpState = PumpState(pumpID: pumpID)
- if let timeZone = pumpTimeZone {
- pumpState?.timeZone = timeZone
+ if let timeZone = Config.sharedInstance().pumpTimeZone {
+ pumpState.timeZone = timeZone
}
- } else {
- pumpState = nil
+
+ if let pumpModelNumber = Config.sharedInstance().pumpModelNumber {
+ if let model = PumpModel(rawValue: pumpModelNumber) {
+ pumpState.pumpModel = model
+
+ idleListeningEnabled = model.larger
+ }
+ }
+
+ self.pumpState = pumpState
}
rileyLinkManager = RileyLinkDeviceManager(
- pumpState: pumpState,
+ pumpState: self.pumpState,
autoConnectIDs: connectedPeripheralIDs
)
+ rileyLinkManager.idleListeningEnabled = idleListeningEnabled
+ rileyLinkManager.timerTickEnabled = !idleListeningEnabled
- getHistoryTimer = NSTimer.scheduledTimerWithTimeInterval(5.0 * 60, target:self, selector:#selector(DeviceDataManager.timerTriggered), userInfo:nil, repeats:true)
-
- // This triggers one history fetch right away (in 10s)
-// let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(10 * Double(NSEC_PER_SEC)))
-// dispatch_after(delayTime, dispatch_get_main_queue()) {
-// if let rl = DeviceDataManager.sharedManager.preferredRileyLink() {
-// DeviceDataManager.sharedManager.getPumpHistory(rl)
-// }
-// }
-
UIDevice.currentDevice().batteryMonitoringEnabled = true
- rileyLinkManager.timerTickEnabled = false
- rileyLinkManagerObserver = NSNotificationCenter.defaultCenter().addObserverForName(nil, object: rileyLinkManager, queue: nil) { [weak self] (note) -> Void in
- self?.receivedRileyLinkManagerNotification(note)
- }
+ NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(receivedRileyLinkManagerNotification(_:)), name: nil, object: rileyLinkManager)
+ NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(receivedRileyLinkPacketNotification(_:)), name: RileyLinkDevice.DidReceiveIdleMessageNotification, object: nil)
+ NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(receivedRileyLinkTimerTickNotification(_:)), name: RileyLinkDevice.DidUpdateTimerTickNotification, object: nil)
- // TODO: Use delegation instead.
- rileyLinkDevicePacketObserver = NSNotificationCenter.defaultCenter().addObserverForName(RileyLinkDevice.DidReceiveIdleMessageNotification, object: nil, queue: nil) { [weak self] (note) -> Void in
- self?.receivedRileyLinkPacketNotification(note)
+ if let pumpState = pumpState {
+ NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(pumpStateValuesDidChange(_:)), name: PumpState.ValuesDidChangeNotification, object: pumpState)
}
-
}
deinit {
diff --git a/RileyLink/RemoteDataManager.swift b/RileyLink/RemoteDataManager.swift
index cec2c6c61..de7a48d66 100644
--- a/RileyLink/RemoteDataManager.swift
+++ b/RileyLink/RemoteDataManager.swift
@@ -18,7 +18,7 @@ class RemoteDataManager {
var nightscoutService: NightscoutService {
didSet {
- try! keychain.setNightscoutURL(nightscoutService.siteURL, secret: nightscoutService.APISecret)
+ keychain.setNightscoutURL(nightscoutService.siteURL, secret: nightscoutService.APISecret)
}
}
@@ -32,7 +32,7 @@ class RemoteDataManager {
} else if let siteURL = Config.sharedInstance().nightscoutURL,
APISecret = Config.sharedInstance().nightscoutAPISecret
{
- try! keychain.setNightscoutURL(siteURL, secret: APISecret)
+ keychain.setNightscoutURL(siteURL, secret: APISecret)
nightscoutService = NightscoutService(siteURL: siteURL, APISecret: APISecret)
} else {
nightscoutService = NightscoutService(siteURL: nil, APISecret: nil)
diff --git a/RileyLink/RileyLink-Info.plist b/RileyLink/RileyLink-Info.plist
index 1deb996b6..7a682dd5f 100644
--- a/RileyLink/RileyLink-Info.plist
+++ b/RileyLink/RileyLink-Info.plist
@@ -19,7 +19,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 0.7.1
+ 0.8.0
CFBundleSignature
????
CFBundleVersion
diff --git a/RileyLinkBLEKit/Info.plist b/RileyLinkBLEKit/Info.plist
index 425ef70fb..5d7827c27 100644
--- a/RileyLinkBLEKit/Info.plist
+++ b/RileyLinkBLEKit/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- 0.7.1
+ 0.8.0
CFBundleSignature
????
CFBundleVersion
diff --git a/RileyLinkBLEKitTests/Info.plist b/RileyLinkBLEKitTests/Info.plist
index 621016d74..ab895996c 100644
--- a/RileyLinkBLEKitTests/Info.plist
+++ b/RileyLinkBLEKitTests/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
BNDL
CFBundleShortVersionString
- 0.7.1
+ 0.8.0
CFBundleSignature
????
CFBundleVersion
diff --git a/RileyLinkKit/Info.plist b/RileyLinkKit/Info.plist
index 425ef70fb..5d7827c27 100644
--- a/RileyLinkKit/Info.plist
+++ b/RileyLinkKit/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- 0.7.1
+ 0.8.0
CFBundleSignature
????
CFBundleVersion
diff --git a/RileyLinkKit/PumpOps.swift b/RileyLinkKit/PumpOps.swift
index 4902eabf2..1cee3002e 100644
--- a/RileyLinkKit/PumpOps.swift
+++ b/RileyLinkKit/PumpOps.swift
@@ -105,7 +105,7 @@ public class PumpOps {
- parameter startDate: The earliest date of events to retrieve
- parameter completion: A closure called after the command is complete. This closure takes a single Result argument:
- - Success(events): An array of fetched history entries
+ - Success(events): An array of fetched history entries, in ascending order of insertion
- Failure(error): An error describing why the command failed
*/
@@ -149,6 +149,30 @@ public class PumpOps {
}
}
+
+ /**
+ Reads clock, reservoir, battery, bolusing, and suspended state from pump
+
+ This operation is performed asynchronously and the completion will be executed on an arbitrary background queue.
+
+ - parameter completion: A closure called after the command is complete. This closure takes a single Result argument:
+ - Success(status): A structure describing the current status of the pump
+ - Failure(error): An error describing why the command failed
+ */
+ public func readPumpStatus(completion: (Either) -> Void) {
+ device.runSession { (session) in
+ let ops = PumpOpsSynchronous(pumpState: self.pumpState, session: session)
+
+ do {
+ let response: PumpStatus = try ops.readPumpStatus()
+ completion(.Success(response))
+ } catch let error {
+ completion(.Failure(error))
+ }
+ }
+ }
+
+
/**
Sets a bolus
diff --git a/RileyLinkKit/PumpOpsSynchronous.swift b/RileyLinkKit/PumpOpsSynchronous.swift
index ead51960d..131cdb5d1 100644
--- a/RileyLinkKit/PumpOpsSynchronous.swift
+++ b/RileyLinkKit/PumpOpsSynchronous.swift
@@ -366,6 +366,16 @@ class PumpOpsSynchronous {
events.insert(TimestampedHistoryEvent(pumpEvent: event, date: date), atIndex: 0)
}
}
+
+ if let alarm = event as? PumpAlarmPumpEvent {
+ switch alarm.alarmType {
+ case .BatteryDepleted, .BatteryOutLimitExceeded, .DeviceReset:
+ print("Found clock loss in pump history. Ending history fetch.")
+ break pages
+ default:
+ break
+ }
+ }
}
if let event = event as? ChangeTimePumpEvent {
@@ -411,6 +421,34 @@ class PumpOpsSynchronous {
}
return frameData
}
+
+ internal func readPumpStatus() throws -> PumpStatus {
+ let clockResp: ReadTimeCarelinkMessageBody = try getMessageBodyWithType(.ReadTime)
+
+ let pumpModel = try getPumpModel()
+
+ let resResp: ReadRemainingInsulinMessageBody = try getMessageBodyWithType(.ReadRemainingInsulin)
+
+ let reservoir = resResp.getUnitsRemainingForStrokes(pumpModel.strokesPerUnit)
+
+ let battResp: GetBatteryCarelinkMessageBody = try getMessageBodyWithType(.GetBattery)
+
+ let statusResp: ReadPumpStatusMessageBody = try getMessageBodyWithType(.ReadPumpStatus)
+
+ return PumpStatus(clock: clockResp.dateComponents, batteryVolts: battResp.volts, batteryStatus: battResp.status, suspended: statusResp.suspended, bolusing: statusResp.bolusing, reservoir: reservoir, model: pumpModel, pumpID: pump.pumpID)
+
+ }
+}
+
+public struct PumpStatus {
+ public let clock: NSDateComponents
+ public let batteryVolts: Double
+ public let batteryStatus: BatteryStatus
+ public let suspended: Bool
+ public let bolusing: Bool
+ public let reservoir: Double
+ public let model: PumpModel
+ public let pumpID: String
}
public struct FrequencyTrial {
diff --git a/RileyLinkKit/UI/RileyLinkDeviceTableViewController.swift b/RileyLinkKit/UI/RileyLinkDeviceTableViewController.swift
index ab24ec932..e418a9211 100644
--- a/RileyLinkKit/UI/RileyLinkDeviceTableViewController.swift
+++ b/RileyLinkKit/UI/RileyLinkDeviceTableViewController.swift
@@ -153,7 +153,7 @@ public class RileyLinkDeviceTableViewController: UITableViewController, TextFiel
case DumpHistory
case GetPumpModel
case PressDownButton
- case ReadRemainingInsulin
+ case ReadPumpStatus
static let count = 7
}
@@ -288,8 +288,8 @@ public class RileyLinkDeviceTableViewController: UITableViewController, TextFiel
case .PressDownButton:
cell.textLabel?.text = NSLocalizedString("Send Button Press", comment: "The title of the command to send a button press")
- case .ReadRemainingInsulin:
- cell.textLabel?.text = NSLocalizedString("Read Remaining Insulin", comment: "The title of the command to read remaining insulin")
+ case .ReadPumpStatus:
+ cell.textLabel?.text = NSLocalizedString("Read Pump Status", comment: "The title of the command to read pump status")
}
}
@@ -477,21 +477,25 @@ public class RileyLinkDeviceTableViewController: UITableViewController, TextFiel
})
return NSLocalizedString("Sending button press…", comment: "Progress message for sending button press to pump.")
}
- case .ReadRemainingInsulin:
+ case .ReadPumpStatus:
vc = CommandResponseViewController {
[unowned self] (completionHandler) -> String in
- self.device.ops?.readRemainingInsulin { (result) in
+ self.device.ops?.readPumpStatus { (result) in
dispatch_async(dispatch_get_main_queue()) {
switch result {
- case .Success(let units):
- completionHandler(responseText: String(format: NSLocalizedString("%1$@ Units remaining", comment: "The format string describing units of insulin remaining: (1: number of units)"), self.decimalFormatter.stringFromNumber(units)!))
+ case .Success(let status):
+ var str = String(format: NSLocalizedString("%1$@ Units of insulin remaining\n", comment: "The format string describing units of insulin remaining: (1: number of units)"), self.decimalFormatter.stringFromNumber(status.reservoir)!)
+ str += String(format: NSLocalizedString("Battery: %1$@ volts\n", comment: "The format string describing pump battery voltage: (1: battery voltage)"), self.decimalFormatter.stringFromNumber(status.batteryVolts)!)
+ str += String(format: NSLocalizedString("Suspended: %1$@\n", comment: "The format string describing pump suspended state: (1: suspended)"), String(status.suspended))
+ str += String(format: NSLocalizedString("Bolusing: %1$@\n", comment: "The format string describing pump bolusing state: (1: bolusing)"), String(status.bolusing))
+ completionHandler(responseText: str)
case .Failure(let error):
completionHandler(responseText: String(error))
}
}
}
- return NSLocalizedString("Reading remaining insulin…", comment: "Progress message for reading pump insulin reservoir volume")
+ return NSLocalizedString("Reading pump status…", comment: "Progress message for reading pump status")
}
}
diff --git a/RileyLinkKitTests/Info.plist b/RileyLinkKitTests/Info.plist
index 621016d74..ab895996c 100644
--- a/RileyLinkKitTests/Info.plist
+++ b/RileyLinkKitTests/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
BNDL
CFBundleShortVersionString
- 0.7.1
+ 0.8.0
CFBundleSignature
????
CFBundleVersion
diff --git a/RileyLinkTests/RileyLinkTests-Info.plist b/RileyLinkTests/RileyLinkTests-Info.plist
index c3315ea15..81ef2657b 100644
--- a/RileyLinkTests/RileyLinkTests-Info.plist
+++ b/RileyLinkTests/RileyLinkTests-Info.plist
@@ -13,7 +13,7 @@
CFBundlePackageType
BNDL
CFBundleShortVersionString
- 0.7.1
+ 0.8.0
CFBundleSignature
????
CFBundleVersion