def to_representation(self): header = f"{constants.SOH}{self.command}{self.command_type}" if self.data_set: body = f"{constants.STX}{self.data_set.to_representation()}{constants.ETX}" else: body = f"{constants.ETX}" message = f"{header}{body}" return utils.add_bcc(message)
def to_representation(self): if self.partial_blocks: command = "R3" rows_per_block = self.rows_per_block else: command = "R1" rows_per_block = "" rep = ( f"{constants.SOH}{command}{constants.STX}{self.archive}:V.{self.attribute}" f"({self.position};{self.start};{self.end};{rows_per_block}){constants.ETX}" ) return utils.add_bcc(rep)
def read(self, timeout=None): """ Will read a normal readout. Supports both full and partial block readout. When using partial blocks it will recreate the messages as it was not sent with partial blocks :param timeout: :return: """ start_chars = [b"\x01", b"\x02"] end_chars = [b"\x03", b"\x04"] total_data = b"" packets = 0 start_char_received = False start_char = None end_char = None timeout = timeout or self.timeout while True: in_data = b"" duration = 0 start_time = time.time() while True: b = self.recv(1) duration = time.time() - start_time if duration > self.timeout: raise TimeoutError( f"Read in {self.__class__.__name__} timed out") if b == b'\x15' or b == b'\x06': in_data += b logger.debug( f"Received {in_data!r} over transport: {self.__class__.__name__}" ) return in_data if not start_char_received: # is start char? if b in start_chars: in_data += b start_char_received = True start_char = b continue else: continue else: # is end char? if b in end_chars: in_data += b end_char = b break else: in_data += b continue packets += 1 bcc = self.recv(1) in_data += bcc logger.debug( f"Received {in_data!r} over transport: {self.__class__.__name__}" ) if start_char == b"\x01": # This is a command message, probably Password challange. total_data += in_data break if end_char == b"\x04": # EOT (partial read) # we received a partial block if not utils.bcc_valid(in_data): # Nack and read again self.send(constants.NACK.encode(constants.ENCODING)) continue else: # ack and read next self.send(constants.ACK.encode(constants.ENCODING)) # remove bcc and eot and add line end. in_data = in_data[:-2] + constants.LINE_END.encode( constants.ENCODING) if packets > 1: # remove the leading STX in_data = in_data[1:] total_data += in_data continue if end_char == b"\x03": # Either it was the only message or we got the last message. if not utils.bcc_valid(in_data): # Nack and read again self.send(constants.NACK.encode(constants.ENCODING)) continue else: if packets > 1: in_data = in_data[1:] # removing the leading STX total_data += in_data if packets > 1: # The last bcc is not correct compared to the whole # message. But we have verified all the bccs along the way so # we just compute it so the message is usable. total_data = utils.add_bcc(total_data[:-1]) break return total_data
def to_representation(self): # TODO: this is not valid in case reading out partial blocks. rep = f"{constants.STX}{self.data_block.to_representation()}{constants.ETX}" return utils.add_bcc(rep)
def to_representation(self): data = ( f"{constants.STX}{self.data_block.to_representation()}{constants.END_CHAR}" f"{constants.LINE_END}{constants.ETX}") return utils.add_bcc(data)
def test_add_bcc1(self): data = "\x01P0\x02(1234567)\x03" correct_data = "\x01P0\x02(1234567)\x03P" with_bcc = add_bcc(data) assert with_bcc == correct_data