def get_request() -> xdlms.GetRequestNormal: # invocation counter return xdlms.GetRequestNormal(cosem_attribute=cosem.CosemAttribute( interface=enumerations.CosemInterface.DATA, instance=cosem.Obis(0, 0, 0x2B, 1, 0), attribute=2, ))
def send_hls_reply(self) -> Optional[bytes]: return self.action( method=cosem.CosemMethod( enumerations.CosemInterface.ASSOCIATION_LN, cosem.Obis(0, 0, 40, 0, 0), 1, ), data=dlms_data.OctetStringData( self.dlms_connection.get_hls_reply()).to_bytes(), )
def test_parse_buffer(): data = b"\x01\x04\x02\x04\t\x0c\x07\xe3\x0c\x1f\x02\x17\x00\x00\x00\xff\xc4\x00\x11\x06\x06\x00\x00\x05\xed\x06\x00\x00\x06T\x02\x04\x00\x11\x06\x06\x00\x00\x05\xed\x06\x00\x00\x06T\x02\x04\x00\x11\x06\x06\x00\x00\x05\xed\x06\x00\x00\x06T\x02\x04\x00\x11\x06\x06\x00\x00\x05\xed\x06\x00\x00\x06T" parser = ProfileGenericBufferParser( capture_objects=[ cosem.CosemAttribute( interface=enumerations.CosemInterface.CLOCK, instance=cosem.Obis(0, 0, 1, 0, 0, 255), attribute=2, ), cosem.CosemAttribute( interface=enumerations.CosemInterface.DATA, instance=cosem.Obis(0, 0, 96, 10, 1, 255), attribute=2, ), cosem.CosemAttribute( interface=enumerations.CosemInterface.REGISTER, instance=cosem.Obis(1, 0, 1, 8, 0, 255), attribute=2, ), cosem.CosemAttribute( interface=enumerations.CosemInterface.REGISTER, instance=cosem.Obis(1, 0, 2, 8, 0, 255), attribute=2, ), ], capture_period=60, ) result = parser.parse_bytes(data) assert len(result) == 4 assert len(result[0]) == 4 assert result[0][0].attribute.attribute == 2 assert result[0][ 0].attribute.interface == enumerations.CosemInterface.CLOCK assert result[0][0].attribute.instance.to_string() == "0-0:1.0.0.255" assert (result[1][0].value - result[0][0].value).total_seconds() == 60 * 60
def set_request() -> xdlms.SetRequestNormal: # invocation counter return xdlms.SetRequestNormal( cosem_attribute=cosem.CosemAttribute( interface=enumerations.CosemInterface.CLOCK, instance=cosem.Obis(a=0, b=0, c=1, d=0, e=0, f=255), attribute=2, ), data=b"\t\x0c\x07\xe5\x01\x18\xff\x0e09P\xff\xc4\x00", access_selection=None, invoke_id_and_priority=xdlms.InvokeIdAndPriority(invoke_id=1, confirmed=True, high_priority=True), )
def test_range_descriptor_to_bytes(): rd = RangeDescriptor( restricting_object=selective_access.CaptureObject( cosem_attribute=cosem.CosemAttribute( interface=enumerations.CosemInterface.CLOCK, instance=cosem.Obis(0, 0, 1, 0, 0, 255), attribute=2, ), data_index=0, ), from_value=parser.parse("2020-01-01T00:03:00+02:00"), to_value=parser.parse("2020-01-06T00:03:00+01:00"), ) data = b"\x01\x02\x04\x02\x04\x12\x00\x08\t\x06\x00\x00\x01\x00\x00\xff\x0f\x02\x12\x00\x00\t\x0c\x07\xe4\x01\x01\xff\x00\x03\x00\x00\xff\x88\x00\t\x0c\x07\xe4\x01\x06\xff\x00\x03\x00\x00\xff\xc4\x00\x01\x00" assert rd.to_bytes() == data
def test_transform_bytes_without_data(self): data = b"\xc3\x01\xc0\x00\x0f\x00\x00(\x00\x00\xff\x01\x00" action = xdlms.ActionRequestNormal( cosem_method=cosem.CosemMethod( interface=enumerations.CosemInterface.ASSOCIATION_LN, instance=cosem.Obis(a=0, b=0, c=40, d=0, e=0, f=255), method=1, ), data=None, invoke_id_and_priority=xdlms.InvokeIdAndPriority( invoke_id=0, confirmed=True, high_priority=True), ) assert data == action.to_bytes() assert action == xdlms.ActionRequestNormal.from_bytes(data)
def test_transform_bytes(self): data = b"\xc1\x01\xc1\x00\x08\x00\x00\x01\x00\x00\xff\x02\x00\t\x0c\x07\xe5\x01\x18\xff\x0e09P\xff\xc4\x00" request = xdlms.SetRequestNormal( cosem_attribute=cosem.CosemAttribute( interface=enumerations.CosemInterface.CLOCK, instance=cosem.Obis(a=0, b=0, c=1, d=0, e=0, f=255), attribute=2, ), data=b"\t\x0c\x07\xe5\x01\x18\xff\x0e09P\xff\xc4\x00", access_selection=None, invoke_id_and_priority=xdlms.InvokeIdAndPriority( invoke_id=1, confirmed=True, high_priority=True ), ) assert data == request.to_bytes() assert request == xdlms.SetRequestNormal.from_bytes(data)
def test_transform_bytes(self): data = b'\xc3\x01\xc0\x00\x0f\x00\x00(\x00\x00\xff\x01\x01\t\x11\x10\x00\x00\x1a\x90\xe6\xd2"\x1f\xa2\xfd\x85\xee\xd6\x1a\xcc"' action = xdlms.ActionRequestNormal( cosem_method=cosem.CosemMethod( interface=enumerations.CosemInterface.ASSOCIATION_LN, instance=cosem.Obis(a=0, b=0, c=40, d=0, e=0, f=255), method=1, ), data= b'\t\x11\x10\x00\x00\x1a\x90\xe6\xd2"\x1f\xa2\xfd\x85\xee\xd6\x1a\xcc"', invoke_id_and_priority=xdlms.InvokeIdAndPriority( invoke_id=0, confirmed=True, high_priority=True), ) assert data == action.to_bytes() assert action == xdlms.ActionRequestNormal.from_bytes(data)
def test_capture_object_definition(): x = selective_access.CaptureObject( cosem_attribute=cosem.CosemAttribute( interface=enumerations.CosemInterface.CLOCK, instance=cosem.Obis(0, 0, 1, 0, 0, 255), attribute=2, ), data_index=0, ) assert x.to_bytes() == ( b"\x02\x04" # structure of 4 elements b"\x12\x00\x08" # Clock interface class (unsigned long int) b"\t\x06\x00\x00\x01\x00\x00\xff" # Clock instance octet string of 0.0.1.0.0.255 b"\x0f\x02" # attribute index = 2 (integer) b"\x12\x00\x00" # data index = 0 (long unsigned) )
management_client = partial( DlmsClient.with_tcp_transport, server_logical_address=1, client_logical_address=1, authentication_method=auth, encryption_key=encryption_key, authentication_key=authentication_key, ) with public_client(host=host, port=port).session() as client: response_data = client.get( cosem.CosemAttribute( interface=enumerations.CosemInterface.DATA, instance=cosem.Obis(0, 0, 0x2B, 1, 0), attribute=2, ) ) data_decoder = a_xdr.AXdrDecoder( encoding_conf=a_xdr.EncodingConf( attributes=[a_xdr.Sequence(attribute_name="data")] ) ) invocation_counter = data_decoder.decode(response_data)["data"] print(f"meter_initial_invocation_counter = {invocation_counter}") # we are not reusing the socket as of now. We just need to give the meter some time to # close the connection on its side sleep(1)
def test_obis_from_dotted(self): obis = cosem.Obis.from_dotted("1.0.1.8.0.255") assert obis == cosem.Obis(1, 0, 1, 8, 0, 255)
def test_obis_to_dotted(self): obis = cosem.Obis(1, 0, 1, 8, 0, 255) assert obis.dotted_repr() == "1.0.1.8.0.255"
def test_obis_to_bytes(self): data = b"\x00\x00+\x01\x00\xff" assert cosem.Obis(0, 0, 43, 1, 0, 255).to_bytes() == data
def test_obis_from_bytes(self): data = b"\x00\x00+\x01\x00\xff" assert cosem.Obis.from_bytes(data) == cosem.Obis(0, 0, 43, 1, 0, 255)
def test_obis_to_verbose(self): obis = cosem.Obis(1, 0, 1, 8, 0, 255) assert obis.verbose_repr() == "1-0:1.8.0*255"