BasalScheduleExtraCommand.swift 4.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. //
  2. // BasalScheduleExtraCommand.swift
  3. // OmniKit
  4. //
  5. // Created by Pete Schwamb on 3/30/18.
  6. // Copyright © 2018 Pete Schwamb. All rights reserved.
  7. //
  8. import Foundation
  9. public struct BasalScheduleExtraCommand : MessageBlock {
  10. public let blockType: MessageBlockType = .basalScheduleExtra
  11. public let acknowledgementBeep: Bool
  12. public let completionBeep: Bool
  13. public let programReminderInterval: TimeInterval
  14. public let currentEntryIndex: UInt8
  15. public let remainingPulses: Double
  16. public let delayUntilNextTenthOfPulse: TimeInterval
  17. public let rateEntries: [RateEntry]
  18. public var data: Data {
  19. let beepOptions = (UInt8(programReminderInterval.minutes) & 0x3f) + (completionBeep ? (1<<6) : 0) + (acknowledgementBeep ? (1<<7) : 0)
  20. var data = Data([
  21. blockType.rawValue,
  22. UInt8(8 + rateEntries.count * 6),
  23. beepOptions,
  24. currentEntryIndex
  25. ])
  26. data.appendBigEndian(UInt16(round(remainingPulses * 10)))
  27. data.appendBigEndian(UInt32(round(delayUntilNextTenthOfPulse.milliseconds * 1000)))
  28. for entry in rateEntries {
  29. data.append(entry.data)
  30. }
  31. return data
  32. }
  33. public init(encodedData: Data) throws {
  34. if encodedData.count < 14 {
  35. throw MessageBlockError.notEnoughData
  36. }
  37. let length = encodedData[1]
  38. let numEntries = (length - 8) / 6
  39. acknowledgementBeep = encodedData[2] & (1<<7) != 0
  40. completionBeep = encodedData[2] & (1<<6) != 0
  41. programReminderInterval = TimeInterval(minutes: Double(encodedData[2] & 0x3f))
  42. currentEntryIndex = encodedData[3]
  43. remainingPulses = Double(encodedData[4...].toBigEndian(UInt16.self)) / 10.0
  44. let timerCounter = encodedData[6...].toBigEndian(UInt32.self)
  45. delayUntilNextTenthOfPulse = TimeInterval(hundredthsOfMilliseconds: Double(timerCounter))
  46. var entries = [RateEntry]()
  47. for entryIndex in (0..<numEntries) {
  48. let offset = 10 + entryIndex * 6
  49. let totalPulses = Double(encodedData[offset...].toBigEndian(UInt16.self)) / 10.0
  50. let timerCounter = encodedData[(offset+2)...].toBigEndian(UInt32.self)
  51. let delayBetweenPulses = TimeInterval(hundredthsOfMilliseconds: Double(timerCounter))
  52. entries.append(RateEntry(totalPulses: totalPulses, delayBetweenPulses: delayBetweenPulses))
  53. }
  54. rateEntries = entries
  55. }
  56. public init(currentEntryIndex: UInt8, remainingPulses: Double, delayUntilNextTenthOfPulse: TimeInterval, rateEntries: [RateEntry], acknowledgementBeep: Bool = false, completionBeep: Bool = false, programReminderInterval: TimeInterval = 0) {
  57. self.currentEntryIndex = currentEntryIndex
  58. self.remainingPulses = remainingPulses
  59. self.delayUntilNextTenthOfPulse = delayUntilNextTenthOfPulse
  60. self.rateEntries = rateEntries
  61. self.acknowledgementBeep = acknowledgementBeep
  62. self.completionBeep = completionBeep
  63. self.programReminderInterval = programReminderInterval
  64. }
  65. public init(schedule: BasalSchedule, scheduleOffset: TimeInterval, acknowledgementBeep: Bool = false, completionBeep: Bool = false, programReminderInterval: TimeInterval = 0) {
  66. var rateEntries = [RateEntry]()
  67. let mergedSchedule = BasalSchedule(entries: schedule.entries.adjacentEqualRatesMerged())
  68. for entry in mergedSchedule.durations() {
  69. rateEntries.append(contentsOf: RateEntry.makeEntries(rate: entry.rate, duration: entry.duration))
  70. }
  71. self.rateEntries = rateEntries
  72. let scheduleOffsetNearestSecond = round(scheduleOffset)
  73. let (entryIndex, entry, duration) = mergedSchedule.lookup(offset: scheduleOffsetNearestSecond)
  74. self.currentEntryIndex = UInt8(entryIndex)
  75. let timeRemainingInEntry = duration - (scheduleOffsetNearestSecond - entry.startTime)
  76. let rate = mergedSchedule.rateAt(offset: scheduleOffsetNearestSecond)
  77. let pulsesPerHour = round(rate / Pod.pulseSize)
  78. let timeBetweenPulses = TimeInterval(hours: 1) / pulsesPerHour
  79. self.delayUntilNextTenthOfPulse = timeRemainingInEntry.truncatingRemainder(dividingBy: (timeBetweenPulses / 10))
  80. self.remainingPulses = pulsesPerHour * (timeRemainingInEntry-self.delayUntilNextTenthOfPulse) / .hours(1) + 0.1
  81. self.acknowledgementBeep = acknowledgementBeep
  82. self.completionBeep = completionBeep
  83. self.programReminderInterval = programReminderInterval
  84. }
  85. }