DLMS-SPODES 0.87.17__py3-none-any.whl → 0.88.1__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.
Files changed (103) hide show
  1. DLMS_SPODES/Values/EN/__init__.py +1 -1
  2. DLMS_SPODES/Values/EN/actors.py +8 -8
  3. DLMS_SPODES/Values/EN/relation_to_obis_names.py +387 -387
  4. DLMS_SPODES/Values/RU/__init__.py +1 -1
  5. DLMS_SPODES/Values/RU/actors.py +8 -8
  6. DLMS_SPODES/Values/RU/relation_to_obis_names.py +396 -396
  7. DLMS_SPODES/__init__.py +6 -6
  8. DLMS_SPODES/configEN.ini +126 -126
  9. DLMS_SPODES/config_parser.py +53 -53
  10. DLMS_SPODES/cosem_interface_classes/Overview/__init__.py +0 -0
  11. DLMS_SPODES/cosem_interface_classes/Overview/class_id.py +107 -0
  12. DLMS_SPODES/cosem_interface_classes/__class_init__.py +3 -3
  13. DLMS_SPODES/cosem_interface_classes/__init__.py +3 -2
  14. DLMS_SPODES/cosem_interface_classes/activity_calendar.py +210 -254
  15. DLMS_SPODES/cosem_interface_classes/arbitrator.py +78 -105
  16. DLMS_SPODES/cosem_interface_classes/association_ln/abstract.py +50 -34
  17. DLMS_SPODES/cosem_interface_classes/association_ln/authentication_mechanism_name.py +25 -25
  18. DLMS_SPODES/cosem_interface_classes/association_ln/mechanism_id.py +25 -25
  19. DLMS_SPODES/cosem_interface_classes/association_ln/method.py +5 -5
  20. DLMS_SPODES/cosem_interface_classes/association_ln/ver0.py +440 -485
  21. DLMS_SPODES/cosem_interface_classes/association_ln/ver1.py +126 -133
  22. DLMS_SPODES/cosem_interface_classes/association_ln/ver2.py +30 -36
  23. DLMS_SPODES/cosem_interface_classes/association_ln/ver3.py +3 -4
  24. DLMS_SPODES/cosem_interface_classes/association_sn/ver0.py +14 -12
  25. DLMS_SPODES/cosem_interface_classes/clock.py +81 -131
  26. DLMS_SPODES/cosem_interface_classes/collection.py +2106 -2122
  27. DLMS_SPODES/cosem_interface_classes/cosem_interface_class.py +525 -583
  28. DLMS_SPODES/cosem_interface_classes/data.py +12 -21
  29. DLMS_SPODES/cosem_interface_classes/demand_register/ver0.py +32 -59
  30. DLMS_SPODES/cosem_interface_classes/disconnect_control.py +56 -74
  31. DLMS_SPODES/cosem_interface_classes/extended_register.py +18 -27
  32. DLMS_SPODES/cosem_interface_classes/gprs_modem_setup.py +33 -43
  33. DLMS_SPODES/cosem_interface_classes/gsm_diagnostic/ver0.py +78 -103
  34. DLMS_SPODES/cosem_interface_classes/gsm_diagnostic/ver1.py +42 -40
  35. DLMS_SPODES/cosem_interface_classes/gsm_diagnostic/ver2.py +6 -9
  36. DLMS_SPODES/cosem_interface_classes/iec_hdlc_setup/ver0.py +11 -11
  37. DLMS_SPODES/cosem_interface_classes/iec_hdlc_setup/ver1.py +27 -53
  38. DLMS_SPODES/cosem_interface_classes/iec_local_port_setup.py +9 -11
  39. DLMS_SPODES/cosem_interface_classes/image_transfer/image_transfer_status.py +15 -15
  40. DLMS_SPODES/cosem_interface_classes/image_transfer/ver0.py +54 -126
  41. DLMS_SPODES/cosem_interface_classes/implementations/__init__.py +3 -3
  42. DLMS_SPODES/cosem_interface_classes/implementations/arbitrator.py +19 -19
  43. DLMS_SPODES/cosem_interface_classes/implementations/data.py +491 -487
  44. DLMS_SPODES/cosem_interface_classes/implementations/profile_generic.py +85 -83
  45. DLMS_SPODES/cosem_interface_classes/ipv4_setup.py +42 -72
  46. DLMS_SPODES/cosem_interface_classes/limiter.py +77 -111
  47. DLMS_SPODES/cosem_interface_classes/ln_pattern.py +334 -333
  48. DLMS_SPODES/cosem_interface_classes/modem_configuration/ver0.py +51 -65
  49. DLMS_SPODES/cosem_interface_classes/modem_configuration/ver1.py +27 -39
  50. DLMS_SPODES/cosem_interface_classes/ntp_setup/ver0.py +48 -67
  51. DLMS_SPODES/cosem_interface_classes/obis.py +28 -23
  52. DLMS_SPODES/cosem_interface_classes/overview.py +198 -197
  53. DLMS_SPODES/cosem_interface_classes/parameter.py +548 -547
  54. DLMS_SPODES/cosem_interface_classes/parameters.py +172 -172
  55. DLMS_SPODES/cosem_interface_classes/profile_generic/ver0.py +90 -133
  56. DLMS_SPODES/cosem_interface_classes/profile_generic/ver1.py +268 -277
  57. DLMS_SPODES/cosem_interface_classes/push_setup/ver0.py +13 -12
  58. DLMS_SPODES/cosem_interface_classes/push_setup/ver1.py +9 -10
  59. DLMS_SPODES/cosem_interface_classes/push_setup/ver2.py +124 -166
  60. DLMS_SPODES/cosem_interface_classes/register.py +18 -45
  61. DLMS_SPODES/cosem_interface_classes/register_activation/ver0.py +45 -80
  62. DLMS_SPODES/cosem_interface_classes/register_monitor.py +33 -46
  63. DLMS_SPODES/cosem_interface_classes/reports.py +72 -70
  64. DLMS_SPODES/cosem_interface_classes/schedule.py +88 -176
  65. DLMS_SPODES/cosem_interface_classes/script_table.py +54 -87
  66. DLMS_SPODES/cosem_interface_classes/security_setup/ver0.py +45 -68
  67. DLMS_SPODES/cosem_interface_classes/security_setup/ver1.py +122 -158
  68. DLMS_SPODES/cosem_interface_classes/single_action_schedule.py +34 -50
  69. DLMS_SPODES/cosem_interface_classes/special_days_table.py +54 -84
  70. DLMS_SPODES/cosem_interface_classes/tcp_udp_setup.py +20 -42
  71. DLMS_SPODES/cosem_pdu.py +93 -93
  72. DLMS_SPODES/enums.py +625 -625
  73. DLMS_SPODES/exceptions.py +106 -106
  74. DLMS_SPODES/firmwares.py +99 -99
  75. DLMS_SPODES/hdlc/frame.py +875 -875
  76. DLMS_SPODES/hdlc/sub_layer.py +54 -54
  77. DLMS_SPODES/literals.py +17 -17
  78. DLMS_SPODES/obis/__init__.py +1 -1
  79. DLMS_SPODES/obis/media_id.py +931 -931
  80. DLMS_SPODES/pardata.py +22 -22
  81. DLMS_SPODES/pdu_enums.py +98 -98
  82. DLMS_SPODES/relation_to_OBIS.py +463 -465
  83. DLMS_SPODES/settings.py +551 -551
  84. DLMS_SPODES/types/choices.py +140 -142
  85. DLMS_SPODES/types/common_data_types.py +2379 -2401
  86. DLMS_SPODES/types/cosem_service_types.py +109 -109
  87. DLMS_SPODES/types/implementations/arrays.py +25 -25
  88. DLMS_SPODES/types/implementations/bitstrings.py +97 -97
  89. DLMS_SPODES/types/implementations/double_long_usingneds.py +35 -35
  90. DLMS_SPODES/types/implementations/enums.py +57 -57
  91. DLMS_SPODES/types/implementations/integers.py +12 -11
  92. DLMS_SPODES/types/implementations/long_unsigneds.py +127 -127
  93. DLMS_SPODES/types/implementations/octet_string.py +11 -11
  94. DLMS_SPODES/types/implementations/structs.py +64 -64
  95. DLMS_SPODES/types/type_alias.py +74 -0
  96. DLMS_SPODES/types/useful_types.py +627 -677
  97. {dlms_spodes-0.87.17.dist-info → dlms_spodes-0.88.1.dist-info}/METADATA +30 -30
  98. dlms_spodes-0.88.1.dist-info/RECORD +118 -0
  99. {dlms_spodes-0.87.17.dist-info → dlms_spodes-0.88.1.dist-info}/WHEEL +1 -1
  100. DLMS_SPODES/cosem_interface_classes/a_parameter.py +0 -20
  101. DLMS_SPODES/cosem_interface_classes/attr_indexes.py +0 -12
  102. dlms_spodes-0.87.17.dist-info/RECORD +0 -117
  103. {dlms_spodes-0.87.17.dist-info → dlms_spodes-0.88.1.dist-info}/top_level.txt +0 -0
@@ -1,487 +1,491 @@
1
- import re
2
- import logging
3
- from ...types import cdt, cst
4
- from ..data import Data, ic, choices
5
- from ... import enums as enu
6
- from ...types import implementations as impl
7
- from ...config_parser import get_message
8
-
9
-
10
- class DataStatic(Data):
11
- A_ELEMENTS = Data.getAElement(2).unwrap().get_change(classifier=ic.Classifier.STATIC),
12
-
13
-
14
- class DataDynamic(Data):
15
- A_ELEMENTS = Data.getAElement(2).unwrap().get_change(classifier=ic.Classifier.DYNAMIC),
16
-
17
-
18
- class DataNotSpecific(Data):
19
- A_ELEMENTS = Data.getAElement(2).unwrap().get_change(classifier=ic.Classifier.NOT_SPECIFIC),
20
-
21
-
22
- class LDN(DataStatic):
23
- """for ldn"""
24
- A_ELEMENTS = Data.getAElement(2).unwrap().get_change(data_type=impl.octet_string.LDN),
25
-
26
- @property
27
- def get_manufacturer(self) -> bytes:
28
- return self.value.contents[:3]
29
-
30
-
31
- class ActiveFirmwareId(Data):
32
- """for keep version in collection"""
33
- def characteristics_init(self):
34
- """"""
35
-
36
-
37
- class Unsigned(DataDynamic):
38
- """ with value type: Unsigned """
39
- A_ELEMENTS = DataDynamic.get_attr_element(2).get_change(data_type=cdt.Unsigned),
40
-
41
-
42
- class OctetStringDateTime(DataDynamic):
43
- """ with value type: Unsigned """
44
- A_ELEMENTS = DataDynamic.get_attr_element(2).get_change(data_type=cst.OctetStringDateTime),
45
-
46
-
47
- class OpeningBodyUnsigned(cdt.ReportMixin, cdt.Unsigned): # todo: make as cdt.FlagEnum
48
- def get_report(self) -> cdt.Report:
49
- """ СПОДЭСv.3 Е.12.5"""
50
- match int(self) & 0b1:
51
- case 0: return cdt.Report(
52
- msg=get_message("$normal$"),
53
- log=cdt.INFO_LOG)
54
- case 1: return cdt.Report(
55
- msg=get_message("$case_is_opened$"),
56
- log=cdt.Log(logging.WARN))
57
-
58
-
59
- class OpeningBody(DataDynamic):
60
- """ RU. 0.0.96.51.0.255. СТО_34.01-5.1-006-2019v3. E 12.1 """
61
- A_ELEMENTS = DataDynamic.get_attr_element(2).get_change(data_type=OpeningBodyUnsigned),
62
-
63
-
64
- class OpeningCoverUnsigned(cdt.ReportMixin, cdt.Unsigned): # todo: make as cdt.FlagEnum
65
- def get_report(self) -> cdt.Report:
66
- """ СПОДЭСv.3 Е.12.5"""
67
- match int(self) & 0b1:
68
- case 0: return cdt.Report(
69
- msg=get_message("$normal$"),
70
- log=cdt.INFO_LOG)
71
- case 1: return cdt.Report(
72
- msg=get_message("$cover_is_opened$"),
73
- log=cdt.Log(logging.WARN))
74
-
75
-
76
- class OpeningCover(DataDynamic):
77
- """ RU. 0.0.96.51.1.255. СТО_34.01-5.1-006-2019v3. E 12.2 """
78
- A_ELEMENTS = DataDynamic.get_attr_element(2).get_change(data_type=OpeningCoverUnsigned),
79
-
80
-
81
- class ExposureToFieldUnsigned(cdt.ReportMixin, cdt.Unsigned): # todo: make as cdt.FlagEnum
82
- def get_report(self) -> cdt.Report:
83
- if (value := (int(self) & 0b101)) == 0:
84
- return cdt.Report(get_message("$normal$"), log=cdt.INFO_LOG)
85
- else:
86
- ret = ""
87
- if value & 0b001:
88
- ret += get_message("$fixed_field$")
89
- if value & 0b100:
90
- ret += get_message("$exist_field$")
91
- return cdt.Report(ret, log=cdt.Log(logging.WARN))
92
-
93
-
94
- class ExposureToMagnet(DataDynamic):
95
- """ RU. 0.0.96.51.3.255. СТО_34.01-5.1-006-2019v3. E 12.3 """
96
- A_ELEMENTS = DataDynamic.get_attr_element(2).get_change(data_type=ExposureToFieldUnsigned),
97
-
98
-
99
- class ExposureToHSField(DataDynamic):
100
- """ RU. 0.0.96.51.4.255. СТО_34.01-5.1-006-2019v3. E 12.3 """
101
- A_ELEMENTS = DataDynamic.get_attr_element(2).get_change(data_type=ExposureToFieldUnsigned),
102
-
103
-
104
- class SealUnsigned(cdt.ReportMixin, cdt.Unsigned): # todo: make as cdt.FlagEnum??
105
- def get_report(self) -> cdt.Report:
106
- def get_name(value: int):
107
- """ СПОДЭСv.3 Е.12.5"""
108
- match value & 0b11:
109
- case 0: return "$undefined$"
110
- case 1: return "$contentions$"
111
- case 2: return "$breaked_open$"
112
- case 3: return "$subsequent_autopsy$"
113
- return cdt.Report(
114
- msg=get_message(F"$for_cover$ - {get_name(int(self) & 0b11)}, $for_terminals_cover$ - {get_name((int(self) >> 2) & 0b11)}"),
115
- log=cdt.Log(logging.INFO if int(self) == 0b101 else logging.WARN))
116
-
117
-
118
- class SealStatus(DataDynamic):
119
- """ RU. 0.0.96.51.5.255. СТО_34.01-5.1-006-2019v3. E 12.5 """
120
- A_ELEMENTS = DataDynamic.A_ELEMENTS[0].get_change(data_type=SealUnsigned),
121
-
122
-
123
- class TerminalsCoverOpeningState(DataDynamic):
124
- """ RU. 0.0.96.51.1.255. СТО_34.01-5.1-006-2019v3. E 12.2 """
125
- A_ELEMENTS = DataDynamic.get_attr_element(2).get_change(data_type=cdt.Unsigned),
126
-
127
-
128
- class BitMapData(cdt.Structure):
129
- start_time: cst.OctetStringDateTime
130
- stop_time: cst.OctetStringDateTime
131
- bitmap_data: cdt.OctetString
132
-
133
-
134
- class ITEBitMap(DataStatic):
135
- """ITE 0.128.96.13.1.255. Use for send struct lcd screen bitmap(BMP) with start/stop period to server"""
136
- A_ELEMENTS = Data.get_attr_element(2).get_change(data_type=BitMapData),
137
-
138
-
139
- class ChannelNumberValue(cdt.ReportMixin, cdt.Unsigned):
140
- @property
141
- def channel(self) -> enu.ChannelNumber:
142
- return enu.ChannelNumber(int(self) & 0b0000_0111)
143
-
144
- @channel.setter
145
- def channel(self, value: enu.ChannelNumber):
146
- self.set((int(self) & 0b1111_1000) | value)
147
-
148
- @property
149
- def interface(self) -> enu.Interface:
150
- return enu.Interface((int(self) & 0b1111_1000) >> 3)
151
-
152
- @interface.setter
153
- def interface(self, value: enu.Interface):
154
- self.set((int(self) & 0b0001_1111) | (value << 3))
155
-
156
- def get_report(self) -> cdt.Report:
157
- return cdt.Report(F"({int(self)}) Номер канала связи: {self.channel.name}, Тип интерфейса: {self.interface.name}")
158
-
159
-
160
- class CommunicationPortParameter(Data):
161
- """ RU. 0.0.96.12.4.255. СТО_34.01-5.1-006-2019v3. 13.10. Определение номера порта по которому установлено соединение"""
162
- A_ELEMENTS = ic.ICAElement("value", ChannelNumberValue, default=enu.ChannelNumber.OPTO_P1 + (enu.Interface.OPTO << 3), classifier=ic.Classifier.DYNAMIC),
163
-
164
- @property
165
- def value(self) -> ChannelNumberValue:
166
- """override returned type"""
167
- return self.get_attr(2)
168
-
169
-
170
- class AnyDateTime(DataDynamic):
171
- """for a-anotation DLMS UA 1000-1 Ed. 14 Table 60"""
172
- A_ELEMENTS = DataDynamic.get_attr_element(2).get_change(data_type=choices.any_date_time),
173
-
174
-
175
- class SPODES3VoltageEventValues(cdt.IntegerEnum, cdt.LongUnsigned):
176
- pass
177
-
178
-
179
- class SPODES3VoltageEvent(DataDynamic):
180
- """СТО_34.01-5.1-006-2019v3 Д.2 События, связанные с напряжением"""
181
- A_ELEMENTS = DataDynamic.get_attr_element(2).get_change(data_type=SPODES3VoltageEventValues),
182
-
183
-
184
- class SPODES3CurrentEventValues(cdt.IntegerEnum, cdt.LongUnsigned):
185
- pass
186
-
187
- class SPODES3CurrentEvent(DataDynamic):
188
- """СТО_34.01-5.1-006-2019v3 Д.3 События, связанные с током"""
189
- A_ELEMENTS = DataDynamic.get_attr_element(2).get_change(data_type=SPODES3CurrentEventValues),
190
-
191
-
192
- class SPODES3CommutationEventValues(cdt.IntegerEnum, cdt.LongUnsigned):
193
- pass
194
-
195
- class SPODES3CommutationEvent(DataDynamic):
196
- """СТО_34.01-5.1-006-2019v3 Д.4 События, связанные с вкл./выкл. ПУ, коммутации реле нагрузки"""
197
- A_ELEMENTS = DataDynamic.get_attr_element(2).get_change(data_type=SPODES3CommutationEventValues),
198
-
199
-
200
- class SPODES3ProgrammingEventValues(cdt.IntegerEnum, cdt.LongUnsigned):
201
- pass
202
-
203
-
204
- class SPODES3ProgrammingEvent(DataDynamic):
205
- """СТО_34.01-5.1-006-2019v3 Д.5 События программирования параметров ПУ"""
206
- A_ELEMENTS = DataDynamic.get_attr_element(2).get_change(data_type=SPODES3ProgrammingEventValues),
207
-
208
-
209
- class SPODES3ExternalEventValues(cdt.IntegerEnum, cdt.LongUnsigned):
210
- pass
211
-
212
-
213
- class SPODES3ExternalEvent(DataDynamic):
214
- """СТО_34.01-5.1-006-2019v3 Д.6 События внешних воздействий"""
215
- A_ELEMENTS = DataDynamic.get_attr_element(2).get_change(data_type=SPODES3ExternalEventValues),
216
-
217
-
218
- class SPODES3CommunicationEventValues(cdt.IntegerEnum, cdt.LongUnsigned):
219
- pass
220
-
221
- class SPODES3CommunicationEvent(DataDynamic):
222
- """СТО_34.01-5.1-006-2019v3 Д.7 Коммуникационные события"""
223
- A_ELEMENTS = DataDynamic.get_attr_element(2).get_change(data_type=SPODES3CommunicationEventValues),
224
-
225
-
226
- class SPODES3AccessEventValues(cdt.IntegerEnum, cdt.LongUnsigned):
227
- pass
228
-
229
- class SPODES3AccessEvent(DataDynamic):
230
- """СТО_34.01-5.1-006-2019v3 Д.8 События контроля доступа"""
231
- A_ELEMENTS = DataDynamic.get_attr_element(2).get_change(data_type=SPODES3AccessEventValues),
232
-
233
-
234
- class SPODES3SelfDiagnosticEventValues(cdt.IntegerEnum, cdt.LongUnsigned):
235
- pass
236
-
237
- class SPODES3SelfDiagnosticEvent(DataDynamic):
238
- """СТО_34.01-5.1-006-2019v3 Д.9 Коды событий для журнала самодиагностики"""
239
- A_ELEMENTS = DataDynamic.get_attr_element(2).get_change(data_type=SPODES3SelfDiagnosticEventValues),
240
-
241
-
242
- class SPODES3ReactivePowerEventValues(cdt.IntegerEnum, cdt.LongUnsigned):
243
- pass
244
-
245
- class SPODES3ReactivePowerEvent(DataDynamic):
246
- """СТО_34.01-5.1-006-2019v3 Д.10 События по превышению реактивной мощности"""
247
- A_ELEMENTS = DataDynamic.get_attr_element(2).get_change(data_type=SPODES3ReactivePowerEventValues),
248
-
249
-
250
- class SPODES3PowerQuality2EventValues(cdt.IntegerFlag, cdt.LongUnsigned):
251
- pass
252
-
253
-
254
- class SPODES3PowerQuality2Event(DataNotSpecific):
255
- """СТО_34.01-5.1-006-2019v3 E.1 Статус качества сети (журнал качества сети)"""
256
- A_ELEMENTS = DataNotSpecific.get_attr_element(2).get_change(data_type=SPODES3PowerQuality2EventValues),
257
-
258
-
259
- class LoadLockerValue(cdt.IntegerEnum, cdt.Unsigned):
260
- def __init_subclass__(cls, **kwargs):
261
- """not need"""
262
-
263
- def get_report(self) -> cdt.Report:
264
- match val := int(self):
265
- case 0:
266
- return cdt.Report(
267
- msg=get_message(F"({val}) $lock$ $turn_off$"),
268
- log=cdt.INFO_LOG)
269
- case 1:
270
- return cdt.Report(
271
- msg=get_message(F"({val}) $lock$ $turn_on$"),
272
- log=cdt.Log(logging.WARN))
273
- case _:
274
- return cdt.Report(
275
- msg=get_message(F"({val})"),
276
- log=cdt.Log(logging.ERROR, "unknown state"))
277
-
278
-
279
- class SPODES3LoadLocker(DataStatic):
280
- """СТО 34.01-5.1-006-2023 E7. Блокиратор реле нагрузки"""
281
- A_ELEMENTS = DataNotSpecific.get_attr_element(2).get_change(data_type=LoadLockerValue),
282
-
283
-
284
- class SPODES3PowerQuality1EventValues(cdt.IntegerFlag, cdt.LongUnsigned):
285
- pass
286
-
287
-
288
- class SPODES3Alarm1Values(cdt.IntegerFlag, cdt.DoubleLongUnsigned):
289
- ...
290
-
291
-
292
- class SPODES3Alarm1(DataStatic):
293
- """СТО_34.01-5.1-006-2019v3 9.8 Поддержка инициативного выхода"""
294
- A_ELEMENTS = DataStatic.get_attr_element(2).get_change(data_type=SPODES3Alarm1Values),
295
-
296
-
297
- class KPZAlarm1Values(SPODES3Alarm1Values):
298
- ...
299
-
300
-
301
- class KPZAlarm1(DataStatic):
302
- A_ELEMENTS = DataStatic.get_attr_element(2).get_change(data_type=KPZAlarm1Values),
303
-
304
-
305
- class SPODES3ControlAlarm1Values(cdt.IntegerFlag, cdt.DoubleLongUnsigned):
306
- ...
307
-
308
-
309
- class SPODES3ControlAlarm1(DataDynamic):
310
- """СТО 34.01-5.1-006-2023v4 Таблица 13.5 Распределение событий отключения реле нагрузки по битам"""
311
- A_ELEMENTS = DataNotSpecific.get_attr_element(2).get_change(data_type=SPODES3ControlAlarm1Values),
312
-
313
-
314
- class SPODES3PowerQuality1Event(DataNotSpecific):
315
- """СТО_34.01-5.1-006-2019v3 E.1 Статус качества сети (журнал качества сети)"""
316
- A_ELEMENTS = DataNotSpecific.get_attr_element(2).get_change(data_type=SPODES3PowerQuality1EventValues),
317
-
318
-
319
- # KPZ implements
320
- class KPZExternalEventValues(cdt.IntegerEnum, cdt.LongUnsigned):
321
- NAMES = SPODES3ExternalEventValues.NAMES
322
-
323
-
324
- class KPZSPODES3ExternalEvent(DataStatic):
325
- """СТО_34.01-5.1-006-2019v3 Д.6 События внешних воздействий"""
326
- A_ELEMENTS = DataStatic.get_attr_element(2).get_change(data_type=KPZExternalEventValues),
327
-
328
-
329
- class KPZ1VoltageEventValues(cdt.IntegerEnum, cdt.DoubleLongUnsigned):
330
- NAMES = SPODES3VoltageEventValues.NAMES
331
-
332
-
333
- class KPZ1SPODES3VoltageEvent(DataStatic):
334
- """СТО_34.01-5.1-006-2019v3 Д.2 События, связанные с напряжением with bag in value type"""
335
- A_ELEMENTS = DataStatic.get_attr_element(2).get_change(data_type=KPZ1VoltageEventValues),
336
-
337
-
338
- class KPZ1CurrentEventValues(cdt.IntegerEnum, cdt.DoubleLongUnsigned):
339
- NAMES = SPODES3CurrentEventValues.NAMES
340
-
341
-
342
- class KPZ1SPODES3CurrentEvent(DataStatic):
343
- """СТО_34.01-5.1-006-2019v3 Д.3 События, связанные с током"""
344
- A_ELEMENTS = DataStatic.get_attr_element(2).get_change(data_type=KPZ1CurrentEventValues),
345
-
346
-
347
- class KPZ1CommutationEventValues(cdt.IntegerEnum, cdt.DoubleLongUnsigned):
348
- NAMES = SPODES3CommutationEventValues.NAMES
349
-
350
-
351
- class KPZ1SPODES3CommutationEvent(DataStatic):
352
- """СТО_34.01-5.1-006-2019v3 Д.4 События, связанные с вкл./выкл. ПУ, коммутации реле нагрузки"""
353
- A_ELEMENTS = DataStatic.get_attr_element(2).get_change(data_type=KPZ1CommutationEventValues),
354
-
355
-
356
- class KPZ1ProgrammingEventValues(cdt.IntegerEnum, cdt.DoubleLongUnsigned):
357
- NAMES = SPODES3ProgrammingEventValues.NAMES
358
-
359
-
360
- class KPZ1SPODES3ProgrammingEvent(DataStatic):
361
- """СТО_34.01-5.1-006-2019v3 Д.5 События программирования параметров ПУ"""
362
- A_ELEMENTS = DataStatic.get_attr_element(2).get_change(data_type=KPZ1ProgrammingEventValues),
363
-
364
-
365
- class KPZ1ExternalEventValues(cdt.IntegerEnum, cdt.DoubleLongUnsigned):
366
- NAMES = SPODES3ExternalEventValues.NAMES
367
-
368
-
369
- class KPZ1SPODES3ExternalEvent(DataStatic):
370
- """СТО_34.01-5.1-006-2019v3 Д.6 События внешних воздействий"""
371
- A_ELEMENTS = DataStatic.get_attr_element(2).get_change(data_type=KPZ1ExternalEventValues),
372
-
373
-
374
- class KPZ1CommunicationEventValues(cdt.IntegerEnum, cdt.DoubleLongUnsigned):
375
- NAMES = SPODES3CommunicationEventValues.NAMES
376
-
377
-
378
- class KPZ1SPODES3CommunicationEvent(DataStatic):
379
- """СТО_34.01-5.1-006-2019v3 Д.7 Коммуникационные события"""
380
- A_ELEMENTS = DataStatic.get_attr_element(2).get_change(data_type=KPZ1CommunicationEventValues),
381
-
382
-
383
- class KPZ1AccessEventValues(cdt.IntegerEnum, cdt.DoubleLongUnsigned):
384
- NAMES = SPODES3AccessEventValues.NAMES
385
-
386
-
387
- class KPZ1SPODES3AccessEvent(DataStatic):
388
- """СТО_34.01-5.1-006-2019v3 Д.8 События контроля доступа"""
389
- A_ELEMENTS = DataStatic.get_attr_element(2).get_change(data_type=KPZ1AccessEventValues),
390
-
391
-
392
- class KPZ1SelfDiagnosticEventValues(cdt.IntegerEnum, cdt.DoubleLongUnsigned):
393
- NAMES = SPODES3SelfDiagnosticEventValues.NAMES
394
-
395
-
396
- class KPZ1SPODES3SelfDiagnosticEvent(DataStatic):
397
- """СТО_34.01-5.1-006-2019v3 Д.9 Коды событий для журнала самодиагностики"""
398
- A_ELEMENTS = DataStatic.get_attr_element(2).get_change(data_type=KPZ1SelfDiagnosticEventValues),
399
-
400
-
401
- class KPZ1ReactivePowerEventValues(cdt.IntegerEnum, cdt.DoubleLongUnsigned):
402
- NAMES = SPODES3ReactivePowerEventValues.NAMES
403
-
404
-
405
- class KPZ1SPODES3ReactivePowerEvent(DataStatic):
406
- """СТО_34.01-5.1-006-2019v3 Д.10 События по превышению реактивной мощности"""
407
- A_ELEMENTS = DataStatic.get_attr_element(2).get_change(data_type=KPZ1ReactivePowerEventValues),
408
-
409
-
410
- class SPODES3MeasurementPeriodValue(cdt.Unsigned):
411
- def validate(self):
412
- super(SPODES3MeasurementPeriodValue, self).validate()
413
- values: tuple[int, ...] = (1, 2, 3, 5, 10, 15, 20, 30, 60)
414
- if int(self) not in values:
415
- raise ValueError(F"for {self} got value: {int(self)}, expected: {values}")
416
-
417
-
418
- class SPODES3MeasurementPeriod(DataStatic):
419
- """СТО_34.01-5.1-006-2019v3 Г.2 Программируемые параметры и функции. Пункт 14"""
420
- A_ELEMENTS = DataStatic.get_attr_element(2).get_change(data_type=SPODES3MeasurementPeriodValue),
421
-
422
-
423
- class DLMSDeviceIDObject(DataStatic):
424
- """DLMS UA 1000-1 Ed. 14. 6.2.42 Device ID objects"""
425
- A_ELEMENTS = DataStatic.get_attr_element(2).get_change(data_type=choices.device_id_object),
426
-
427
-
428
- class SPODES3SPODESVersionValue(cdt.ReportMixin, cdt.OctetString):
429
- __pattern = re.compile(b"\\d{1,2}\\.\\d{1,2}")
430
-
431
- def get_report(self) -> cdt.Report:
432
- """custom string represent"""
433
- try:
434
- self.validate()
435
- msg = self.contents.decode("ascii", errors="ignore")
436
- log = cdt.INFO_LOG
437
- except ValueError as e:
438
- msg = str(self)
439
- log = cdt.Log(logging.ERROR, msg=e)
440
- return cdt.Report(
441
- msg=msg,
442
- log=log
443
- )
444
-
445
- def validate(self):
446
- if self.__pattern.fullmatch(self.contents) is None:
447
- raise ValueError(F"не соответствует СТО 34.01-5.1. Приложение Г")
448
-
449
-
450
- class SPODES3SPODESVersion(DLMSDeviceIDObject):
451
- """СТО_34.01-5.1-006-2019v3 Г.1 Примечание 2"""
452
- A_ELEMENTS = DLMSDeviceIDObject.get_attr_element(2).get_change(data_type=SPODES3SPODESVersionValue),
453
-
454
-
455
- class SPODES3IDNotSpecific(DLMSDeviceIDObject):
456
- """СТО_34.01-5.1-006-2019v3 13.1. Чтение расширенных паспортных данных ПУ. Для специфических идентификаторов"""
457
- A_ELEMENTS = DLMSDeviceIDObject.get_attr_element(2).get_change(classifier=ic.Classifier.NOT_SPECIFIC),
458
-
459
-
460
- class KPZGSMPingIPValue(cdt.Structure):
461
- """Содержит настройки для проведения Ping теста"""
462
- enable: cdt.Unsigned
463
- multicast_IP_address: impl.arrays.MulticastIPAddress
464
-
465
-
466
- class KPZGSMPingIP(DataStatic):
467
- """Проприетарный объект"""
468
- A_ELEMENTS = DataStatic.get_attr_element(2).get_change(data_type=KPZGSMPingIPValue),
469
-
470
-
471
- class AFERegister(cdt.Structure):
472
- name: cdt.VisibleString
473
- value: choices.common_dt
474
-
475
-
476
- class AFERegisters(cdt.Array):
477
- TYPE = AFERegister
478
- values: list[AFERegister]
479
-
480
-
481
- class AFEOffsets(cdt.Structure):
482
- identifier: cdt.VisibleString
483
- register_list: AFERegisters
484
-
485
-
486
- class KPZAFEOffsets(DataDynamic):
487
- A_ELEMENTS = DataStatic.get_attr_element(2).get_change(data_type=AFEOffsets),
1
+ import re
2
+ from typing import Optional
3
+ import logging
4
+ from ...types import cdt, cst
5
+ from ..cosem_interface_class import Classifier, ICAElement
6
+ from ..data import Data, choices
7
+ from ... import enums as enu
8
+ from ...types import implementations as impl
9
+ from ...config_parser import get_message
10
+
11
+
12
+ class DataStatic(Data):
13
+ A_ELEMENTS = Data.getAElement(2).unwrap().get_change(classifier=Classifier.STATIC),
14
+
15
+
16
+ class DataDynamic(Data):
17
+ A_ELEMENTS = Data.getAElement(2).unwrap().get_change(classifier=Classifier.DYNAMIC),
18
+
19
+
20
+ class DataNotSpecific(Data):
21
+ A_ELEMENTS = Data.getAElement(2).unwrap().get_change(classifier=Classifier.NOT_SPECIFIC),
22
+
23
+
24
+ class LDN(DataStatic):
25
+ """for ldn"""
26
+ A_ELEMENTS = Data.getAElement(2).unwrap().get_change(data_type=impl.octet_string.LDN),
27
+
28
+ @property
29
+ def get_manufacturer(self) -> bytes:
30
+ return self.value.contents[:3]
31
+
32
+
33
+ class ActiveFirmwareId(Data):
34
+ """for keep version in collection"""
35
+ def characteristics_init(self):
36
+ """"""
37
+
38
+
39
+ class Unsigned(DataDynamic):
40
+ """ with value type: Unsigned """
41
+ A_ELEMENTS = DataDynamic.getAElement(2).unwrap().get_change(data_type=cdt.Unsigned),
42
+
43
+
44
+ class OctetStringDateTime(DataDynamic):
45
+ """ with value type: Unsigned """
46
+ A_ELEMENTS = DataDynamic.getAElement(2).unwrap().get_change(data_type=cst.OctetStringDateTime),
47
+
48
+
49
+ class OpeningBodyUnsigned(cdt.Unsigned, cdt.ReportMixin): # todo: make as cdt.FlagEnum
50
+ def get_report(self) -> cdt.Report:
51
+ """ СПОДЭСv.3 Е.12.5"""
52
+ match int(self) & 0b1:
53
+ case 0: return cdt.Report(
54
+ msg=get_message("$normal$"),
55
+ log=cdt.INFO_LOG)
56
+ case 1: return cdt.Report(
57
+ msg=get_message("$case_is_opened$"),
58
+ log=cdt.Log(logging.WARN))
59
+
60
+
61
+ class OpeningBody(DataDynamic):
62
+ """ RU. 0.0.96.51.0.255. СТО_34.01-5.1-006-2019v3. E 12.1 """
63
+ A_ELEMENTS = DataDynamic.getAElement(2).unwrap().get_change(data_type=OpeningBodyUnsigned),
64
+
65
+
66
+ class OpeningCoverUnsigned(cdt.Unsigned, cdt.ReportMixin): # todo: make as cdt.FlagEnum
67
+ def get_report(self) -> cdt.Report:
68
+ """ СПОДЭСv.3 Е.12.5"""
69
+ match int(self) & 0b1:
70
+ case 0: return cdt.Report(
71
+ msg=get_message("$normal$"),
72
+ log=cdt.INFO_LOG)
73
+ case 1: return cdt.Report(
74
+ msg=get_message("$cover_is_opened$"),
75
+ log=cdt.Log(logging.WARN))
76
+
77
+
78
+ class OpeningCover(DataDynamic):
79
+ """ RU. 0.0.96.51.1.255. СТО_34.01-5.1-006-2019v3. E 12.2 """
80
+ A_ELEMENTS = DataDynamic.getAElement(2).unwrap().get_change(data_type=OpeningCoverUnsigned),
81
+
82
+
83
+ class ExposureToFieldUnsigned(cdt.Unsigned, cdt.ReportMixin): # todo: make as cdt.FlagEnum
84
+ def get_report(self) -> cdt.Report:
85
+ if (value := (int(self) & 0b101)) == 0:
86
+ return cdt.Report(get_message("$normal$"), log=cdt.INFO_LOG)
87
+ else:
88
+ ret = ""
89
+ if value & 0b001:
90
+ ret += get_message("$fixed_field$")
91
+ if value & 0b100:
92
+ ret += get_message("$exist_field$")
93
+ return cdt.Report(ret, log=cdt.Log(logging.WARN))
94
+
95
+
96
+ class ExposureToMagnet(DataDynamic):
97
+ """ RU. 0.0.96.51.3.255. СТО_34.01-5.1-006-2019v3. E 12.3 """
98
+ A_ELEMENTS = DataDynamic.getAElement(2).unwrap().get_change(data_type=ExposureToFieldUnsigned),
99
+
100
+
101
+ class ExposureToHSField(DataDynamic):
102
+ """ RU. 0.0.96.51.4.255. СТО_34.01-5.1-006-2019v3. E 12.3 """
103
+ A_ELEMENTS = DataDynamic.getAElement(2).unwrap().get_change(data_type=ExposureToFieldUnsigned),
104
+
105
+
106
+ class SealUnsigned(cdt.Unsigned, cdt.ReportMixin): # todo: make as cdt.FlagEnum??
107
+ def get_report(self) -> cdt.Report:
108
+ def get_name(value: int):
109
+ """ СПОДЭСv.3 Е.12.5"""
110
+ match value & 0b11:
111
+ case 0: return "$undefined$"
112
+ case 1: return "$contentions$"
113
+ case 2: return "$breaked_open$"
114
+ case 3: return "$subsequent_autopsy$"
115
+ return cdt.Report(
116
+ msg=get_message(F"$for_cover$ - {get_name(int(self) & 0b11)}, $for_terminals_cover$ - {get_name((int(self) >> 2) & 0b11)}"),
117
+ log=cdt.Log(logging.INFO if int(self) == 0b101 else logging.WARN))
118
+
119
+
120
+ class SealStatus(DataDynamic):
121
+ """ RU. 0.0.96.51.5.255. СТО_34.01-5.1-006-2019v3. E 12.5 """
122
+ A_ELEMENTS = DataDynamic.A_ELEMENTS[0].get_change(data_type=SealUnsigned),
123
+
124
+
125
+ class TerminalsCoverOpeningState(DataDynamic):
126
+ """ RU. 0.0.96.51.1.255. СТО_34.01-5.1-006-2019v3. E 12.2 """
127
+ A_ELEMENTS = DataDynamic.getAElement(2).unwrap().get_change(data_type=cdt.Unsigned),
128
+
129
+
130
+ class BitMapData(cdt.Structure):
131
+ start_time: cst.OctetStringDateTime
132
+ stop_time: cst.OctetStringDateTime
133
+ bitmap_data: cdt.OctetString
134
+
135
+
136
+ class ITEBitMap(DataStatic):
137
+ """ITE 0.128.96.13.1.255. Use for send struct lcd screen bitmap(BMP) with start/stop period to server"""
138
+ A_ELEMENTS = Data.getAElement(2).unwrap().get_change(data_type=BitMapData),
139
+
140
+
141
+ class ChannelNumberValue(cdt.Unsigned, cdt.ReportMixin):
142
+ @property
143
+ def channel(self) -> enu.ChannelNumber:
144
+ return enu.ChannelNumber(int(self) & 0b0000_0111)
145
+
146
+ @channel.setter
147
+ def channel(self, value: enu.ChannelNumber):
148
+ self.set((int(self) & 0b1111_1000) | value)
149
+
150
+ @property
151
+ def interface(self) -> enu.Interface:
152
+ return enu.Interface((int(self) & 0b1111_1000) >> 3)
153
+
154
+ @interface.setter
155
+ def interface(self, value: enu.Interface):
156
+ self.set((int(self) & 0b0001_1111) | (value << 3))
157
+
158
+ def get_report(self) -> cdt.Report:
159
+ return cdt.Report(F"({int(self)}) Номер канала связи: {self.channel.name}, Тип интерфейса: {self.interface.name}")
160
+
161
+
162
+ class CommunicationPortParameter(Data):
163
+ """ RU. 0.0.96.12.4.255. СТО_34.01-5.1-006-2019v3. 13.10. Определение номера порта по которому установлено соединение"""
164
+ A_ELEMENTS = ICAElement(2, "value", ChannelNumberValue, default=enu.ChannelNumber.OPTO_P1 + (enu.Interface.OPTO << 3), classifier=Classifier.DYNAMIC),
165
+ value: Optional[ChannelNumberValue]
166
+
167
+
168
+ class AnyDateTime(DataDynamic):
169
+ """for a-anotation DLMS UA 1000-1 Ed. 14 Table 60"""
170
+ A_ELEMENTS = DataDynamic.getAElement(2).unwrap().get_change(data_type=choices.any_date_time),
171
+
172
+
173
+ class SPODES3VoltageEventValues(cdt.IntegerEnum, cdt.LongUnsigned):
174
+ ...
175
+
176
+
177
+ class SPODES3VoltageEvent(DataDynamic):
178
+ """СТО_34.01-5.1-006-2019v3 Д.2 События, связанные с напряжением"""
179
+ A_ELEMENTS = DataDynamic.getAElement(2).unwrap().get_change(data_type=SPODES3VoltageEventValues),
180
+
181
+
182
+ class SPODES3CurrentEventValues(cdt.IntegerEnum, cdt.LongUnsigned):
183
+ ...
184
+
185
+
186
+ class SPODES3CurrentEvent(DataDynamic):
187
+ """СТО_34.01-5.1-006-2019v3 Д.3 События, связанные с током"""
188
+ A_ELEMENTS = DataDynamic.getAElement(2).unwrap().get_change(data_type=SPODES3CurrentEventValues),
189
+
190
+
191
+ class SPODES3CommutationEventValues(cdt.IntegerEnum, cdt.LongUnsigned):
192
+ pass
193
+
194
+
195
+ class SPODES3CommutationEvent(DataDynamic):
196
+ """СТО_34.01-5.1-006-2019v3 Д.4 События, связанные с вкл./выкл. ПУ, коммутации реле нагрузки"""
197
+ A_ELEMENTS = DataDynamic.getAElement(2).unwrap().get_change(data_type=SPODES3CommutationEventValues),
198
+
199
+
200
+ class SPODES3ProgrammingEventValues(cdt.IntegerEnum, cdt.LongUnsigned):
201
+ pass
202
+
203
+
204
+ class SPODES3ProgrammingEvent(DataDynamic):
205
+ """СТО_34.01-5.1-006-2019v3 Д.5 События программирования параметров ПУ"""
206
+ A_ELEMENTS = DataDynamic.getAElement(2).unwrap().get_change(data_type=SPODES3ProgrammingEventValues),
207
+
208
+
209
+ class SPODES3ExternalEventValues(cdt.IntegerEnum, cdt.LongUnsigned):
210
+ pass
211
+
212
+
213
+ class SPODES3ExternalEvent(DataDynamic):
214
+ """СТО_34.01-5.1-006-2019v3 Д.6 События внешних воздействий"""
215
+ A_ELEMENTS = DataDynamic.getAElement(2).unwrap().get_change(data_type=SPODES3ExternalEventValues),
216
+
217
+
218
+ class SPODES3CommunicationEventValues(cdt.IntegerEnum, cdt.LongUnsigned):
219
+ pass
220
+
221
+
222
+ class SPODES3CommunicationEvent(DataDynamic):
223
+ """СТО_34.01-5.1-006-2019v3 Д.7 Коммуникационные события"""
224
+ A_ELEMENTS = DataDynamic.getAElement(2).unwrap().get_change(data_type=SPODES3CommunicationEventValues),
225
+
226
+
227
+ class SPODES3AccessEventValues(cdt.IntegerEnum, cdt.LongUnsigned):
228
+ pass
229
+
230
+
231
+ class SPODES3AccessEvent(DataDynamic):
232
+ """СТО_34.01-5.1-006-2019v3 Д.8 События контроля доступа"""
233
+ A_ELEMENTS = DataDynamic.getAElement(2).unwrap().get_change(data_type=SPODES3AccessEventValues),
234
+
235
+
236
+ class SPODES3SelfDiagnosticEventValues(cdt.IntegerEnum, cdt.LongUnsigned):
237
+ pass
238
+
239
+
240
+ class SPODES3SelfDiagnosticEvent(DataDynamic):
241
+ """СТО_34.01-5.1-006-2019v3 Д.9 Коды событий для журнала самодиагностики"""
242
+ A_ELEMENTS = DataDynamic.getAElement(2).unwrap().get_change(data_type=SPODES3SelfDiagnosticEventValues),
243
+
244
+
245
+ class SPODES3ReactivePowerEventValues(cdt.IntegerEnum, cdt.LongUnsigned):
246
+ pass
247
+
248
+
249
+ class SPODES3ReactivePowerEvent(DataDynamic):
250
+ """СТО_34.01-5.1-006-2019v3 Д.10 События по превышению реактивной мощности"""
251
+ A_ELEMENTS = DataDynamic.getAElement(2).unwrap().get_change(data_type=SPODES3ReactivePowerEventValues),
252
+
253
+
254
+ class SPODES3PowerQuality2EventValues(cdt.IntegerFlag, cdt.LongUnsigned):
255
+ pass
256
+
257
+
258
+ class SPODES3PowerQuality2Event(DataNotSpecific):
259
+ """СТО_34.01-5.1-006-2019v3 E.1 Статус качества сети (журнал качества сети)"""
260
+ A_ELEMENTS = DataNotSpecific.getAElement(2).unwrap().get_change(data_type=SPODES3PowerQuality2EventValues),
261
+
262
+
263
+ class LoadLockerValue(cdt.IntegerEnum, cdt.Unsigned):
264
+ def __init_subclass__(cls, **kwargs):
265
+ """not need"""
266
+
267
+ def get_report(self) -> cdt.Report:
268
+ match val := int(self):
269
+ case 0:
270
+ return cdt.Report(
271
+ msg=get_message(F"({val}) $lock$ $turn_off$"),
272
+ log=cdt.INFO_LOG)
273
+ case 1:
274
+ return cdt.Report(
275
+ msg=get_message(F"({val}) $lock$ $turn_on$"),
276
+ log=cdt.Log(logging.WARN))
277
+ case _:
278
+ return cdt.Report(
279
+ msg=get_message(F"({val})"),
280
+ log=cdt.Log(logging.ERROR, "unknown state"))
281
+
282
+
283
+ class SPODES3LoadLocker(DataStatic):
284
+ """СТО 34.01-5.1-006-2023 E7. Блокиратор реле нагрузки"""
285
+ A_ELEMENTS = DataNotSpecific.getAElement(2).unwrap().get_change(data_type=LoadLockerValue),
286
+
287
+
288
+ class SPODES3PowerQuality1EventValues(cdt.IntegerFlag, cdt.LongUnsigned):
289
+ pass
290
+
291
+
292
+ class SPODES3Alarm1Values(cdt.IntegerFlag, cdt.DoubleLongUnsigned):
293
+ ...
294
+
295
+
296
+ class SPODES3Alarm1(DataStatic):
297
+ """СТО_34.01-5.1-006-2019v3 9.8 Поддержка инициативного выхода"""
298
+ A_ELEMENTS = DataStatic.getAElement(2).unwrap().get_change(data_type=SPODES3Alarm1Values),
299
+
300
+
301
+ class KPZAlarm1Values(SPODES3Alarm1Values):
302
+ ...
303
+
304
+
305
+ class KPZAlarm1(DataStatic):
306
+ A_ELEMENTS = DataStatic.getAElement(2).unwrap().get_change(data_type=KPZAlarm1Values),
307
+
308
+
309
+ class SPODES3ControlAlarm1Values(cdt.IntegerFlag, cdt.DoubleLongUnsigned):
310
+ ...
311
+
312
+
313
+ class SPODES3ControlAlarm1(DataDynamic):
314
+ """СТО 34.01-5.1-006-2023v4 Таблица 13.5 Распределение событий отключения реле нагрузки по битам"""
315
+ A_ELEMENTS = DataNotSpecific.getAElement(2).unwrap().get_change(data_type=SPODES3ControlAlarm1Values),
316
+
317
+
318
+ class SPODES3PowerQuality1Event(DataNotSpecific):
319
+ """СТО_34.01-5.1-006-2019v3 E.1 Статус качества сети (журнал качества сети)"""
320
+ A_ELEMENTS = DataNotSpecific.getAElement(2).unwrap().get_change(data_type=SPODES3PowerQuality1EventValues),
321
+
322
+
323
+ # KPZ implements
324
+ class KPZExternalEventValues(cdt.IntegerEnum, cdt.LongUnsigned):
325
+ NAMES = SPODES3ExternalEventValues.NAMES
326
+
327
+
328
+ class KPZSPODES3ExternalEvent(DataStatic):
329
+ """СТО_34.01-5.1-006-2019v3 Д.6 События внешних воздействий"""
330
+ A_ELEMENTS = DataStatic.getAElement(2).unwrap().get_change(data_type=KPZExternalEventValues),
331
+
332
+
333
+ class KPZ1VoltageEventValues(cdt.IntegerEnum, cdt.DoubleLongUnsigned):
334
+ NAMES = SPODES3VoltageEventValues.NAMES
335
+
336
+
337
+ class KPZ1SPODES3VoltageEvent(DataStatic):
338
+ """СТО_34.01-5.1-006-2019v3 Д.2 События, связанные с напряжением with bag in value type"""
339
+ A_ELEMENTS = DataStatic.getAElement(2).unwrap().get_change(data_type=KPZ1VoltageEventValues),
340
+
341
+
342
+ class KPZ1CurrentEventValues(cdt.IntegerEnum, cdt.DoubleLongUnsigned):
343
+ NAMES = SPODES3CurrentEventValues.NAMES
344
+
345
+
346
+ class KPZ1SPODES3CurrentEvent(DataStatic):
347
+ """СТО_34.01-5.1-006-2019v3 Д.3 События, связанные с током"""
348
+ A_ELEMENTS = DataStatic.getAElement(2).unwrap().get_change(data_type=KPZ1CurrentEventValues),
349
+
350
+
351
+ class KPZ1CommutationEventValues(cdt.IntegerEnum, cdt.DoubleLongUnsigned):
352
+ NAMES = SPODES3CommutationEventValues.NAMES
353
+
354
+
355
+ class KPZ1SPODES3CommutationEvent(DataStatic):
356
+ """СТО_34.01-5.1-006-2019v3 Д.4 События, связанные с вкл./выкл. ПУ, коммутации реле нагрузки"""
357
+ A_ELEMENTS = DataStatic.getAElement(2).unwrap().get_change(data_type=KPZ1CommutationEventValues),
358
+
359
+
360
+ class KPZ1ProgrammingEventValues(cdt.IntegerEnum, cdt.DoubleLongUnsigned):
361
+ NAMES = SPODES3ProgrammingEventValues.NAMES
362
+
363
+
364
+ class KPZ1SPODES3ProgrammingEvent(DataStatic):
365
+ """СТО_34.01-5.1-006-2019v3 Д.5 События программирования параметров ПУ"""
366
+ A_ELEMENTS = DataStatic.getAElement(2).unwrap().get_change(data_type=KPZ1ProgrammingEventValues),
367
+
368
+
369
+ class KPZ1ExternalEventValues(cdt.IntegerEnum, cdt.DoubleLongUnsigned):
370
+ NAMES = SPODES3ExternalEventValues.NAMES
371
+
372
+
373
+ class KPZ1SPODES3ExternalEvent(DataStatic):
374
+ """СТО_34.01-5.1-006-2019v3 Д.6 События внешних воздействий"""
375
+ A_ELEMENTS = DataStatic.getAElement(2).unwrap().get_change(data_type=KPZ1ExternalEventValues),
376
+
377
+
378
+ class KPZ1CommunicationEventValues(cdt.IntegerEnum, cdt.DoubleLongUnsigned):
379
+ NAMES = SPODES3CommunicationEventValues.NAMES
380
+
381
+
382
+ class KPZ1SPODES3CommunicationEvent(DataStatic):
383
+ """СТО_34.01-5.1-006-2019v3 Д.7 Коммуникационные события"""
384
+ A_ELEMENTS = DataStatic.getAElement(2).unwrap().get_change(data_type=KPZ1CommunicationEventValues),
385
+
386
+
387
+ class KPZ1AccessEventValues(cdt.IntegerEnum, cdt.DoubleLongUnsigned):
388
+ NAMES = SPODES3AccessEventValues.NAMES
389
+
390
+
391
+ class KPZ1SPODES3AccessEvent(DataStatic):
392
+ """СТО_34.01-5.1-006-2019v3 Д.8 События контроля доступа"""
393
+ A_ELEMENTS = DataStatic.getAElement(2).unwrap().get_change(data_type=KPZ1AccessEventValues),
394
+
395
+
396
+ class KPZ1SelfDiagnosticEventValues(cdt.IntegerEnum, cdt.DoubleLongUnsigned):
397
+ NAMES = SPODES3SelfDiagnosticEventValues.NAMES
398
+
399
+
400
+ class KPZ1SPODES3SelfDiagnosticEvent(DataStatic):
401
+ """СТО_34.01-5.1-006-2019v3 Д.9 Коды событий для журнала самодиагностики"""
402
+ A_ELEMENTS = DataStatic.getAElement(2).unwrap().get_change(data_type=KPZ1SelfDiagnosticEventValues),
403
+
404
+
405
+ class KPZ1ReactivePowerEventValues(cdt.IntegerEnum, cdt.DoubleLongUnsigned):
406
+ NAMES = SPODES3ReactivePowerEventValues.NAMES
407
+
408
+
409
+ class KPZ1SPODES3ReactivePowerEvent(DataStatic):
410
+ """СТО_34.01-5.1-006-2019v3 Д.10 События по превышению реактивной мощности"""
411
+ A_ELEMENTS = DataStatic.getAElement(2).unwrap().get_change(data_type=KPZ1ReactivePowerEventValues),
412
+
413
+
414
+ class SPODES3MeasurementPeriodValue(cdt.Unsigned):
415
+ def validate(self):
416
+ super(SPODES3MeasurementPeriodValue, self).validate()
417
+ values: tuple[int, ...] = (1, 2, 3, 5, 10, 15, 20, 30, 60)
418
+ if int(self) not in values:
419
+ raise ValueError(F"for {self} got value: {int(self)}, expected: {values}")
420
+
421
+
422
+ class SPODES3MeasurementPeriod(DataStatic):
423
+ """СТО_34.01-5.1-006-2019v3 Г.2 Программируемые параметры и функции. Пункт 14"""
424
+ A_ELEMENTS = DataStatic.getAElement(2).unwrap().get_change(data_type=SPODES3MeasurementPeriodValue),
425
+
426
+
427
+ class DLMSDeviceIDObject(DataStatic):
428
+ """DLMS UA 1000-1 Ed. 14. 6.2.42 Device ID objects"""
429
+ A_ELEMENTS = DataStatic.getAElement(2).unwrap().get_change(data_type=choices.device_id_object),
430
+
431
+
432
+ class SPODES3SPODESVersionValue(cdt.OctetString, cdt.ReportMixin):
433
+ __pattern = re.compile(b"\\d{1,2}\\.\\d{1,2}")
434
+
435
+ def get_report(self) -> cdt.Report:
436
+ """custom string represent"""
437
+ try:
438
+ self.validate()
439
+ msg = self.contents.decode("ascii", errors="ignore")
440
+ log = cdt.INFO_LOG
441
+ except ValueError as e:
442
+ msg = str(self)
443
+ log = cdt.Log(logging.ERROR, msg=e)
444
+ return cdt.Report(
445
+ msg=msg,
446
+ log=log
447
+ )
448
+
449
+ def validate(self):
450
+ if self.__pattern.fullmatch(self.contents) is None:
451
+ raise ValueError(F"не соответствует СТО 34.01-5.1. Приложение Г")
452
+
453
+
454
+ class SPODES3SPODESVersion(DLMSDeviceIDObject):
455
+ """СТО_34.01-5.1-006-2019v3 Г.1 Примечание 2"""
456
+ A_ELEMENTS = DLMSDeviceIDObject.getAElement(2).unwrap().get_change(data_type=SPODES3SPODESVersionValue),
457
+
458
+
459
+ class SPODES3IDNotSpecific(DLMSDeviceIDObject):
460
+ """СТО_34.01-5.1-006-2019v3 13.1. Чтение расширенных паспортных данных ПУ. Для специфических идентификаторов"""
461
+ A_ELEMENTS = DLMSDeviceIDObject.getAElement(2).unwrap().get_change(classifier=Classifier.NOT_SPECIFIC),
462
+
463
+
464
+ class KPZGSMPingIPValue(cdt.Structure):
465
+ """Содержит настройки для проведения Ping теста"""
466
+ enable: cdt.Unsigned
467
+ multicast_IP_address: impl.arrays.MulticastIPAddress
468
+
469
+
470
+ class KPZGSMPingIP(DataStatic):
471
+ """Проприетарный объект"""
472
+ A_ELEMENTS = DataStatic.getAElement(2).unwrap().get_change(data_type=KPZGSMPingIPValue),
473
+
474
+
475
+ class AFERegister(cdt.Structure):
476
+ name: cdt.VisibleString
477
+ value: choices.common_dt
478
+
479
+
480
+ class AFERegisters(cdt.Array):
481
+ TYPE = AFERegister
482
+ values: list[AFERegister]
483
+
484
+
485
+ class AFEOffsets(cdt.Structure):
486
+ identifier: cdt.VisibleString
487
+ register_list: AFERegisters
488
+
489
+
490
+ class KPZAFEOffsets(DataDynamic):
491
+ A_ELEMENTS = DataStatic.getAElement(2).unwrap().get_change(data_type=AFEOffsets),