BolusNormalPumpEvent.swift 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. //
  2. // BolusNormalPumpEvent.swift
  3. // RileyLink
  4. //
  5. // Created by Pete Schwamb on 3/7/16.
  6. // Copyright © 2016 Pete Schwamb. All rights reserved.
  7. //
  8. import Foundation
  9. public struct BolusNormalPumpEvent: TimestampedPumpEvent {
  10. public enum BolusType: String {
  11. case normal = "Normal"
  12. case square = "Square"
  13. }
  14. public let length: Int
  15. public let rawData: Data
  16. public let timestamp: DateComponents
  17. public var unabsorbedInsulinRecord: UnabsorbedInsulinPumpEvent?
  18. public let amount: Double
  19. public let programmed: Double
  20. public let unabsorbedInsulinTotal: Double
  21. public let type: BolusType
  22. public let duration: TimeInterval
  23. public let wasRemotelyTriggered: Bool
  24. public init(length: Int, rawData: Data, timestamp: DateComponents, unabsorbedInsulinRecord: UnabsorbedInsulinPumpEvent?, amount: Double, programmed: Double, unabsorbedInsulinTotal: Double, type: BolusType, duration: TimeInterval, wasRemotelyTriggered: Bool) {
  25. self.length = length
  26. self.rawData = rawData
  27. self.timestamp = timestamp
  28. self.unabsorbedInsulinRecord = unabsorbedInsulinRecord
  29. self.amount = amount
  30. self.programmed = programmed
  31. self.unabsorbedInsulinTotal = unabsorbedInsulinTotal
  32. self.type = type
  33. self.duration = duration
  34. self.wasRemotelyTriggered = wasRemotelyTriggered
  35. }
  36. /*
  37. It takes a MM pump about 40s to deliver 1 Unit while bolusing
  38. See: http://www.healthline.com/diabetesmine/ask-dmine-speed-insulin-pumps#3
  39. */
  40. private let deliveryUnitsPerMinute = 1.5
  41. // The actual expected time of delivery, based on bolus speed
  42. public var deliveryTime: TimeInterval {
  43. if duration > 0 {
  44. return duration
  45. } else {
  46. return TimeInterval(minutes: programmed / deliveryUnitsPerMinute)
  47. }
  48. }
  49. public init?(availableData: Data, pumpModel: PumpModel) {
  50. func doubleValueFromData(at index: Int) -> Double {
  51. return Double(availableData[index])
  52. }
  53. func decodeInsulin(from bytes: Data) -> Double {
  54. return Double(Int(bigEndianBytes: bytes)) / Double(pumpModel.insulinBitPackingScale)
  55. }
  56. length = BolusNormalPumpEvent.calculateLength(pumpModel.larger)
  57. guard length <= availableData.count else {
  58. return nil
  59. }
  60. rawData = availableData.subdata(in: 0..<length)
  61. if pumpModel.larger {
  62. timestamp = DateComponents(pumpEventData: availableData, offset: 8)
  63. wasRemotelyTriggered = availableData[11] & 0b01000000 != 0
  64. programmed = decodeInsulin(from: availableData.subdata(in: 1..<3))
  65. amount = decodeInsulin(from: availableData.subdata(in: 3..<5))
  66. unabsorbedInsulinTotal = decodeInsulin(from: availableData.subdata(in: 5..<7))
  67. duration = TimeInterval(minutes: 30 * doubleValueFromData(at: 7))
  68. } else {
  69. timestamp = DateComponents(pumpEventData: availableData, offset: 4)
  70. wasRemotelyTriggered = availableData[7] & 0b01000000 != 0
  71. programmed = decodeInsulin(from: availableData.subdata(in: 1..<2))
  72. amount = decodeInsulin(from: availableData.subdata(in: 2..<3))
  73. duration = TimeInterval(minutes: 30 * doubleValueFromData(at: 3))
  74. unabsorbedInsulinTotal = 0
  75. }
  76. type = duration > 0 ? .square : .normal
  77. }
  78. public var dictionaryRepresentation: [String: Any] {
  79. var dictionary: [String: Any] = [
  80. "_type": "BolusNormal",
  81. "amount": amount,
  82. "programmed": programmed,
  83. "type": type.rawValue,
  84. "wasRemotelyTriggered": wasRemotelyTriggered,
  85. ]
  86. if let unabsorbedInsulinRecord = unabsorbedInsulinRecord {
  87. dictionary["appended"] = unabsorbedInsulinRecord.dictionaryRepresentation
  88. }
  89. if unabsorbedInsulinTotal > 0 {
  90. dictionary["unabsorbed"] = unabsorbedInsulinTotal
  91. }
  92. if duration > 0 {
  93. dictionary["duration"] = duration
  94. }
  95. return dictionary
  96. }
  97. public static func calculateLength(_ isLarger:Bool) -> Int {
  98. if isLarger {
  99. return 13
  100. } else {
  101. return 9
  102. }
  103. }
  104. }