MockPumpMessageSender.swift 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. //
  2. // MockPumpMessageSender.swift
  3. // MinimedKitTests
  4. //
  5. // Created by Pete Schwamb on 1/7/23.
  6. // Copyright © 2023 LoopKit Authors. All rights reserved.
  7. //
  8. import MinimedKit
  9. import RileyLinkBLEKit
  10. class MockPumpMessageSender: PumpMessageSender {
  11. var pumpID = "636781"
  12. func listenForPacket(onChannel channel: Int, timeout: TimeInterval) throws -> RileyLinkBLEKit.RFPacket? {
  13. // do nothing
  14. return nil
  15. }
  16. func getRileyLinkStatistics() throws -> RileyLinkStatistics {
  17. throw PumpOpsError.noResponse(during: "Tests")
  18. }
  19. func makeMockResponse(_ messageType: MessageType, _ messageBody: MessageBody) -> PumpMessage {
  20. return PumpMessage(packetType: .carelink, address: pumpID, messageType: messageType, messageBody: messageBody)
  21. }
  22. var ack: PumpMessage {
  23. return PumpMessage(pumpID: pumpID, type: .pumpAck)
  24. }
  25. func sendAndListen(_ data: Data, repeatCount: Int, timeout: TimeInterval, retryCount: Int) throws -> RFPacket {
  26. guard let decoded = MinimedPacket(encodedData: data),
  27. let messageType = MessageType(rawValue: decoded.data[4])
  28. else {
  29. throw PumpOpsError.noResponse(during: "Tests")
  30. }
  31. let response: PumpMessage
  32. if let responseArray = responses[messageType] {
  33. let numberOfResponsesReceived: Int
  34. if let someValue = responsesHaveOccured[messageType] {
  35. numberOfResponsesReceived = someValue
  36. } else {
  37. numberOfResponsesReceived = 0
  38. }
  39. let nextNumberOfResponsesReceived = numberOfResponsesReceived + 1
  40. responsesHaveOccured[messageType] = nextNumberOfResponsesReceived
  41. if responseArray.count <= numberOfResponsesReceived {
  42. throw PumpOpsError.noResponse(during: data)
  43. }
  44. response = responseArray[numberOfResponsesReceived]
  45. } else {
  46. // .pumpAck from 636781 ?
  47. let packet = MinimedPacket(encodedData: Data(hexadecimalString: "a969a39966b1566555b235")!)!
  48. response = PumpMessage(rxData: packet.data)!
  49. }
  50. var encoded = MinimedPacket(outgoingData: response.txData).encodedData()
  51. encoded.insert(contentsOf: [0, 0], at: 0)
  52. guard let rfPacket = RFPacket(rfspyResponse: encoded) else {
  53. throw PumpOpsError.noResponse(during: data)
  54. }
  55. return rfPacket
  56. }
  57. func getResponse<T: MessageBody>(to message: PumpMessage, responseType: MessageType, repeatCount: Int, timeout: TimeInterval, retryCount: Int) throws -> T {
  58. let response = try sendAndListen(message, repeatCount: repeatCount, timeout: timeout, retryCount: retryCount)
  59. guard response.messageType == responseType, let body = response.messageBody as? T else {
  60. if let body = response.messageBody as? PumpErrorMessageBody {
  61. switch body.errorCode {
  62. case .known(let code):
  63. throw PumpOpsError.pumpError(code)
  64. case .unknown(let code):
  65. throw PumpOpsError.unknownPumpErrorCode(code)
  66. }
  67. } else {
  68. throw PumpOpsError.unexpectedResponse(response, from: message)
  69. }
  70. }
  71. return body
  72. }
  73. /// Sends a message to the pump, listening for a any known PumpMessage in reply
  74. ///
  75. /// - Parameters:
  76. /// - message: The message to send
  77. /// - repeatCount: The number of times to repeat the message before listening begins
  78. /// - timeout: The length of time to listen for a pump response
  79. /// - retryCount: The number of times to repeat the send & listen sequence
  80. /// - Returns: The message reply
  81. /// - Throws: An error describing a failure in the sending or receiving of a message:
  82. /// - PumpOpsError.couldNotDecode
  83. /// - PumpOpsError.crosstalk
  84. /// - PumpOpsError.deviceError
  85. /// - PumpOpsError.noResponse
  86. /// - PumpOpsError.unknownResponse
  87. func sendAndListen(_ message: PumpMessage, repeatCount: Int, timeout: TimeInterval, retryCount: Int) throws -> PumpMessage {
  88. let rfPacket = try sendAndListenForPacket(message, repeatCount: repeatCount, timeout: timeout, retryCount: retryCount)
  89. guard let packet = MinimedPacket(encodedData: rfPacket.data) else {
  90. throw PumpOpsError.couldNotDecode(rx: rfPacket.data, during: message)
  91. }
  92. guard let response = PumpMessage(rxData: packet.data) else {
  93. // Unknown packet type or message type
  94. throw PumpOpsError.unknownResponse(rx: packet.data, during: message)
  95. }
  96. guard response.address == message.address else {
  97. throw PumpOpsError.crosstalk(response, during: message)
  98. }
  99. return response
  100. }
  101. // Send a PumpMessage, and listens for a packet; used by callers who need to see RSSI
  102. /// - Throws:
  103. /// - PumpOpsError.noResponse
  104. /// - PumpOpsError.deviceError
  105. func sendAndListenForPacket(_ message: PumpMessage, repeatCount: Int, timeout: TimeInterval, retryCount: Int) throws -> RFPacket {
  106. let packet: RFPacket?
  107. do {
  108. packet = try sendAndListen(MinimedPacket(outgoingData: message.txData).encodedData(), repeatCount: repeatCount, timeout: timeout, retryCount: retryCount)
  109. } catch let error as LocalizedError {
  110. throw error
  111. }
  112. guard let rfPacket = packet else {
  113. throw PumpOpsError.noResponse(during: message)
  114. }
  115. return rfPacket
  116. }
  117. func listen(onChannel channel: Int, timeout: TimeInterval) throws -> RFPacket? {
  118. throw PumpOpsError.noResponse(during: "Tests")
  119. }
  120. func send(_ msg: MinimedKit.PumpMessage) throws {
  121. // Do nothing
  122. }
  123. func updateRegister(_ address: CC111XRegister, value: UInt8) throws {
  124. throw PumpOpsError.noResponse(during: "Tests")
  125. }
  126. func resetRadioConfig() throws {
  127. throw PumpOpsError.noResponse(during: "Tests")
  128. }
  129. func setBaseFrequency(_ frequency: Measurement<UnitFrequency>) throws {
  130. throw PumpOpsError.noResponse(during: "Tests")
  131. }
  132. var responses = [MessageType: [PumpMessage]]()
  133. // internal tracking of how many times a response type has been received
  134. private var responsesHaveOccured = [MessageType: Int]()
  135. }
  136. extension MockPumpMessageSender: PumpOpsSessionDelegate {
  137. func pumpOpsSession(_ session: PumpOpsSession, didChange state: PumpState) {
  138. }
  139. func pumpOpsSessionDidChangeRadioConfig(_ session: PumpOpsSession) {
  140. }
  141. }