def encode_datagram(self, value): protocol_version = value.get( 'protocol_version', PROTOCOL_MAJOR_VERSION) timestamp = get_timestamp_or_now(value) packet_seq = value.get('packet_seq', get_packet_sequence_number()) packet_type = value.get('packet_type', 0) plugin_id = value.get('plugin_id', 0) plugin_major_version = value.get('plugin_major_version', 0) plugin_minor_version = value.get('plugin_minor_version', 0) plugin_patch_version = value.get('plugin_patch_version', 0) plugin_instance = value.get('plugin_instance', 0) plugin_run_id = value.get('plugin_run_id', RUN_ID) body = value['body'] body_length = len(body) body_crc = crc8(body) self.encode_uint(1, START_FLAG) self.encode_uint(3, body_length) self.encode_uint(1, protocol_version) self.encode_uint(4, timestamp) self.encode_uint(2, packet_seq) self.encode_uint(1, packet_type) self.encode_uint(2, plugin_id) self.encode_uint(1, plugin_major_version) self.encode_uint(1, plugin_minor_version) self.encode_uint(1, plugin_patch_version) self.encode_uint(1, plugin_instance) self.encode_uint(2, plugin_run_id) self.encode_bytes(body) self.encode_uint(1, body_crc) self.encode_uint(1, END_FLAG)
def request_data(self, sensors): # Packaging buffer = bytearray() buffer.append(0xAA) # preamble buffer.append(0x02) # data type (request) | protocol version (2) buffer.append(len(buffer)) third_byte = 0x80 | self.SQN if self.SQN < 0x7F: self.SQN += 1 else: self.SQN = 0 buffer.append(third_byte) # sequence ( 0 ) data = bytearray() while (len(sensors) != 0): if sensors[0] <= 0x06: data.append(sensors[0]) # function type data.append(0x01) data.append(sensors[1]) # sensor id sensors = sensors[2::] elif sensors[0] >= 0x11 and sensors[0] <= 0x16: data.append(sensors[0]) # function type data.append(sensors[1]) # bus type data.append(sensors[2]) # bus address data.extend(sensors[3:sensors[1] + 2]) # parameters sensors = sensors[sensors[1] + 2::] buffer.extend(data) buffer[2] = len(data) + 1 buffer.append(crc8(buffer[3:])) # crc buffer.append(0x55) # postscript self.serial.write(bytes(buffer)) return self.read_response()
def test_crc8(self): test_cases = [ (bytes([]), 0), (bytes([0x80]), 0x8c), (bytes([1, 2, 3]), 216), (bytes([0xff] * 1024), 201), ] for data, crc in test_cases: self.assertEqual(crc8(data), crc)
def read_response(self, timeout=180): data = bytearray() packets = bytearray() # The response must be received within 3 minutes for i in range(timeout * 2): if self.serial.inWaiting() > 0 or len(data) > 0: data.extend(self.serial.read(self.serial.inWaiting())) while True: try: del data[:data.index(self.START_BYTE)] except ValueError: del data[:] if len(data) >= self.HEADER_SIZE: packet_length = data[2] if len( data ) >= self.HEADER_SIZE + packet_length + self.FOOTER_SIZE: packet = data[:self.HEADER_SIZE + packet_length + self.FOOTER_SIZE] crc = packet[-2] if crc != crc8(packet[self.HEADER_SIZE:-2]): return None sequence = data[3] packets.extend(packet) del data[:len(packet)] if (sequence & 0x80) == 0x80: return packets else: time.sleep(0.5) break else: time.sleep(0.5) break else: time.sleep(0.5) # TIMEOUT: return packet that have been received return packets
def decode_datagram(self): start_flag = self.decode_uint(1) if start_flag != START_FLAG: raise ValueError('Invalid start flag.') body_length = self.decode_uint(3) protocol_version = self.decode_uint(1) timestamp = self.decode_uint(4) packet_seq = self.decode_uint(2) packet_type = self.decode_uint(1) plugin_id = self.decode_uint(2) plugin_major_version = self.decode_uint(1) plugin_minor_version = self.decode_uint(1) plugin_patch_version = self.decode_uint(1) plugin_instance = self.decode_uint(1) plugin_run_id = self.decode_uint(2) body = self.decode_bytes(body_length) body_crc = self.decode_uint(1) if crc8(body) != body_crc: raise ValueError('Invalid body CRC.') end_flag = self.decode_uint(1) if end_flag != END_FLAG: raise ValueError('Invalid end flag.') return { 'timestamp': timestamp, 'packet_seq': packet_seq, 'packet_type': packet_type, 'plugin_id': plugin_id, 'plugin_major_version': plugin_major_version, 'plugin_minor_version': plugin_minor_version, 'plugin_patch_version': plugin_patch_version, 'plugin_instance': plugin_instance, 'plugin_run_id': plugin_run_id, 'body': body, }