def read_next_message(self): """ Read the next message from the serial port, assuming the message-start character has just been read. Returned message is array of bytes. It is decoded from the ASCII representation, and includes the checksum on the end, and the length byte at the start. The checksum is NOT validated. A valid message will have at 2 bytes for length & checksum, plus at least a single byte for the command code, so 3 or more bytes in total. This function will read as many length bytes as are indicated at the start of the message, which may *not* be a valid message, and so the message returned from here may be as short as only one byte (the length byte). May raise TimeoutException if there is a timeout while reading the message. If any special control character is encountered while reading the message, control_char_cb will be called with that character. """ # Read length; this is is encoded as a hex string with two ascii # bytes; the length includes the single checksum byte at the end, # which is also encoded as a hex string. len_bytes, ctrl_chars = self._try_to_read(2) try: msg_len = ascii_hex_to_byte(len_bytes) except ValueError: raise BadEncoding("Invalid length encoding: 0x%x 0x%x" % \ (len_bytes[0], len_bytes[1])) # Read the rest of the message, including checksum. msg_ascii = [' '] * (msg_len + 1) * 2 msg_ascii[0:2] = len_bytes msg_bytes, ctrl_chars2 = self._try_to_read(msg_len * 2) msg_ascii[2:] = msg_bytes ctrl_chars.extend(ctrl_chars2) # Handle any control characters; we are assuming it's ok to wait # until the end of the message to deal with them, since they can # be sent asynchronously with respect to other messages sent by # the panel e.g. an ACK to one of our sent messages for cc in ctrl_chars: self.control_char_cb(cc) # Decode from ascii hex representation to binary. msg_bin = [0] * (msg_len + 1) try: for i in range(msg_len + 1): msg_bin[i] = ascii_hex_to_byte(msg_ascii[2 * i:2 * i + 2]) except ValueError: raise BadEncoding("Invalid message encoding: %r" % msg_ascii) return msg_bin
def decode_message_from_ascii(ascii_msg): n = len(ascii_msg) if n % 2 != 0: raise BadEncoding("ASCII message has uneven number of characters.") b = [0] * (n / 2) for i in range(n / 2): b[i] = ascii_hex_to_byte(ascii_msg[2 * i:2 * i + 2]) return b