import Foundation import NIOCore /** Encapsulates a response from a device. */ struct DeviceResponse { /// Shorthand property for a timeout event. static var deviceTimedOut: DeviceResponse { .init(event: .deviceTimedOut) } /// Shorthand property for a disconnected event. static var deviceNotConnected: DeviceResponse { .init(event: .deviceNotConnected) } /// Shorthand property for a connected event. static var deviceConnected: DeviceResponse { .init(event: .deviceConnected) } /// Shorthand property for an unexpected socket event. static var unexpectedSocketEvent: DeviceResponse { .init(event: .unexpectedSocketEvent) } /// Shorthand property for an invalid message. static var invalidMessageData: DeviceResponse { .init(event: .invalidMessageData) } /// Shorthand property for missing body data. static var noBodyData: DeviceResponse { .init(event: .noBodyData) } /// Shorthand property for a busy connection static var operationInProgress: DeviceResponse { .init(event: .operationInProgress) } /// The response to a key from the server let event: MessageResult /// The index of the next key to use let response: Message? /** Decode a message from a buffer. The buffer must contain `Message.length+1` bytes. The first byte denotes the event type, the remaining bytes contain the message. - Parameter buffer: The buffer where the message bytes are stored */ init?(_ buffer: ByteBuffer, request: String) { guard let byte = buffer.getBytes(at: 0, length: 1) else { log("\(request): No bytes received from device") return nil } guard let event = MessageResult(rawValue: byte[0]) else { log("\(request): Unknown response \(byte[0]) received from device") return nil } self.event = event guard let data = buffer.getSlice(at: 1, length: Message.length) else { log("\(request): Insufficient data received from device (expected \(Message.length + 1), got \(buffer.readableBytes))") self.response = nil return } guard let message = Message(decodeFrom: data) else { log("\(request): Failed to decode message received from device") self.response = nil return } self.response = message } /** Create a response from an event without a message from the device. - Parameter event: The response from the device. */ init(event: MessageResult) { self.event = event self.response = nil } /// Get the reponse encoded in bytes. var encoded: Data { guard let message = response else { return Data([event.rawValue]) } return Data([event.rawValue]) + message.encoded } }