DLMS-SPODES 0.86.23__py3-none-any.whl → 0.87.0__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.
@@ -4,6 +4,7 @@ import numpy as np
4
4
  from struct import Struct, pack, unpack_from
5
5
  from typing import Optional, cast, Iterator
6
6
  import re
7
+ from functools import cached_property
7
8
  from .. import exceptions as exc
8
9
  from .obis import OBIS
9
10
 
@@ -37,10 +38,10 @@ class Parameter:
37
38
  piece OPTIONAL
38
39
  }
39
40
  """
40
- value: bytes
41
+ _value: bytes
41
42
 
42
43
  def __bytes__(self) -> bytes:
43
- return self.value
44
+ return self._value
44
45
 
45
46
  @classmethod
46
47
  def parse(cls, value: str) -> "Parameter":
@@ -59,25 +60,29 @@ class Parameter:
59
60
  ret += (g1 + int(a)).to_bytes(2)
60
61
  return cls(ret)
61
62
 
63
+ @cached_property
64
+ def logical_name(self) -> "Parameter":
65
+ return self.get_attr(2)
66
+
62
67
  def __eq__(self, other) -> bool:
63
68
  if isinstance(other, Parameter):
64
- return cast("bool", self.value == other.value)
69
+ return cast("bool", self._value==other._value)
65
70
  return NotImplemented
66
71
 
67
72
  def __lt__(self, other: "Parameter") -> bool:
68
73
  """comparing for sort method"""
69
- if len(self.value) > len(other.value):
74
+ if len(self._value) > len(other._value):
70
75
  return True
71
76
  else:
72
77
  return False
73
78
 
74
79
  def __str__(self) -> str:
75
- if (l := len(self.value)) < 6:
80
+ if (l := len(self._value)) < 6:
76
81
  return "No valid"
77
82
  elif l == 7:
78
83
  return "No valid Index"
79
84
  else:
80
- res = F"{".".join(map(str, self.value[:6]))}"
85
+ res = F"{".".join(map(str, self._value[:6]))}"
81
86
  if l > 6:
82
87
  res += F":{"m" if self.is_method() else ""}{self.i}"
83
88
  if l > 8:
@@ -87,41 +92,51 @@ class Parameter:
87
92
  return res
88
93
 
89
94
  def validate(self) -> None:
90
- if (length := len(self.value)) < 6:
95
+ if (length := len(self._value)) < 6:
91
96
  raise exc.DLMSException(F"Parameter got {length=}, expected at least 6")
92
97
  if length == 7:
93
98
  raise exc.DLMSException(F"Parameter got wrong index")
94
99
 
95
100
  @property
96
101
  def has_index(self) -> bool:
97
- return len(self.value) > 6
102
+ return len(self._value) > 6
98
103
 
99
104
  @property
100
105
  @deprecated("use obis")
101
106
  def ln(self) -> bytes:
102
107
  """Logical Name"""
103
- return self.value[:6]
108
+ return self._value[:6]
104
109
 
105
110
  def is_method(self) -> bool:
106
- return self.value[6] == 1
111
+ return self._value[6] == 1
107
112
 
108
113
  @property
109
114
  def i(self) -> int:
110
115
  """attribute or method index"""
111
- return self.value[7]
116
+ return self._value[7]
117
+
118
+ def get_attr(self, i: int) -> "Parameter":
119
+ """get attribute"""
120
+ val = Index.pack(0, i)
121
+ return self.__class__(self._value[:6] + val)
122
+
123
+ def get_meth(self, i: int) -> "Parameter":
124
+ """get method"""
125
+ val = Index.pack(1, i)
126
+ return self.__class__(self._value[:6] + val)
112
127
 
113
128
  def set_i(self, index: int, is_method: bool = False) -> "Parameter":
114
129
  val = Index.pack(is_method, index)
115
- if len(self.value) == 6:
116
- tmp = self.value + val
130
+ if len(self._value) == 6:
131
+ tmp = self._value + val
117
132
  else:
118
- tmp = bytearray(self.value)
133
+ tmp = bytearray(self._value)
119
134
  tmp[6:8] = val
120
135
  tmp = bytes(tmp)
121
136
  return self.__class__(tmp)
122
137
 
123
138
  def append_validate(self) -> None:
124
- if (l := len(self.value)) < 7:
139
+ if (l := len(self._value)) < 7:
125
140
  raise exc.DLMSException(F"Parameter must has index before")
126
141
  elif l % 2 != 0:
127
142
  raise exc.DLMSException(F"Can't append to Parameter with piece")
@@ -129,11 +144,11 @@ class Parameter:
129
144
  def append(self, index: int) -> "Parameter":
130
145
  """add new sequence(array or struct) index element"""
131
146
  self.append_validate()
132
- return self.__class__(self.value + pack(">H", index))
147
+ return self.__class__(self._value + pack(">H", index))
133
148
 
134
149
  def extend(self, *indexes: int) -> "Parameter":
135
150
  self.append_validate()
136
- return self.__class__(self.value + pack(F">{len(indexes)}H", *indexes))
151
+ return self.__class__(self._value + pack(F">{len(indexes)}H", *indexes))
137
152
 
138
153
  def pop(self) -> tuple[Optional[int], int, "Parameter"]:
139
154
  """
@@ -141,20 +156,20 @@ class Parameter:
141
156
  ex.: Parameter("0.0.0.0.0.0:2 1/1/1 p3") => (1, Parameter("0.0.0.0.0.0:2 1/1"))
142
157
  """
143
158
  if self.has_piece():
144
- return self.value[-1], int.from_bytes(self.value[-3:-1]), self.__class__(self.value[:-3])
159
+ return self._value[-1], int.from_bytes(self._value[-3:-1]), self.__class__(self._value[:-3])
145
160
  else:
146
- return None, int.from_bytes(self.value[-2:]), self.__class__(self.value[:-2])
161
+ return None, int.from_bytes(self._value[-2:]), self.__class__(self._value[:-2])
147
162
 
148
163
  def set_piece(self, index: int) -> "Parameter":
149
164
  """add new sequence(array or struct) index element"""
150
- if len(self.value) >= 7:
151
- return self.__class__(self.value + pack("B", index))
165
+ if len(self._value) >= 7:
166
+ return self.__class__(self._value + pack("B", index))
152
167
  else:
153
168
  raise exc.DLMSException(F"Parameter must has index before")
154
169
 
155
170
  def has_piece(self) -> bool:
156
171
  if (
157
- (l := len(self.value)) >= 9
172
+ (l := len(self._value)) >= 9
158
173
  and l % 2 != 0
159
174
  ):
160
175
  return True
@@ -164,22 +179,22 @@ class Parameter:
164
179
  @property
165
180
  def piece(self) -> Optional[int]:
166
181
  if self.has_piece():
167
- return self.value[-1]
182
+ return self._value[-1]
168
183
 
169
184
  def clear_piece(self) -> "Parameter":
170
185
  if self.has_piece():
171
- return self.__class__(self.value[:-1])
186
+ return self.__class__(self._value[:-1])
172
187
 
173
188
  def elements(self, start: int = 0) -> Iterator[int]:
174
189
  """return: index elements nested in attribute, started with"""
175
190
  for i in range(8 + start, 8 + 2 * self.n_elements, 2):
176
- res = int.from_bytes(self.value[i:i+2], "big")
191
+ res = int.from_bytes(self._value[i:i + 2], "big")
177
192
  yield res
178
193
 
179
194
  def __iter__(self) -> Iterator[int]:
180
- for it in self.value[:6]:
195
+ for it in self._value[:6]:
181
196
  yield it
182
- if self.value[6] == 1:
197
+ if self._value[6] == 1:
183
198
  yield -self.i
184
199
  else:
185
200
  yield self.i
@@ -190,15 +205,15 @@ class Parameter:
190
205
  if self.n_elements == 0:
191
206
  raise ValueError("Parameter hasn't elements")
192
207
  if self.has_piece():
193
- val = self.value[-3: -1]
208
+ val = self._value[-3: -1]
194
209
  else:
195
- val = self.value[-2:]
210
+ val = self._value[-2:]
196
211
  return int.from_bytes(val, "big")
197
212
 
198
213
  @property
199
214
  def n_elements(self) -> int:
200
215
  """return: amount of elements nested in attribute"""
201
- return max(0, (len(self.value) - 8) // 2)
216
+ return max(0, (len(self._value) - 8) // 2)
202
217
 
203
218
  def set(self,
204
219
  a: int = None,
@@ -208,7 +223,7 @@ class Parameter:
208
223
  e: int = None,
209
224
  f: int = None
210
225
  ) -> "Parameter":
211
- val = bytearray(self.value)
226
+ val = bytearray(self._value)
212
227
  if a is not None:
213
228
  val[0] = a
214
229
  if b is not None:
@@ -224,52 +239,52 @@ class Parameter:
224
239
  return self.__class__(bytes(val))
225
240
 
226
241
  def __contains__(self, item: "Parameter"):
227
- return item.value in self.value
242
+ return item._value in self._value
228
243
 
229
244
  def __getitem__(self, item) -> Optional[int]:
230
245
  if self.n_elements > 0:
231
- return unpack_from(">H", self.value, item*2 + 8)[0]
246
+ return unpack_from(">H", self._value, item * 2 + 8)[0]
232
247
  else:
233
248
  return None
234
249
 
235
250
  @property
236
251
  def a(self) -> int:
237
- return self.value[0]
252
+ return self._value[0]
238
253
 
239
254
  @property
240
255
  def b(self) -> int:
241
- return self.value[1]
256
+ return self._value[1]
242
257
 
243
258
  @property
244
259
  def c(self) -> int:
245
- return self.value[2]
260
+ return self._value[2]
246
261
 
247
262
  @property
248
263
  def d(self) -> int:
249
- return self.value[3]
264
+ return self._value[3]
250
265
 
251
266
  @property
252
267
  def e(self) -> int:
253
- return self.value[4]
268
+ return self._value[4]
254
269
 
255
270
  @property
256
271
  def f(self) -> int:
257
- return self.value[5]
272
+ return self._value[5]
258
273
 
259
274
  @property
260
275
  def attr(self) -> "Parameter":
261
276
  if self.has_index:
262
- return Parameter(self.value[:8])
277
+ return Parameter(self._value[:8])
263
278
  else:
264
279
  raise exc.DLMSException(F"Parameter must has index before")
265
280
 
266
281
  @property
267
282
  def obj(self) -> "Parameter":
268
- return Parameter(self.value[:6])
283
+ return Parameter(self._value[:6])
269
284
 
270
285
  @property
271
286
  def obis(self) -> OBIS:
272
- return OBIS(self.value[:6])
287
+ return OBIS(self._value[:6])
273
288
 
274
289
 
275
290
  RANGE64 = bytes(range(65)) # Предвычисленный диапазон 0-64
@@ -1,26 +1,41 @@
1
1
  from dataclasses import dataclass
2
2
  from functools import cached_property
3
+ from typing import Self
3
4
  from .parameter import Parameter
4
5
 
5
6
 
6
- @dataclass
7
- class Base:
8
- OBIS: Parameter
7
+ @dataclass(frozen=True)
8
+ class Data(Parameter):
9
+ @property
10
+ def value(self) -> Parameter:
11
+ return self.get_attr(2)
9
12
 
10
- @cached_property
11
- def LN(self) -> Parameter:
12
- return self.OBIS.set_i(1)
13
13
 
14
+ @dataclass(frozen=True)
15
+ class Register(Data):
16
+ @property
17
+ def scaler_unit(self) -> Parameter:
18
+ return self.get_attr(3)
14
19
 
15
- @dataclass
16
- class Data(Base):
17
- @cached_property
18
- def VALUE(self) -> Parameter:
19
- return self.OBIS.set_i(2)
20
20
 
21
+ @dataclass(frozen=True)
22
+ class DisconnectControl(Parameter):
21
23
 
22
- @dataclass
23
- class Register(Data):
24
- @cached_property
25
- def SCALER_UNIT(self) -> Parameter:
26
- return self.OBIS.set_i(3)
24
+ @classmethod
25
+ def from_b(cls, b: int) -> "DisconnectControl":
26
+ return cls.parse(f"0.{b}.96.3.10.255")
27
+
28
+ @property
29
+ def output_state(self) -> "DisconnectControl":
30
+ return self.get_attr(2)
31
+
32
+ @property
33
+ def control_state(self) -> "DisconnectControl":
34
+ return self.get_attr(3)
35
+
36
+ @property
37
+ def control_mode(self) -> "DisconnectControl":
38
+ return self.get_attr(4)
39
+
40
+
41
+ DISCONNECT_CONTROL_0 = DisconnectControl.from_b(0)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: DLMS_SPODES
3
- Version: 0.86.23
3
+ Version: 0.87.0
4
4
  Summary: dlms-spodes
5
5
  Author-email: Serj Kotilevski <youserj@outlook.com>
6
6
  Project-URL: Source, https://github.com/youserj/DlmsSPODES-project
@@ -37,8 +37,8 @@ DLMS_SPODES/cosem_interface_classes/limiter.py,sha256=LDVoix4L2yq4yPxbfSv6zoyA5p
37
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=0eko1CW0eH397J5kM20G7RSQUzCGV6lGCMPbLsKPEqQ,7146
40
- DLMS_SPODES/cosem_interface_classes/parameter.py,sha256=ukoDSqGutYV4K4QSaM7i9zKYm8eyqQ8gnOWvqqAeDCo,18252
41
- DLMS_SPODES/cosem_interface_classes/parameters.py,sha256=UOsqKZeqxDjqtXOcpnxInwgmFTWOkCar9ZuIOaIEjvo,513
40
+ DLMS_SPODES/cosem_interface_classes/parameter.py,sha256=3jisBFy5JwssActfoA7l4RWwR5Hg7wNHu-x3QwoOKAU,18769
41
+ DLMS_SPODES/cosem_interface_classes/parameters.py,sha256=VzBgxWLrMFgbKcBAyahqcLR6-SygXMyVnm9-0V3SV3E,960
42
42
  DLMS_SPODES/cosem_interface_classes/register.py,sha256=Cfikftpo1Nzg_B2drOmJDwoGkbS2wXlqQpxVgXL1w2U,1886
43
43
  DLMS_SPODES/cosem_interface_classes/register_monitor.py,sha256=fNM-JrjHxQB8b5DgUOtDcnkO_hxu5bFICiuKEoZa37g,1792
44
44
  DLMS_SPODES/cosem_interface_classes/reports.py,sha256=9kOt9Ztyp5D59j3k3x5URy7WD1qlFNMa8xFlMu7nUmA,3320
@@ -112,7 +112,7 @@ DLMS_SPODES/types/implementations/integers.py,sha256=KAcaTY8ZwhBaJThbLSr39Oh_-9h
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.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,,
115
+ dlms_spodes-0.87.0.dist-info/METADATA,sha256=2jD61CR1E2XCM2X8egSNxQSfYh6qvxVwZLSv7RGxbNc,1027
116
+ dlms_spodes-0.87.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
117
+ dlms_spodes-0.87.0.dist-info/top_level.txt,sha256=k26SRuRdwBZrSM3NgNZECAUNIDZREbJuLCnPbWtTNak,12
118
+ dlms_spodes-0.87.0.dist-info/RECORD,,