DLMS-SPODES 0.86.21__py3-none-any.whl → 0.86.23__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- DLMS_SPODES/cosem_interface_classes/collection.py +24 -21
- DLMS_SPODES/cosem_interface_classes/cosem_interface_class.py +0 -7
- DLMS_SPODES/pardata.py +3 -2
- DLMS_SPODES/settings.py +28 -0
- DLMS_SPODES/types/common_data_types.py +1 -1
- DLMS_SPODES/types/implementations/bitstrings.py +2 -0
- DLMS_SPODES/types/useful_types.py +4 -7
- {dlms_spodes-0.86.21.dist-info → dlms_spodes-0.86.23.dist-info}/METADATA +1 -1
- {dlms_spodes-0.86.21.dist-info → dlms_spodes-0.86.23.dist-info}/RECORD +11 -11
- {dlms_spodes-0.86.21.dist-info → dlms_spodes-0.86.23.dist-info}/WHEEL +0 -0
- {dlms_spodes-0.86.21.dist-info → dlms_spodes-0.86.23.dist-info}/top_level.txt +0 -0
|
@@ -946,7 +946,7 @@ class Collection:
|
|
|
946
946
|
|
|
947
947
|
def get_object(self, value: LNContaining) -> InterfaceClass:
|
|
948
948
|
""" return object from obis<string> or raise exception if it absence """
|
|
949
|
-
return self.
|
|
949
|
+
return self.obis2obj(lnContents2obis(value)).unwrap()
|
|
950
950
|
|
|
951
951
|
@deprecated("use <par2rep>")
|
|
952
952
|
def get_report(self,
|
|
@@ -1114,7 +1114,7 @@ class Collection:
|
|
|
1114
1114
|
"""return only association objects"""
|
|
1115
1115
|
ret = list()
|
|
1116
1116
|
for olt in self.getASSOCIATION(ass_id).object_list:
|
|
1117
|
-
ret.append(self.
|
|
1117
|
+
ret.append(self.par2obj(Parameter(olt.logical_name.contents)).unwrap())
|
|
1118
1118
|
return ret
|
|
1119
1119
|
|
|
1120
1120
|
def sap2objects(self, value: enums.ClientSAP) -> result.List[ic.COSEMInterfaceClasses]:
|
|
@@ -1138,11 +1138,6 @@ class Collection:
|
|
|
1138
1138
|
ret.append(obj)
|
|
1139
1139
|
return ret
|
|
1140
1140
|
|
|
1141
|
-
|
|
1142
|
-
def get_attr(self, value: ut.CosemAttributeDescriptor) -> cdt.CommonDataTypes:
|
|
1143
|
-
"""attribute value from descriptor"""
|
|
1144
|
-
return self.__get_object(value.instance_id.contents).get_attr(int(value.attribute_id))
|
|
1145
|
-
|
|
1146
1141
|
def get_first(self, values: list[str | bytes | cst.LogicalName]) -> InterfaceClass:
|
|
1147
1142
|
""" return first object from it exist in collection from value"""
|
|
1148
1143
|
for val in values:
|
|
@@ -1199,7 +1194,7 @@ class Collection:
|
|
|
1199
1194
|
def copy_obj_attr_values_from(self, other: InterfaceClass) -> bool:
|
|
1200
1195
|
""" copy all attributes value from other and return bool result """
|
|
1201
1196
|
try:
|
|
1202
|
-
obj: InterfaceClass = self.
|
|
1197
|
+
obj: InterfaceClass = self.par2obj(Parameter(other.logical_name.contents)).unwrap()
|
|
1203
1198
|
for i, attr in other.get_index_with_attributes(in_init_order=True):
|
|
1204
1199
|
if i == 1:
|
|
1205
1200
|
continue
|
|
@@ -1217,18 +1212,10 @@ class Collection:
|
|
|
1217
1212
|
else:
|
|
1218
1213
|
return False
|
|
1219
1214
|
|
|
1220
|
-
@deprecated("use <obis2obj>")
|
|
1221
|
-
def __get_object(self, obis: bytes) -> InterfaceClass:
|
|
1222
|
-
if (obj := self.__objs.get(obis)) is None:
|
|
1223
|
-
logical_name = cst.LogicalName(bytearray(obis))
|
|
1224
|
-
raise exc.NoObject(F"{get_name(logical_name)}:{logical_name} is absence")
|
|
1225
|
-
else:
|
|
1226
|
-
return obj
|
|
1227
|
-
|
|
1228
1215
|
def obis2obj(self, obis: o.OBIS) -> result.SimpleOrError[InterfaceClass]:
|
|
1229
1216
|
if obj := self.__objs.get(obis):
|
|
1230
|
-
return result.
|
|
1231
|
-
return result.
|
|
1217
|
+
return result.Simple(obj)
|
|
1218
|
+
return result.Error.from_e(exc.NoObject(obis))
|
|
1232
1219
|
|
|
1233
1220
|
def logicalName2obj(self, ln: cst.LogicalName) -> result.SimpleOrError[InterfaceClass]:
|
|
1234
1221
|
return self.obis2obj(o.OBIS(ln.contents))
|
|
@@ -1317,14 +1304,14 @@ class Collection:
|
|
|
1317
1304
|
|
|
1318
1305
|
def get_script_names(self, ln: cst.LogicalName, selector: cdt.LongUnsigned) -> str:
|
|
1319
1306
|
"""return name from script by selector"""
|
|
1320
|
-
obj = self.
|
|
1307
|
+
obj = self.par2obj(Parameter(ln.contents))
|
|
1321
1308
|
if isinstance(obj, ScriptTable):
|
|
1322
1309
|
for script in obj.scripts:
|
|
1323
1310
|
script: ScriptTable.scripts
|
|
1324
1311
|
if script.script_identifier == selector:
|
|
1325
1312
|
names: list[str] = list()
|
|
1326
1313
|
for action in script.actions:
|
|
1327
|
-
action_obj = self.
|
|
1314
|
+
action_obj = self.par2obj(Parameter(action.logical_name.contents)).unwrap()
|
|
1328
1315
|
if int(action_obj.CLASS_ID) != int(action.class_id):
|
|
1329
1316
|
raise ValueError(F"got {action_obj.CLASS_ID}, expected {action.class_id}")
|
|
1330
1317
|
match int(action.service_id):
|
|
@@ -1391,6 +1378,22 @@ class Collection:
|
|
|
1391
1378
|
security_policy=security_policy
|
|
1392
1379
|
)
|
|
1393
1380
|
|
|
1381
|
+
@lru_cache(maxsize=1000)
|
|
1382
|
+
def isnt_mutable(self,
|
|
1383
|
+
par: Parameter,
|
|
1384
|
+
association_id: int,
|
|
1385
|
+
security_policy: pdu.SecurityPolicy = pdu.SecurityPolicyVer0.NOTHING
|
|
1386
|
+
) -> bool:
|
|
1387
|
+
"""is not writable and STATIC data"""
|
|
1388
|
+
if (
|
|
1389
|
+
not self.is_writable(par.ln, par.i, association_id, security_policy, security_policy)
|
|
1390
|
+
and self.par2obj(par
|
|
1391
|
+
).unwrap().getAElement(par.i
|
|
1392
|
+
).unwrap().classifier == ic.Classifier.STATIC
|
|
1393
|
+
):
|
|
1394
|
+
return True
|
|
1395
|
+
return False
|
|
1396
|
+
|
|
1394
1397
|
@lru_cache(maxsize=1000)
|
|
1395
1398
|
def is_accessible(self, ln: cst.LogicalName,
|
|
1396
1399
|
index: int,
|
|
@@ -1409,7 +1412,7 @@ class Collection:
|
|
|
1409
1412
|
def get_name_and_type(self, value: structs.CaptureObjectDefinition) -> tuple[list[str], Type[cdt.CommonDataType]]:
|
|
1410
1413
|
""" return names and type of element from collection"""
|
|
1411
1414
|
names: list[str] = list()
|
|
1412
|
-
obj = self.
|
|
1415
|
+
obj = self.par2obj(Parameter(value.logical_name.contents)).unwrap()
|
|
1413
1416
|
names.append(get_name(obj.logical_name))
|
|
1414
1417
|
attr_index = int(value.attribute_index)
|
|
1415
1418
|
data_index = int(value.data_index)
|
|
@@ -8,21 +8,14 @@ from typing import Iterator, Type, TypeAlias, Callable, Any, Self, Literal, Opti
|
|
|
8
8
|
from ..types import cdt, ut, cst
|
|
9
9
|
from StructResult import result
|
|
10
10
|
from ..relation_to_OBIS import get_name
|
|
11
|
-
import logging
|
|
12
11
|
from enum import IntEnum
|
|
13
12
|
from itertools import count
|
|
14
13
|
from .. import exceptions as exc
|
|
15
14
|
from .overview import ClassID
|
|
16
15
|
from ..settings import settings
|
|
17
|
-
from ..config_parser import get_values
|
|
18
16
|
from .. import literals
|
|
19
17
|
|
|
20
18
|
|
|
21
|
-
logger = logging.getLogger(__name__)
|
|
22
|
-
logger.level = logging.INFO
|
|
23
|
-
|
|
24
|
-
logger.info(F'Register start')
|
|
25
|
-
|
|
26
19
|
_n_class = count(0)
|
|
27
20
|
|
|
28
21
|
|
DLMS_SPODES/pardata.py
CHANGED
|
@@ -18,7 +18,8 @@ class ParValues[T]:
|
|
|
18
18
|
raise StopIteration
|
|
19
19
|
|
|
20
20
|
def __iter__(self) -> Iterator[Parameter | T]:
|
|
21
|
-
|
|
21
|
+
yield self.par
|
|
22
|
+
yield self.data
|
|
22
23
|
|
|
23
24
|
def __str__(self):
|
|
24
25
|
return F"{self.par} - {self.data}"
|
|
@@ -26,4 +27,4 @@ class ParValues[T]:
|
|
|
26
27
|
|
|
27
28
|
@dataclass(frozen=True)
|
|
28
29
|
class ParData(ParValues[cdt.CommonDataType]):
|
|
29
|
-
data:
|
|
30
|
+
data: cdt.CommonDataType
|
DLMS_SPODES/settings.py
CHANGED
|
@@ -478,11 +478,39 @@ class _AmNames(BaseModel):
|
|
|
478
478
|
xDLMS_context_info: str = "xDLMS context info"
|
|
479
479
|
|
|
480
480
|
|
|
481
|
+
class Conformance(BaseModel):
|
|
482
|
+
reserved_zero: str = "reserved-zero"
|
|
483
|
+
general_protection: str = "general-protection"
|
|
484
|
+
general_block_transfer: str = "general-block-transfer"
|
|
485
|
+
read: str = "read"
|
|
486
|
+
write: str = "write"
|
|
487
|
+
unconfirmed_write: str = "unconfirmed-write"
|
|
488
|
+
reserved_six: str = "reserved-six"
|
|
489
|
+
reserved_seven: str = "reserved-seven"
|
|
490
|
+
attribute0_supported_with_set: str = "attribute0-supported-with-set"
|
|
491
|
+
priority_mgmt_supported: str = "priority-mgmt-supported"
|
|
492
|
+
attribute0_supported_with_get: str = "attribute0-supported-with-get"
|
|
493
|
+
block_transfer_with_get_or_read: str = "block-transfer-with-get-or-read"
|
|
494
|
+
block_transfer_with_set_or_write: str = "block-transfer-with-set-or-write"
|
|
495
|
+
block_transfer_with_action: str = "block-transfer-with-action"
|
|
496
|
+
multiple_references: str = "multiple-references"
|
|
497
|
+
information_report: str = "information-report"
|
|
498
|
+
data_notification: str = "data-notification"
|
|
499
|
+
access: str = "access"
|
|
500
|
+
parameterized_access: str = "parameterized-access"
|
|
501
|
+
get: str = "get"
|
|
502
|
+
set: str = "set"
|
|
503
|
+
selective_access: str = "selective-access"
|
|
504
|
+
event_notification: str = "event-notification"
|
|
505
|
+
action: str = "action"
|
|
506
|
+
|
|
507
|
+
|
|
481
508
|
class Settings(BaseModel):
|
|
482
509
|
collection: _Collection = Field(default_factory=_Collection)
|
|
483
510
|
report: _Report = Field(default_factory=_Report)
|
|
484
511
|
firmwares: list[_Firmware] = Field(default_factory=list)
|
|
485
512
|
am_names: _AmNames = Field(default_factory=_AmNames)
|
|
513
|
+
class_name: dict[int, str] = Field(default={1: "Data"})
|
|
486
514
|
|
|
487
515
|
|
|
488
516
|
if not os.path.isfile(path := ".//config.toml"):
|
|
@@ -1669,7 +1669,7 @@ class OctetString(_String, SimpleDataType):
|
|
|
1669
1669
|
temp = list()
|
|
1670
1670
|
for i in self.contents:
|
|
1671
1671
|
temp.append(i if i > 32 else 63)
|
|
1672
|
-
return bytes(temp).decode(encoding)
|
|
1672
|
+
return bytes(temp).decode(encoding, errors="ignore")
|
|
1673
1673
|
|
|
1674
1674
|
def pretty_str(self) -> str:
|
|
1675
1675
|
"""decode to utf-8 or hex labal"""
|
|
@@ -5,7 +5,7 @@ from typing import Type, Any, Callable
|
|
|
5
5
|
from dataclasses import dataclass
|
|
6
6
|
from ..types import common_data_types as cdt
|
|
7
7
|
from ..exceptions import DLMSException
|
|
8
|
-
from ..
|
|
8
|
+
from ..settings import settings
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class UserfulTypesException(DLMSException):
|
|
@@ -401,9 +401,9 @@ class CosemClassId(Unsigned16):
|
|
|
401
401
|
- class_id-s from 32 768 to 65 535 are reserved for user group specific ICs.
|
|
402
402
|
The DLMS UA reserves the right to assign ranges to individual manufacturers or user groups. """
|
|
403
403
|
|
|
404
|
-
def __str__(self):
|
|
405
|
-
if
|
|
406
|
-
return
|
|
404
|
+
def __str__(self) -> str:
|
|
405
|
+
if res := settings.class_name.get(int(self)):
|
|
406
|
+
return res
|
|
407
407
|
else:
|
|
408
408
|
return repr(self)
|
|
409
409
|
|
|
@@ -411,9 +411,6 @@ class CosemClassId(Unsigned16):
|
|
|
411
411
|
return F"{self.__class__.__name__}({int(self)})"
|
|
412
412
|
|
|
413
413
|
|
|
414
|
-
_class_names = {CosemClassId(k): v for k, v in class_names.items()} if (class_names := get_values("DLMS", "class_name")) else None
|
|
415
|
-
|
|
416
|
-
|
|
417
414
|
class CosemObjectInstanceId(OCTET_STRING, UsefulType):
|
|
418
415
|
LENGTH = 6
|
|
419
416
|
|
|
@@ -6,11 +6,11 @@ DLMS_SPODES/enums.py,sha256=13BE0owOyJBNlOI4NY1d-kpqVoHF7JPR9brkPKHLERE,17789
|
|
|
6
6
|
DLMS_SPODES/exceptions.py,sha256=UBZRQlQIRi1CzRxWTeqX5PVNuFS770f77BAizQ99IDU,3006
|
|
7
7
|
DLMS_SPODES/firmwares.py,sha256=lFRnxtq4joYhpZPxHD8Pv30-GvgcEfZCDZUYo_pIeQU,3850
|
|
8
8
|
DLMS_SPODES/literals.py,sha256=5u6hreLSXgmN7Z_5pXchyBKsuPYJ5deqxKHqewQEFoI,1632
|
|
9
|
-
DLMS_SPODES/pardata.py,sha256=
|
|
9
|
+
DLMS_SPODES/pardata.py,sha256=yktr4g59FITC_L1kRbQuwp0PMQvGdMwXqWxpXcCDpQU,700
|
|
10
10
|
DLMS_SPODES/pdu_enums.py,sha256=5xiV-tZTPXOcHT8XQcHWrwAMKTOmCH09Sk4iL1N7I3c,2276
|
|
11
11
|
DLMS_SPODES/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
12
|
DLMS_SPODES/relation_to_OBIS.py,sha256=KcSMIQ_5amjeT0Lya3HbYoaDdz_BjZC2JLVhl2nffwo,32761
|
|
13
|
-
DLMS_SPODES/settings.py,sha256=
|
|
13
|
+
DLMS_SPODES/settings.py,sha256=iR85_X90hrGdhh2tG7EjJF-j0RQPrklpfTLzwUNQzWw,25306
|
|
14
14
|
DLMS_SPODES/Values/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
DLMS_SPODES/Values/EN/__init__.py,sha256=FVBOniaIeM6Mv24u0h_1fsEz2xyJZgyR7CWb9aW-DAc,46
|
|
16
16
|
DLMS_SPODES/Values/EN/actors.py,sha256=mKjBGhikbISSZP9ZBcqsZGolXeJ7_k-NYOMa8Ny8aaY,261
|
|
@@ -25,8 +25,8 @@ DLMS_SPODES/cosem_interface_classes/activity_calendar.py,sha256=VWSiKn2LNBA1VLAA
|
|
|
25
25
|
DLMS_SPODES/cosem_interface_classes/arbitrator.py,sha256=S9TguoMG6O5DpMBp6mpcJpw6PHanvh4SEAN3M_v6qts,3240
|
|
26
26
|
DLMS_SPODES/cosem_interface_classes/attr_indexes.py,sha256=aUSnT-dKoBsDbwLhlgtLIHGRl7PZrT-ld2ThCEUjUeA,328
|
|
27
27
|
DLMS_SPODES/cosem_interface_classes/clock.py,sha256=9OJwRGrbFPws_VZPayHv-hzFJegIcjgoJoenIqofd5w,4525
|
|
28
|
-
DLMS_SPODES/cosem_interface_classes/collection.py,sha256=
|
|
29
|
-
DLMS_SPODES/cosem_interface_classes/cosem_interface_class.py,sha256=
|
|
28
|
+
DLMS_SPODES/cosem_interface_classes/collection.py,sha256=xZdYSDFJeyB4P_kBaETt9IJWrY5i9-VcpJhRTGo6wy8,96445
|
|
29
|
+
DLMS_SPODES/cosem_interface_classes/cosem_interface_class.py,sha256=SIME0IC1XyX9RSsfxt0cbghN7rCyWzjqCbesQEpTCM8,23347
|
|
30
30
|
DLMS_SPODES/cosem_interface_classes/data.py,sha256=YSjA3Y0M5NMcfYzWPEuZw6ojIqr2UghgW_ck8dXySMU,809
|
|
31
31
|
DLMS_SPODES/cosem_interface_classes/disconnect_control.py,sha256=CIx7I4QRpPxAC5iYxpbhCIuv6U2P3s6ELam8eD-kD5w,2926
|
|
32
32
|
DLMS_SPODES/cosem_interface_classes/extended_register.py,sha256=xULCS11YVWjFMoaRUrm4whvH39Gx0Cu6breUos_oLCs,1153
|
|
@@ -100,19 +100,19 @@ DLMS_SPODES/obis/abstract_objects.py,sha256=0ZoJKRQ_7FoChC2rNSgNV573hso8JYZQKdLF
|
|
|
100
100
|
DLMS_SPODES/obis/media_id.py,sha256=GRiwHPe9-3iCg4u_J6qf2rMc3Wjw0aJHKiSnBtNYD3o,22339
|
|
101
101
|
DLMS_SPODES/types/__init__.py,sha256=UFiP4suA72o_kvaqUnHLGK-cedDXLl8kVHYsjXHYUDw,116
|
|
102
102
|
DLMS_SPODES/types/choices.py,sha256=z7IasrlRaagOYNfRvgbpojDxf1jgYUc9cz59PH2PMi0,6350
|
|
103
|
-
DLMS_SPODES/types/common_data_types.py,sha256=
|
|
103
|
+
DLMS_SPODES/types/common_data_types.py,sha256=jUQem7YkKNL93d-F7MArMiAFu-pxfaeMY4aDPKrOkKc,96953
|
|
104
104
|
DLMS_SPODES/types/cosem_service_types.py,sha256=XLWPDfdSxyYpr_3NwAxICRgxjPJdHf7EgQ4694M-erQ,4360
|
|
105
|
-
DLMS_SPODES/types/useful_types.py,sha256=
|
|
105
|
+
DLMS_SPODES/types/useful_types.py,sha256=TBHNRJcstw6CmgJNT9esQ5-xI7PG1IAJDBSCxglaaf0,27288
|
|
106
106
|
DLMS_SPODES/types/implementations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
107
107
|
DLMS_SPODES/types/implementations/arrays.py,sha256=xdx_o3TZw6JN2BABlhuzIByhxbI1-tlvAdW37enV4zM,763
|
|
108
|
-
DLMS_SPODES/types/implementations/bitstrings.py,sha256=
|
|
108
|
+
DLMS_SPODES/types/implementations/bitstrings.py,sha256=cOCD3ftajdAwK_m7m-ELdY0hvMPNADKhgJLFFKCoxvk,3651
|
|
109
109
|
DLMS_SPODES/types/implementations/double_long_usingneds.py,sha256=zwemISdpQUzov9TxH9t4wYFBTo0SnPd2sdDksJ0wb-I,1232
|
|
110
110
|
DLMS_SPODES/types/implementations/enums.py,sha256=58HcMxuwXY-MKjiBpY4lAOpdEHD3LLWBye8vidNz6JQ,2022
|
|
111
111
|
DLMS_SPODES/types/implementations/integers.py,sha256=KAcaTY8ZwhBaJThbLSr39Oh_-9h8g6dxKXtDfBQppo4,169
|
|
112
112
|
DLMS_SPODES/types/implementations/long_unsigneds.py,sha256=SxmFvD2moQ03p-KZSBYK1Rv7bQSaywlHVXBfkTZG1OQ,8761
|
|
113
113
|
DLMS_SPODES/types/implementations/octet_string.py,sha256=Jo_sfWcsfstiP4O6mXfBOOQlksx1c2qJMI-vbAOV-yM,294
|
|
114
114
|
DLMS_SPODES/types/implementations/structs.py,sha256=GMOo6Jy8jA9d6KTLs0D-j5t0oSRvxUIwtBr_4UePwbA,2059
|
|
115
|
-
dlms_spodes-0.86.
|
|
116
|
-
dlms_spodes-0.86.
|
|
117
|
-
dlms_spodes-0.86.
|
|
118
|
-
dlms_spodes-0.86.
|
|
115
|
+
dlms_spodes-0.86.23.dist-info/METADATA,sha256=M1BybUqRFelStgVtaXOxSuvMqxPDJlQZfDQFuz6eG0s,1028
|
|
116
|
+
dlms_spodes-0.86.23.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
117
|
+
dlms_spodes-0.86.23.dist-info/top_level.txt,sha256=k26SRuRdwBZrSM3NgNZECAUNIDZREbJuLCnPbWtTNak,12
|
|
118
|
+
dlms_spodes-0.86.23.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|