Example #1
0
    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
Example #2
0
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