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.
- 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/Overview/__init__.py +0 -0
- DLMS_SPODES/cosem_interface_classes/Overview/class_id.py +107 -0
- DLMS_SPODES/cosem_interface_classes/__class_init__.py +3 -3
- DLMS_SPODES/cosem_interface_classes/__init__.py +3 -2
- DLMS_SPODES/cosem_interface_classes/activity_calendar.py +210 -254
- DLMS_SPODES/cosem_interface_classes/arbitrator.py +78 -105
- DLMS_SPODES/cosem_interface_classes/association_ln/abstract.py +50 -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 +440 -485
- DLMS_SPODES/cosem_interface_classes/association_ln/ver1.py +126 -133
- DLMS_SPODES/cosem_interface_classes/association_ln/ver2.py +30 -36
- DLMS_SPODES/cosem_interface_classes/association_ln/ver3.py +3 -4
- DLMS_SPODES/cosem_interface_classes/association_sn/ver0.py +14 -12
- DLMS_SPODES/cosem_interface_classes/clock.py +81 -131
- DLMS_SPODES/cosem_interface_classes/collection.py +2106 -2122
- DLMS_SPODES/cosem_interface_classes/cosem_interface_class.py +525 -583
- DLMS_SPODES/cosem_interface_classes/data.py +12 -21
- DLMS_SPODES/cosem_interface_classes/demand_register/ver0.py +32 -59
- DLMS_SPODES/cosem_interface_classes/disconnect_control.py +56 -74
- DLMS_SPODES/cosem_interface_classes/extended_register.py +18 -27
- DLMS_SPODES/cosem_interface_classes/gprs_modem_setup.py +33 -43
- DLMS_SPODES/cosem_interface_classes/gsm_diagnostic/ver0.py +78 -103
- DLMS_SPODES/cosem_interface_classes/gsm_diagnostic/ver1.py +42 -40
- DLMS_SPODES/cosem_interface_classes/gsm_diagnostic/ver2.py +6 -9
- DLMS_SPODES/cosem_interface_classes/iec_hdlc_setup/ver0.py +11 -11
- DLMS_SPODES/cosem_interface_classes/iec_hdlc_setup/ver1.py +27 -53
- DLMS_SPODES/cosem_interface_classes/iec_local_port_setup.py +9 -11
- DLMS_SPODES/cosem_interface_classes/image_transfer/image_transfer_status.py +15 -15
- DLMS_SPODES/cosem_interface_classes/image_transfer/ver0.py +54 -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 +491 -487
- DLMS_SPODES/cosem_interface_classes/implementations/profile_generic.py +85 -83
- DLMS_SPODES/cosem_interface_classes/ipv4_setup.py +42 -72
- DLMS_SPODES/cosem_interface_classes/limiter.py +77 -111
- DLMS_SPODES/cosem_interface_classes/ln_pattern.py +334 -333
- DLMS_SPODES/cosem_interface_classes/modem_configuration/ver0.py +51 -65
- DLMS_SPODES/cosem_interface_classes/modem_configuration/ver1.py +27 -39
- DLMS_SPODES/cosem_interface_classes/ntp_setup/ver0.py +48 -67
- DLMS_SPODES/cosem_interface_classes/obis.py +28 -23
- DLMS_SPODES/cosem_interface_classes/overview.py +198 -197
- DLMS_SPODES/cosem_interface_classes/parameter.py +548 -547
- DLMS_SPODES/cosem_interface_classes/parameters.py +172 -172
- DLMS_SPODES/cosem_interface_classes/profile_generic/ver0.py +90 -133
- DLMS_SPODES/cosem_interface_classes/profile_generic/ver1.py +268 -277
- DLMS_SPODES/cosem_interface_classes/push_setup/ver0.py +13 -12
- DLMS_SPODES/cosem_interface_classes/push_setup/ver1.py +9 -10
- DLMS_SPODES/cosem_interface_classes/push_setup/ver2.py +124 -166
- DLMS_SPODES/cosem_interface_classes/register.py +18 -45
- DLMS_SPODES/cosem_interface_classes/register_activation/ver0.py +45 -80
- DLMS_SPODES/cosem_interface_classes/register_monitor.py +33 -46
- DLMS_SPODES/cosem_interface_classes/reports.py +72 -70
- DLMS_SPODES/cosem_interface_classes/schedule.py +88 -176
- DLMS_SPODES/cosem_interface_classes/script_table.py +54 -87
- DLMS_SPODES/cosem_interface_classes/security_setup/ver0.py +45 -68
- DLMS_SPODES/cosem_interface_classes/security_setup/ver1.py +122 -158
- DLMS_SPODES/cosem_interface_classes/single_action_schedule.py +34 -50
- DLMS_SPODES/cosem_interface_classes/special_days_table.py +54 -84
- DLMS_SPODES/cosem_interface_classes/tcp_udp_setup.py +20 -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 +463 -465
- DLMS_SPODES/settings.py +551 -551
- DLMS_SPODES/types/choices.py +140 -142
- DLMS_SPODES/types/common_data_types.py +2379 -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 +12 -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/type_alias.py +74 -0
- DLMS_SPODES/types/useful_types.py +627 -677
- {dlms_spodes-0.87.17.dist-info → dlms_spodes-0.88.1.dist-info}/METADATA +30 -30
- dlms_spodes-0.88.1.dist-info/RECORD +118 -0
- {dlms_spodes-0.87.17.dist-info → dlms_spodes-0.88.1.dist-info}/WHEEL +1 -1
- DLMS_SPODES/cosem_interface_classes/a_parameter.py +0 -20
- DLMS_SPODES/cosem_interface_classes/attr_indexes.py +0 -12
- dlms_spodes-0.87.17.dist-info/RECORD +0 -117
- {dlms_spodes-0.87.17.dist-info → dlms_spodes-0.88.1.dist-info}/top_level.txt +0 -0
|
@@ -1,485 +1,440 @@
|
|
|
1
|
-
from typing import Iterator
|
|
2
|
-
from enum import IntFlag, auto
|
|
3
|
-
from ..parameters import Parameter
|
|
4
|
-
from ... import exceptions as exc
|
|
5
|
-
from
|
|
6
|
-
from ...types import
|
|
7
|
-
from ...
|
|
8
|
-
from
|
|
9
|
-
from . import
|
|
10
|
-
from . import
|
|
11
|
-
from
|
|
12
|
-
from ..
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
case
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
return
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
case Representation.
|
|
238
|
-
case
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
type(self)(value
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
def
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
case
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
index: int,
|
|
442
|
-
m_id: mechanism_id.MechanismIdElement = None
|
|
443
|
-
) -> bool:
|
|
444
|
-
"""for ver 0 and 1 only"""
|
|
445
|
-
self.__check_empty_object_list()
|
|
446
|
-
match self.object_list.get_meth_access(ln, index):
|
|
447
|
-
case pdu.MethodAccess.NO_ACCESS:
|
|
448
|
-
return False
|
|
449
|
-
case pdu.MethodAccess.ACCESS:
|
|
450
|
-
return True
|
|
451
|
-
case pdu.MethodAccess.AUTHENTICATED_ACCESS:
|
|
452
|
-
if not m_id:
|
|
453
|
-
m_id = self.authentication_mechanism_name.mechanism_id_element
|
|
454
|
-
if m_id > mechanism_id.NONE:
|
|
455
|
-
return True
|
|
456
|
-
else:
|
|
457
|
-
return False
|
|
458
|
-
case err:
|
|
459
|
-
raise exc.ITEApplication(F"unsupport access: {err}")
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
def is_attr_writable(
|
|
463
|
-
mode: AccessMode,
|
|
464
|
-
security_policy: pdu.SecurityPolicy = pdu.SecurityPolicyVer0.NOTHING) -> bool:
|
|
465
|
-
match int(mode):
|
|
466
|
-
case pdu.AttributeAccess.NO_ACCESS | pdu.AttributeAccess.READ_ONLY | pdu.AttributeAccess.AUTHENTICATED_READ_ONLY:
|
|
467
|
-
return False
|
|
468
|
-
case pdu.AttributeAccess.WRITE_ONLY | pdu.AttributeAccess.READ_AND_WRITE:
|
|
469
|
-
return True
|
|
470
|
-
case pdu.AttributeAccess.AUTHENTICATED_WRITE_ONLY | pdu.AttributeAccess.AUTHENTICATED_READ_AND_WRITE:
|
|
471
|
-
if isinstance(security_policy, pdu.SecurityPolicyVer0):
|
|
472
|
-
match security_policy:
|
|
473
|
-
case pdu.SecurityPolicyVer0.AUTHENTICATED | pdu.SecurityPolicyVer0.AUTHENTICATED_AND_ENCRYPTED:
|
|
474
|
-
return True
|
|
475
|
-
case _:
|
|
476
|
-
return False
|
|
477
|
-
elif isinstance(security_policy, pdu.SecurityPolicyVer1):
|
|
478
|
-
if bool(security_policy & (pdu.SecurityPolicyVer1.AUTHENTICATED_REQUEST | pdu.SecurityPolicyVer1.AUTHENTICATED_RESPONSE)):
|
|
479
|
-
return True
|
|
480
|
-
else:
|
|
481
|
-
return False
|
|
482
|
-
else:
|
|
483
|
-
raise TypeError(F"unknown {security_policy.__class__}: {security_policy}")
|
|
484
|
-
case err:
|
|
485
|
-
raise exc.ITEApplication(F"unsupport access: {err}")
|
|
1
|
+
from typing import Iterator, Optional
|
|
2
|
+
from enum import IntFlag, auto
|
|
3
|
+
from ..parameters import Parameter
|
|
4
|
+
from ... import exceptions as exc
|
|
5
|
+
from ...types.implementations import arrays, enums, bitstrings, long_unsigneds, structs
|
|
6
|
+
from ...types.type_alias import Attr
|
|
7
|
+
from ... import pdu_enums as pdu
|
|
8
|
+
from . import mechanism_id, authentication_mechanism_name
|
|
9
|
+
from . import method
|
|
10
|
+
from . import abstract
|
|
11
|
+
from ...types import choices, cdt, cst, ut
|
|
12
|
+
from ..cosem_interface_class import ICAuto, ICAElement, ICMElement, Classifier
|
|
13
|
+
from ..Overview import class_id
|
|
14
|
+
from ...types.type_alias import Obis
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class AccessMode(abstract.AccessMode, elements=(0, 1, 2, 3)):
|
|
18
|
+
""" TODO: """
|
|
19
|
+
def is_writable(self) -> bool:
|
|
20
|
+
return True if int(self) >= 2 else False
|
|
21
|
+
|
|
22
|
+
def is_readable(self) -> bool:
|
|
23
|
+
return True if int(self) in (1, 3) else False
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class AttributeAccessItem(abstract.AttributeAccessItem):
|
|
27
|
+
""" Implemented attribute and it access . Use in Association LN """
|
|
28
|
+
DEFAULT = b'\x02\x03\x0f\x01\x16\x00\x00'
|
|
29
|
+
attribute_id: cdt.Integer
|
|
30
|
+
access_mode: AccessMode
|
|
31
|
+
access_selectors: choices.access_selectors
|
|
32
|
+
|
|
33
|
+
def abstract_marker(self):
|
|
34
|
+
...
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class AttributeAccessDescriptor(abstract.AttributeAccessDescriptor):
|
|
38
|
+
""" Array of attribute_access_item """
|
|
39
|
+
TYPE = AttributeAccessItem
|
|
40
|
+
|
|
41
|
+
def set_read_access(self, attribute_id: cdt.Integer):
|
|
42
|
+
it: AttributeAccessItem
|
|
43
|
+
for it in self:
|
|
44
|
+
if it.attribute_id == attribute_id:
|
|
45
|
+
it.access_mode.set(1)
|
|
46
|
+
break
|
|
47
|
+
else:
|
|
48
|
+
self.append(AttributeAccessItem((attribute_id, AccessMode.parse("1"), None)))
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class MethodAccessItem(cdt.Structure):
|
|
52
|
+
""" Implemented method and it access . Use in Association LN """
|
|
53
|
+
method_id: cdt.Integer
|
|
54
|
+
access_mode: cdt.Boolean
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class MethodAccessDescriptor(cdt.Array):
|
|
58
|
+
""" Contain all implemented methods """
|
|
59
|
+
TYPE = MethodAccessItem
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class AccessRight(cdt.Structure):
|
|
63
|
+
""" TODO: """
|
|
64
|
+
attribute_access: AttributeAccessDescriptor
|
|
65
|
+
method_access: MethodAccessDescriptor
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class ObjectListElement(structs.ObjectListElement, access_rights=AccessRight):
|
|
69
|
+
""" Visible COSEM objects with their class_id, version, logical name and the access rights to their attributes and methods within the given application association"""
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class ObjectListType(arrays.SelectionAccess, abstract.ObjectListType):
|
|
73
|
+
""" Array of object_list_element. The range for the client_SAP is 0…0x7F. The range for the server_SAP is 0x000…0x3FFF."""
|
|
74
|
+
TYPE = ObjectListElement
|
|
75
|
+
__getitem__: ObjectListElement
|
|
76
|
+
|
|
77
|
+
def is_writable(self, obis: Obis, indexes: set[int]) -> bool:
|
|
78
|
+
""" index - DLMS object attribute index.
|
|
79
|
+
True: AccessRight is WriteOnly or ReadAndWrite """
|
|
80
|
+
el: ObjectListElement = next(filter(lambda it: it.logical_name.contents == obis, self), None)
|
|
81
|
+
if el is None:
|
|
82
|
+
raise exc.NoObject(F"not find {obis=} in object_list")
|
|
83
|
+
item: AttributeAccessItem
|
|
84
|
+
for index in indexes:
|
|
85
|
+
for item in el.access_rights.attribute_access:
|
|
86
|
+
if int(item.attribute_id) == index:
|
|
87
|
+
if int(item.access_mode) not in (2, 3):
|
|
88
|
+
return False
|
|
89
|
+
else:
|
|
90
|
+
break
|
|
91
|
+
else:
|
|
92
|
+
continue
|
|
93
|
+
else:
|
|
94
|
+
raise ValueError(F"not find in {obis=} attribute index: {index}")
|
|
95
|
+
return True
|
|
96
|
+
|
|
97
|
+
def __get_access_right(self, obis: Obis) -> AccessRight:
|
|
98
|
+
"""return object_list_element of object_list AssociationLN"""
|
|
99
|
+
el: ObjectListElement = next(filter(lambda it: it.logical_name.contents == obis, self), None)
|
|
100
|
+
if el is None:
|
|
101
|
+
raise exc.NoObject(F"not find {obis=} in object_list")
|
|
102
|
+
else:
|
|
103
|
+
return el.access_rights
|
|
104
|
+
|
|
105
|
+
def get_attr_access(self, obis: Obis, index: int) -> pdu.AttributeAccess:
|
|
106
|
+
""" index - DLMS object attribute index """
|
|
107
|
+
for item in self.__get_access_right(obis).attribute_access: # item: AttributeAccessItem
|
|
108
|
+
item: AttributeAccessItem
|
|
109
|
+
if int(item.attribute_id) == index:
|
|
110
|
+
return pdu.AttributeAccess(int(item.access_mode))
|
|
111
|
+
else:
|
|
112
|
+
continue
|
|
113
|
+
else:
|
|
114
|
+
raise ValueError(F"access for {obis}: {index} is absense")
|
|
115
|
+
|
|
116
|
+
def get_access_mode(self, obis: Obis, i: int) -> AccessMode:
|
|
117
|
+
""" index - DLMS object attribute index """
|
|
118
|
+
for item in self.__get_access_right(obis).attribute_access: # item: AttributeAccessItem
|
|
119
|
+
item: AttributeAccessItem
|
|
120
|
+
if int(item.attribute_id) == i:
|
|
121
|
+
return item.access_mode
|
|
122
|
+
else:
|
|
123
|
+
continue
|
|
124
|
+
else:
|
|
125
|
+
raise ValueError(F"access for {obis=}: {i} is absense")
|
|
126
|
+
|
|
127
|
+
def get_meth_access(self, obis: Obis, index: int) -> pdu.MethodAccess:
|
|
128
|
+
""" index - DLMS object method index """
|
|
129
|
+
for item in self.__get_access_right(obis).method_access: # item: MethodAccessItem
|
|
130
|
+
item: MethodAccessItem
|
|
131
|
+
if int(item.method_id) == index:
|
|
132
|
+
return pdu.MethodAccess(int(item.access_mode))
|
|
133
|
+
else:
|
|
134
|
+
continue
|
|
135
|
+
else:
|
|
136
|
+
raise exc.ITEApplication(F"not find method access rules in object_list for {obis=}:{index}") # todo: make custom error
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class AssociatedPartnersType(cdt.Structure):
|
|
140
|
+
""" Contains the identifiers of the COSEM client and the COSEM server (logical device) application processes within the physical devices
|
|
141
|
+
hosting these processes, which belong to the application association modelled by the “Association LN” object. """
|
|
142
|
+
DEFAULT = (0x10, 1)
|
|
143
|
+
client_SAP: enums.ClientSAP
|
|
144
|
+
server_SAP: long_unsigneds.ServerSAP
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class ApplicationContextName(cdt.Structure):
|
|
148
|
+
""" In the COSEM environment, it is intended that an application context pre-exists and is referenced by its name during the establishment of an
|
|
149
|
+
application association. This attribute contains the name of the application context for that association."""
|
|
150
|
+
DEFAULT = (2, 16, 116, 5, 8, 1, 1)
|
|
151
|
+
joint_iso_ctt_element: cdt.Unsigned
|
|
152
|
+
country_element: cdt.Unsigned
|
|
153
|
+
country_name_element: cdt.LongUnsigned
|
|
154
|
+
identified_organization_element: cdt.Unsigned
|
|
155
|
+
DLMS_UA_element: cdt.Unsigned
|
|
156
|
+
application_context_element: cdt.Unsigned
|
|
157
|
+
context_id_element: cdt.Unsigned
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class XDLMSContextType(cdt.Structure):
|
|
161
|
+
""" Contains all the necessary information on the xDLMS context for the given association. """
|
|
162
|
+
DEFAULT = (None, 1024, 1024, 6, 0, b'\x09\x07\x60\x85\x74\x05\x08\x02\x00')
|
|
163
|
+
conformance: bitstrings.Conformance
|
|
164
|
+
max_receive_pdu_size: cdt.LongUnsigned
|
|
165
|
+
max_send_pdu_size: cdt.LongUnsigned
|
|
166
|
+
dlms_version_number: cdt.Unsigned
|
|
167
|
+
quality_of_service: cdt.Integer
|
|
168
|
+
cyphering_info: cdt.OctetString
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class AssociationStatus(cdt.Enum, elements=(0, 1, 2)):
|
|
172
|
+
""" Enum of access mode for methods """
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
class ClassList(cdt.Array):
|
|
176
|
+
""" Access by class. In this case, only those object_list_elements of the object_list shall be included in the response, which have a class_id
|
|
177
|
+
equal to one of the class_id-s of the class-list. No access_right information is included """
|
|
178
|
+
TYPE = long_unsigneds.ClassId
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class ObjectId(cdt.Structure):
|
|
182
|
+
DEFAULT = b'\x02\x02\x12\x00\x08\x09\x06\x00\x00\x01\x00\x00\xff'
|
|
183
|
+
class_id: long_unsigneds.ClassId
|
|
184
|
+
logical_name: cst.LogicalName
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
class ObjectIdList(cdt.Array):
|
|
188
|
+
""" Access by object. The full information record of object instances on the object_Id_list shall be returned. """
|
|
189
|
+
TYPE = ObjectId
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
class Representation(IntFlag):
|
|
193
|
+
HEX = 0
|
|
194
|
+
ASCII = auto()
|
|
195
|
+
HIDDEN = auto()
|
|
196
|
+
ASCII_HIDDEN = ASCII | HIDDEN
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
class LLCSecret(cdt.OctetString):
|
|
200
|
+
""" representation for secret """
|
|
201
|
+
__representation: Representation = Representation.HEX
|
|
202
|
+
# used for set class property from instance
|
|
203
|
+
|
|
204
|
+
def __init__(self, value: bytes | bytearray | str | int = None):
|
|
205
|
+
|
|
206
|
+
super(LLCSecret, self).__init__(value)
|
|
207
|
+
# self.representation = Representation(0)
|
|
208
|
+
|
|
209
|
+
def __setattr__(self, key, value):
|
|
210
|
+
match key:
|
|
211
|
+
case 'representation' if not isinstance(value, Representation): raise ValueError(F"Error representation type")
|
|
212
|
+
case 'representation' as rep: LLCSecret.__representation = value
|
|
213
|
+
case _: super().__setattr__(key, value)
|
|
214
|
+
|
|
215
|
+
@property
|
|
216
|
+
def representation(self) -> Representation:
|
|
217
|
+
"""used for set class property from instance"""
|
|
218
|
+
return self.__representation
|
|
219
|
+
|
|
220
|
+
def __getattr__(self, item):
|
|
221
|
+
raise AttributeError(F'LLCSecret not has {item}')
|
|
222
|
+
|
|
223
|
+
@staticmethod
|
|
224
|
+
def __hide_all(value: str) -> str:
|
|
225
|
+
for char_ in filter(lambda it: it != ' ', value):
|
|
226
|
+
value = value.replace(char_, '*')
|
|
227
|
+
return value
|
|
228
|
+
|
|
229
|
+
def from_str(self, value: str) -> bytes:
|
|
230
|
+
if self.__representation & Representation.ASCII:
|
|
231
|
+
return cdt.VisibleString.from_str(self, value)
|
|
232
|
+
else:
|
|
233
|
+
return super(LLCSecret, self).from_str(value)
|
|
234
|
+
|
|
235
|
+
def __str__(self):
|
|
236
|
+
match self.__representation:
|
|
237
|
+
case Representation.ASCII: return cdt.VisibleString.__str__(self)
|
|
238
|
+
case Representation.HIDDEN: return self.__hide_all(super(LLCSecret, self).__str__())
|
|
239
|
+
case Representation.ASCII_HIDDEN: return self.__hide_all(cdt.VisibleString.__str__(self))
|
|
240
|
+
case _: return super(LLCSecret, self).__str__()
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
class LLCSecretHigh(LLCSecret):
|
|
244
|
+
DEFAULT = b'0000000000000000'
|
|
245
|
+
|
|
246
|
+
def validation(self):
|
|
247
|
+
""" check for length equal 16 """
|
|
248
|
+
if len(self) != 16:
|
|
249
|
+
raise ValueError(F'Got length of High secret: {len(self)}, expected 16')
|
|
250
|
+
|
|
251
|
+
def validate_from(self, value: str, cursor_position=None) -> tuple[str, int]:
|
|
252
|
+
try:
|
|
253
|
+
correct = type(self)(value)
|
|
254
|
+
return str(correct), cursor_position + (len(str(correct))-len(value))
|
|
255
|
+
except ValueError:
|
|
256
|
+
match self.representation & 0b1:
|
|
257
|
+
case Representation.HEX:
|
|
258
|
+
cursor_position: int = len(value)-1 if cursor_position is None else cursor_position
|
|
259
|
+
type(self)(F'{value[:cursor_position]}0{value[cursor_position:]}') # check possible
|
|
260
|
+
case Representation.ASCII:
|
|
261
|
+
type(self)(value.zfill(16))
|
|
262
|
+
return value, cursor_position
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
class AccessSelector(ut.Unsigned8):
|
|
266
|
+
""" Unsigned8 1..4 """
|
|
267
|
+
def __init__(self, value: int | str | ut.Unsigned8 = 1):
|
|
268
|
+
super(AccessSelector, self).__init__(value)
|
|
269
|
+
if int(self) > 4 or int(self) < 1:
|
|
270
|
+
raise ValueError(F'The {self.__class__.__name__} got {self}, expected 1..4')
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
class Data(ut.Data):
|
|
274
|
+
ELEMENTS = {1: ut.SequenceElement('All information', cdt.NullData),
|
|
275
|
+
2: ut.SequenceElement('Access by class', ClassList),
|
|
276
|
+
3: ut.SequenceElement('Access by object', ObjectIdList),
|
|
277
|
+
4: ut.SequenceElement('Full object information', ObjectId)}
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
class SelectiveAccessDescriptor(ut.SelectiveAccessDescriptor):
|
|
281
|
+
""" Selective access specification always starts with an access selector, followed by an access-specific access parameter list.
|
|
282
|
+
Specified IS/IEC 62056-53 : 2006, 7.4.1.6 Selective access """
|
|
283
|
+
access_selector: AccessSelector
|
|
284
|
+
access_parameters: Data
|
|
285
|
+
ELEMENTS = (ut.SequenceElement('access_selector', AccessSelector),
|
|
286
|
+
ut.SequenceElement('access_parameters', Data))
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
class CosemAttributeDescriptorWithSelection(ut.CosemAttributeDescriptorWithSelection):
|
|
290
|
+
access_selection: SelectiveAccessDescriptor
|
|
291
|
+
ELEMENTS = (ut.SequenceElement('cosem_attribute_descriptor', ut.CosemAttributeDescriptor),
|
|
292
|
+
ut.SequenceElement('access_selection', SelectiveAccessDescriptor))
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
class AssociationLN(ICAuto):
|
|
296
|
+
"""5.4.5 Association LN"""
|
|
297
|
+
CLASS_ID = class_id.ASSOCIATION_LN
|
|
298
|
+
VERSION = 0
|
|
299
|
+
A_ELEMENTS = (ICAElement(2, "object_list", ObjectListType, selective_access=SelectiveAccessDescriptor),
|
|
300
|
+
ICAElement(3, "associated_partners_id", AssociatedPartnersType),
|
|
301
|
+
ICAElement(4, "application_context_name", ApplicationContextName),
|
|
302
|
+
ICAElement(5, "xDLMS_context_info", XDLMSContextType),
|
|
303
|
+
ICAElement(6, "authentication_mechanism_name", authentication_mechanism_name.AuthenticationMechanismName),
|
|
304
|
+
ICAElement(7, "LLS_secret", LLCSecret, classifier=Classifier.NOT_SPECIFIC),
|
|
305
|
+
ICAElement(8, "association_status", AssociationStatus, classifier=Classifier.DYNAMIC))
|
|
306
|
+
M_ELEMENTS = (ICMElement(1, "reply_to_HLS_authentication", method.ReplyToHLSAuthentication),
|
|
307
|
+
ICMElement(2, "change_HLS_secret", LLCSecret),
|
|
308
|
+
ICMElement(3, "add_object", ObjectListElement),
|
|
309
|
+
ICMElement(4, "remove_object", ObjectListElement))
|
|
310
|
+
object_list: Attr
|
|
311
|
+
associated_partners_id: Attr
|
|
312
|
+
application_context_name: Attr
|
|
313
|
+
xDLMS_context_info: Attr
|
|
314
|
+
authentication_mechanism_name: Attr
|
|
315
|
+
LLS_secret: Attr
|
|
316
|
+
association_status: Attr
|
|
317
|
+
|
|
318
|
+
def __check_mechanism_id_existing(self):
|
|
319
|
+
"""check for existing mechanism ID else ERASE setting"""
|
|
320
|
+
if self.authentication_mechanism_name is None:
|
|
321
|
+
self.clear_attr(7)
|
|
322
|
+
self._cbs_attr_post_init[7] = self.__check_mechanism_id_existing
|
|
323
|
+
else:
|
|
324
|
+
"""nothing do it"""
|
|
325
|
+
|
|
326
|
+
def __init_secret(self):
|
|
327
|
+
""" before initiating secret need knowledge what kind of mechanism ID """
|
|
328
|
+
match self.authentication_mechanism_name.mechanism_id_element, self.LLS_secret:
|
|
329
|
+
case mechanism_id.NONE | mechanism_id.LOW, LLCSecret(): """keep secret value"""
|
|
330
|
+
case mechanism_id.NONE | mechanism_id.LOW, _: self.set_attr_link(7, LLCSecret())
|
|
331
|
+
case mechanism_id.HIGH, LLCSecretHigh(): """keep secret value"""
|
|
332
|
+
case mechanism_id.HIGH, _: self.set_attr_link(7, LLCSecretHigh())
|
|
333
|
+
case unknown, _: raise ValueError(F'Not support Secret with {unknown}')
|
|
334
|
+
|
|
335
|
+
# def get_attr_descriptor(self,
|
|
336
|
+
# i: int,
|
|
337
|
+
# with_selection: bool = False) -> ut.CosemAttributeDescriptor | CosemAttributeDescriptorWithSelection:
|
|
338
|
+
# """ with selection for object_list. TODO: Copypast ProfileGeneric"""
|
|
339
|
+
# descriptor: ut.CosemAttributeDescriptor = super(AssociationLN, self).get_attr_descriptor(i)
|
|
340
|
+
# if i == 2 and with_selection and self.object_list:
|
|
341
|
+
# return CosemAttributeDescriptorWithSelection((descriptor, self.object_list.selective_access))
|
|
342
|
+
# else:
|
|
343
|
+
# return descriptor
|
|
344
|
+
#
|
|
345
|
+
def get_lns(self) -> list[cst.LogicalName]:
|
|
346
|
+
"""return all LogicalNames"""
|
|
347
|
+
el: ObjectListElement
|
|
348
|
+
return [el.logical_name for el in self.object_list]
|
|
349
|
+
|
|
350
|
+
def iter_pars(self) -> Iterator[Parameter]:
|
|
351
|
+
return (Parameter(el.logical_name.contents) for el in self.object_list)
|
|
352
|
+
|
|
353
|
+
def __check_empty_object_list(self):
|
|
354
|
+
if self.object_list is None:
|
|
355
|
+
raise exc.ITEApplication(F"empty <{self.get_attr_element(2).NAME}> in {self}")
|
|
356
|
+
|
|
357
|
+
def is_readable(self,
|
|
358
|
+
ln: cst.LogicalName,
|
|
359
|
+
index: int,
|
|
360
|
+
security_policy: pdu.SecurityPolicy = pdu.SecurityPolicyVer0.NOTHING
|
|
361
|
+
) -> bool:
|
|
362
|
+
self.__check_empty_object_list()
|
|
363
|
+
match self.object_list.get_attr_access(ln, index):
|
|
364
|
+
case pdu.AttributeAccess.NO_ACCESS | pdu.AttributeAccess.WRITE_ONLY | pdu.AttributeAccess.AUTHENTICATED_WRITE_ONLY:
|
|
365
|
+
return False
|
|
366
|
+
case pdu.AttributeAccess.READ_ONLY | pdu.AttributeAccess.READ_AND_WRITE:
|
|
367
|
+
return True
|
|
368
|
+
case pdu.AttributeAccess.AUTHENTICATED_READ_ONLY | pdu.AttributeAccess.AUTHENTICATED_READ_AND_WRITE:
|
|
369
|
+
if isinstance(security_policy, pdu.SecurityPolicyVer0):
|
|
370
|
+
match security_policy:
|
|
371
|
+
case pdu.SecurityPolicyVer0.AUTHENTICATED | pdu.SecurityPolicyVer0.AUTHENTICATED_AND_ENCRYPTED:
|
|
372
|
+
return True
|
|
373
|
+
case _:
|
|
374
|
+
return False
|
|
375
|
+
elif isinstance(security_policy, pdu.SecurityPolicyVer1):
|
|
376
|
+
if bool(security_policy & (pdu.SecurityPolicyVer1.AUTHENTICATED_REQUEST | pdu.SecurityPolicyVer1.AUTHENTICATED_RESPONSE)):
|
|
377
|
+
return True
|
|
378
|
+
else:
|
|
379
|
+
return False
|
|
380
|
+
else:
|
|
381
|
+
raise TypeError(F"unknown {security_policy.__class__}: {security_policy}")
|
|
382
|
+
case err:
|
|
383
|
+
raise exc.ITEApplication(F"unsupport access: {err}")
|
|
384
|
+
|
|
385
|
+
def is_writable(self,
|
|
386
|
+
ln: cst.LogicalName,
|
|
387
|
+
index: int,
|
|
388
|
+
security_policy: pdu.SecurityPolicy = pdu.SecurityPolicyVer0.NOTHING
|
|
389
|
+
) -> bool:
|
|
390
|
+
self.__check_empty_object_list()
|
|
391
|
+
return is_attr_writable(
|
|
392
|
+
mode=self.object_list.get_access_mode(ln, index),
|
|
393
|
+
security_policy=security_policy)
|
|
394
|
+
|
|
395
|
+
def is_accessible(self, ln: cst.LogicalName,
|
|
396
|
+
index: int,
|
|
397
|
+
m_id: mechanism_id.MechanismIdElement = None
|
|
398
|
+
) -> bool:
|
|
399
|
+
"""for ver 0 and 1 only"""
|
|
400
|
+
self.__check_empty_object_list()
|
|
401
|
+
match self.object_list.get_meth_access(ln, index):
|
|
402
|
+
case pdu.MethodAccess.NO_ACCESS:
|
|
403
|
+
return False
|
|
404
|
+
case pdu.MethodAccess.ACCESS:
|
|
405
|
+
return True
|
|
406
|
+
case pdu.MethodAccess.AUTHENTICATED_ACCESS:
|
|
407
|
+
if not m_id:
|
|
408
|
+
m_id = self.authentication_mechanism_name.mechanism_id_element
|
|
409
|
+
if m_id > mechanism_id.NONE:
|
|
410
|
+
return True
|
|
411
|
+
else:
|
|
412
|
+
return False
|
|
413
|
+
case err:
|
|
414
|
+
raise exc.ITEApplication(F"unsupport access: {err}")
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
def is_attr_writable(
|
|
418
|
+
mode: AccessMode,
|
|
419
|
+
security_policy: pdu.SecurityPolicy = pdu.SecurityPolicyVer0.NOTHING) -> bool:
|
|
420
|
+
match int(mode):
|
|
421
|
+
case pdu.AttributeAccess.NO_ACCESS | pdu.AttributeAccess.READ_ONLY | pdu.AttributeAccess.AUTHENTICATED_READ_ONLY:
|
|
422
|
+
return False
|
|
423
|
+
case pdu.AttributeAccess.WRITE_ONLY | pdu.AttributeAccess.READ_AND_WRITE:
|
|
424
|
+
return True
|
|
425
|
+
case pdu.AttributeAccess.AUTHENTICATED_WRITE_ONLY | pdu.AttributeAccess.AUTHENTICATED_READ_AND_WRITE:
|
|
426
|
+
if isinstance(security_policy, pdu.SecurityPolicyVer0):
|
|
427
|
+
match security_policy:
|
|
428
|
+
case pdu.SecurityPolicyVer0.AUTHENTICATED | pdu.SecurityPolicyVer0.AUTHENTICATED_AND_ENCRYPTED:
|
|
429
|
+
return True
|
|
430
|
+
case _:
|
|
431
|
+
return False
|
|
432
|
+
elif isinstance(security_policy, pdu.SecurityPolicyVer1):
|
|
433
|
+
if bool(security_policy & (pdu.SecurityPolicyVer1.AUTHENTICATED_REQUEST | pdu.SecurityPolicyVer1.AUTHENTICATED_RESPONSE)):
|
|
434
|
+
return True
|
|
435
|
+
else:
|
|
436
|
+
return False
|
|
437
|
+
else:
|
|
438
|
+
raise TypeError(F"unknown {security_policy.__class__}: {security_policy}")
|
|
439
|
+
case err:
|
|
440
|
+
raise exc.ITEApplication(F"unsupport access: {err}")
|