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,277 +1,277 @@
|
|
|
1
|
-
"""DLMS UA 1000-1 Ed. 14"""
|
|
2
|
-
from . import ver0
|
|
3
|
-
from typing import Type, Iterator
|
|
4
|
-
from ... import cosem_interface_classes
|
|
5
|
-
from ...relation_to_OBIS import get_name
|
|
6
|
-
from ... import exceptions as exc
|
|
7
|
-
from ..__class_init__ import *
|
|
8
|
-
from ...types.implementations import integers, arrays, structs
|
|
9
|
-
from ...types.choices import CommonDataTypeChoiceBase
|
|
10
|
-
from ..overview import VERSION_1
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class CaptureObjects(cdt.Array):
|
|
14
|
-
""" Specifies the list of capture objects """
|
|
15
|
-
TYPE = structs.CaptureObjectDefinition
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class FromEntry(cdt.DoubleLongUnsigned, min=1):
|
|
19
|
-
""" Access selector value for selective access to the object_list attribute """
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class EntryDescriptor(cdt.Structure):
|
|
23
|
-
""" Only buffer elements corresponding to the entry_descriptor shall be returned in the response.
|
|
24
|
-
NOTE: from_entry and to_entry identify the lines, from_selected_value to_selected_value identify the columns of the buffer to be retrieved. """
|
|
25
|
-
DEFAULT = (1, 0, 1, 0)
|
|
26
|
-
from_entry: FromEntry
|
|
27
|
-
to_entry: cdt.DoubleLongUnsigned
|
|
28
|
-
from_selected_value: cdt.LongUnsigned
|
|
29
|
-
to_selected_value: cdt.LongUnsigned
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
class AccessSelector(ut.Unsigned8):
|
|
33
|
-
""" Unsigned8 1..2. Default is 2 for read all buffer """
|
|
34
|
-
def __init__(self, value: int | str | ut.Unsigned8 = 2):
|
|
35
|
-
super(AccessSelector, self).__init__(value)
|
|
36
|
-
if int(self) not in (1, 2):
|
|
37
|
-
raise ValueError(F'The {self.__class__.__name__} got {int(self)}, expected 1..2')
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class RangeDescriptorValueChoice(CommonDataTypeChoiceBase, types=(
|
|
41
|
-
cdt.DoubleLong,
|
|
42
|
-
cdt.DoubleLongUnsigned,
|
|
43
|
-
cdt.OctetString,
|
|
44
|
-
cdt.VisibleString,
|
|
45
|
-
cdt.Utf8String,
|
|
46
|
-
cdt.Integer,
|
|
47
|
-
cdt.Unsigned,
|
|
48
|
-
cdt.LongUnsigned,
|
|
49
|
-
cdt.Long,
|
|
50
|
-
cdt.Long64Unsigned,
|
|
51
|
-
cdt.Float32,
|
|
52
|
-
cdt.Float64,
|
|
53
|
-
cdt.DateTime,
|
|
54
|
-
cdt.Date,
|
|
55
|
-
cdt.Time
|
|
56
|
-
)):
|
|
57
|
-
"""Types of range_descriptor.from_value/to_value"""
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
# class RangeDescriptor(cdt.Structure):
|
|
61
|
-
# restricting_object: structs.CaptureObjectDefinition
|
|
62
|
-
# from_value: RangeDescriptorValueChoice
|
|
63
|
-
# to_value: RangeDescriptorValueChoice
|
|
64
|
-
# selected_values: CaptureObjects
|
|
65
|
-
#
|
|
66
|
-
# def __setattr__(self, key, value):
|
|
67
|
-
# """Allow setting from_value and to_value with a CommonDataType of allowed types.
|
|
68
|
-
# Other attributes remain immutable as per base Structure behavior."""
|
|
69
|
-
# if key in ("from_value", "to_value"):
|
|
70
|
-
# index = 1 if key == "from_value" else 2
|
|
71
|
-
# # Accept only CommonDataType instances of allowed types
|
|
72
|
-
# if isinstance(value, cdt.CommonDataType):
|
|
73
|
-
# # Build allowed types tuple from Choice definition
|
|
74
|
-
# allowed_types = tuple(el.TYPE if isinstance(el, ut.SequenceElement) else None for el in RangeDescriptorValueChoice.ELEMENTS.values())
|
|
75
|
-
# allowed_types = tuple(t for t in allowed_types if t is not None)
|
|
76
|
-
# if isinstance(value, allowed_types):
|
|
77
|
-
# self.values[index] = value
|
|
78
|
-
# return
|
|
79
|
-
# else:
|
|
80
|
-
# raise ValueError(F"Type got {value.__class__.__name__}, expected one of: "
|
|
81
|
-
# + ", ".join(t.__name__ for t in allowed_types))
|
|
82
|
-
# else:
|
|
83
|
-
# raise TypeError(F"Unsupported value type for {key}: {value.__class__.__name__}. Provide a CommonDataType instance.")
|
|
84
|
-
# else:
|
|
85
|
-
# super().__setattr__(key, value)
|
|
86
|
-
#
|
|
87
|
-
#
|
|
88
|
-
# class Data(ut.Data):
|
|
89
|
-
# restricting_object: structs.CaptureObjectDefinition
|
|
90
|
-
# from_value: cdt.SimpleDataType
|
|
91
|
-
# to_value: cdt.SimpleDataType
|
|
92
|
-
# selected_values: CaptureObjects
|
|
93
|
-
# from_entry: FromEntry
|
|
94
|
-
# to_entry: cdt.DoubleLongUnsigned
|
|
95
|
-
# from_selected_value: cdt.LongUnsigned
|
|
96
|
-
# to_selected_value: cdt.LongUnsigned
|
|
97
|
-
# ELEMENTS = {1: ut.SequenceElement('range_descriptor', RangeDescriptor),
|
|
98
|
-
# 2: ut.SequenceElement('entry_descriptor', EntryDescriptor)}
|
|
99
|
-
#
|
|
100
|
-
#
|
|
101
|
-
# class SelectiveAccessDescriptor(ut.SelectiveAccessDescriptor):
|
|
102
|
-
# access_selector: AccessSelector
|
|
103
|
-
# access_parameters: Data
|
|
104
|
-
# ELEMENTS = (ut.SequenceElement('access_selector', AccessSelector),
|
|
105
|
-
# ut.SequenceElement('access_parameters', Data))
|
|
106
|
-
#
|
|
107
|
-
#
|
|
108
|
-
# class CosemAttributeDescriptorWithSelection(ut.CosemAttributeDescriptorWithSelection):
|
|
109
|
-
# access_selection: SelectiveAccessDescriptor
|
|
110
|
-
# ELEMENTS = (ut.SequenceElement('cosem_attribute_descriptor', ut.CosemAttributeDescriptor),
|
|
111
|
-
# ut.SequenceElement('access_selection', SelectiveAccessDescriptor))
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
class ProfileGeneric(ver0.ProfileGeneric):
|
|
115
|
-
"""4.3.6 Profile generic"""
|
|
116
|
-
VERSION = VERSION_1
|
|
117
|
-
A_ELEMENTS = (ic.ICAElement("buffer", arrays.SelectionAccess, classifier=ic.Classifier.DYNAMIC),
|
|
118
|
-
ic.ICAElement("capture_objects", CaptureObjects),
|
|
119
|
-
ver0.ProfileGeneric.get_attr_element(4),
|
|
120
|
-
ver0.ProfileGeneric.get_attr_element(5),
|
|
121
|
-
ic.ICAElement("sort_object", structs.CaptureObjectDefinition),
|
|
122
|
-
ic.ICAElement("entries_in_use", cdt.DoubleLongUnsigned, 0, default=0, classifier=ic.Classifier.DYNAMIC),
|
|
123
|
-
ic.ICAElement("profile_entries", cdt.DoubleLongUnsigned, 1, default=1))
|
|
124
|
-
M_ELEMENTS = (
|
|
125
|
-
ver0.ProfileGeneric.get_meth_element(1),
|
|
126
|
-
ver0.ProfileGeneric.get_meth_element(2)
|
|
127
|
-
)
|
|
128
|
-
|
|
129
|
-
def characteristics_init(self):
|
|
130
|
-
self.set_attr(ver0.BUFFER, None)
|
|
131
|
-
|
|
132
|
-
# todo remove it
|
|
133
|
-
self.buffer.register_cb_preset(lambda _: self.__create_buffer_struct_type()) # value not used for creating struct type
|
|
134
|
-
|
|
135
|
-
self._cbs_attr_post_init.update({ver0.CAPTURE_OBJECTS: self.__create_buffer_struct_type,
|
|
136
|
-
ver0.SORT_OBJECT: self.__create_selective_access_descriptor})
|
|
137
|
-
|
|
138
|
-
self.buffer_capture_objects = self.capture_objects
|
|
139
|
-
""" objects for buffer. Change with access_selection """
|
|
140
|
-
|
|
141
|
-
@property
|
|
142
|
-
def buffer(self) -> arrays.SelectionAccess:
|
|
143
|
-
return self.get_attr(2)
|
|
144
|
-
|
|
145
|
-
@property
|
|
146
|
-
def capture_objects(self) -> CaptureObjects:
|
|
147
|
-
return self.get_attr(3)
|
|
148
|
-
|
|
149
|
-
@property
|
|
150
|
-
def sort_object(self) -> structs.CaptureObjectDefinition:
|
|
151
|
-
return self.get_attr(6)
|
|
152
|
-
|
|
153
|
-
def get_attr_descriptor(self,
|
|
154
|
-
value: int,
|
|
155
|
-
with_selection: bool = False) -> ut.CosemAttributeDescriptor | ut.CosemAttributeDescriptorWithSelection:
|
|
156
|
-
""" with selection for object_list. TODO: Copypast AssociationLN"""
|
|
157
|
-
descriptor: ut.CosemAttributeDescriptor = super(ProfileGeneric, self).get_attr_descriptor(value)
|
|
158
|
-
if value == ver0.BUFFER and with_selection:
|
|
159
|
-
if self.attr_descriptor_with_selection is None:
|
|
160
|
-
self.__create_selective_access_descriptor()
|
|
161
|
-
return self.attr_descriptor_with_selection((descriptor.contents, self.buffer.selective_access.contents))
|
|
162
|
-
else:
|
|
163
|
-
return descriptor
|
|
164
|
-
|
|
165
|
-
def __create_buffer_struct_type(self):
|
|
166
|
-
""" TODO: more refactoring !!! """
|
|
167
|
-
# rename CaptureObjectDefinition's and adding object if it absense in collection
|
|
168
|
-
if self.buffer.selective_access is None:
|
|
169
|
-
self.__create_selective_access_descriptor()
|
|
170
|
-
if self.capture_objects is None:
|
|
171
|
-
raise ValueError(F"{self}: create buffer Struct type, not set <capture_object> attribute. Need initiate <capture_objects> before")
|
|
172
|
-
for el_value in self.capture_objects:
|
|
173
|
-
el_value: structs.CaptureObjectDefinition
|
|
174
|
-
obj = self.collection.add_if_missing(class_id=ut.CosemClassId(el_value.class_id.contents),
|
|
175
|
-
version=None,
|
|
176
|
-
logical_name=el_value.logical_name)
|
|
177
|
-
el_value.set_name(self.collection.get_name_and_type(el_value)[0][-1])
|
|
178
|
-
match self.buffer.selective_access:
|
|
179
|
-
case ut.SelectiveAccessDescriptor() as desc:
|
|
180
|
-
match int(desc.access_selector):
|
|
181
|
-
# case 0: self.buffer_capture_objects = self.capture_objects
|
|
182
|
-
case 1 if len(desc.access_parameters.selected_values) == 0: self.buffer_capture_objects = self.capture_objects
|
|
183
|
-
case 1: self.buffer_capture_objects = desc.access_parameters.selected_values
|
|
184
|
-
case 2:
|
|
185
|
-
from_selected_value = int(desc.access_parameters.from_selected_value)-1
|
|
186
|
-
to_selected_value = int(desc.access_parameters.to_selected_value)
|
|
187
|
-
if to_selected_value == 0:
|
|
188
|
-
to_selected_value = len(self.capture_objects)
|
|
189
|
-
self.buffer_capture_objects = self.capture_objects[from_selected_value:to_selected_value]
|
|
190
|
-
case _ as err: raise ValueError(F'access_selection out of range, got {err}, must be (0..2)')
|
|
191
|
-
case None:
|
|
192
|
-
self.clear_attr(ver0.CAPTURE_OBJECTS)
|
|
193
|
-
self._cbs_attr_post_init[ver0.CAPTURE_OBJECTS] = self.__create_buffer_struct_type
|
|
194
|
-
raise exc.EmptyObj(F"need set <sort_object> before for {self}")
|
|
195
|
-
buffer_elements: list[cdt.StructElement] = list()
|
|
196
|
-
for el_value in self.buffer_capture_objects:
|
|
197
|
-
names, type_ = self.collection.get_name_and_type(el_value)
|
|
198
|
-
buffer_elements.append(cdt.StructElement(NAME=". ".join(names), TYPE=type_))
|
|
199
|
-
|
|
200
|
-
class Entry(cdt.Structure):
|
|
201
|
-
"""4.3.6 Profile generic: entry"""
|
|
202
|
-
ELEMENTS = tuple(buffer_elements)
|
|
203
|
-
|
|
204
|
-
self.buffer.set_type(Entry)
|
|
205
|
-
|
|
206
|
-
def __create_selective_access_descriptor(self):
|
|
207
|
-
""" Available after got sort object. TODO: need rewrite. maybe replace to collection level. Wrong used sort_obj, it can be any element from capture_objects"""
|
|
208
|
-
if self.sort_object is None:
|
|
209
|
-
raise exc.EmptyObj(F"<sort object> is empty")
|
|
210
|
-
sort_obj: ic.COSEMInterfaceClasses = self.collection.get_object(self.sort_object.logical_name)
|
|
211
|
-
if sort_obj.CLASS_ID.contents == self.sort_object.class_id.contents:
|
|
212
|
-
value_type: Type[cdt.CommonDataType] = sort_obj.get_attr_data_type(int(self.sort_object.attribute_index))
|
|
213
|
-
else:
|
|
214
|
-
exc.NoObject(F"got {self.sort_object.class_id=}, expected {sort_obj.CLASS_ID=} from collection")
|
|
215
|
-
|
|
216
|
-
class RangeDescriptor(cdt.Structure):
|
|
217
|
-
# cb_preset = TODO: make check 'selected_values' from self.capture_objects or
|
|
218
|
-
# cb_post_set = TODO: make check 'selected_values' from self.capture_objects
|
|
219
|
-
DEFAULT = b'\x02\x04\x02\x04\x12\x00\x01\x09\x06\x00\x00\x01\x00\x00\xff\x0f\x02\x12\x00\x00\x09\x0c\x07\xe4\x01\x01\xff\xff\xff\xff\xff\x80\x00\xff' \
|
|
220
|
-
b'\x09\x0c\x07\xe4\x01\x02\xff\xff\xff\xff\xff\x80\x00\xff\x01\x00'
|
|
221
|
-
restricting_object: structs.CaptureObjectDefinition
|
|
222
|
-
from_value: value_type
|
|
223
|
-
to_value: value_type
|
|
224
|
-
selected_values: CaptureObjects
|
|
225
|
-
|
|
226
|
-
class Data(ut.Data):
|
|
227
|
-
restricting_object: structs.CaptureObjectDefinition
|
|
228
|
-
from_value: cdt.SimpleDataType
|
|
229
|
-
to_value: cdt.SimpleDataType
|
|
230
|
-
selected_values: CaptureObjects
|
|
231
|
-
from_entry: FromEntry
|
|
232
|
-
to_entry: cdt.DoubleLongUnsigned
|
|
233
|
-
from_selected_value: cdt.LongUnsigned
|
|
234
|
-
to_selected_value: cdt.LongUnsigned
|
|
235
|
-
ELEMENTS = {1: ut.SequenceElement('range_descriptor', RangeDescriptor),
|
|
236
|
-
2: ut.SequenceElement('entry_descriptor', EntryDescriptor)}
|
|
237
|
-
|
|
238
|
-
class SelectiveAccessDescriptor(ut.SelectiveAccessDescriptor):
|
|
239
|
-
access_selector: AccessSelector
|
|
240
|
-
access_parameters: Data
|
|
241
|
-
ELEMENTS = (ut.SequenceElement('access_selector', AccessSelector),
|
|
242
|
-
ut.SequenceElement('access_parameters', Data))
|
|
243
|
-
|
|
244
|
-
class CosemAttributeDescriptorWithSelection(ut.CosemAttributeDescriptorWithSelection):
|
|
245
|
-
access_selection: SelectiveAccessDescriptor
|
|
246
|
-
ELEMENTS = (ut.SequenceElement('cosem_attribute_descriptor', ut.CosemAttributeDescriptor),
|
|
247
|
-
ut.SequenceElement('access_selection', SelectiveAccessDescriptor))
|
|
248
|
-
|
|
249
|
-
self.attr_descriptor_with_selection = CosemAttributeDescriptorWithSelection
|
|
250
|
-
self.buffer.selective_access = SelectiveAccessDescriptor()
|
|
251
|
-
|
|
252
|
-
def get_capture_object_names(self) -> list[str]:
|
|
253
|
-
""" return all capture object names from collection """
|
|
254
|
-
if self.capture_objects is None:
|
|
255
|
-
raise ValueError(F'{self}: Empty capture objects')
|
|
256
|
-
else:
|
|
257
|
-
definition: structs.CaptureObjectDefinition
|
|
258
|
-
ret = list()
|
|
259
|
-
for definition in self.capture_objects:
|
|
260
|
-
ret.append(get_name(definition.logical_name))
|
|
261
|
-
return ret
|
|
262
|
-
|
|
263
|
-
def get_buffer_objects(self) -> list[cosem_interface_classes.cosem_interface_class.COSEMInterfaceClasses]:
|
|
264
|
-
""" get objects of current buffer container """
|
|
265
|
-
return [self.collection.get(obj_def.logical_name.contents) for obj_def in self.buffer_capture_objects]
|
|
266
|
-
|
|
267
|
-
# todo remove it
|
|
268
|
-
def get_index_with_attributes(self, in_init_order: bool = False) -> Iterator[tuple[int, cdt.CommonDataType | None]]:
|
|
269
|
-
""" override common method """
|
|
270
|
-
return iter(((1, self.logical_name),
|
|
271
|
-
(6, self.sort_object),
|
|
272
|
-
(3, self.capture_objects),
|
|
273
|
-
(2, self.buffer),
|
|
274
|
-
(4, self.capture_period),
|
|
275
|
-
(5, self.sort_method),
|
|
276
|
-
(7, self.entries_in_use),
|
|
277
|
-
(8, self.profile_entries)))
|
|
1
|
+
"""DLMS UA 1000-1 Ed. 14"""
|
|
2
|
+
from . import ver0
|
|
3
|
+
from typing import Type, Iterator
|
|
4
|
+
from ... import cosem_interface_classes
|
|
5
|
+
from ...relation_to_OBIS import get_name
|
|
6
|
+
from ... import exceptions as exc
|
|
7
|
+
from ..__class_init__ import *
|
|
8
|
+
from ...types.implementations import integers, arrays, structs
|
|
9
|
+
from ...types.choices import CommonDataTypeChoiceBase
|
|
10
|
+
from ..overview import VERSION_1
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class CaptureObjects(cdt.Array):
|
|
14
|
+
""" Specifies the list of capture objects """
|
|
15
|
+
TYPE = structs.CaptureObjectDefinition
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class FromEntry(cdt.DoubleLongUnsigned, min=1):
|
|
19
|
+
""" Access selector value for selective access to the object_list attribute """
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class EntryDescriptor(cdt.Structure):
|
|
23
|
+
""" Only buffer elements corresponding to the entry_descriptor shall be returned in the response.
|
|
24
|
+
NOTE: from_entry and to_entry identify the lines, from_selected_value to_selected_value identify the columns of the buffer to be retrieved. """
|
|
25
|
+
DEFAULT = (1, 0, 1, 0)
|
|
26
|
+
from_entry: FromEntry
|
|
27
|
+
to_entry: cdt.DoubleLongUnsigned
|
|
28
|
+
from_selected_value: cdt.LongUnsigned
|
|
29
|
+
to_selected_value: cdt.LongUnsigned
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class AccessSelector(ut.Unsigned8):
|
|
33
|
+
""" Unsigned8 1..2. Default is 2 for read all buffer """
|
|
34
|
+
def __init__(self, value: int | str | ut.Unsigned8 = 2):
|
|
35
|
+
super(AccessSelector, self).__init__(value)
|
|
36
|
+
if int(self) not in (1, 2):
|
|
37
|
+
raise ValueError(F'The {self.__class__.__name__} got {int(self)}, expected 1..2')
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class RangeDescriptorValueChoice(CommonDataTypeChoiceBase, types=(
|
|
41
|
+
cdt.DoubleLong,
|
|
42
|
+
cdt.DoubleLongUnsigned,
|
|
43
|
+
cdt.OctetString,
|
|
44
|
+
cdt.VisibleString,
|
|
45
|
+
cdt.Utf8String,
|
|
46
|
+
cdt.Integer,
|
|
47
|
+
cdt.Unsigned,
|
|
48
|
+
cdt.LongUnsigned,
|
|
49
|
+
cdt.Long,
|
|
50
|
+
cdt.Long64Unsigned,
|
|
51
|
+
cdt.Float32,
|
|
52
|
+
cdt.Float64,
|
|
53
|
+
cdt.DateTime,
|
|
54
|
+
cdt.Date,
|
|
55
|
+
cdt.Time
|
|
56
|
+
)):
|
|
57
|
+
"""Types of range_descriptor.from_value/to_value"""
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# class RangeDescriptor(cdt.Structure):
|
|
61
|
+
# restricting_object: structs.CaptureObjectDefinition
|
|
62
|
+
# from_value: RangeDescriptorValueChoice
|
|
63
|
+
# to_value: RangeDescriptorValueChoice
|
|
64
|
+
# selected_values: CaptureObjects
|
|
65
|
+
#
|
|
66
|
+
# def __setattr__(self, key, value):
|
|
67
|
+
# """Allow setting from_value and to_value with a CommonDataType of allowed types.
|
|
68
|
+
# Other attributes remain immutable as per base Structure behavior."""
|
|
69
|
+
# if key in ("from_value", "to_value"):
|
|
70
|
+
# index = 1 if key == "from_value" else 2
|
|
71
|
+
# # Accept only CommonDataType instances of allowed types
|
|
72
|
+
# if isinstance(value, cdt.CommonDataType):
|
|
73
|
+
# # Build allowed types tuple from Choice definition
|
|
74
|
+
# allowed_types = tuple(el.TYPE if isinstance(el, ut.SequenceElement) else None for el in RangeDescriptorValueChoice.ELEMENTS.values())
|
|
75
|
+
# allowed_types = tuple(t for t in allowed_types if t is not None)
|
|
76
|
+
# if isinstance(value, allowed_types):
|
|
77
|
+
# self.values[index] = value
|
|
78
|
+
# return
|
|
79
|
+
# else:
|
|
80
|
+
# raise ValueError(F"Type got {value.__class__.__name__}, expected one of: "
|
|
81
|
+
# + ", ".join(t.__name__ for t in allowed_types))
|
|
82
|
+
# else:
|
|
83
|
+
# raise TypeError(F"Unsupported value type for {key}: {value.__class__.__name__}. Provide a CommonDataType instance.")
|
|
84
|
+
# else:
|
|
85
|
+
# super().__setattr__(key, value)
|
|
86
|
+
#
|
|
87
|
+
#
|
|
88
|
+
# class Data(ut.Data):
|
|
89
|
+
# restricting_object: structs.CaptureObjectDefinition
|
|
90
|
+
# from_value: cdt.SimpleDataType
|
|
91
|
+
# to_value: cdt.SimpleDataType
|
|
92
|
+
# selected_values: CaptureObjects
|
|
93
|
+
# from_entry: FromEntry
|
|
94
|
+
# to_entry: cdt.DoubleLongUnsigned
|
|
95
|
+
# from_selected_value: cdt.LongUnsigned
|
|
96
|
+
# to_selected_value: cdt.LongUnsigned
|
|
97
|
+
# ELEMENTS = {1: ut.SequenceElement('range_descriptor', RangeDescriptor),
|
|
98
|
+
# 2: ut.SequenceElement('entry_descriptor', EntryDescriptor)}
|
|
99
|
+
#
|
|
100
|
+
#
|
|
101
|
+
# class SelectiveAccessDescriptor(ut.SelectiveAccessDescriptor):
|
|
102
|
+
# access_selector: AccessSelector
|
|
103
|
+
# access_parameters: Data
|
|
104
|
+
# ELEMENTS = (ut.SequenceElement('access_selector', AccessSelector),
|
|
105
|
+
# ut.SequenceElement('access_parameters', Data))
|
|
106
|
+
#
|
|
107
|
+
#
|
|
108
|
+
# class CosemAttributeDescriptorWithSelection(ut.CosemAttributeDescriptorWithSelection):
|
|
109
|
+
# access_selection: SelectiveAccessDescriptor
|
|
110
|
+
# ELEMENTS = (ut.SequenceElement('cosem_attribute_descriptor', ut.CosemAttributeDescriptor),
|
|
111
|
+
# ut.SequenceElement('access_selection', SelectiveAccessDescriptor))
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class ProfileGeneric(ver0.ProfileGeneric):
|
|
115
|
+
"""4.3.6 Profile generic"""
|
|
116
|
+
VERSION = VERSION_1
|
|
117
|
+
A_ELEMENTS = (ic.ICAElement("buffer", arrays.SelectionAccess, classifier=ic.Classifier.DYNAMIC),
|
|
118
|
+
ic.ICAElement("capture_objects", CaptureObjects),
|
|
119
|
+
ver0.ProfileGeneric.get_attr_element(4),
|
|
120
|
+
ver0.ProfileGeneric.get_attr_element(5),
|
|
121
|
+
ic.ICAElement("sort_object", structs.CaptureObjectDefinition),
|
|
122
|
+
ic.ICAElement("entries_in_use", cdt.DoubleLongUnsigned, 0, default=0, classifier=ic.Classifier.DYNAMIC),
|
|
123
|
+
ic.ICAElement("profile_entries", cdt.DoubleLongUnsigned, 1, default=1))
|
|
124
|
+
M_ELEMENTS = (
|
|
125
|
+
ver0.ProfileGeneric.get_meth_element(1),
|
|
126
|
+
ver0.ProfileGeneric.get_meth_element(2)
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
def characteristics_init(self):
|
|
130
|
+
self.set_attr(ver0.BUFFER, None)
|
|
131
|
+
|
|
132
|
+
# todo remove it
|
|
133
|
+
self.buffer.register_cb_preset(lambda _: self.__create_buffer_struct_type()) # value not used for creating struct type
|
|
134
|
+
|
|
135
|
+
self._cbs_attr_post_init.update({ver0.CAPTURE_OBJECTS: self.__create_buffer_struct_type,
|
|
136
|
+
ver0.SORT_OBJECT: self.__create_selective_access_descriptor})
|
|
137
|
+
|
|
138
|
+
self.buffer_capture_objects = self.capture_objects
|
|
139
|
+
""" objects for buffer. Change with access_selection """
|
|
140
|
+
|
|
141
|
+
@property
|
|
142
|
+
def buffer(self) -> arrays.SelectionAccess:
|
|
143
|
+
return self.get_attr(2)
|
|
144
|
+
|
|
145
|
+
@property
|
|
146
|
+
def capture_objects(self) -> CaptureObjects:
|
|
147
|
+
return self.get_attr(3)
|
|
148
|
+
|
|
149
|
+
@property
|
|
150
|
+
def sort_object(self) -> structs.CaptureObjectDefinition:
|
|
151
|
+
return self.get_attr(6)
|
|
152
|
+
|
|
153
|
+
def get_attr_descriptor(self,
|
|
154
|
+
value: int,
|
|
155
|
+
with_selection: bool = False) -> ut.CosemAttributeDescriptor | ut.CosemAttributeDescriptorWithSelection:
|
|
156
|
+
""" with selection for object_list. TODO: Copypast AssociationLN"""
|
|
157
|
+
descriptor: ut.CosemAttributeDescriptor = super(ProfileGeneric, self).get_attr_descriptor(value)
|
|
158
|
+
if value == ver0.BUFFER and with_selection:
|
|
159
|
+
if self.attr_descriptor_with_selection is None:
|
|
160
|
+
self.__create_selective_access_descriptor()
|
|
161
|
+
return self.attr_descriptor_with_selection((descriptor.contents, self.buffer.selective_access.contents))
|
|
162
|
+
else:
|
|
163
|
+
return descriptor
|
|
164
|
+
|
|
165
|
+
def __create_buffer_struct_type(self):
|
|
166
|
+
""" TODO: more refactoring !!! """
|
|
167
|
+
# rename CaptureObjectDefinition's and adding object if it absense in collection
|
|
168
|
+
if self.buffer.selective_access is None:
|
|
169
|
+
self.__create_selective_access_descriptor()
|
|
170
|
+
if self.capture_objects is None:
|
|
171
|
+
raise ValueError(F"{self}: create buffer Struct type, not set <capture_object> attribute. Need initiate <capture_objects> before")
|
|
172
|
+
for el_value in self.capture_objects:
|
|
173
|
+
el_value: structs.CaptureObjectDefinition
|
|
174
|
+
obj = self.collection.add_if_missing(class_id=ut.CosemClassId(el_value.class_id.contents),
|
|
175
|
+
version=None,
|
|
176
|
+
logical_name=el_value.logical_name)
|
|
177
|
+
el_value.set_name(self.collection.get_name_and_type(el_value)[0][-1])
|
|
178
|
+
match self.buffer.selective_access:
|
|
179
|
+
case ut.SelectiveAccessDescriptor() as desc:
|
|
180
|
+
match int(desc.access_selector):
|
|
181
|
+
# case 0: self.buffer_capture_objects = self.capture_objects
|
|
182
|
+
case 1 if len(desc.access_parameters.selected_values) == 0: self.buffer_capture_objects = self.capture_objects
|
|
183
|
+
case 1: self.buffer_capture_objects = desc.access_parameters.selected_values
|
|
184
|
+
case 2:
|
|
185
|
+
from_selected_value = int(desc.access_parameters.from_selected_value)-1
|
|
186
|
+
to_selected_value = int(desc.access_parameters.to_selected_value)
|
|
187
|
+
if to_selected_value == 0:
|
|
188
|
+
to_selected_value = len(self.capture_objects)
|
|
189
|
+
self.buffer_capture_objects = self.capture_objects[from_selected_value:to_selected_value]
|
|
190
|
+
case _ as err: raise ValueError(F'access_selection out of range, got {err}, must be (0..2)')
|
|
191
|
+
case None:
|
|
192
|
+
self.clear_attr(ver0.CAPTURE_OBJECTS)
|
|
193
|
+
self._cbs_attr_post_init[ver0.CAPTURE_OBJECTS] = self.__create_buffer_struct_type
|
|
194
|
+
raise exc.EmptyObj(F"need set <sort_object> before for {self}")
|
|
195
|
+
buffer_elements: list[cdt.StructElement] = list()
|
|
196
|
+
for el_value in self.buffer_capture_objects:
|
|
197
|
+
names, type_ = self.collection.get_name_and_type(el_value)
|
|
198
|
+
buffer_elements.append(cdt.StructElement(NAME=". ".join(names), TYPE=type_))
|
|
199
|
+
|
|
200
|
+
class Entry(cdt.Structure):
|
|
201
|
+
"""4.3.6 Profile generic: entry"""
|
|
202
|
+
ELEMENTS = tuple(buffer_elements)
|
|
203
|
+
|
|
204
|
+
self.buffer.set_type(Entry)
|
|
205
|
+
|
|
206
|
+
def __create_selective_access_descriptor(self):
|
|
207
|
+
""" Available after got sort object. TODO: need rewrite. maybe replace to collection level. Wrong used sort_obj, it can be any element from capture_objects"""
|
|
208
|
+
if self.sort_object is None:
|
|
209
|
+
raise exc.EmptyObj(F"<sort object> is empty")
|
|
210
|
+
sort_obj: ic.COSEMInterfaceClasses = self.collection.get_object(self.sort_object.logical_name)
|
|
211
|
+
if sort_obj.CLASS_ID.contents == self.sort_object.class_id.contents:
|
|
212
|
+
value_type: Type[cdt.CommonDataType] = sort_obj.get_attr_data_type(int(self.sort_object.attribute_index))
|
|
213
|
+
else:
|
|
214
|
+
exc.NoObject(F"got {self.sort_object.class_id=}, expected {sort_obj.CLASS_ID=} from collection")
|
|
215
|
+
|
|
216
|
+
class RangeDescriptor(cdt.Structure):
|
|
217
|
+
# cb_preset = TODO: make check 'selected_values' from self.capture_objects or
|
|
218
|
+
# cb_post_set = TODO: make check 'selected_values' from self.capture_objects
|
|
219
|
+
DEFAULT = b'\x02\x04\x02\x04\x12\x00\x01\x09\x06\x00\x00\x01\x00\x00\xff\x0f\x02\x12\x00\x00\x09\x0c\x07\xe4\x01\x01\xff\xff\xff\xff\xff\x80\x00\xff' \
|
|
220
|
+
b'\x09\x0c\x07\xe4\x01\x02\xff\xff\xff\xff\xff\x80\x00\xff\x01\x00'
|
|
221
|
+
restricting_object: structs.CaptureObjectDefinition
|
|
222
|
+
from_value: value_type
|
|
223
|
+
to_value: value_type
|
|
224
|
+
selected_values: CaptureObjects
|
|
225
|
+
|
|
226
|
+
class Data(ut.Data):
|
|
227
|
+
restricting_object: structs.CaptureObjectDefinition
|
|
228
|
+
from_value: cdt.SimpleDataType
|
|
229
|
+
to_value: cdt.SimpleDataType
|
|
230
|
+
selected_values: CaptureObjects
|
|
231
|
+
from_entry: FromEntry
|
|
232
|
+
to_entry: cdt.DoubleLongUnsigned
|
|
233
|
+
from_selected_value: cdt.LongUnsigned
|
|
234
|
+
to_selected_value: cdt.LongUnsigned
|
|
235
|
+
ELEMENTS = {1: ut.SequenceElement('range_descriptor', RangeDescriptor),
|
|
236
|
+
2: ut.SequenceElement('entry_descriptor', EntryDescriptor)}
|
|
237
|
+
|
|
238
|
+
class SelectiveAccessDescriptor(ut.SelectiveAccessDescriptor):
|
|
239
|
+
access_selector: AccessSelector
|
|
240
|
+
access_parameters: Data
|
|
241
|
+
ELEMENTS = (ut.SequenceElement('access_selector', AccessSelector),
|
|
242
|
+
ut.SequenceElement('access_parameters', Data))
|
|
243
|
+
|
|
244
|
+
class CosemAttributeDescriptorWithSelection(ut.CosemAttributeDescriptorWithSelection):
|
|
245
|
+
access_selection: SelectiveAccessDescriptor
|
|
246
|
+
ELEMENTS = (ut.SequenceElement('cosem_attribute_descriptor', ut.CosemAttributeDescriptor),
|
|
247
|
+
ut.SequenceElement('access_selection', SelectiveAccessDescriptor))
|
|
248
|
+
|
|
249
|
+
self.attr_descriptor_with_selection = CosemAttributeDescriptorWithSelection
|
|
250
|
+
self.buffer.selective_access = SelectiveAccessDescriptor()
|
|
251
|
+
|
|
252
|
+
def get_capture_object_names(self) -> list[str]:
|
|
253
|
+
""" return all capture object names from collection """
|
|
254
|
+
if self.capture_objects is None:
|
|
255
|
+
raise ValueError(F'{self}: Empty capture objects')
|
|
256
|
+
else:
|
|
257
|
+
definition: structs.CaptureObjectDefinition
|
|
258
|
+
ret = list()
|
|
259
|
+
for definition in self.capture_objects:
|
|
260
|
+
ret.append(get_name(definition.logical_name))
|
|
261
|
+
return ret
|
|
262
|
+
|
|
263
|
+
def get_buffer_objects(self) -> list[cosem_interface_classes.cosem_interface_class.COSEMInterfaceClasses]:
|
|
264
|
+
""" get objects of current buffer container """
|
|
265
|
+
return [self.collection.get(obj_def.logical_name.contents) for obj_def in self.buffer_capture_objects]
|
|
266
|
+
|
|
267
|
+
# todo remove it
|
|
268
|
+
def get_index_with_attributes(self, in_init_order: bool = False) -> Iterator[tuple[int, cdt.CommonDataType | None]]:
|
|
269
|
+
""" override common method """
|
|
270
|
+
return iter(((1, self.logical_name),
|
|
271
|
+
(6, self.sort_object),
|
|
272
|
+
(3, self.capture_objects),
|
|
273
|
+
(2, self.buffer),
|
|
274
|
+
(4, self.capture_period),
|
|
275
|
+
(5, self.sort_method),
|
|
276
|
+
(7, self.entries_in_use),
|
|
277
|
+
(8, self.profile_entries)))
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
from ..__class_init__ import *
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class PushSetup(ic.COSEMInterfaceClasses):
|
|
5
|
-
"""dummy class"""
|
|
6
|
-
CLASS_ID = ClassID.PUSH_SETUP
|
|
7
|
-
|
|
8
|
-
def __new__(cls, *args, **kwargs):
|
|
9
|
-
raise ValueError(F"version: {__name__[-1]} of {cls.__class__.__name__} not support framework")
|
|
10
|
-
|
|
11
|
-
def characteristics_init(self):
|
|
12
|
-
""" initiate all attributes and methods of class """
|
|
1
|
+
from ..__class_init__ import *
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class PushSetup(ic.COSEMInterfaceClasses):
|
|
5
|
+
"""dummy class"""
|
|
6
|
+
CLASS_ID = ClassID.PUSH_SETUP
|
|
7
|
+
|
|
8
|
+
def __new__(cls, *args, **kwargs):
|
|
9
|
+
raise ValueError(F"version: {__name__[-1]} of {cls.__class__.__name__} not support framework")
|
|
10
|
+
|
|
11
|
+
def characteristics_init(self):
|
|
12
|
+
""" initiate all attributes and methods of class """
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
from ..__class_init__ import *
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class PushSetup(ic.COSEMInterfaceClasses):
|
|
5
|
-
"""dummy class"""
|
|
6
|
-
def __new__(cls, *args, **kwargs):
|
|
7
|
-
raise ValueError(F"version: {__name__[-1]} of {cls.__class__.__name__} not support framework")
|
|
8
|
-
|
|
9
|
-
def characteristics_init(self):
|
|
10
|
-
""" initiate all attributes and methods of class """
|
|
1
|
+
from ..__class_init__ import *
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class PushSetup(ic.COSEMInterfaceClasses):
|
|
5
|
+
"""dummy class"""
|
|
6
|
+
def __new__(cls, *args, **kwargs):
|
|
7
|
+
raise ValueError(F"version: {__name__[-1]} of {cls.__class__.__name__} not support framework")
|
|
8
|
+
|
|
9
|
+
def characteristics_init(self):
|
|
10
|
+
""" initiate all attributes and methods of class """
|