DLMS-SPODES 0.86.8__py3-none-any.whl → 0.86.10__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 +20 -10
- DLMS_SPODES/cosem_interface_classes/implementations/data.py +19 -0
- DLMS_SPODES/cosem_interface_classes/ln_pattern.py +155 -66
- DLMS_SPODES/cosem_interface_classes/parameter.py +0 -1
- DLMS_SPODES/pardata.py +1 -1
- DLMS_SPODES/types/common_data_types.py +7 -6
- {dlms_spodes-0.86.8.dist-info → dlms_spodes-0.86.10.dist-info}/METADATA +3 -2
- {dlms_spodes-0.86.8.dist-info → dlms_spodes-0.86.10.dist-info}/RECORD +10 -10
- {dlms_spodes-0.86.8.dist-info → dlms_spodes-0.86.10.dist-info}/WHEEL +0 -0
- {dlms_spodes-0.86.8.dist-info → dlms_spodes-0.86.10.dist-info}/top_level.txt +0 -0
|
@@ -522,8 +522,6 @@ __func_map_for_create.update({
|
|
|
522
522
|
(1, 0, 148, 136, 0): RegisterMap,
|
|
523
523
|
(1, 94, 7, 0): ProfileGenericMap.renew(1, impl.profile_generic.SPODES3CurrentProfile),
|
|
524
524
|
(1, 94, 7, (1, 2, 3, 4, 5, 6)): ProfileGenericMap.renew(1, impl.profile_generic.SPODES3ScalesProfile), # Todo: RU. Scaler-profile With 1 entry and more
|
|
525
|
-
# KPZ
|
|
526
|
-
(128, 0, tuple(range(20)), 0, 0): RegisterMap
|
|
527
525
|
})
|
|
528
526
|
|
|
529
527
|
func_maps["SPODES_3"] = get_func_map(__func_map_for_create)
|
|
@@ -533,9 +531,11 @@ __func_map_for_create.update({
|
|
|
533
531
|
(0, 96, 11, 4): ClassMap({0: impl.data.KPZSPODES3ExternalEvent}),
|
|
534
532
|
(0, 0, 97, 98, (0, 10, 20)): ClassMap({0: impl.data.KPZAlarm1}),
|
|
535
533
|
(0, 128, 25, 6, 0): ClassMap({0: impl.data.DataStatic}),
|
|
534
|
+
(0, 128, 96, 2, (0, 1, 2)): ClassMap({0: impl.data.KPZAFEOffsets}),
|
|
536
535
|
(0, 128, 96, 13, 1): ClassMap({0: impl.data.ITEBitMap}),
|
|
537
536
|
(0, 128, 154, 0, 0): ClassMap({0: impl.data.KPZGSMPingIP}),
|
|
538
537
|
(0, 0, 128, (100, 101, 102, 103, 150, 151, 152, 170)): DataMap,
|
|
538
|
+
(128, 0, tuple(range(20)), 0, 0): RegisterMap
|
|
539
539
|
})
|
|
540
540
|
func_maps["KPZ"]: FUNC_MAP = get_func_map(__func_map_for_create)
|
|
541
541
|
# KPZ1 with bag in log event profiles
|
|
@@ -606,7 +606,7 @@ def get_filtered(objects: Iterable[InterfaceClass],
|
|
|
606
606
|
keys: ObjFilteredKey) -> list[InterfaceClass]:
|
|
607
607
|
c_ids: list[ut.CosemClassId] = list()
|
|
608
608
|
patterns: list[LNPattern] = list()
|
|
609
|
-
ch: Channel
|
|
609
|
+
ch: Optional[Channel] = None
|
|
610
610
|
for k in keys:
|
|
611
611
|
if isinstance(k, ut.CosemClassId):
|
|
612
612
|
c_ids.append(k)
|
|
@@ -679,7 +679,7 @@ class Collection:
|
|
|
679
679
|
self.__country_ver = cntr_ver
|
|
680
680
|
"""country version specification"""
|
|
681
681
|
self.spec_map = "DLMS_6"
|
|
682
|
-
self.__objs =
|
|
682
|
+
self.__objs = {}
|
|
683
683
|
""" all DLMS objects container with obis key """
|
|
684
684
|
|
|
685
685
|
@property
|
|
@@ -1127,6 +1127,19 @@ class Collection:
|
|
|
1127
1127
|
res.append_err(e)
|
|
1128
1128
|
return res
|
|
1129
1129
|
|
|
1130
|
+
def iter_classID_objects(self,
|
|
1131
|
+
class_id: ut.CosemClassId) -> Iterator[InterfaceClass]:
|
|
1132
|
+
return (obj for obj in self.__objs.values() if obj.CLASS_ID == value)
|
|
1133
|
+
|
|
1134
|
+
def LNPattern2objects(self,
|
|
1135
|
+
pat: LNPattern) -> list[InterfaceClass]:
|
|
1136
|
+
ret = []
|
|
1137
|
+
for obj in self.__objs.values():
|
|
1138
|
+
if obj.logical_name in pat:
|
|
1139
|
+
ret.append(obj)
|
|
1140
|
+
return ret
|
|
1141
|
+
|
|
1142
|
+
|
|
1130
1143
|
def get_attr(self, value: ut.CosemAttributeDescriptor) -> cdt.CommonDataTypes:
|
|
1131
1144
|
"""attribute value from descriptor"""
|
|
1132
1145
|
return self.__get_object(value.instance_id.contents).get_attr(int(value.attribute_id))
|
|
@@ -1141,17 +1154,14 @@ class Collection:
|
|
|
1141
1154
|
else:
|
|
1142
1155
|
raise exc.NoObject(F"not found at least one DLMS Objects from collection with {values=}")
|
|
1143
1156
|
|
|
1157
|
+
@deprecated("use <iter_classID_objects>")
|
|
1144
1158
|
def get_objects_by_class_id(self, value: ut.CosemClassId) -> list[InterfaceClass]:
|
|
1145
1159
|
return list(filter(lambda obj: obj.CLASS_ID == value, self.__objs.values()))
|
|
1146
1160
|
|
|
1147
|
-
def get_objects_descriptions(self) -> list[tuple[cst.LogicalName, cdt.LongUnsigned, cdt.Unsigned]]:
|
|
1148
|
-
""" return container of objects for get device clone """
|
|
1149
|
-
return list(map(lambda obj: (obj.logical_name, obj.CLASS_ID, obj.VERSION), self.__objs.values()))
|
|
1150
|
-
|
|
1151
1161
|
def get_writable_attr(self) -> UsedAttributes:
|
|
1152
1162
|
"""return all writable {obj.ln: {attribute_index}}"""
|
|
1153
1163
|
ret: UsedAttributes = dict()
|
|
1154
|
-
for ass in self.
|
|
1164
|
+
for ass in self.iter_classID_objects(ClassID.ASSOCIATION_LN):
|
|
1155
1165
|
if (
|
|
1156
1166
|
ass.logical_name.e == 0
|
|
1157
1167
|
or ass.object_list is None
|
|
@@ -1351,7 +1361,7 @@ class Collection:
|
|
|
1351
1361
|
raise ValueError(F"absent association with {client_sap}")
|
|
1352
1362
|
|
|
1353
1363
|
def sap2association(self, sap: enums.ClientSAP) -> AssociationLN:
|
|
1354
|
-
for ass in
|
|
1364
|
+
for ass in self.iter_classID_objects(ClassID.ASSOCIATION_LN):
|
|
1355
1365
|
if (
|
|
1356
1366
|
ass.associated_partners_id is not None
|
|
1357
1367
|
and ass.associated_partners_id.client_SAP == sap
|
|
@@ -456,3 +456,22 @@ class KPZGSMPingIPValue(cdt.Structure):
|
|
|
456
456
|
class KPZGSMPingIP(DataStatic):
|
|
457
457
|
"""Проприетарный объект"""
|
|
458
458
|
A_ELEMENTS = DataStatic.get_attr_element(2).get_change(data_type=KPZGSMPingIPValue),
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
class AFERegister(cdt.Structure):
|
|
462
|
+
name: cdt.VisibleString
|
|
463
|
+
value: choices.common_dt
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
class AFERegisters(cdt.Array):
|
|
467
|
+
TYPE = AFERegister
|
|
468
|
+
values: list[AFERegister]
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
class AFEOffsets(cdt.Structure):
|
|
472
|
+
identifier: cdt.VisibleString
|
|
473
|
+
register_list: AFERegisters
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
class KPZAFEOffsets(DataDynamic):
|
|
477
|
+
A_ELEMENTS = DataStatic.get_attr_element(2).get_change(data_type=AFEOffsets),
|
|
@@ -1,48 +1,87 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
from typing import Self, Literal
|
|
3
3
|
from ..types import cst
|
|
4
|
+
from copy import copy
|
|
4
5
|
|
|
5
|
-
SKIP =
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
SKIP: int = 0
|
|
7
|
+
RANGE256 = set(range(256))
|
|
8
|
+
RANGE64 = bytes(range(64))
|
|
9
|
+
RANGE64_WITH_LENGTH = b'\x40' + RANGE64
|
|
9
10
|
|
|
10
11
|
|
|
11
|
-
@dataclass
|
|
12
|
+
@dataclass(frozen=True, slots=True)
|
|
12
13
|
class LNPattern:
|
|
13
|
-
"""pattern for use in get_filtered.
|
|
14
|
-
value "x.x.x.x.x.x" where x is:
|
|
15
|
-
0..255 - simple value
|
|
16
|
-
a,b,c,d,e,f - for skip value in each group
|
|
17
|
-
(y, z, ...) - set of simple values(y or z)
|
|
18
|
-
((y-z), ...) - set of simple values with range(from y to z)
|
|
19
|
-
!() - as () but, set of exclude values
|
|
20
|
-
example: "a.0.(1,2,3).(0-64).0.f"
|
|
21
14
|
"""
|
|
22
|
-
|
|
15
|
+
LNPattern ::= SEQUENCE (SIZE (6)) OF GroupPattern
|
|
16
|
+
|
|
17
|
+
GroupPattern ::= CHOICE {
|
|
18
|
+
skip [0] NULL, -- SKIP marker
|
|
19
|
+
single [1] INTEGER (0..255), -- single value
|
|
20
|
+
multiple [2] SEQUENCE OF INTEGER (0..255) -- set of values
|
|
21
|
+
}
|
|
22
|
+
LNPattern Binary Encoding Specification:
|
|
23
|
+
---------------------------------------
|
|
24
|
+
A compact tag-less binary format for storing 6 OBIS-like groups.
|
|
25
|
+
|
|
26
|
+
Structure:
|
|
27
|
+
[L1][V1][L2][V2]...[L6][V6]
|
|
28
|
+
where:
|
|
29
|
+
- Ln: 1-byte length prefix for group n (0-255)
|
|
30
|
+
- Vn: Value bytes (interpretation depends on Ln)
|
|
23
31
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
32
|
+
Length Semantics:
|
|
33
|
+
- L=0 : SKIP group (no value bytes follow)
|
|
34
|
+
- L=1 : Single value (V is 1-byte integer 0-255)
|
|
35
|
+
- L=2..255 : Value set (V contains L bytes as possible values)
|
|
36
|
+
|
|
37
|
+
Special Cases:
|
|
38
|
+
- Group 'b' (index 1) when marked SKIP uses predefined RANGE64 (0-64)
|
|
39
|
+
- Empty exclusion sets "!()" are prohibited
|
|
40
|
+
|
|
41
|
+
Example:
|
|
42
|
+
Pattern "a.1.(2-5).!().0.f" encodes as:
|
|
43
|
+
[00][01][01][04][02][03][04][05][00][01][00][00]
|
|
44
|
+
(SKIP|1|{2,3,4,5}|SKIP|0|SKIP)
|
|
45
|
+
|
|
46
|
+
Properties:
|
|
47
|
+
- Fixed overhead: 6 bytes (1 length byte per group)
|
|
48
|
+
- Max size: 6 + 255*6 = 1536 bytes
|
|
49
|
+
- Order-preserving
|
|
50
|
+
- Comparison-friendly memory layout
|
|
51
|
+
"""
|
|
52
|
+
buffer: bytes
|
|
27
53
|
|
|
28
54
|
@classmethod
|
|
29
55
|
def parse(cls, value: str) -> Self:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
):
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
56
|
+
buffer = bytearray()
|
|
57
|
+
parts = value.split('.', maxsplit=5)
|
|
58
|
+
if len(parts) != 6:
|
|
59
|
+
raise ValueError(f"got {len(parts)} elements, expected 6")
|
|
60
|
+
for i, val in enumerate(parts):
|
|
61
|
+
if val.isdigit():
|
|
62
|
+
num = int(val)
|
|
63
|
+
if 0 <= num <= 255:
|
|
64
|
+
buffer.extend((1, num))
|
|
65
|
+
continue
|
|
66
|
+
raise ValueError(f"Value {val} out of range 0-255")
|
|
67
|
+
if len(val) == 1:
|
|
68
|
+
if val == "x":
|
|
69
|
+
buffer.append(SKIP)
|
|
70
|
+
continue
|
|
71
|
+
elif (
|
|
72
|
+
i == 1
|
|
73
|
+
and val == "b"
|
|
74
|
+
):
|
|
75
|
+
buffer.extend(RANGE64_WITH_LENGTH)
|
|
39
76
|
continue
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
77
|
+
elif ord(val) == i + 97:
|
|
78
|
+
buffer.append(SKIP)
|
|
79
|
+
continue
|
|
80
|
+
if val == "":
|
|
81
|
+
buffer.append(SKIP)
|
|
82
|
+
continue
|
|
83
|
+
if val[0]=='(' and val[-1]==')':
|
|
84
|
+
el = set()
|
|
46
85
|
val = val.replace('(', "").replace(')', "")
|
|
47
86
|
for j in val.split(","):
|
|
48
87
|
j = j.replace(" ", '')
|
|
@@ -53,12 +92,16 @@ class LNPattern:
|
|
|
53
92
|
start, end = j.split("-")
|
|
54
93
|
el.update(range(
|
|
55
94
|
cls.__simple_validate(start),
|
|
56
|
-
cls.__simple_validate(end)+1))
|
|
95
|
+
cls.__simple_validate(end) + 1))
|
|
57
96
|
case err:
|
|
58
97
|
raise ValueError(F"got a lot of <-> in pattern: {value}, expected one")
|
|
59
|
-
values
|
|
60
|
-
|
|
61
|
-
|
|
98
|
+
# values = bytes(el)
|
|
99
|
+
# buffer.extend([len(values)] + list(values))
|
|
100
|
+
buffer.append(len(el))
|
|
101
|
+
buffer.extend(el)
|
|
102
|
+
continue
|
|
103
|
+
if val.startswith('!(') and val.endswith(')'):
|
|
104
|
+
el = copy(RANGE256)
|
|
62
105
|
val = val.replace('!(', "").replace(')', "")
|
|
63
106
|
for j in val.split(","):
|
|
64
107
|
j = j.replace(" ", '')
|
|
@@ -69,15 +112,18 @@ class LNPattern:
|
|
|
69
112
|
start, end = j.split("-")
|
|
70
113
|
el.difference_update(range(
|
|
71
114
|
cls.__simple_validate(start),
|
|
72
|
-
cls.__simple_validate(end)+1))
|
|
115
|
+
cls.__simple_validate(end) + 1))
|
|
73
116
|
case err:
|
|
74
117
|
raise ValueError(F"got a lot of <-> in pattern: {value}, expected one")
|
|
75
|
-
if len(el)
|
|
76
|
-
raise ValueError(F"no one element in group: {chr(97+i)}")
|
|
77
|
-
values
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
118
|
+
if len(el)==0:
|
|
119
|
+
raise ValueError(F"no one element in group: {chr(97 + i)}")
|
|
120
|
+
# values = bytes(el)
|
|
121
|
+
# buffer.extend([len(values)] + list(values))
|
|
122
|
+
buffer.append(len(el))
|
|
123
|
+
buffer.extend(el)
|
|
124
|
+
continue
|
|
125
|
+
raise ValueError(f"Invalid pattern: {val}")
|
|
126
|
+
return cls(bytes(buffer))
|
|
81
127
|
|
|
82
128
|
@staticmethod
|
|
83
129
|
def __simple_validate(value: str) -> int:
|
|
@@ -86,26 +132,66 @@ class LNPattern:
|
|
|
86
132
|
else:
|
|
87
133
|
raise ValueError(F"got not valid element: {value} in pattern, expected 0..255")
|
|
88
134
|
|
|
89
|
-
def
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
for i, j in zip(self.__values, other):
|
|
96
|
-
if i == j or (i == -1):
|
|
97
|
-
continue
|
|
98
|
-
elif isinstance(i, set) and j in i:
|
|
135
|
+
def __eq__(self, other: "LNPattern") -> bool:
|
|
136
|
+
ptr = 0
|
|
137
|
+
for i in range(6):
|
|
138
|
+
length = self.buffer[ptr]
|
|
139
|
+
ptr += 1
|
|
140
|
+
if length == 0: # SKIP
|
|
99
141
|
continue
|
|
100
|
-
|
|
101
|
-
|
|
142
|
+
other_byte = other.contents[i]
|
|
143
|
+
if length == 1: # Single byte
|
|
144
|
+
if self.buffer[ptr]!=other_byte:
|
|
145
|
+
return False
|
|
146
|
+
else: # Multiple bytes
|
|
147
|
+
if other_byte not in self.buffer[ptr:ptr + length]:
|
|
148
|
+
return False
|
|
149
|
+
ptr += length
|
|
102
150
|
return True
|
|
103
151
|
|
|
104
|
-
|
|
105
|
-
|
|
152
|
+
@staticmethod
|
|
153
|
+
def _format_ranges(values: list[int]) -> str:
|
|
154
|
+
if not values:
|
|
155
|
+
return "!()"
|
|
156
|
+
ranges = []
|
|
157
|
+
start = end = values[0]
|
|
158
|
+
for num in values[1:]:
|
|
159
|
+
if num==end + 1:
|
|
160
|
+
end = num
|
|
161
|
+
else:
|
|
162
|
+
ranges.append((start, end))
|
|
163
|
+
start = end = num
|
|
164
|
+
ranges.append((start, end))
|
|
165
|
+
parts = []
|
|
166
|
+
for start, end in ranges:
|
|
167
|
+
if start==end:
|
|
168
|
+
parts.append(str(start))
|
|
169
|
+
elif end==start + 1: # Диапазон из 2 чисел
|
|
170
|
+
parts.extend([str(start), str(end)])
|
|
171
|
+
else:
|
|
172
|
+
parts.append(f"{start}-{end}")
|
|
173
|
+
if len(parts) > 3 and len(values) > 128: # Эмпирический порог
|
|
174
|
+
all_values = set(range(256))
|
|
175
|
+
excluded = sorted(all_values - set(values))
|
|
176
|
+
if len(excluded) < len(values):
|
|
177
|
+
return f"!({','.join(self._format_ranges(excluded))})"
|
|
178
|
+
return f"({','.join(parts)})"
|
|
106
179
|
|
|
107
|
-
def
|
|
108
|
-
|
|
180
|
+
def __str__(self) -> str:
|
|
181
|
+
parts = []
|
|
182
|
+
ptr = 0
|
|
183
|
+
for _ in range(6):
|
|
184
|
+
length = self.buffer[ptr]
|
|
185
|
+
ptr += 1
|
|
186
|
+
if length == 0:
|
|
187
|
+
parts.append("x")
|
|
188
|
+
elif length == 1:
|
|
189
|
+
parts.append(str(self.buffer[ptr]))
|
|
190
|
+
else:
|
|
191
|
+
values = sorted(set(self.buffer[ptr:ptr + length]))
|
|
192
|
+
parts.append(self._format_ranges(values))
|
|
193
|
+
ptr += length
|
|
194
|
+
return ".".join(parts)
|
|
109
195
|
|
|
110
196
|
|
|
111
197
|
@dataclass
|
|
@@ -115,14 +201,17 @@ class LNPatterns:
|
|
|
115
201
|
def __iter__(self):
|
|
116
202
|
return iter(self.value)
|
|
117
203
|
|
|
204
|
+
def __str__(self) -> str:
|
|
205
|
+
return f"[{" | ".join(map(str, self.value))}]"
|
|
206
|
+
|
|
118
207
|
|
|
119
|
-
ABSTRACT = LNPattern.parse("0")
|
|
120
|
-
ELECTRICITY = LNPattern.parse("1")
|
|
121
|
-
HCA = LNPattern.parse("4")
|
|
122
|
-
THERMAL = LNPattern.parse("(5,6)")
|
|
123
|
-
GAS = LNPattern.parse("7")
|
|
124
|
-
WATER = LNPattern.parse("(8,9)")
|
|
125
|
-
OTHER_MEDIA = LNPattern.parse("15")
|
|
208
|
+
ABSTRACT = LNPattern.parse("0.....")
|
|
209
|
+
ELECTRICITY = LNPattern.parse("1.....")
|
|
210
|
+
HCA = LNPattern.parse("4.....")
|
|
211
|
+
THERMAL = LNPattern.parse("(5,6).....")
|
|
212
|
+
GAS = LNPattern.parse("7.....")
|
|
213
|
+
WATER = LNPattern.parse("(8,9).....")
|
|
214
|
+
OTHER_MEDIA = LNPattern.parse("15.....")
|
|
126
215
|
|
|
127
216
|
|
|
128
217
|
BILLING_PERIOD_VALUES_RESET_COUNTER_ENTRIES = LNPatterns((
|
DLMS_SPODES/pardata.py
CHANGED
|
@@ -620,10 +620,10 @@ class Float(SimpleDataType, ABC):
|
|
|
620
620
|
case None: self.clear()
|
|
621
621
|
case bytes() as encoding:
|
|
622
622
|
length_and_contents = encoding[1:]
|
|
623
|
-
match encoding[:1],
|
|
624
|
-
case self.TAG, int() if
|
|
623
|
+
match encoding[:1], self.SIZE:
|
|
624
|
+
case self.TAG, int() if self.SIZE <= len(length_and_contents): self.contents = length_and_contents[:self.SIZE]
|
|
625
625
|
case self.TAG, _: raise ValueError(F'Length of contents for {self.TAG} must be at least '
|
|
626
|
-
F'{
|
|
626
|
+
F'{self.SIZE}, but got {len(length_and_contents)}')
|
|
627
627
|
case _ as wrong_tag, _: raise ValueError(F'Expected {self.TAG} type, got {get_common_data_type_from(wrong_tag).TAG}')
|
|
628
628
|
case bytearray(): self.contents = bytes(value) # Attention!!! changed method content getting from bytearray
|
|
629
629
|
case str(): self.contents = self.from_str(value)
|
|
@@ -668,13 +668,13 @@ class Float(SimpleDataType, ABC):
|
|
|
668
668
|
|
|
669
669
|
def __float__(self):
|
|
670
670
|
""" return the build in float type IEEE 60559"""
|
|
671
|
-
return unpack(
|
|
671
|
+
return unpack(self.FORMAT, self.contents)[0]
|
|
672
672
|
|
|
673
673
|
def __str__(self):
|
|
674
674
|
return str(float(self))
|
|
675
675
|
|
|
676
676
|
def clear(self): # todo: remove this
|
|
677
|
-
self.contents = bytes(
|
|
677
|
+
self.contents = bytes(self.SIZE)
|
|
678
678
|
|
|
679
679
|
|
|
680
680
|
class LIST(ABC):
|
|
@@ -1903,12 +1903,13 @@ class Float32(Float, SimpleDataType):
|
|
|
1903
1903
|
"""float32. ISO/IEC/IEEE 60559:2011"""
|
|
1904
1904
|
TAG = TAG(b'\x17')
|
|
1905
1905
|
FORMAT = ">f"
|
|
1906
|
-
|
|
1906
|
+
SIZE = 4
|
|
1907
1907
|
|
|
1908
1908
|
class Float64(Float, SimpleDataType):
|
|
1909
1909
|
"""float64. ISO/IEC/IEEE 60559:2011"""
|
|
1910
1910
|
TAG = TAG(b'\x18')
|
|
1911
1911
|
FORMAT = ">d"
|
|
1912
|
+
SIZE = 8
|
|
1912
1913
|
|
|
1913
1914
|
|
|
1914
1915
|
_SHORT_MONTHS = (4, 6, 9, 11)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: DLMS_SPODES
|
|
3
|
-
Version: 0.86.
|
|
3
|
+
Version: 0.86.10
|
|
4
4
|
Summary: dlms-spodes
|
|
5
5
|
Author-email: Serj Kotilevski <youserj@outlook.com>
|
|
6
|
+
Project-URL: Source, https://github.com/youserj/DlmsSPODES-project
|
|
6
7
|
Keywords: dlms
|
|
7
8
|
Classifier: Programming Language :: Python :: 3
|
|
8
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -13,7 +14,7 @@ Requires-Dist: pydantic>=2.11
|
|
|
13
14
|
Requires-Dist: cryptography>=45.0
|
|
14
15
|
Requires-Dist: semver>=3.0
|
|
15
16
|
Requires-Dist: typing-extensions>=4.12.2
|
|
16
|
-
Requires-Dist: StructResult>=0.
|
|
17
|
+
Requires-Dist: StructResult>=0.8.0
|
|
17
18
|
Provides-Extra: dev
|
|
18
19
|
Requires-Dist: mypy>=1.5.0; extra == "dev"
|
|
19
20
|
Requires-Dist: ruff>=0.11; extra == "dev"
|
|
@@ -6,7 +6,7 @@ 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=8Pl2Bq-hGrsmH9sajqCf1kxSzpzPsySeq_MYRrRyWFk,705
|
|
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
|
|
@@ -25,7 +25,7 @@ DLMS_SPODES/cosem_interface_classes/activity_calendar.py,sha256=1kKRxBmMRKaKRYpR
|
|
|
25
25
|
DLMS_SPODES/cosem_interface_classes/arbitrator.py,sha256=CvrYknl6xfg8hZR5RijzWsMh34XBQKsQ0nQp_Jtm__E,3208
|
|
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=AQiMtW13_Y74M2kYYfhZsKGPWtHqOkBNvEPX2QCfXfg,4493
|
|
28
|
-
DLMS_SPODES/cosem_interface_classes/collection.py,sha256=
|
|
28
|
+
DLMS_SPODES/cosem_interface_classes/collection.py,sha256=daTqYyMfdGHC5upqVrIJARsMLPs0JQP-b5DPlwUREw8,96343
|
|
29
29
|
DLMS_SPODES/cosem_interface_classes/cosem_interface_class.py,sha256=k-eMPkFK2myfII2sRH8JdwoE7bxtBep-gHE-tqMR71I,22929
|
|
30
30
|
DLMS_SPODES/cosem_interface_classes/data.py,sha256=ELFfBX_VFsKRpAB7SVUp1sBnhjDgttGXa96jSYYLOH8,734
|
|
31
31
|
DLMS_SPODES/cosem_interface_classes/disconnect_control.py,sha256=21qKu4cpOEeiuhQAk4tGcfsm32ibCgQv8W3vVdOO4Wo,2894
|
|
@@ -34,10 +34,10 @@ DLMS_SPODES/cosem_interface_classes/gprs_modem_setup.py,sha256=TM0PcTNOmk0GApHwp
|
|
|
34
34
|
DLMS_SPODES/cosem_interface_classes/iec_local_port_setup.py,sha256=Tu6WB8S7gT-9X7IWYuFFIdtNnbkHM_prG_f-Ock8jUM,410
|
|
35
35
|
DLMS_SPODES/cosem_interface_classes/ipv4_setup.py,sha256=kFixHUH8D7_hVRvOWAQPdcUjCcJT5QtjincOQew2vDU,2823
|
|
36
36
|
DLMS_SPODES/cosem_interface_classes/limiter.py,sha256=a4vyTbglRUPRxP9dGhyrcyYwO5bjy0r-KfG6Kim5sek,5249
|
|
37
|
-
DLMS_SPODES/cosem_interface_classes/ln_pattern.py,sha256=
|
|
37
|
+
DLMS_SPODES/cosem_interface_classes/ln_pattern.py,sha256=IPluhyGWJQLBEUjOjdfEMct8JP_4orUwF92c3sQfSNM,13921
|
|
38
38
|
DLMS_SPODES/cosem_interface_classes/obis.py,sha256=yEwYm5CshJx8X8uSy3QH8XIbdVPg8Tt6zPUjFgkAB0M,575
|
|
39
39
|
DLMS_SPODES/cosem_interface_classes/overview.py,sha256=4RjE6_5x_dDGv4M5J2rjT8MZDF-Q4nFE8JSOUA7OD84,6973
|
|
40
|
-
DLMS_SPODES/cosem_interface_classes/parameter.py,sha256=
|
|
40
|
+
DLMS_SPODES/cosem_interface_classes/parameter.py,sha256=ukoDSqGutYV4K4QSaM7i9zKYm8eyqQ8gnOWvqqAeDCo,18252
|
|
41
41
|
DLMS_SPODES/cosem_interface_classes/register.py,sha256=ClnkQ9-lg9NCxxCtFLR0soQ7VuNdigHia9qx1suGVZE,1854
|
|
42
42
|
DLMS_SPODES/cosem_interface_classes/register_monitor.py,sha256=CrcFqas157kGaaDDwy8a0DKy5wK1Jm-tzCOBGBLuIKM,1760
|
|
43
43
|
DLMS_SPODES/cosem_interface_classes/reports.py,sha256=9kOt9Ztyp5D59j3k3x5URy7WD1qlFNMa8xFlMu7nUmA,3320
|
|
@@ -71,7 +71,7 @@ DLMS_SPODES/cosem_interface_classes/image_transfer/image_transfer_status.py,sha2
|
|
|
71
71
|
DLMS_SPODES/cosem_interface_classes/image_transfer/ver0.py,sha256=YD1Col7297zKt2HcjgZZ4EkahSvSuC0DruX07-hk2uo,5338
|
|
72
72
|
DLMS_SPODES/cosem_interface_classes/implementations/__init__.py,sha256=z4OfnPPyYr6f94rj-PU3---Wk05ddduf9MkmWxhczXA,77
|
|
73
73
|
DLMS_SPODES/cosem_interface_classes/implementations/arbitrator.py,sha256=cMhYLi9ZFqfJ0yxjONHq9JZZJ3QuzrF0jtPjk4nf0eo,573
|
|
74
|
-
DLMS_SPODES/cosem_interface_classes/implementations/data.py,sha256=
|
|
74
|
+
DLMS_SPODES/cosem_interface_classes/implementations/data.py,sha256=g-3SZCSodet9gILK7SsrTPc72Fsq87YDtaZTb0Vucdc,18561
|
|
75
75
|
DLMS_SPODES/cosem_interface_classes/implementations/profile_generic.py,sha256=oibO3EV9fRHxxaBdMQqz436GrMMqo1BlT6lgVtzUKU0,4318
|
|
76
76
|
DLMS_SPODES/cosem_interface_classes/modem_configuration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
77
77
|
DLMS_SPODES/cosem_interface_classes/modem_configuration/ver0.py,sha256=6fzbsID_cOmYsl3alLHHcMM1zpD7NjsK77NzTViQOmo,3038
|
|
@@ -99,7 +99,7 @@ DLMS_SPODES/obis/abstract_objects.py,sha256=0ZoJKRQ_7FoChC2rNSgNV573hso8JYZQKdLF
|
|
|
99
99
|
DLMS_SPODES/obis/media_id.py,sha256=GRiwHPe9-3iCg4u_J6qf2rMc3Wjw0aJHKiSnBtNYD3o,22339
|
|
100
100
|
DLMS_SPODES/types/__init__.py,sha256=UFiP4suA72o_kvaqUnHLGK-cedDXLl8kVHYsjXHYUDw,116
|
|
101
101
|
DLMS_SPODES/types/choices.py,sha256=z7IasrlRaagOYNfRvgbpojDxf1jgYUc9cz59PH2PMi0,6350
|
|
102
|
-
DLMS_SPODES/types/common_data_types.py,sha256=
|
|
102
|
+
DLMS_SPODES/types/common_data_types.py,sha256=IzFFsCWAEORh82aUTg41InfTsXym1i2lynWd5gGWfyc,96936
|
|
103
103
|
DLMS_SPODES/types/cosem_service_types.py,sha256=XLWPDfdSxyYpr_3NwAxICRgxjPJdHf7EgQ4694M-erQ,4360
|
|
104
104
|
DLMS_SPODES/types/useful_types.py,sha256=sRboTj7ZUjEHF9ypCgdXNOk_uOLXL6pjdbqKuPZrtEE,27426
|
|
105
105
|
DLMS_SPODES/types/implementations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -111,7 +111,7 @@ DLMS_SPODES/types/implementations/integers.py,sha256=KAcaTY8ZwhBaJThbLSr39Oh_-9h
|
|
|
111
111
|
DLMS_SPODES/types/implementations/long_unsigneds.py,sha256=SxmFvD2moQ03p-KZSBYK1Rv7bQSaywlHVXBfkTZG1OQ,8761
|
|
112
112
|
DLMS_SPODES/types/implementations/octet_string.py,sha256=Jo_sfWcsfstiP4O6mXfBOOQlksx1c2qJMI-vbAOV-yM,294
|
|
113
113
|
DLMS_SPODES/types/implementations/structs.py,sha256=GMOo6Jy8jA9d6KTLs0D-j5t0oSRvxUIwtBr_4UePwbA,2059
|
|
114
|
-
dlms_spodes-0.86.
|
|
115
|
-
dlms_spodes-0.86.
|
|
116
|
-
dlms_spodes-0.86.
|
|
117
|
-
dlms_spodes-0.86.
|
|
114
|
+
dlms_spodes-0.86.10.dist-info/METADATA,sha256=TIED87Nv6wSzhQegjcQTg-_5uFsI5aQJIzoLb9CqeA8,999
|
|
115
|
+
dlms_spodes-0.86.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
116
|
+
dlms_spodes-0.86.10.dist-info/top_level.txt,sha256=k26SRuRdwBZrSM3NgNZECAUNIDZREbJuLCnPbWtTNak,12
|
|
117
|
+
dlms_spodes-0.86.10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|