forked from FreeOpcUa/python-opcua
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtests_custom_structures_optional_fields.py
More file actions
107 lines (93 loc) · 4.2 KB
/
Copy pathtests_custom_structures_optional_fields.py
File metadata and controls
107 lines (93 loc) · 4.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
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
import inspect
import sys
import unittest
from datetime import datetime
from enum import EnumMeta
from opcua import ua
from opcua.common.structures import StructGenerator, Struct, EnumType
from opcua.ua.ua_binary import struct_to_binary, struct_from_binary
# An ExtensionObject that is decoded becomes a generated class of a custom name.
# The class below represents an example that includes OPC UA optional fields.
class ObjectWithOptionalFields(object):
ua_switches = {
'cavityId': ('BitEncoding0', 0),
'description': ('BitEncoding0', 1),
# This exists in xml but gets ignored because no matching switches.
# 'Reserved1': ('ByteEncoding0', 2)
}
ua_types = [
# The bits fields are not necessary because 'ua_switches' provides us with
# the related bit we care about.
# ('cavityIdSpecified', 'Bit'),
# ('descriptionSpecified', 'Bit'),
# ('Reserved1', 'Bit'),
('BitEncoding0', 'UInt32'),
('name', 'CharArray'),
('value', 'Double'),
('assignment', 'UInt32'),
('source', 'UInt32'),
('cavityId', 'UInt32'),
('id', 'CharArray'),
('description', 'CharArray'),
]
def __str__(self):
vals = [name + ": " + str(val) for name, val in self.__dict__.items()]
return self.__class__.__name__ + "(" + ", ".join(vals) + ")"
__repr__ = __str__
def __init__(self):
self.BitEncoding0 = 0x03
self.name = 'SomeAmazingCycleParameter'
self.value = 8
self.assignment = 8
self.source = 8
self.cavityId = 5
self.id = 'abcdefgh'
self.description = 'BBA'
class CustomStructTestCase(unittest.TestCase):
def setUp(self):
self.identifier_count = 0
def _generate_node_id(self):
self.identifier_count += 1
return f"ns=0;i={self.identifier_count}"
@staticmethod
def is_struct(obj):
# TODO: putting this definition in the generated class would be better
return hasattr(obj, 'ua_types')
def assertCustomStructEqual(self, original, deserialized):
if hasattr(original, 'ua_switches'):
self.assertEqual(len(original.ua_switches), len(deserialized.ua_switches))
self.assertEqual(len(original.ua_types), len(deserialized.ua_types))
for field, _ in original.ua_types:
field_obj = getattr(original, field)
deserialized_obj = getattr(deserialized, field)
if self.is_struct(field_obj):
self.assertCustomStructEqual(field_obj, deserialized_obj)
else:
self.assertEqual(getattr(original, field), getattr(deserialized, field))
def test_binary_struct_example(self):
# Example test so that we can manually control the object that gets
# generated and see how it gets serialized/deserialized
original = ObjectWithOptionalFields()
serialized = struct_to_binary(original)
deserialized = struct_from_binary(ObjectWithOptionalFields, ua.utils.Buffer(serialized))
self.assertEqual(len(original.ua_switches), len(deserialized.ua_switches))
self.assertEqual(len(original.ua_types), len(deserialized.ua_types))
for field, _ in original.ua_types:
self.assertEqual(getattr(original, field), getattr(deserialized, field))
def test_custom_struct_with_optional_fields(self):
xmlpath = "custom_extension_with_optional_fields.xml"
c = StructGenerator()
c.make_model_from_file(xmlpath)
for m in c.model:
if type(m) in (Struct, EnumType):
m.typeid = self._generate_node_id()
c.save_to_file("custom_extension_with_optional_fields.py", register=True)
import como_structures as s
for name, obj in inspect.getmembers(sys.modules[s.__name__], predicate=inspect.isclass):
if name.startswith('__') or obj in (datetime,) or isinstance(obj, EnumMeta):
continue
with self.subTest(name=name):
original = obj()
serialized = struct_to_binary(original)
deserialized = struct_from_binary(obj, ua.utils.Buffer(serialized))
self.assertCustomStructEqual(original, deserialized)