Commit ac15d133 authored by Olivier R-D's avatar Olivier R-D

add high level namespace api, set server namespace array

parent ef58b9d6
......@@ -214,6 +214,15 @@ class Client(object):
params.Priority = 0
return Subscription(self.bclient, params, handler)
def get_namespace_array(self):
ns_node = self.get_node(ua.NodeId(ua.ObjectIds.Server_NamespaceArray))
return ns_node.get_value()
def get_namespace_index(self, uri):
uries = self.get_namespace_array()
return uries.index(uri)
......@@ -46,6 +46,9 @@ class InternalServer(object):
self._stopev = False
self._timer = None
self.current_time_node = Node(self.isession, ua.NodeId(ua.ObjectIds.Server_ServerStatus_CurrentTime))
uries = ["http://opcfoundation.org/UA/"]
ns_node = Node(self.isession, ua.NodeId(ua.ObjectIds.Server_NamespaceArray))
ns_node.set_value(uries)
def start(self):
self.logger.info("starting internal server")
......
......@@ -7,8 +7,8 @@ import opcua.uaprotocol as ua
class Node(object):
"""
High level node object, to access node attribute
and browse address space
High level node object, to access node attribute,
browse and populate address space
"""
def __init__(self, server, nodeid):
self.server = server
......@@ -28,19 +28,27 @@ class Node(object):
return "Node({})".format(self.nodeid)
__repr__ = __str__
def get_name(self):
def get_browse_name(self):
result = self.get_attribute(ua.AttributeIds.BrowseName)
return result.Value
def get_value(self):
result = self.get_attribute(ua.AttributeIds.Value)
def get_display_name(self):
result = self.get_attribute(ua.AttributeIds.DisplayName)
return result.Value
def _value(self):
def get_value(self):
"""
Get value of a node. Only variables(properties) have values.
An exception will be generated for other node types.
"""
result = self.get_attribute(ua.AttributeIds.Value)
return result.Value
def set_value(self, value, varianttype=None):
"""
Set value of a node. Only variables(properties) have values.
An exception will be generated for other node types.
"""
variant = None
if type(value) == ua.Variant:
variant = value
......@@ -49,6 +57,9 @@ class Node(object):
self.set_attribute(ua.AttributeIds.Value, ua.DataValue(variant))
def set_attribute(self, attributeid, datavalue):
"""
Set an attribute of a node
"""
attr = ua.WriteValue()
attr.NodeId = self.nodeid
attr.AttributeId = attributeid
......@@ -59,6 +70,9 @@ class Node(object):
result[0].check()
def get_attribute(self, attr):
"""
Get an attribute of a node
"""
rv = ua.ReadValueId()
rv.NodeId = self.nodeid
rv.AttributeId = attr
......@@ -68,10 +82,31 @@ class Node(object):
result[0].StatusCode.check()
return result[0].Value
def get_children(self):
def get_children(self, refs=ua.ObjectIds.HierarchicalReferences):
"""
Get all children of a node. By default hierarchical references are returnes.
Other types may be given:
References = 31
NonHierarchicalReferences = 32
HierarchicalReferences = 33
HasChild = 34
Organizes = 35
HasEventSource = 36
HasModellingRule = 37
HasEncoding = 38
HasDescription = 39
HasTypeDefinition = 40
GeneratesEvent = 41
Aggregates = 44
HasSubtype = 45
HasProperty = 46
HasComponent = 47
HasNotifier = 48
HasOrderedComponent = 49
"""
desc = ua.BrowseDescription()
desc.BrowseDirection = ua.BrowseDirection.Forward
desc.ReferenceTypeId = ua.TwoByteNodeId(ua.ObjectIds.References)
desc.ReferenceTypeId = ua.TwoByteNodeId(refs)
desc.IncludeSubtypes = True
desc.NodeClassMask = ua.NodeClass.Unspecified
desc.ResultMask = ua.BrowseResultMask.None_
......@@ -87,6 +122,14 @@ class Node(object):
return nodes
def get_child(self, path):
"""
get a child specified by its path from this node.
A path might be:
* a string representing a qualified name.
* a qualified name
* a list of string
* a list of qualified names
"""
if type(path) not in (list, tuple):
path = [path]
rpath = ua.RelativePath()
......@@ -138,6 +181,8 @@ class Node(object):
def add_object(self, *args):
"""
create a child node object
arguments are nodeid, browsename
or namespace index, name
"""
nodeid, qname = self._parse_add_args(*args)
return self._add_object(nodeid, qname)
......@@ -210,7 +255,36 @@ class Node(object):
results = self.server.add_nodes([node])
results[0].StatusCode.check()
return Node(self.server, nodeid)
def add_method(self, *args):
"""
create a child method object
"""
nodeid, qname = self._parse_add_args(*args)
return self._add_object(nodeid, qname)
def _add_method(self, nodeid, qname):
node = ua.AddNodesItem()
node.RequestedNewNodeId = nodeid
node.BrowseName = qname
node.NodeClass = ua.NodeClass.Object
node.ParentNodeId = self.nodeid
node.ReferenceTypeId = ua.NodeId.from_string("i=35")
node.TypeDefinition = ua.NodeId(ua.ObjectIds.BaseObjectType)
attrs = ua.MethodAttributes()
attrs.Description = ua.LocalizedText(qname.Name)
attrs.DisplayName = ua.LocalizedText(qname.Name)
attrs.WriteMask = 0
attrs.UserWriteMask = 0
self.Executable = True
self.UserExecutable = True
node.NodeAttributes = attrs
results = self.server.add_nodes([node])
results[0].StatusCode.check()
return Node(self.server, nodeid)
def _vtype_to_uatype(self, vtype):
return eval("ua.NodeId(ua.ObjectIds.{})".format(vtype.name))
......
......@@ -30,8 +30,14 @@ class Server(object):
def set_endpoint(self, url):
self.endpoint = urlparse(url)
def _set_endpoints(self):
def _setup_server_nodes(self):
#to be called just before starting server since it needs all parameters to be setup
self._set_endpoints()
self.register_namespace(self.server_uri)
sa_node = self.get_node(ua.NodeId(ua.ObjectIds.Server_ServerArray))
sa_node.set_value([self.server_uri])
def _set_endpoints(self):
idtoken = ua.UserTokenPolicy()
idtoken.PolicyId = 'anonymous'
idtoken.TokenType = ua.UserTokenType.Anonymous
......@@ -58,7 +64,7 @@ class Server(object):
def start(self):
self.iserver.start()
self._set_endpoints()
self._setup_server_nodes()
self.bserver = BinaryServer(self.iserver, self.endpoint.hostname, self.endpoint.port)
self.bserver.start()
......@@ -94,6 +100,21 @@ class Server(object):
params.Priority = 0
return Subscription(self.iserver.isession, params, handler)
def get_namespace_array(self):
ns_node = self.get_node(ua.NodeId(ua.ObjectIds.Server_NamespaceArray))
return ns_node.get_value()
def register_namespace(self, uri):
ns_node = self.get_node(ua.NodeId(ua.ObjectIds.Server_NamespaceArray))
uries = ns_node.get_value()
uries.append(uri)
ns_node.set_value(uries)
return (len(uries)-1)
def get_namespace_index(self, uri):
uries = self.get_namespace_array()
return uries.index(uri)
......
......@@ -185,13 +185,13 @@ class CommonTests(object):
def test_root(self):
root = self.opc.get_root_node()
self.assertEqual(ua.QualifiedName('Root', 0), root.get_name())
self.assertEqual(ua.QualifiedName('Root', 0), root.get_browse_name())
nid = ua.NodeId(84, 0)
self.assertEqual(nid, root.nodeid)
def test_objects(self):
objects = self.opc.get_objects_node()
self.assertEqual(ua.QualifiedName('Objects', 0), objects.get_name())
self.assertEqual(ua.QualifiedName('Objects', 0), objects.get_browse_name())
nid = ua.NodeId(85, 0)
self.assertEqual(nid, objects.nodeid)
......@@ -242,13 +242,13 @@ class CommonTests(object):
#sub.delete()
#def test_get_NamespaceIndex(self):
#idx = self.opc.get_NamespaceIndex('http://freeua.github.io')
#def test_get_browse_namespaceIndex(self):
#idx = self.opc.get_browse_namespaceIndex('http://freeua.github.io')
#self.assertEqual(idx, 1)
#def test_use_namespace(self):
#root = self.opc.get_root_node()
#idx = self.opc.get_NamespaceIndex('http://freeua.github.io')
#idx = self.opc.get_browse_namespaceIndex('http://freeua.github.io')
#o = root.add_object(idx, 'test_namespace')
#self.assertEqual(idx, o.nodeid.NamespaceIndex)
#o2 = root.get_child('{}:test_namespace'.format(idx))
......@@ -286,7 +286,7 @@ class CommonTests(object):
nid = ua.NodeId(888, 3)
qn = ua.QualifiedName('numericnodefromstring', 3)
self.assertEqual(nid, v.nodeid)
self.assertEqual(qn, v.get_name())
self.assertEqual(qn, v.get_browse_name())
def test_add_string_variable(self):
objects = self.opc.get_objects_node()
......@@ -294,7 +294,7 @@ class CommonTests(object):
nid = ua.NodeId('stringid', 3)
qn = ua.QualifiedName('stringnodefromstring', 3)
self.assertEqual(nid, v.nodeid)
self.assertEqual(qn, v.get_name())
self.assertEqual(qn, v.get_browse_name())
def test_add_string_array_variable(self):
objects = self.opc.get_objects_node()
......@@ -302,7 +302,7 @@ class CommonTests(object):
nid = ua.NodeId('stringarrayid', 3)
qn = ua.QualifiedName('stringarray', 9)
self.assertEqual(nid, v.nodeid)
self.assertEqual(qn, v.get_name())
self.assertEqual(qn, v.get_browse_name())
val = v.get_value()
self.assertEqual(['l', 'b'], val)
......@@ -312,7 +312,7 @@ class CommonTests(object):
qn = ua.QualifiedName('AddNodeVar1', 3)
v1 = objects.add_variable(nid, qn, 0)
self.assertEqual(nid, v1.nodeid)
self.assertEqual(qn, v1.get_name())
self.assertEqual(qn, v1.get_browse_name())
def test_add_string_node(self):
objects = self.opc.get_objects_node()
......@@ -320,7 +320,7 @@ class CommonTests(object):
nid = ua.NodeId('AddNodeVar2Id', 3)
v2 = objects.add_variable(nid, qn, 0)
self.assertEqual(nid, v2.nodeid)
self.assertEqual(qn, v2.get_name())
self.assertEqual(qn, v2.get_browse_name())
def test_add_find_node_(self):
objects = self.opc.get_objects_node()
......@@ -341,7 +341,7 @@ class CommonTests(object):
nid = ua.NodeId(102, 2)
self.assertEqual(o.nodeid, nid)
qn = ua.QualifiedName('AddReadObject', 2)
self.assertEqual(o.get_name(), qn)
self.assertEqual(o.get_browse_name(), qn)
def test_simple_value(self):
o = self.opc.get_objects_node()
......@@ -438,6 +438,13 @@ class CommonTests(object):
sub.unsubscribe(handle)
sub.delete()
def test_use_namespace(self):
idx = self.opc.get_namespace_index("urn:freeopcua:python:server")
self.assertEqual(idx, 1)
root = self.opc.get_root_node()
myvar = root.add_variable(idx, 'var_in_custom_namespace', [5])
myid = myvar.nodeid
self.assertEqual(idx, myid.NamespaceIndex)
......@@ -501,7 +508,7 @@ class TestClient(unittest.TestCase, CommonTests):
# new one before this one is really stopped
self.srv.join()
"""
class TestServer(unittest.TestCase, CommonTests):
'''
......@@ -527,11 +534,11 @@ class TestServer(unittest.TestCase, CommonTests):
self.assertTrue(v in childs)
self.assertTrue(p in childs)
'''
def test_register_namespace(self):
uri = 'http://mycustom.Namespace.com'
idx1 = self.opc.register_namespace(uri)
idx2 = self.opc.get_NamespaceIndex(uri)
idx2 = self.opc.get_namespace_index(uri)
self.assertEqual(idx1, idx2)
def test_register_use_namespace(self):
......@@ -541,9 +548,8 @@ class TestServer(unittest.TestCase, CommonTests):
myvar = root.add_variable(idx, 'var_in_custom_namespace', [5])
myid = myvar.nodeid
self.assertEqual(idx, myid.NamespaceIndex)
#self.assertEqual(uri, myid.Namespace_uri) #FIXME: should return uri!!!
'''
"""
......
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