def _check_ack(self, message, check_ACK=False): function_code = message.get_function() if function_code == 0x15: # NAK raise CommunicationError('Received a NAK') if check_ACK == True and function_code != 0x06: # ACK raise CommunicationError('Received NOT a ACK')
def _read_response(self, command: Command): try: # Read exactly one byte. This is the verification of the cesar unit # its either ACK (0x06) or NACK (0x15) verification = self._transport.read(1) self._logger.debug( "Received ACK/NAK byte: {}".format(verification)) if verification == self.ACK: pass elif verification == self.NAK: raise CommunicationError("Device returned NAK") # in fact, we can compute how long the response will be, based on the first two bytes read # but this works for us and we dont care about more details... raw_response = self._transport.read(self.RESPONSE_MAX_LENGTH) self._logger.debug("Received {}".format(" ".join( map(hex, raw_response)))) # Now send back a ACK since we got our data, even if the data is not valid # We just don't care about this. If the data is not valid, we throw an exception # and the calling api will re-engage into sending the message self._transport.write(bytearray([self.ACK])) self._logger.debug("Sent ACK to device") except SerialTimeoutException: raise CommunicationError("Could not read response. Timeout") raw_response = bytearray(raw_response) msg = MessagePacket.from_raw(raw_response) if not msg.is_valid(): raise CommunicationError("Received response is not valid") response = Response(command.get_outputs()) # we received not the same amount of data than expected. This occurs only in two cases: # 1. The protocol was not correctly specified by the user # 2. The device returns just an CSR code instead of the data if command.get_expected_response_data_length() != msg.get_data_length( ): # This is then the case 2 if msg.get_data_length() == 1: response.get_csr().set_raw(msg.get_data()) else: raise CommunicationError( "Received an unexpected amount of data ({} bytes) from device. Expected {} bytes (excluding CSR)" .format(msg.get_data_length, command.get_expected_response_data_length())) else: # Here we just assign the data to the correct output self._assign_data(msg.get_data(), command.get_outputs()) return response
def is_acknowledged(self): response = self.get_response() if self.is_nack(response): raise CommunicationError( "Acknowledgement error! Negative Acknowledgement received") if not self.is_ack(response): raise CommunicationError( "Acknowledgement error! No acknowledgement was sent back from gauge" )
def _read_response(self, msg): assert isinstance(msg, AbstractMessage) frames = self._read_response_frames() responses = [] resp_class = msg.get_response_class() for frame in frames: # We received an invalid frame. This can mean the following: # 1. the relay did not produce a correct message # 2. we got some bit errors on the transmission process # # However, one invalid frame means that we cant trust any other frame. if not frame.is_valid(): self._logger.error("Received an invalid frame: {}", frame) raise CommunicationError("Received an invalid frame") message = Message() message.set_frame(frame) # create the response from the message. the response class is derived from the message which was # sent to the relay card. Every message has a corresponding response. response = resp_class(message) # only add valid responses, and discard 'relayed messages' # # A relayed message can appear in the following case: # Any cmd is sent to a non-existing relay (eg. address not existing), the # cmd will be forwarded to the next relay until the last relay in the chain reads it. # This relay will then just send the cmd back to the controlling pc. if response.is_valid(): responses.append(response) else: self._logger.debug( "Got invalid response '{}' of type {}".format( response, resp_class.__name__)) # At least one response has to be valid. Note that not all responses are necessary valid. # # # Note: An invalid response is not the same as an invalid frame. # Invalid frame: the byte representation is not correct # Invalid response: We received a correct frame, but the content (e.g. command id) is unexpected or unknown. # # Consider for example the Setup message. The last response will be a relayed message, thus being invalid. # If we get only invalid messages, raise this exception. if len(responses) == 0: raise CommunicationError("Received no valid response") return Responses(responses)
def _read_response(self, transport): try: resp = list(transport.read_bytes(5)) self.logger.debug('Received message: %s', repr(map(hex, resp))) return resp except slave.transport.Timeout: raise CommunicationError('Timeout while receive response')
def get_response(self, transport): try: raw = transport.read_until(RawMessage.TERMINATOR) return "".join([chr(x) for x in raw]) + RawMessage.TERMINATOR except slave.transport.Timeout: raise CommunicationError( "Received a timeout while reading response")
def query(self, transport, message): with InterProcessTransportLock(transport): self.send_message(transport, message) length = message.response_length() raw_response = transport.read_bytes(length) self.logger.debug('Recevied response (%s bytes): "%s"', str(length), " ".join(map(hex, raw_response))) response_as_hex = [] for i in range(0, length): response_as_hex.append(raw_response[i]) response = message.create_response(response_as_hex) if not response.is_valid_crc(): raise CommunicationError( 'Received an invalid response packet. CRC dismatch.') if response.is_nack(): self.logger.warning('Received a NAK Response') return response
def _send_message(self, message): try: raw_message = message + "\r" self._logger.debug("Sending message %s", repr(message)) self._transport.write(raw_message) except SerialTimeoutException: self._logger.exception("Error while sending message") raise CommunicationError("Could not send message. timeout")
def read_response(self): try: # remove the last two bytes since they are just \r\n resp = self._transport.read_until("\r\n")[0:-2] self._logger.debug('Response: "%s"', repr(resp)) return resp except: raise CommunicationError("Could not read response")
def _receive_message(self): try: msg = self._transport.read_until("\r\n") self._logger.debug("Received message %s", repr(msg)) return "".join(map(chr, msg)) except SerialTimeoutException: self._logger.exception("Error while receiving message") raise CommunicationError("Could not receive message. Timeout")
def read_response(self, transport): with InterProcessTransportLock(transport): try: resp = transport.read_exactly(21) self.logger.debug('Received response: "%s"', repr(resp)) return resp except slave.transport.Timeout: raise CommunicationError("Could not read response")
def get_response(self): try: resp = self._transport.read_until( self.responseTerminal.encode(self.encoding)) self._logger.debug("Received {}".format(repr(resp))) # now remove the response terminal return resp[:-len(self.responseTerminal)] except SerialTimeoutException: raise CommunicationError("Received a timeout")
def _read_response(self): raw_response = self._transport.read_until(AsciiMessage.END) self._logger.debug("Received message '{}'".format(repr(raw_response))) response = AsciiResponse.from_raw(raw_response) if response.get_cmd() == '???': raise CommunicationError( "Unknown message send to device. Device did not understand.") return response
def read_response(self, transport): try: response = transport.read_until(Message.ETX) ret = [] for chunk in response: ret.append(chr(chunk)) ret.append(Message.ETX) return ret except: raise CommunicationError("Could not read response")
def query(self, transport, message): with InterProcessTransportLock(transport): if not isinstance(message, AbstractMessage): raise TypeError( "message must be an instance of AbstractMessage") msg = message.get_message() msg.set_address(self.receiver) msg.set_checksum(msg.compute_checksum()) self.send_message(transport, msg) response = self.read_response(transport) resp = message.create_response(response) if not resp.is_valid(): self.logger.error("Received invalid response: %s", resp) raise CommunicationError("Invalid response") if not resp.is_successful(): self.logger.warning("Action (%s) was not successful: %s", message, resp) return resp
def check_checksum(self, message): if message.compute_checksum() != message.get_checksum(): raise CommunicationError('Received an invalid checksum')
def _send_raw(self, transport, data): try: self.logger.debug('Sending message: %s', repr(data)) transport.write(data) except slave.transport.Timeout: raise CommunicationError('Timeout while sending message %s' % repr(data))
def send_message(self, raw_data): try: self._logger.debug('Sending: "%s"', repr(raw_data)) self._transport.write(raw_data) except: raise CommunicationError("Could not send data")