Commit 5436c28c authored by oroulet's avatar oroulet Committed by oroulet

add DataTypeDefition when importing xml DataTypes

parent be2fe807
......@@ -152,11 +152,19 @@ class Node:
async def read_data_type_definition(self):
"""
get node class attribute of node
read data type definition attribute of node
only DataType nodes following spec >= 1.04 have that atttribute
"""
result = await self.read_attribute(ua.AttributeIds.DataTypeDefinition)
return result.Value.Value
async def write_data_type_definition(self, sdef: ua.DataTypeDefinition):
"""
write data type definition attribute of node
only DataType nodes following spec >= 1.04 have that atttribute
"""
v = ua.Variant(sdef, ua.VariantType.ExtensionObject)
await self.write_attribute(ua.AttributeIds.DataTypeDefinition, ua.DataValue(v))
async def read_description(self):
"""
......
......@@ -88,17 +88,14 @@ class XmlImporter:
raise ValueError(f"Not implemented node type: {nodedata.nodetype} ")
return node
async def _add_node(self, node: "Node") -> Coroutine:
def _get_server(self):
if hasattr(self.server, "iserver"):
return await self.server.iserver.isession.add_nodes([node])
return self.server.iserver.isession
else:
return await self.server.uaclient.add_nodes([node])
return self.server.uaclient
async def _add_references(self, refs):
if hasattr(self.server, "iserver"):
res = await self.server.iserver.isession.add_references(refs)
else:
res = await self.server.uaclient.add_references(refs)
res = await self._get_server().add_references(refs)
for sc, ref in zip(res, refs):
if not sc.is_good():
......@@ -171,7 +168,7 @@ class XmlImporter:
attrs.DisplayName = ua.LocalizedText(obj.displayname)
attrs.EventNotifier = obj.eventnotifier
node.NodeAttributes = attrs
res = await self._add_node(node)
res = await self._get_server().add_nodes([node])
await self._add_refs(obj)
res[0].StatusCode.check()
return res[0].AddedNodeId
......@@ -184,7 +181,7 @@ class XmlImporter:
attrs.DisplayName = ua.LocalizedText(obj.displayname)
attrs.IsAbstract = obj.abstract
node.NodeAttributes = attrs
res = await self._add_node(node)
res = await self._get_server().add_nodes([node])
await self._add_refs(obj)
res[0].StatusCode.check()
return res[0].AddedNodeId
......@@ -209,7 +206,7 @@ class XmlImporter:
if obj.dimensions:
attrs.ArrayDimensions = obj.dimensions
node.NodeAttributes = attrs
res = await self._add_node(node)
res = await self._get_server().add_nodes([node])
await self._add_refs(obj)
res[0].StatusCode.check()
return res[0].AddedNodeId
......@@ -332,7 +329,7 @@ class XmlImporter:
if obj.dimensions:
attrs.ArrayDimensions = obj.dimensions
node.NodeAttributes = attrs
res = await self._add_node(node)
res = await self._get_server().add_nodes([node])
await self._add_refs(obj)
res[0].StatusCode.check()
return res[0].AddedNodeId
......@@ -352,7 +349,7 @@ class XmlImporter:
if obj.dimensions:
attrs.ArrayDimensions = obj.dimensions
node.NodeAttributes = attrs
res = await self._add_node(node)
res = await self._get_server().add_nodes([node])
await self._add_refs(obj)
res[0].StatusCode.check()
return res[0].AddedNodeId
......@@ -370,7 +367,7 @@ class XmlImporter:
if obj.symmetric:
attrs.Symmetric = obj.symmetric
node.NodeAttributes = attrs
res = await self._add_node(node)
res = await self._get_server().add_nodes([node])
await self._add_refs(obj)
res[0].StatusCode.check()
return res[0].AddedNodeId
......@@ -383,10 +380,11 @@ class XmlImporter:
attrs.DisplayName = ua.LocalizedText(obj.displayname)
if obj.abstract:
attrs.IsAbstract = obj.abstract
attrs.DataTypeDefinition = self._get_sdef(node, obj)
node.NodeAttributes = attrs
res = await self._add_node(node)
await self._add_refs(obj)
res = await self._get_server().add_nodes([node])
res[0].StatusCode.check()
await self._add_refs(obj)
return res[0].AddedNodeId
async def _add_refs(self, obj):
......@@ -402,6 +400,28 @@ class XmlImporter:
refs.append(ref)
await self._add_references(refs)
def _get_sdef(self, node, obj):
if not obj.definitions:
return None
sdef = ua.StructureDefinition()
if obj.parent:
sdef.BaseDataType = self.to_nodeid(obj.parent)
sdef.StructureType = ua.StructureType.Structure
for data in obj.refs:
if data.reftype == "HasEncoding":
# looks likebinary encodingisthe firt one...can someone confirm?
sdef.DefaultEncodingId = self.to_nodeid(data.target)
break
for field in obj.definitions:
f = ua.StructureField()
f.Name = field.name
f.DataType = self.to_nodeid(field.datatype)
f.ValueRank = field.valuerank
f.IsOptional = field.optional
f.ArrayDimensions = field.arraydim
sdef.Fields.append(f)
return sdef
def _sort_nodes_by_parentid(self, ndatas):
"""
Sort the list of nodes according their parent node in order to respect
......
......@@ -60,13 +60,20 @@ class NodeData:
self.symmetric = False
# datatype
self.definition = []
self.definitions = []
def __str__(self):
return f"NodeData(nodeid:{self.nodeid})"
__repr__ = __str__
class Field:
def __init__(self, data):
self.datatype = data.get("DataType")
self.name = data.get("Name")
self.optional = bool(data.get("IsOptional", False))
self.valuerank = int(data.get("ValueRank", -1))
self.arraydim = data.get("ArrayDimensions", None) #FIXME: check type
class RefStruct:
......@@ -75,6 +82,10 @@ class RefStruct:
self.forward = True
self.target = None
def __str__(self):
return f"RefStruct({self.reftype, self.forward, self.target})"
__repr__ = __str__
class ExtObj:
......@@ -213,10 +224,14 @@ class XMLParser:
obj.inversename = el.text
elif tag == "Definition":
for field in el:
obj.definition.append(field)
field = self._parse_field(field)
obj.definitions.append(field)
else:
self.logger.info("Not implemented tag: %s", el)
def _parse_field(self, field):
return Field(field)
def _parse_contained_value(self, el, obj):
"""
Parse the child of el as a constant.
......@@ -302,7 +317,7 @@ class XMLParser:
for name, val in mylist:
item.update({str(name): val})
# value is an array of dictionaries with localized texts
value.append(item)
value.append(item)
return value
def _parse_list_of_extension_object(self, el):
......@@ -365,4 +380,5 @@ class XMLParser:
obj.parentlink = "HasComponent"
if not obj.parent:
obj.parent, obj.parentlink = parent, parentlink
if not obj.parent:
self.logger.info("Could not find parent for node '%s'", obj.nodeid)
......@@ -392,7 +392,7 @@ class NodeManagementService:
rdesc.BrowseName = bname
dname = self._aspace.read_attribute_value(addref.TargetNodeId, ua.AttributeIds.DisplayName).Value.Value
if dname:
rdesc.DisplayUser = dname
rdesc.DisplayName = dname
return self._add_unique_reference(sourcedata, rdesc)
def delete_references(self, refs, user=User(role=UserRole.Admin)):
......@@ -458,6 +458,7 @@ class NodeManagementService:
self._add_node_attr(item, nodedata, "ValueRank", ua.VariantType.Int32)
self._add_node_attr(item, nodedata, "WriteMask", ua.VariantType.UInt32)
self._add_node_attr(item, nodedata, "UserWriteMask", ua.VariantType.UInt32)
self._add_node_attr(item, nodedata, "DataTypeDefinition", ua.VariantType.ExtensionObject)
self._add_node_attr(item, nodedata, "Value", add_timestamps=add_timestamps)
......
......@@ -337,7 +337,10 @@ class ReferenceTypeAttributes(auto.ReferenceTypeAttributes):
class DataTypeAttributes(auto.DataTypeAttributes):
def __init__(self):
auto.DataTypeAttributes.__init__(self)
self.SpecifiedAttributes = ana.DisplayName | ana.Description | ana.WriteMask | ana.UserWriteMask | ana.IsAbstract
self.SpecifiedAttributes = ana.DisplayName | ana.Description | ana.WriteMask | ana.UserWriteMask | ana.IsAbstract | ana.DataTypeDefinition
self._freeze = False
self.DataTypeDefinition = auto.ExtensionObject()
self._freeze = True
class ViewAttributes(auto.ViewAttributes):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment