Commit 962ab91c authored by Andrew's avatar Andrew Committed by ORD

Improve instantiate when parent has string node id + small fixes (#342)

* Improve instantiate when parent has string node id

* Make String node id instantiation more clear

* Fix string to value for boolean

Can't use bool(string); will always return true
Make string to UA ints more readable

* Ignore XML Extensions tag

Other modelers make this XML element which contains a model and hash
from the generation tool

* Add test for instaniate with String NodeIds

* Handle import of Null values
parent 466e159e
...@@ -72,6 +72,11 @@ def _instantiate_node(server, parentid, rdesc, nodeid, bname, recursive=True): ...@@ -72,6 +72,11 @@ def _instantiate_node(server, parentid, rdesc, nodeid, bname, recursive=True):
for c_rdesc in descs: for c_rdesc in descs:
# skip items that already exists, prefer the 'lowest' one in object hierarchy # skip items that already exists, prefer the 'lowest' one in object hierarchy
if not ua_utils.is_child_present(node, c_rdesc.BrowseName): if not ua_utils.is_child_present(node, c_rdesc.BrowseName):
# if root node being instantiated has a String NodeId, create the children with a String NodeId
if res.AddedNodeId.NodeIdType is ua.NodeIdType.String:
inst_nodeid = res.AddedNodeId.Identifier + "." + c_rdesc.BrowseName.Name
nodeids = _instantiate_node(server, res.AddedNodeId, c_rdesc, nodeid=ua.NodeId(identifier=inst_nodeid, namespaceidx=res.AddedNodeId.NamespaceIndex), bname=c_rdesc.BrowseName)
else:
nodeids = _instantiate_node(server, res.AddedNodeId, c_rdesc, nodeid=ua.NodeId(namespaceidx=res.AddedNodeId.NamespaceIndex), bname=c_rdesc.BrowseName) nodeids = _instantiate_node(server, res.AddedNodeId, c_rdesc, nodeid=ua.NodeId(namespaceidx=res.AddedNodeId.NamespaceIndex), bname=c_rdesc.BrowseName)
added_nodes.extend(nodeids) added_nodes.extend(nodeids)
......
...@@ -74,8 +74,13 @@ def string_to_val(string, vtype): ...@@ -74,8 +74,13 @@ def string_to_val(string, vtype):
if vtype == ua.VariantType.Null: if vtype == ua.VariantType.Null:
val = None val = None
elif vtype == ua.VariantType.Boolean: elif vtype == ua.VariantType.Boolean:
val = bool(string) if string in ("True", "true", "on", "On", "1"):
elif 4 <= vtype.value < 9: val = True
else:
val = False
elif vtype in (ua.VariantType.Int16, ua.VariantType.Int32, ua.VariantType.Int64):
val = int(string)
elif vtype in (ua.VariantType.UInt16, ua.VariantType.UInt32, ua.VariantType.UInt64):
val = int(string) val = int(string)
elif vtype in (ua.VariantType.Float, ua.VariantType.Double): elif vtype in (ua.VariantType.Float, ua.VariantType.Double):
val = float(string) val = float(string)
......
...@@ -136,7 +136,7 @@ class XMLParser(object): ...@@ -136,7 +136,7 @@ class XMLParser(object):
nodes = [] nodes = []
for child in self.root: for child in self.root:
tag = self._retag.match(child.tag).groups()[1] tag = self._retag.match(child.tag).groups()[1]
if tag not in ["Aliases", "NamespaceUris"]: if tag not in ["Aliases", "NamespaceUris", "Extensions"]: # these XML tags don't contain nodes
node = self._parse_node(tag, child) node = self._parse_node(tag, child)
nodes.append(node) nodes.append(node)
return nodes return nodes
...@@ -208,7 +208,10 @@ class XMLParser(object): ...@@ -208,7 +208,10 @@ class XMLParser(object):
def _parse_value(self, val_el, obj): def _parse_value(self, val_el, obj):
child_el = val_el.find(".//") # should be only one child child_el = val_el.find(".//") # should be only one child
if child_el is not None:
ntag = self._retag.match(child_el.tag).groups()[1] ntag = self._retag.match(child_el.tag).groups()[1]
else:
ntag = "Null"
obj.valuetype = ntag obj.valuetype = ntag
if ntag in ("Int8", "UInt8", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64"): if ntag in ("Int8", "UInt8", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64"):
...@@ -242,6 +245,8 @@ class XMLParser(object): ...@@ -242,6 +245,8 @@ class XMLParser(object):
obj.value = self._parse_list(child_el) obj.value = self._parse_list(child_el)
elif ntag == "ExtensionObject": elif ntag == "ExtensionObject":
obj.value = self._parse_ext_obj(child_el) obj.value = self._parse_ext_obj(child_el)
elif ntag == "Null":
obj.value = None
else: else:
self.logger.warning("Parsing value of type '%s' not implemented", ntag) self.logger.warning("Parsing value of type '%s' not implemented", ntag)
......
...@@ -609,6 +609,27 @@ class CommonTests(object): ...@@ -609,6 +609,27 @@ class CommonTests(object):
var_parent = mydevicederived.get_child(["0:sensor"]) var_parent = mydevicederived.get_child(["0:sensor"])
prop_parent = mydevicederived.get_child(["0:sensor_id"]) prop_parent = mydevicederived.get_child(["0:sensor_id"])
def test_instantiate_string_nodeid(self):
# Create device type
dev_t = self.opc.nodes.base_object_type.add_object_type(0, "MyDevice2")
v_t = dev_t.add_variable(0, "sensor", 1.0)
p_t = dev_t.add_property(0, "sensor_id", "0340")
ctrl_t = dev_t.add_object(0, "controller")
prop_t = ctrl_t.add_property(0, "state", "Running")
# instanciate device
nodes = instantiate(self.opc.nodes.objects, dev_t, nodeid=ua.NodeId("InstDevice", 2, ua.NodeIdType.String), bname="2:InstDevice")
mydevice = nodes[0]
self.assertEqual(mydevice.get_node_class(), ua.NodeClass.Object)
self.assertEqual(mydevice.get_type_definition(), dev_t.nodeid)
obj = mydevice.get_child(["0:controller"])
obj_nodeid_ident = obj.nodeid.Identifier
prop = mydevice.get_child(["0:controller", "0:state"])
self.assertEqual(obj_nodeid_ident, "InstDevice.controller")
self.assertEqual(prop.get_type_definition().Identifier, ua.ObjectIds.PropertyType)
self.assertEqual(prop.get_value(), "Running")
self.assertNotEqual(prop.nodeid, prop_t.nodeid)
def test_variable_with_datatype(self): def test_variable_with_datatype(self):
v1 = self.opc.nodes.objects.add_variable(3, 'VariableEnumType1', ua.ApplicationType.ClientAndServer, datatype=ua.NodeId(ua.ObjectIds.ApplicationType)) v1 = self.opc.nodes.objects.add_variable(3, 'VariableEnumType1', ua.ApplicationType.ClientAndServer, datatype=ua.NodeId(ua.ObjectIds.ApplicationType))
......
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