コード例 #1
0
    def get(
        self,
        logical_name: Union[str, Obis],
        attribute: int,
        selective_access: Optional[RangeDescriptor] = None,
    ):
        obis = force_obis(logical_name)
        instance = self.objects.get(obis.dotted_repr(), None)
        if instance is None:
            raise ValueError(
                f"Object with logical name {obis.dotted_repr()} does not exist on meter"
            )
        if instance.is_static_attribute(attribute):
            # check if the value is already present on the meter
            value = getattr(
                instance, instance.STATIC_ATTRIBUTES[attribute].attribute_name)
            if value:
                return value

        value = utils.parse_as_dlms_data(
            self.dlms_client.get(cosem_attribute=cosem.CosemAttribute(
                interface=instance.INTERFACE_CLASS_ID,
                instance=obis,
                attribute=attribute,
            )))

        if instance.is_static_attribute(attribute):
            setattr(instance,
                    instance.STATIC_ATTRIBUTES[attribute].attribute_name,
                    value)

        converter = instance.DYNAMIC_CONVERTERS.get(attribute, None)
        if converter:
            return converter(instance, value)
        return value
コード例 #2
0
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,
    ))
コード例 #3
0
ファイル: test_parsers.py プロジェクト: pwitab/dlms-cosem
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
コード例 #4
0
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),
    )
コード例 #5
0
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
コード例 #6
0
ファイル: test_set.py プロジェクト: tijme/forked-dlms-cosem
 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)
コード例 #7
0
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)
    )
コード例 #8
0
    def from_bytes(cls, source_bytes: bytes) -> "RangeDescriptor":
        data = bytearray(source_bytes)
        access_descriptor = data.pop(0)
        if access_descriptor is not cls.ACCESS_DESCRIPTOR:
            raise ValueError(
                f"Access descriptor {access_descriptor} is not valid for "
                f"RangeDescriptor. It should be {cls.ACCESS_DESCRIPTOR}"
            )
        parsed_data = utils.parse_as_dlms_data(data)

        restricting_object_data = parsed_data[0]
        from_value_data = parsed_data[1]
        to_value_data = parsed_data[2]
        selected_values_data = parsed_data[3]

        restricting_cosem_attribute = cosem.CosemAttribute(
            interface=enumerations.CosemInterface(restricting_object_data[0]),
            instance=cosem.Obis.from_bytes(restricting_object_data[1]),
            attribute=restricting_object_data[2],
        )
        restricting_object = CaptureObject(
            cosem_attribute=restricting_cosem_attribute,
            data_index=restricting_object_data[3],
        )
        from_dt, clock_status = time.datetime_from_bytes(from_value_data)
        to_dt, clock_status = time.datetime_from_bytes(to_value_data)
        if selected_values_data:
            raise NotImplementedError()
        else:
            selected_values = None

        return cls(
            restricting_object=restricting_object,
            from_value=from_dt,
            to_value=to_dt,
            selected_values=selected_values,
        )
コード例 #9
0
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)
コード例 #10
0
port = "/dev/tty.usbserial-A704H991"

public_meter = Meter(
    dlms_client=public_client(serial_port=port),
    objects={
        "0.0.43.1.0.255":
        Data(logical_name=cosem.Obis.from_dotted("0.0.43.1.0.255"),
             value=None),
        "1.0.99.1.0.255":
        ProfileGeneric(
            logical_name="1.0.99.1.0.255",
            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),
コード例 #11
0
)

management_client = partial(
    DlmsClient.with_serial_hdlc_transport,
    serial_port=serial_port,
    server_logical_address=1,
    server_physical_address=17,
    client_logical_address=1,
    authentication_method=auth,
    encryption_key=encryption_key,
    authentication_key=authentication_key,
)

LOAD_PROFILE_BUFFER = cosem.CosemAttribute(
    interface=enumerations.CosemInterface.PROFILE_GENERIC,
    instance=cosem.Obis(1, 0, 99, 1, 0),
    attribute=2,
)

CURRENT_ASSOCIATION_OBJECTS = cosem.CosemAttribute(
    interface=enumerations.CosemInterface.ASSOCIATION_LN,
    instance=cosem.Obis(0, 0, 40, 0, 0),
    attribute=2,
)

with public_client().session() as client:
    invocation_counter = utils.parse_as_dlms_data(
        client.get(cosem_attribute=cosem.CosemAttribute(
            interface=enumerations.CosemInterface.DATA,
            instance=cosem.Obis.from_string("0.0.43.1.0.255"),
            attribute=2,
コード例 #12
0
    DlmsClient.with_serial_hdlc_transport,
    server_logical_address=1,
    server_physical_address=17,
    client_logical_address=1,
    authentication_method=auth,
    encryption_key=encryption_key,
    authentication_key=authentication_key,
)

port = "/dev/tty.usbserial-A704H991"
with public_client(serial_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}")

LOAD_PROFILE_BUFFER = cosem.CosemAttribute(
    interface=enumerations.CosemInterface.PROFILE_GENERIC,
    instance=cosem.Obis(1, 0, 99, 1, 0),
    attribute=2,
)

CURRENT_ASSOCIATION_OBJECTS = cosem.CosemAttribute(
    interface=enumerations.CosemInterface.ASSOCIATION_LN,