def from_bytes(cls, source_bytes: bytes): data = bytearray(source_bytes) tag = data.pop(0) if tag != cls.TAG: raise ValueError( f"Tag is not correct. Should be {cls.TAG} but is {tag}") response_type = enums.GetResponseType(data.pop(0)) if response_type != cls.RESPONSE_TYPE: raise ValueError( f"The response type byte: {response_type} is not for a GetResponseNormal" ) invoke_id_and_priority = InvokeIdAndPriority.from_bytes( data.pop(0).to_bytes(1, "big")) last_block = bool(data.pop(0)) if not last_block: raise ValueError( f"Last block is not set to true in a GetResponseLastBlock.") block_number = int.from_bytes(data[:4], "big") data = data[4:] choice = data.pop(0) if choice != 0: raise ValueError( f"The data choice is not 0 to indicate data but: {choice}") data_length, data = dlms_cosem.dlms_data.decode_variable_integer(data) if data_length != len(data): raise ValueError( "The octet string in block data is not of the correct length") return cls(bytes(data), block_number, invoke_id_and_priority)
def from_bytes(cls, source_bytes: bytes): data = bytearray(source_bytes) tag = data.pop(0) if tag != cls.TAG: raise ValueError( f"Tag is not correct. Should be {cls.TAG} but is {tag}") response_type = enums.GetResponseType(data.pop(0)) if response_type != cls.RESPONSE_TYPE: raise ValueError( f"The response type byte: {response_type} is not for a GetResponseNormal" ) invoke_id_and_priority = InvokeIdAndPriority.from_bytes( data.pop(0).to_bytes(1, "big")) last_block = bool(data.pop(0)) if not last_block: raise ValueError( f"Last block is not set to true in a GetResponseLastBlock.") block_number = int.from_bytes(data[:4], "big") data = data[4:] choice = data.pop(0) if choice != 1: raise ValueError( f"The data choice is not 1 to indicate error but: {choice}") assert len(data) == 1 error = enums.DataAccessResult(data.pop(0)) return cls(error, block_number, invoke_id_and_priority)
def from_bytes(source_bytes: bytes): data = bytearray(source_bytes) tag = data.pop(0) if tag != GetResponseFactory.TAG: raise ValueError( f"Tag is not correct. Should be {GetResponseFactory.TAG} but is {tag}" ) response_type = enums.GetResponseType(data.pop(0)) invoke_id_and_priority = InvokeIdAndPriority.from_bytes( data.pop(0).to_bytes(1, "big")) if response_type == enums.GetResponseType.NORMAL: # check if it is an error or data response by assesing the choice. choice = data.pop(0) if choice == 0: return GetResponseNormal( invoke_id_and_priority=invoke_id_and_priority, data=bytes(data)) elif choice == 1: assert len(data) == 1 # should only be one byte left. error = enums.DataAccessResult(data.pop(0)) return GetResponseNormalWithError( invoke_id_and_priority=invoke_id_and_priority, error=error) elif response_type == enums.GetResponseType.WITH_BLOCK: last_block = bool(data.pop(0)) block_number = int.from_bytes(data[:4], "big") data = data[4:] choice = data.pop(0) if choice == 0: data_length, data = dlms_cosem.dlms_data.decode_variable_integer( data) if data_length != len(data): raise ValueError( "The octet string in block data is not of the correct length" ) if last_block: return GetResponseLastBlock(bytes(data), block_number, invoke_id_and_priority) else: return GetResponseWithBlock(bytes(data), block_number, invoke_id_and_priority) elif choice == 1: assert len(data) == 1 # should only be one byte left. error = enums.DataAccessResult(data.pop(0)) if last_block: return GetResponseLastBlockWithError( error, block_number, invoke_id_and_priority) else: raise ValueError( "It is not possible to send an error on a " "GetResponseWithBlock. When an error occurs it " "should always be sent in a GetResponseLastBlockWithError" ) elif response_type == enums.GetResponseType.WITH_LIST: return GetResponseWithList.from_bytes(bytes(source_bytes)) else: raise ValueError("Response type is not a valid GetResponse type")
def from_bytes(cls, source_bytes: bytes): data = bytearray(source_bytes) tag = data.pop(0) if tag != cls.TAG: raise ValueError( f"Tag is not correct. Should be {cls.TAG} but is {tag}") response_type = enums.GetResponseType(data.pop(0)) if response_type != cls.RESPONSE_TYPE: raise ValueError( f"The response type byte: {response_type} is not for a GetResponseNormal" ) invoke_id_and_priority = InvokeIdAndPriority.from_bytes( data.pop(0).to_bytes(1, "big")) choice = data.pop(0) if choice != 0: raise ValueError( f"The data choice is not 0 to indicate data but: {choice}") return cls(bytes(data), invoke_id_and_priority)