PodInfoPulseLog.swift 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. //
  2. // PodInfoPulseLog.swift
  3. // OmniBLE
  4. //
  5. // From OmniKit/MessageTransport/MessageBlocks/PodInfoPulseLog.swift
  6. // Created by Eelke Jager on 26/09/2018.
  7. // Copyright © 2018 Pete Schwamb. All rights reserved.
  8. //
  9. import Foundation
  10. // Type $50 Pod Info returns (up to) the most recent 50 32-bit pulse log entries
  11. public struct PodInfoPulseLogRecent : PodInfo {
  12. // CMD 1 2 3 4 5 6 7 8
  13. // DATA 0 1 2 3 4 5 6
  14. // 02 LL 50 IIII XXXXXXXX ...
  15. public let podInfoType : PodInfoResponseSubType = .pulseLogRecent
  16. public let indexLastEntry: Int // the pulse # for last pulse log entry
  17. public let nEntries : Int // how many 32-bit pulse entries returned (calculated)
  18. public let pulseLog : [UInt32]
  19. public let data : Data
  20. public init(encodedData: Data) throws {
  21. let logStartByteOffset = 3 // starting byte offset of the pulse log in DATA
  22. let nLogBytesReturned = encodedData.count - logStartByteOffset
  23. guard encodedData.count >= logStartByteOffset && (nLogBytesReturned & 0x3) == 0 else {
  24. throw MessageBlockError.notEnoughData // not enough data to start log or a non-integral # of pulse log entries
  25. }
  26. self.nEntries = nLogBytesReturned / MemoryLayout<UInt32>.size
  27. self.indexLastEntry = Int((UInt16(encodedData[1]) << 8) | UInt16(encodedData[2]))
  28. self.pulseLog = createPulseLog(encodedData: encodedData, logStartByteOffset: logStartByteOffset, nEntries: self.nEntries)
  29. self.data = encodedData
  30. }
  31. }
  32. // Type $51 Pod info returns (up to) the most previous 50 32-bit pulse log entries
  33. public struct PodInfoPulseLogPrevious : PodInfo {
  34. // CMD 1 2 3 4 5 6 7 8
  35. // DATA 0 1 2 3 4 5 6
  36. // 02 LL 51 NNNN XXXXXXXX ...
  37. public let podInfoType : PodInfoResponseSubType = .pulseLogPrevious
  38. public let nEntries : Int // how many 32-bit pulse log entries returned
  39. public let pulseLog : [UInt32]
  40. public let data : Data
  41. public init(encodedData: Data) throws {
  42. let logStartByteOffset = 3 // starting byte offset of the pulse log in DATA
  43. let nLogBytesReturned = encodedData.count - logStartByteOffset
  44. guard encodedData.count >= logStartByteOffset && (nLogBytesReturned & 0x3) == 0 else {
  45. throw MessageBlockError.notEnoughData // first 3 bytes missing or non-integral # of pulse log entries
  46. }
  47. let nEntriesCalculated = nLogBytesReturned / MemoryLayout<UInt32>.size
  48. self.nEntries = Int((UInt16(encodedData[1]) << 8) | UInt16(encodedData[2]))
  49. // verify we actually got all the reported entries
  50. if self.nEntries > nEntriesCalculated {
  51. throw MessageBlockError.notEnoughData // some pulse log entry count mismatch issue
  52. }
  53. self.pulseLog = createPulseLog(encodedData: encodedData, logStartByteOffset: logStartByteOffset, nEntries: self.nEntries)
  54. self.data = encodedData
  55. }
  56. }
  57. func createPulseLog(encodedData: Data, logStartByteOffset: Int, nEntries: Int) -> [UInt32] {
  58. var pulseLog: [UInt32] = Array(repeating: 0, count: nEntries)
  59. var index = 0
  60. while index < nEntries {
  61. pulseLog[index] = encodedData[(logStartByteOffset+(index*4))...].toBigEndian(UInt32.self)
  62. index += 1
  63. }
  64. return pulseLog
  65. }
  66. extension BinaryInteger {
  67. var binaryDescription: String {
  68. var binaryString = ""
  69. var internalNumber = self
  70. var counter = 0
  71. for _ in (1...self.bitWidth) {
  72. binaryString.insert(contentsOf: "\(internalNumber & 1)", at: binaryString.startIndex)
  73. internalNumber >>= 1
  74. counter += 1
  75. if counter % 8 == 0 {
  76. binaryString.insert(contentsOf: " ", at: binaryString.startIndex)
  77. }
  78. }
  79. return binaryString
  80. }
  81. }
  82. func pulseLogString(pulseLogEntries: [UInt32], lastPulseNumber: Int) -> String {
  83. var str: String = "Pulse eeeeee0a pppliiib cccccccc dfgggggg"
  84. var index = pulseLogEntries.count - 1
  85. var pulseNumber = lastPulseNumber
  86. while index >= 0 {
  87. str += String(format: "\n%04d:", pulseNumber) + UInt32(pulseLogEntries[index]).binaryDescription
  88. index -= 1
  89. pulseNumber -= 1
  90. }
  91. return str
  92. }