DLMS-SPODES 0.87.13__py3-none-any.whl → 0.87.16__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/Values/EN/__init__.py +1 -1
- DLMS_SPODES/Values/EN/actors.py +8 -8
- DLMS_SPODES/Values/EN/relation_to_obis_names.py +387 -387
- DLMS_SPODES/Values/RU/__init__.py +1 -1
- DLMS_SPODES/Values/RU/actors.py +8 -8
- DLMS_SPODES/Values/RU/relation_to_obis_names.py +396 -396
- DLMS_SPODES/__init__.py +6 -6
- DLMS_SPODES/configEN.ini +126 -126
- DLMS_SPODES/config_parser.py +53 -53
- DLMS_SPODES/cosem_interface_classes/__class_init__.py +3 -3
- DLMS_SPODES/cosem_interface_classes/__init__.py +1 -1
- DLMS_SPODES/cosem_interface_classes/a_parameter.py +20 -20
- DLMS_SPODES/cosem_interface_classes/activity_calendar.py +254 -254
- DLMS_SPODES/cosem_interface_classes/arbitrator.py +105 -105
- DLMS_SPODES/cosem_interface_classes/association_ln/abstract.py +34 -34
- DLMS_SPODES/cosem_interface_classes/association_ln/authentication_mechanism_name.py +25 -25
- DLMS_SPODES/cosem_interface_classes/association_ln/mechanism_id.py +25 -25
- DLMS_SPODES/cosem_interface_classes/association_ln/method.py +5 -5
- DLMS_SPODES/cosem_interface_classes/association_ln/ver0.py +485 -485
- DLMS_SPODES/cosem_interface_classes/association_ln/ver1.py +133 -133
- DLMS_SPODES/cosem_interface_classes/association_ln/ver2.py +36 -36
- DLMS_SPODES/cosem_interface_classes/association_ln/ver3.py +4 -4
- DLMS_SPODES/cosem_interface_classes/association_sn/ver0.py +12 -12
- DLMS_SPODES/cosem_interface_classes/attr_indexes.py +12 -12
- DLMS_SPODES/cosem_interface_classes/clock.py +131 -131
- DLMS_SPODES/cosem_interface_classes/collection.py +2122 -2122
- DLMS_SPODES/cosem_interface_classes/cosem_interface_class.py +583 -583
- DLMS_SPODES/cosem_interface_classes/data.py +21 -21
- DLMS_SPODES/cosem_interface_classes/demand_register/ver0.py +59 -59
- DLMS_SPODES/cosem_interface_classes/disconnect_control.py +74 -74
- DLMS_SPODES/cosem_interface_classes/extended_register.py +27 -27
- DLMS_SPODES/cosem_interface_classes/gprs_modem_setup.py +43 -43
- DLMS_SPODES/cosem_interface_classes/gsm_diagnostic/ver0.py +103 -103
- DLMS_SPODES/cosem_interface_classes/gsm_diagnostic/ver1.py +40 -40
- DLMS_SPODES/cosem_interface_classes/gsm_diagnostic/ver2.py +9 -9
- DLMS_SPODES/cosem_interface_classes/iec_hdlc_setup/ver0.py +11 -11
- DLMS_SPODES/cosem_interface_classes/iec_hdlc_setup/ver1.py +53 -53
- DLMS_SPODES/cosem_interface_classes/iec_local_port_setup.py +11 -11
- DLMS_SPODES/cosem_interface_classes/image_transfer/image_transfer_status.py +15 -15
- DLMS_SPODES/cosem_interface_classes/image_transfer/ver0.py +126 -126
- DLMS_SPODES/cosem_interface_classes/implementations/__init__.py +3 -3
- DLMS_SPODES/cosem_interface_classes/implementations/arbitrator.py +19 -19
- DLMS_SPODES/cosem_interface_classes/implementations/data.py +487 -487
- DLMS_SPODES/cosem_interface_classes/implementations/profile_generic.py +83 -83
- DLMS_SPODES/cosem_interface_classes/ipv4_setup.py +72 -72
- DLMS_SPODES/cosem_interface_classes/limiter.py +111 -111
- DLMS_SPODES/cosem_interface_classes/ln_pattern.py +333 -333
- DLMS_SPODES/cosem_interface_classes/modem_configuration/ver0.py +65 -65
- DLMS_SPODES/cosem_interface_classes/modem_configuration/ver1.py +39 -39
- DLMS_SPODES/cosem_interface_classes/ntp_setup/ver0.py +67 -67
- DLMS_SPODES/cosem_interface_classes/obis.py +23 -23
- DLMS_SPODES/cosem_interface_classes/overview.py +197 -197
- DLMS_SPODES/cosem_interface_classes/parameter.py +547 -547
- DLMS_SPODES/cosem_interface_classes/parameters.py +172 -172
- DLMS_SPODES/cosem_interface_classes/profile_generic/ver0.py +122 -122
- DLMS_SPODES/cosem_interface_classes/profile_generic/ver1.py +277 -277
- DLMS_SPODES/cosem_interface_classes/push_setup/ver0.py +12 -12
- DLMS_SPODES/cosem_interface_classes/push_setup/ver1.py +10 -10
- DLMS_SPODES/cosem_interface_classes/push_setup/ver2.py +166 -166
- DLMS_SPODES/cosem_interface_classes/register.py +45 -45
- DLMS_SPODES/cosem_interface_classes/register_activation/ver0.py +80 -80
- DLMS_SPODES/cosem_interface_classes/register_monitor.py +46 -46
- DLMS_SPODES/cosem_interface_classes/reports.py +70 -70
- DLMS_SPODES/cosem_interface_classes/schedule.py +176 -176
- DLMS_SPODES/cosem_interface_classes/script_table.py +87 -87
- DLMS_SPODES/cosem_interface_classes/security_setup/ver0.py +68 -68
- DLMS_SPODES/cosem_interface_classes/security_setup/ver1.py +158 -158
- DLMS_SPODES/cosem_interface_classes/single_action_schedule.py +50 -50
- DLMS_SPODES/cosem_interface_classes/special_days_table.py +84 -84
- DLMS_SPODES/cosem_interface_classes/tcp_udp_setup.py +42 -42
- DLMS_SPODES/cosem_pdu.py +93 -93
- DLMS_SPODES/enums.py +625 -625
- DLMS_SPODES/exceptions.py +106 -106
- DLMS_SPODES/firmwares.py +99 -99
- DLMS_SPODES/hdlc/frame.py +875 -875
- DLMS_SPODES/hdlc/sub_layer.py +54 -54
- DLMS_SPODES/literals.py +17 -17
- DLMS_SPODES/obis/__init__.py +1 -1
- DLMS_SPODES/obis/media_id.py +931 -931
- DLMS_SPODES/pardata.py +22 -22
- DLMS_SPODES/pdu_enums.py +98 -98
- DLMS_SPODES/relation_to_OBIS.py +465 -463
- DLMS_SPODES/settings.py +551 -551
- DLMS_SPODES/types/choices.py +142 -142
- DLMS_SPODES/types/common_data_types.py +2401 -2401
- DLMS_SPODES/types/cosem_service_types.py +109 -109
- DLMS_SPODES/types/implementations/arrays.py +25 -25
- DLMS_SPODES/types/implementations/bitstrings.py +97 -97
- DLMS_SPODES/types/implementations/double_long_usingneds.py +35 -35
- DLMS_SPODES/types/implementations/enums.py +57 -57
- DLMS_SPODES/types/implementations/integers.py +11 -11
- DLMS_SPODES/types/implementations/long_unsigneds.py +127 -127
- DLMS_SPODES/types/implementations/octet_string.py +11 -11
- DLMS_SPODES/types/implementations/structs.py +64 -64
- DLMS_SPODES/types/useful_types.py +677 -677
- {dlms_spodes-0.87.13.dist-info → dlms_spodes-0.87.16.dist-info}/METADATA +30 -30
- dlms_spodes-0.87.16.dist-info/RECORD +117 -0
- {dlms_spodes-0.87.13.dist-info → dlms_spodes-0.87.16.dist-info}/WHEEL +1 -1
- dlms_spodes-0.87.13.dist-info/RECORD +0 -117
- {dlms_spodes-0.87.13.dist-info → dlms_spodes-0.87.16.dist-info}/top_level.txt +0 -0
|
@@ -1,487 +1,487 @@
|
|
|
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
|
+
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),
|