Commit f4a5dc52 authored by Christian Bergmiller's avatar Christian Bergmiller

cleanup

parent 053cf74f
import os
os.environ['PYOPCUA_NO_TYPO_CHECK'] = 'True'
import asyncio
import logging
from opcua import Client, Node, ua
logging.basicConfig(level=logging.INFO)
......
import os
#os.environ['PYOPCUA_NO_TYPO_CHECK'] = 'True'
import asyncio
import logging
from opcua import Client, Node, ua
logging.basicConfig(level=logging.INFO)
_logger = logging.getLogger('opcua')
async def browse_nodes(node: Node):
"""
Build a nested node tree dict by recursion (filtered by OPC UA objects and variables).
......@@ -28,7 +23,7 @@ async def browse_nodes(node: Node):
try:
var_type = (await node.get_data_type_as_variant_type()).value
except ua.UaError:
_logger.warning('Node Variable Type coudl not be determined for %r', node)
_logger.warning('Node Variable Type could not be determined for %r', node)
var_type = None
return {
'id': node.nodeid.to_string(),
......@@ -40,9 +35,9 @@ async def browse_nodes(node: Node):
async def task(loop):
# url = 'opc.tcp://192.168.2.213:4840'
url = 'opc.tcp://192.168.2.213:4840'
# url = 'opc.tcp://localhost:4840/freeopcua/server/'
url = 'opc.tcp://commsvr.com:51234/UA/CAS_UA_Server'
# url = 'opc.tcp://commsvr.com:51234/UA/CAS_UA_Server'
try:
async with Client(url=url) as client:
# Client has a few methods to get proxy to UA nodes that should always be in address space such as Root or Objects
......
......@@ -77,6 +77,7 @@ class Client(object):
"""
Find endpoint with required security mode and policy URI
"""
_logger.info('find_endpoint %r %r %r', endpoints, security_mode, policy_uri)
for ep in endpoints:
if (ep.EndpointUrl.startswith(ua.OPC_TCP_SCHEME) and
ep.SecurityMode == security_mode and
......@@ -527,6 +528,7 @@ class Client(object):
def import_xml(self, path=None, xmlstring=None):
"""
Import nodes defined in xml
COROUTINE
"""
importer = XmlImporter(self)
return importer.import_xml(path, xmlstring)
......
......@@ -247,6 +247,7 @@ class Node:
attributeid is a member of ua.AttributeIds
datavalue is a ua.DataValue object
"""
_logger.info('Node set_attribute %r %r %r', self, attributeid, datavalue)
attr = ua.WriteValue()
attr.NodeId = self.nodeid
attr.AttributeId = attributeid
......@@ -619,7 +620,7 @@ class Node:
results = await self.server.add_references(params)
_check_results(results, len(params))
def set_modelling_rule(self, mandatory):
async def set_modelling_rule(self, mandatory):
"""
Add a modelling rule reference to Node.
When creating a new object type, its variable and child nodes will not
......
......@@ -26,14 +26,14 @@ class XmlImporter(object):
self.aliases = {}
self.refs = None
def _map_namespaces(self, namespaces_uris):
async def _map_namespaces(self, namespaces_uris):
"""
creates a mapping between the namespaces in the xml file and in the server.
if not present the namespace is registered.
"""
namespaces = {}
for ns_index, ns_uri in enumerate(namespaces_uris):
ns_server_index = self.server.register_namespace(ns_uri)
ns_server_index = await self.server.register_namespace(ns_uri)
namespaces[ns_index + 1] = ns_server_index
return namespaces
......@@ -46,14 +46,14 @@ class XmlImporter(object):
aliases_mapped[alias] = self.to_nodeid(node_id)
return aliases_mapped
def import_xml(self, xmlpath=None, xmlstring=None):
async def import_xml(self, xmlpath=None, xmlstring=None):
"""
import xml and return added nodes
"""
self.logger.info("Importing XML file %s", xmlpath)
self.parser = xmlparser.XMLParser(xmlpath, xmlstring)
self.namespaces = self._map_namespaces(self.parser.get_used_namespaces())
self.namespaces = await self._map_namespaces(self.parser.get_used_namespaces())
self.aliases = self._map_aliases(self.parser.get_aliases())
self.refs = []
......@@ -64,49 +64,50 @@ class XmlImporter(object):
nodes = []
for nodedata in nodes_parsed: # self.parser:
try:
node = self._add_node_data(nodedata)
node = await self._add_node_data(nodedata)
except Exception:
self.logger.warning("failure adding node %s", nodedata)
raise
nodes.append(node)
self.refs, remaining_refs = [], self.refs
self._add_references(remaining_refs)
await self._add_references(remaining_refs)
if len(self.refs) != 0:
self.logger.warning("The following references could not be imported and are probaly broken: %s", self.refs)
return nodes
def _add_node_data(self, nodedata):
async def _add_node_data(self, nodedata):
if nodedata.nodetype == 'UAObject':
node = self.add_object(nodedata)
node = await self.add_object(nodedata)
elif nodedata.nodetype == 'UAObjectType':
node = self.add_object_type(nodedata)
node = await self.add_object_type(nodedata)
elif nodedata.nodetype == 'UAVariable':
node = self.add_variable(nodedata)
node = await self.add_variable(nodedata)
elif nodedata.nodetype == 'UAVariableType':
node = self.add_variable_type(nodedata)
node = await self.add_variable_type(nodedata)
elif nodedata.nodetype == 'UAReferenceType':
node = self.add_reference_type(nodedata)
node = await self.add_reference_type(nodedata)
elif nodedata.nodetype == 'UADataType':
node = self.add_datatype(nodedata)
node = await self.add_datatype(nodedata)
elif nodedata.nodetype == 'UAMethod':
node = self.add_method(nodedata)
node = await self.add_method(nodedata)
else:
self.logger.warning("Not implemented node type: %s ", nodedata.nodetype)
raise ValueError(f"Not implemented node type: {nodedata.nodetype} ")
return node
def _add_node(self, node):
"""COROUTINE"""
if isinstance(self.server, opcua.server.server.Server):
return self.server.iserver.isession.add_nodes([node])
else:
return self.server.uaclient.add_nodes([node])
def _add_references(self, refs):
async def _add_references(self, refs):
if isinstance(self.server, opcua.server.server.Server):
res = self.server.iserver.isession.add_references(refs)
res = await self.server.iserver.isession.add_references(refs)
else:
res = self.server.uaclient.add_references(refs)
res = await self.server.uaclient.add_references(refs)
for sc, ref in zip(res, refs):
if not sc.is_good():
......@@ -170,7 +171,7 @@ class XmlImporter(object):
def to_nodeid(self, nodeid):
return self._migrate_ns(self._to_nodeid(nodeid))
def add_object(self, obj):
async def add_object(self, obj):
node = self._get_node(obj)
attrs = ua.ObjectAttributes()
if obj.desc:
......@@ -178,12 +179,12 @@ class XmlImporter(object):
attrs.DisplayName = ua.LocalizedText(obj.displayname)
attrs.EventNotifier = obj.eventnotifier
node.NodeAttributes = attrs
res = self._add_node(node)
self._add_refs(obj)
res = await self._add_node(node)
await self._add_refs(obj)
res[0].StatusCode.check()
return res[0].AddedNodeId
def add_object_type(self, obj):
async def add_object_type(self, obj):
node = self._get_node(obj)
attrs = ua.ObjectTypeAttributes()
if obj.desc:
......@@ -191,12 +192,12 @@ class XmlImporter(object):
attrs.DisplayName = ua.LocalizedText(obj.displayname)
attrs.IsAbstract = obj.abstract
node.NodeAttributes = attrs
res = self._add_node(node)
self._add_refs(obj)
res = await self._add_node(node)
await self._add_refs(obj)
res[0].StatusCode.check()
return res[0].AddedNodeId
def add_variable(self, obj):
async def add_variable(self, obj):
node = self._get_node(obj)
attrs = ua.VariableAttributes()
if obj.desc:
......@@ -216,14 +217,14 @@ class XmlImporter(object):
if obj.dimensions:
attrs.ArrayDimensions = obj.dimensions
node.NodeAttributes = attrs
res = self._add_node(node)
self._add_refs(obj)
res = await self._add_node(node)
await self._add_refs(obj)
res[0].StatusCode.check()
return res[0].AddedNodeId
def _get_ext_class(self, name):
if hasattr(ua, name):
return getattr(ua, name)
return getattr(ua, name)
elif name in self.aliases.keys():
nodeid = self.aliases[name]
class_type = ua.uatypes.get_extensionobject_class_type(nodeid)
......@@ -319,7 +320,7 @@ class XmlImporter(object):
else:
return ua.Variant(obj.value, getattr(ua.VariantType, obj.valuetype))
def add_variable_type(self, obj):
async def add_variable_type(self, obj):
node = self._get_node(obj)
attrs = ua.VariableTypeAttributes()
if obj.desc:
......@@ -336,11 +337,11 @@ class XmlImporter(object):
attrs.ArrayDimensions = obj.dimensions
node.NodeAttributes = attrs
res = self._add_node(node)
self._add_refs(obj)
await self._add_refs(obj)
res[0].StatusCode.check()
return res[0].AddedNodeId
def add_method(self, obj):
async def add_method(self, obj):
node = self._get_node(obj)
attrs = ua.MethodAttributes()
if obj.desc:
......@@ -355,12 +356,12 @@ class XmlImporter(object):
if obj.dimensions:
attrs.ArrayDimensions = obj.dimensions
node.NodeAttributes = attrs
res = self._add_node(node)
self._add_refs(obj)
res = await self._add_node(node)
await self._add_refs(obj)
res[0].StatusCode.check()
return res[0].AddedNodeId
def add_reference_type(self, obj):
async def add_reference_type(self, obj):
node = self._get_node(obj)
attrs = ua.ReferenceTypeAttributes()
if obj.desc:
......@@ -373,12 +374,12 @@ class XmlImporter(object):
if obj.symmetric:
attrs.Symmetric = obj.symmetric
node.NodeAttributes = attrs
res = self._add_node(node)
self._add_refs(obj)
res = await self._add_node(node)
await self._add_refs(obj)
res[0].StatusCode.check()
return res[0].AddedNodeId
def add_datatype(self, obj):
async def add_datatype(self, obj):
node = self._get_node(obj)
attrs = ua.DataTypeAttributes()
if obj.desc:
......@@ -387,12 +388,12 @@ class XmlImporter(object):
if obj.abstract:
attrs.IsAbstract = obj.abstract
node.NodeAttributes = attrs
res = self._add_node(node)
self._add_refs(obj)
res = await self._add_node(node)
await self._add_refs(obj)
res[0].StatusCode.check()
return res[0].AddedNodeId
def _add_refs(self, obj):
async def _add_refs(self, obj):
if not obj.refs:
return
refs = []
......@@ -404,7 +405,7 @@ class XmlImporter(object):
ref.TargetNodeClass = ua.NodeClass.DataType
ref.TargetNodeId = self.to_nodeid(data.target)
refs.append(ref)
self._add_references(refs)
await self._add_references(refs)
def _sort_nodes_by_parentid(self, ndatas):
"""
......
import pickle
import shelve
import asyncio
import logging
import collections
from threading import RLock
from datetime import datetime
from opcua import ua
from opcua.server.users import User
_logger = logging.getLogger(__name__)
class AttributeValue(object):
......
......@@ -91,13 +91,19 @@ class Server:
self.private_key = None
self._policies = []
self.nodes = Shortcuts(self.iserver.isession)
self._security_policy = ["Basic256_Sign", "Basic256_SignAndEncrypt"]
self._security_policy = [
ua.SecurityPolicyType.NoSecurity,
ua.SecurityPolicyType.Basic128Rsa15_SignAndEncrypt,
ua.SecurityPolicyType.Basic128Rsa15_Sign,
ua.SecurityPolicyType.Basic256_SignAndEncrypt,
ua.SecurityPolicyType.Basic256_Sign
]
self._policyIDs = ["Anonymous", "Basic256", "Basic128", "Username"]
async def init(self, shelf_file=None):
await self.iserver.init(shelf_file)
# setup some expected values
self.set_application_uri(self._application_uri)
await self.set_application_uri(self._application_uri)
sa_node = self.get_node(ua.NodeId(ua.ObjectIds.Server_ServerArray))
await sa_node.set_value([self._application_uri])
status_node = self.get_node(ua.NodeId(ua.ObjectIds.Server_ServerStatus))
......@@ -136,7 +142,7 @@ class Server:
"""
self.iserver.disabled_clock = val
def set_application_uri(self, uri):
async def set_application_uri(self, uri):
"""
Set application/server URI.
This uri is supposed to be unique. If you intent to register
......@@ -250,46 +256,51 @@ class Server:
async def _setup_server_nodes(self):
# to be called just before starting server since it needs all parameters to be setup
if "None" in self._security_policy:
if ua.SecurityPolicyType.NoSecurity in self._security_policy:
self._set_endpoints()
self._policies = [ua.SecurityPolicyFactory()]
if (len(self._security_policy) > 1) and self.private_key:
if self._security_policy != [ua.SecurityPolicyType.NoSecurity]:
if not (self.certificate and self.private_key):
self.logger.warning("Endpoints other than open requested but private key and certificate are not set.")
return
if ua.SecurityPolicyType.NoSecurity in self._security_policy:
self.logger.warning(
"Creating an open endpoint to the server, although encrypted endpoints are enabled.")
if self.certificate and self.private_key:
if "Basic128Rsa15_SignAndEncrypt" in self._security_policy:
if ua.SecurityPolicyType.Basic128Rsa15_SignAndEncrypt in self._security_policy:
self._set_endpoints(security_policies.SecurityPolicyBasic128Rsa15,
ua.MessageSecurityMode.SignAndEncrypt)
ua.MessageSecurityMode.SignAndEncrypt)
self._policies.append(ua.SecurityPolicyFactory(security_policies.SecurityPolicyBasic128Rsa15,
ua.MessageSecurityMode.SignAndEncrypt,
self.certificate,
self.private_key)
)
if "Basic128Rsa15_Sign" in self._security_policy:
ua.MessageSecurityMode.SignAndEncrypt,
self.certificate,
self.private_key)
)
if ua.SecurityPolicyType.Basic128Rsa15_Sign in self._security_policy:
self._set_endpoints(security_policies.SecurityPolicyBasic128Rsa15,
ua.MessageSecurityMode.Sign)
ua.MessageSecurityMode.Sign)
self._policies.append(ua.SecurityPolicyFactory(security_policies.SecurityPolicyBasic128Rsa15,
ua.MessageSecurityMode.Sign,
self.certificate,
self.private_key)
)
if "Basic256_SignAndEncrypt" in self._security_policy:
ua.MessageSecurityMode.Sign,
self.certificate,
self.private_key)
)
if ua.SecurityPolicyType.Basic256_SignAndEncrypt in self._security_policy:
self._set_endpoints(security_policies.SecurityPolicyBasic256,
ua.MessageSecurityMode.SignAndEncrypt)
ua.MessageSecurityMode.SignAndEncrypt)
self._policies.append(ua.SecurityPolicyFactory(security_policies.SecurityPolicyBasic256,
ua.MessageSecurityMode.SignAndEncrypt,
self.certificate,
self.private_key)
)
if "Basic256_Sign" in self._security_policy:
ua.MessageSecurityMode.SignAndEncrypt,
self.certificate,
self.private_key)
)
if ua.SecurityPolicyType.Basic256_Sign in self._security_policy:
self._set_endpoints(security_policies.SecurityPolicyBasic256,
ua.MessageSecurityMode.Sign)
ua.MessageSecurityMode.Sign)
self._policies.append(ua.SecurityPolicyFactory(security_policies.SecurityPolicyBasic256,
ua.MessageSecurityMode.Sign,
self.certificate,
self.private_key)
)
ua.MessageSecurityMode.Sign,
self.certificate,
self.private_key)
)
def _set_endpoints(self, policy=ua.SecurityPolicy, mode=ua.MessageSecurityMode.None_):
idtokens = []
......@@ -503,12 +514,12 @@ class Server:
await custom_t.add_method(idx, method[0], method[1], method[2], method[3])
return custom_t
def import_xml(self, path=None, xmlstring=None):
async def import_xml(self, path=None, xmlstring=None):
"""
Import nodes defined in xml
"""
importer = XmlImporter(self)
return importer.import_xml(path, xmlstring)
return await importer.import_xml(path, xmlstring)
def export_xml(self, nodes, path):
"""
......
......@@ -468,7 +468,7 @@ def uaclient():
sys.exit(0)
def uaserver():
async def uaserver():
parser = argparse.ArgumentParser(description="Run an example OPC-UA server. By importing xml definition and using uawrite command line, it is even possible to expose real data using this server")
# we setup a server, this is a bit different from other tool so we do not reuse common arguments
parser.add_argument("-u",
......@@ -506,15 +506,16 @@ def uaserver():
logging.basicConfig(format="%(levelname)s: %(message)s", level=getattr(logging, args.loglevel))
server = Server()
await server.init()
server.set_endpoint(args.url)
if args.certificate:
server.load_certificate(args.certificate)
await server.load_certificate(args.certificate)
if args.private_key:
server.load_private_key(args.private_key)
await server.load_private_key(args.private_key)
server.disable_clock(args.disable_clock)
server.set_server_name("FreeOpcUa Example Server")
if args.xml:
server.import_xml(args.xml)
await server.import_xml(args.xml)
if args.populate:
@uamethod
def multiply(parent, x, y):
......@@ -522,7 +523,7 @@ def uaserver():
return x * y
uri = "http://examples.freeopcua.github.io"
idx = server.register_namespace(uri)
idx = await server.register_namespace(uri)
objects = server.get_objects_node()
myobj = objects.add_object(idx, "MyObject")
mywritablevar = myobj.add_variable(idx, "MyWritableVariable", 6.7)
......@@ -532,7 +533,7 @@ def uaserver():
myprop = myobj.add_property(idx, "MyProperty", "I am a property")
mymethod = myobj.add_method(idx, "MyMethod", multiply, [ua.VariantType.Double, ua.VariantType.Int64], [ua.VariantType.Double])
server.start()
await server.start()
try:
if args.shell:
embed()
......@@ -547,7 +548,7 @@ def uaserver():
while True:
time.sleep(1)
finally:
server.stop()
await server.stop()
sys.exit(0)
......
......@@ -6,15 +6,14 @@ from opcua import Client
from opcua import Server
from opcua import ua
from .tests_subscriptions import SubscriptionTests
from .tests_common import CommonTests, add_server_methods
from .tests_xml import XmlTests
from .tests_common import add_server_methods
from .tests_enum_struct import add_server_custom_enum_struct
port_num1 = 48510
_logger = logging.getLogger(__name__)
pytestmark = pytest.mark.asyncio
@pytest.fixture()
async def admin_client():
# start admin client
......
......@@ -47,7 +47,7 @@ async def discovery_server():
# start our own server
srv = Server()
await srv.init()
srv.set_application_uri('urn:freeopcua:python:discovery')
await srv.set_application_uri('urn:freeopcua:python:discovery')
srv.set_endpoint(f'opc.tcp://127.0.0.1:{port_discovery}')
await srv.start()
yield srv
......
......@@ -35,7 +35,7 @@ class ExampleStruct(uatypes.FrozenClass):
async def add_server_custom_enum_struct(server: Server):
# import some nodes from xml
server.import_xml("tests/enum_struct_test_nodes.xml")
await server.import_xml("tests/enum_struct_test_nodes.xml")
ns = await server.get_namespace_index('http://yourorganisation.org/struct_enum_example/')
uatypes.register_extension_object('ExampleStruct', ua.NodeId(5001, ns), ExampleStruct)
val = ua.ExampleStruct()
......
......@@ -2,10 +2,14 @@
import sys
import os
import asyncio
import logging
logging.basicConfig(level=logging.DEBUG)
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
from opcua.tools import uaserver
if __name__ == "__main__":
uaserver()
loop = asyncio.get_event_loop()
loop.run_until_complete(uaserver())
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