def connect(): global client cs = ClientSettings("myClient", [server_address]) # Uncomment below for session logging # cs.logToStdOutLevel = loglevels.Info max_attempts = 40 num_attempts = 0 while (True): print "Trying to connect to the OPC UA Server. Attempt #" + str( num_attempts) result = None try: client = Client(cs) rootNode = Address(NodeId(opcuaidentifiers.OpcUaId_RootFolder, 0), server_uri) result = client.browse([rootNode]) except Exception as e: print "Got exception: " + str(e) num_attempts = num_attempts + 1 if num_attempts > max_attempts: msg = 'Despite ' + str( max_attempts ) + ' attempts couldnt establish OPC UA connection: exception is ' + str( e) print msg dcs_test_utils.log_detail(False, msg, '') raise msg time.sleep(3) continue print 'Connected to OPC UA Server' return
def connect(endpoint, server_uri): client_settings = ClientSettings("pnikiel:dump", [endpoint]) client = Client(client_settings) connectionId = client.manuallyConnect(server_uri) sessionInfo = client.sessionInformation(connectionId) if sessionInfo.sessionState != pyuaf.client.sessionstates.Connected: raise Exception('Couldnt connect! TODO: reason') print 'Connected to ' + endpoint return (client, connectionId)
clientSettings.defaultWriteSettings.callTimeoutSec = 2.0 clientSettings.defaultBrowseSettings.callTimeoutSec = 2.0 # and so on, and so on ... # NOTE: for clientSettings, you may also configure SessionSettings for specific servers: clientSettings.specificSessionSettings[ "My/Unreliable/Device/Server/URI"] = SessionSettings() clientSettings.specificSessionSettings[ "My/Unreliable/Device/Server/URI"].sessionTimeoutSec = 200.0 clientSettings.specificSessionSettings[ "My/Unreliable/Device/Server/URI"].connectTimeoutSec = 5.0 # If the client connects to the server with ServerUri = "My/Unreliable/Device/Server/URI", # then it will use these settings instead of the defaultSessionSettings! # Now you can simply create a client that uses these settings: myClient = Client(clientSettings) # or alternatively: # myClient = Client() # myClient.setClientSettings(clientSettings) # let's read 2 nodes: address0 = Address(NodeId("Demo.SimulationSpeed", NAMESPACE_URI), SERVER_URI) address1 = Address(NodeId("Demo.SimulationActive", NAMESPACE_URI), SERVER_URI) # the next line will result in # - a session being created, with the defaultSessionSettings which we configured before # - the Read service being invoked, with the defaultReadSettings we configured before myClient.read([address0, address1]) # when the next line is executed, then: # - the session we created before will be reused (as we're requesting a session with the
logDetailsString = "" logDetailsString += time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime(msg.ctime)) logDetailsString += ".%.3d " % msg.msec logDetailsString += "%-10s " % msg.applicationName logDetailsString += "%-20s " % msg.loggerName logDetailsString += "%-8s " % loglevels.toString(msg.level) # msg.message may contain multiple lines, so we prepend the other logging details in # front of each line: for line in msg.message.splitlines(): f.write("%s: %s\n" % (logDetailsString, line)) # Example 0: create a client with the default settings and no logging callback # -------------------------------------------------------------------------------------------------- client0 = Client() # Example 1: create a client by specifying the settings # -------------------------------------------------------------------------------------------------- client1 = Client(settings) # Example 2: create a client by specifying the settings # -------------------------------------------------------------------------------------------------- client2 = Client(settings, callback) # Example 3: create a client by specifying only the logging callback # -------------------------------------------------------------------------------------------------- client3 = Client(loggingCallback=callback) # you can still provide settings and register a logging callback afterwards, but you'll need to use: # client0.setClientSettings(settings)
demoNsUri = "http://www.unifiedautomation.com/DemoServer" demoServerUri = "urn:UnifiedAutomation:UaServerCpp" # define some addresses which will be used later on address_Server = Address( NodeId(opcuaidentifiers.OpcUaId_Server , 0), demoServerUri ) address_Dynamic = Address( NodeId("Demo.DynamicNodes" , demoNsUri), demoServerUri ) address_Create = Address( NodeId("Demo.DynamicNodes.CreateDynamicNode", demoNsUri), demoServerUri ) address_Delete = Address( NodeId("Demo.DynamicNodes.DeleteDynamicNode", demoNsUri), demoServerUri ) # define the ClientSettings: settings = ClientSettings() settings.applicationName = "MyClient" settings.discoveryUrls.append("opc.tcp://localhost:48010") # create the client myClient = Client(settings) # define the event filter to only receive the GeneralModelChangeEventType events eventFilter = EventFilter() eventFilter.selectClauses.resize(1) eventFilter.selectClauses[0].attributeId = pyuaf.util.attributeids.Value eventFilter.selectClauses[0].browsePath.append(QualifiedName("Changes", 0)) eventFilter.selectClauses[0].typeId = NodeId(opcuaidentifiers.OpcUaId_GeneralModelChangeEventType, 0) # define a callback function to handle the events def myCallback(notification): print("Notification received!") changes = notification.fields[0] print("Changes:") for i in range(len(changes)): change = changes[i]
from pyuaf.util import primitives from pyuaf.util import opcuaidentifiers, attributeids, opcuatypes, structurefielddatatypes from pyuaf.util.errors import UafError # define the namespace URI and server URI of the UaServerCPP demo server demoServerUri = "urn:UnifiedAutomation:UaServerCpp" demoNamespaceUri = "urn:UnifiedAutomation:CppDemoServer:BuildingAutomation" # define the ClientSettings: settings = ClientSettings() settings.applicationName = "MyClient" settings.discoveryUrls.append("opc.tcp://localhost:48010") # create the client myClient = Client(settings) # define the address of the Structure which we would like to read units_address = Address( NodeId("AirConditioner_1.Temperature.EngineeringUnits", demoNamespaceUri), demoServerUri ) range_address = Address( NodeId("AirConditioner_1.Temperature.EURange", demoNamespaceUri), demoServerUri ) # try to read a structure result = myClient.read( [units_address, range_address] ) # we're expecting ExtensionObjects. Let's check this: for i in xrange(2): if isinstance(result.targets[i].data, ExtensionObject): print("We received an ExtensionObject") else: raise Exception("Oops, we were expecting an ExtensionObject, but we received a: %s" %result.targets[0].data)
settings.applicationName = "myClient" settings.logToStdOutLevel = loglevels.Debug settings.logToCallbackLevel = loglevels.Error # define the callback for the logging def myLoggingCallback(msg): print("************ CALLBACK SAYS: ************") if msg.level == loglevels.Error: print("Error message received: %s" % str(msg)) elif msg.level == loglevels.Warning: print("Warning message received: %s" % str(msg)) else: print("Info or debug message received: %s" % str(msg)) # create the client myClient = Client(settings, myLoggingCallback) # try to read the Value attribute of some non-existing node (so errors will be sent to the callback) try: nodeId = NodeId("NonExistingIdentifier", "NonExistingNameSpace") address = Address(nodeId, "NonExistingServerURI") myClient.read([address]) except pyuaf.util.errors.UafError, e: print("UAF error raised: %s" % e) # alternatively: myClient2 = Client() myClient2.registerLoggingCallback(myLoggingCallback) myClient2.setClientSettings(settings)
# examples/pyuaf/client/easiest_client_example.py # Start the demo server ($SDK/bin/uaservercpp) of Unified Automation before running this script! import pyuaf from pyuaf.util import Address, NodeId from pyuaf.client import Client from pyuaf.client.settings import ClientSettings # create a client named "myClient", and provide the discovery URL of the server (uaservercpp): myClient = Client(ClientSettings("myClient", ["opc.tcp://localhost:48010"])) # specify the address of the node of which we would like to read its Value attribute: # (here we're using an absolute address, i.e. a NodeId(<identifier>, <namespace URI>) and a <server URI>) someAddress = Address(NodeId("Demo.SimulationSpeed", # NodeId identifier "http://www.unifiedautomation.com/DemoServer"), # NodeId namespace URI "urn:UnifiedAutomation:UaServerCpp") # server URI # read the Value attribute of the node that we just addressed: result = myClient.read( [someAddress] ) print type(result.targets[0].data) print("The value is %d" %result.targets[0].data.value)
# target 4: status = readResult.targets[4].status # 'status' has type pyuaf.util.Status data = readResult.targets[4].data # 'data' is a list of pyuaf.util.primitives.SByte if status.isGood() and isinstance(data, list): print("The array is:") for i in xrange(len(data)): print(" - array[%d] = %d" %(i, data[i].value)) # define the ClientSettings: settings = ClientSettings() settings.applicationName = "MyClient" settings.discoveryUrls.append("opc.tcp://localhost:48010") # create the client myClient = Client(settings) # read the node attributes all at once print("") print("First option: use the convenience function read() to read data synchronously") print("============================================================================") # OPTIONAL: You could also provide a ReadSettings to configure a call timeout, # or maximum age of the values, or ... serviceSettings = ReadSettings() serviceSettings.callTimeoutSec = 0.5 serviceSettings.maxAgeSec = 1.0 # OPTIONAL: And you could also provide a SessionConfig to configure the sessions
# target 4: status = readResult.targets[4].status # 'status' has type pyuaf.util.Status data = readResult.targets[4].data # 'data' is a list of pyuaf.util.primitives.SByte if status.isGood() and isinstance(data, list): print("The array is:") for i in xrange(len(data)): print(" - array[%d] = %d" %(i, data[i].value)) # define the ClientSettings: settings = ClientSettings() settings.applicationName = "MyClient" settings.discoveryUrls.append("opc.tcp://localhost:48010") # create the client myClient = Client(settings) # read the node attributes all at once print("") print("First option: use the convenience function read() to read data synchronously") print("============================================================================") # OPTIONAL: You could also provide a ReadConfig to configure a call timeout, # or maximum age of the values, or ... serviceConfig = ReadConfig() serviceConfig.serviceSettings.callTimeoutSec = 0.5 serviceConfig.serviceSettings.maxAgeSec = 1.0 # OPTIONAL: And you could also provide a SessionConfig to configure the sessions
import time, os, sys import pyuaf from pyuaf.client import Client from pyuaf.client.settings import ClientSettings from pyuaf.util import Address, NodeId from pyuaf.util.errors import UafError, ConnectionError # define the ClientSettings (note that we do NOT provide a discoveryUrl!!!): settings = ClientSettings() settings.applicationName = "MyClient" # settings.logToStdOutLevel = pyuaf.util.loglevels.Debug # uncomment to see the full UAF logging # create the client myClient = Client(settings) # Now manually connect to an endpoint of the demo server using 'manuallyConnectToEndpoint()'. # - The first argument (endpointUrl) is the URL of the endpoint you want to connect to # - The optional (!) second argument (sessionSettings) a SessionSettings instance. # If you don't provide one, then a default SessionSettings instance will be used. # A default SessionSettings instance has: # - no security policy (pyuaf.util.securitypolicies.UA_None) # - no security mode (pyuaf.util.messagesecuritymodes.Mode_None) # - no authentication (pyuaf.util.usertokentypes.Anonymous) try: print("") print("Now connecting") clientConnectionId = myClient.manuallyConnectToEndpoint( "opc.tcp://localhost:48010") except ConnectionError, e:
from pyuaf.util import GenericStructureValue, GenericStructureVector, GenericUnionValue from pyuaf.util import primitives from pyuaf.util import opcuaidentifiers, attributeids, opcuatypes, structurefielddatatypes from pyuaf.util.errors import UafError # define the namespace URI and server URI of the UaServerCPP demo server demoServerUri = "urn:UnifiedAutomation:UaServerCpp" demoNamespaceUri = "http://www.unifiedautomation.com/DemoServer/" # define the ClientSettings: settings = ClientSettings() settings.applicationName = "MyClient" settings.discoveryUrls.append("opc.tcp://localhost:48010") # create the client myClient = Client(settings) print( "#**************************************************************************************************#" ) print( "# #" ) print( "# 1) To understand a GenericStructureValue instance, let's define the function below to print one: #" ) print( "# #" ) print( "#**************************************************************************************************#"
from pyuaf.util import Address, NodeId, DataChangeFilter from pyuaf.client import Client from pyuaf.client.settings import ClientSettings, SubscriptionSettings, MonitoredItemSettings from pyuaf.client.requests import CreateMonitoredDataRequestTarget # define the namespace URI and server URI of the UaServerCPP demo server demoServerUri = "urn:UnifiedAutomation:UaServerCpp" demoNamespaceUri = "http://www.unifiedautomation.com/DemoServer/" # define the ClientSettings: settings = ClientSettings() settings.applicationName = "MyClient" settings.discoveryUrls.append("opc.tcp://localhost:48010") # create the client myClient = Client(settings) # 1) optionally: configure the subscription # ------------------------------------------ subSettings = SubscriptionSettings() subSettings.publishingIntervalSec = 1.0 subSettings.maxKeepAliveCount = 5 # Explanation: # - The subscription will send at most one bunch of changed data samples per second, due to the # publishing interval of 1 second. # - If the sampled data does not change, then the server does not have to send notifications to # the client. However, when the sampled data does not change for 5 seconds in a row # (5 seconds = maxKeepAliveCount * publishingIntervalSec), then the server # will send a KeepAlive notification to the client, as a kind of "heartbeat".
myStartingPoint = ExpandedNodeId( NodeId(OpcUaId_RootFolder, OPCUA_NAMESPACE_URI), demoServerUri ) myRelativePath = [ RelativePathElement(QualifiedName("Objects" , OPCUA_NAMESPACE_URI)), RelativePathElement(QualifiedName("Demo" , demoNsUri)), RelativePathElement(QualifiedName("BoilerDemo" , demoNsUri)), RelativePathElement(QualifiedName("Boiler1" , demoNsUri)), RelativePathElement(QualifiedName("HeaterStatus", demoNsUri)) ] myBrowsePath = BrowsePath(myStartingPoint, myRelativePath) # define the ClientSettings: settings = ClientSettings() settings.applicationName = "MyClient" settings.discoveryUrls.append("opc.tcp://localhost:48010") # settings.logToStdOutLevel = pyuaf.util.loglevels.Debug # uncomment for seeing debugging information # create the client myClient = Client(settings) # create a request with one target request = TranslateBrowsePathsToNodeIdsRequest(1) request.targets[0].browsePath = myBrowsePath # invoke the request try: result = myClient.processRequest(request) if result.overallStatus.isGood(): print("The browse path was translated into the following ExpandedNodeIds:") for expandedNodeId in result.targets[0].expandedNodeIds: print(" - %s" %expandedNodeId) print("")
from pyuaf.util.errors import UafError # define the namespace URI and server URI of the UaServerCPP demo server demoServerUri = "urn:UnifiedAutomation:UaServerCpp" # define the address of the Root node which we would like to start browsing rootNode = Address( NodeId(opcuaidentifiers.OpcUaId_RootFolder, 0), demoServerUri ) # define the ClientSettings: settings = ClientSettings() settings.applicationName = "MyClient" settings.discoveryUrls.append("opc.tcp://localhost:48010") # create the client myClient = Client(settings) try: print("") print("First option: use the convenience function \"browse()\"") print("===================================================") # now browse the root node # (notice that there is also an argument called 'maxAutoBrowseNext', which we don't mention # here because we can leave it at the default value (100), to make sure that BrowseNext is # automatically being called for us as much as needed!) # (notice too that you can optionally provide a BrowseConfig and a SessionConfig for # more detailed configuration) firstLevelBrowseResult = myClient.browse([rootNode])
# (demoAddress is an absolute address, all the others are relative ones) demoAddress = Address( NodeId("Demo", demoNsUri), demoServerUri ) simulationActiveAddress = Address( demoAddress, [RelativePathElement(QualifiedName("SimulationActive", demoNsUri))] ) startSimulationAddress = Address( demoAddress, [RelativePathElement(QualifiedName("StartSimulation" , demoNsUri))] ) historyAddress = Address( demoAddress, [RelativePathElement(QualifiedName("History", demoNsUri))] ) loggingActiveAddress = Address( historyAddress, [RelativePathElement(QualifiedName("DataLoggerActive", demoNsUri))] ) startLoggingAddress = Address( historyAddress, [RelativePathElement(QualifiedName("StartLogging", demoNsUri))] ) doubleAddress = Address( historyAddress, [RelativePathElement(QualifiedName("DoubleWithHistory", demoNsUri))] ) # define the ClientSettings: settings = ClientSettings() settings.applicationName = "MyClient" settings.discoveryUrls.append("opc.tcp://localhost:48010") # create the client myClient = Client(settings) # first, we need to start the simulation (if it's not already started), # and we need to start the logging (if it's not already started) res = myClient.read( [simulationActiveAddress,loggingActiveAddress] ) if not res.overallStatus.isGood(): raise Exception("Couldn't read some nodes of the server: is uaservercpp started and properly configured?") isSimulationActive = res.targets[0].data.value isLoggingActive = res.targets[1].data.value print("isSimulationActive : %s" %isSimulationActive) print("isLoggingActive : %s" %isLoggingActive) if not isSimulationActive:
def __init__(self, settings): Client.__init__(self, settings)
# same for the writeSettings, methodCallSettings, ... clientSettings.defaultMethodCallSettings.callTimeoutSec = 2.0 clientSettings.defaultWriteSettings.callTimeoutSec = 2.0 clientSettings.defaultBrowseSettings.callTimeoutSec = 2.0 # and so on, and so on ... # NOTE: for clientSettings, you may also configure SessionSettings for specific servers: clientSettings.specificSessionSettings["My/Unreliable/Device/Server/URI"] = SessionSettings() clientSettings.specificSessionSettings["My/Unreliable/Device/Server/URI"].sessionTimeoutSec = 200.0 clientSettings.specificSessionSettings["My/Unreliable/Device/Server/URI"].connectTimeoutSec = 5.0 # If the client connects to the server with ServerUri = "My/Unreliable/Device/Server/URI", # then it will use these settings instead of the defaultSessionSettings! # Now you can simply create a client that uses these settings: myClient = Client(clientSettings) # or alternatively: # myClient = Client() # myClient.setClientSettings(clientSettings) # let's read 2 nodes: address0 = Address(NodeId("Demo.SimulationSpeed" , NAMESPACE_URI), SERVER_URI) address1 = Address(NodeId("Demo.SimulationActive", NAMESPACE_URI), SERVER_URI) # the next line will result in # - a session being created, with the defaultSessionSettings which we configured before # - the Read service being invoked, with the defaultReadSettings we configured before myClient.read( [address0, address1] ) # when the next line is executed, then: # - the session we created before will be reused (as we're requesting a session with the
# When trying to interact with a third-party server (i.e. any server of which you don't know all details # from), you must dynamically discover some "details". # This example will show you how to connect and interact with such an "unknown" server. # # In general, what you *do* know is the IP address and port of the server. Together they are known as # the "discoveryURL". # You can provide a discovery URL like this: import pyuaf from pyuaf.util import Address, NodeId from pyuaf.util import opcuaidentifiers from pyuaf.client import Client from pyuaf.client.settings import ClientSettings # create a client named "myClient", and provide the discovery URL of the server (uaservercpp): myClient = Client(ClientSettings("myClient", ["opc.tcp://localhost:48010"])) # The client now discovers the "opc.tcp://localhost:48010", and fetches the application description # of the UaServerCpp demo server. # Let's print out what the client discovered: listOfApplicationDescriptions = myClient.serversFound() print(listOfApplicationDescriptions) # It's a list of one server description (the demo server). It tells us the application URI, or in # this case, the server uri: SERVER_URI = listOfApplicationDescriptions[0].applicationUri # Okay now that we know the server URI of the demo server, we can connect to it. # We'll just dynamically browse the address space, and let the UAF do the connection for us: rootNode = Address( NodeId(opcuaidentifiers.OpcUaId_RootFolder, 0), SERVER_URI )
# We configure the PKI folder structure (set the PKI_FOLDER to 'PKI' and you get the defaults). # Note that paths must ALWAYS be specified using '/', also on Windows! # You cannot use os.path.join or similar, since these will introduce platform-dependent separators! clientSettings.clientCertificate = PKI_FOLDER + '/client/certs/client.der' clientSettings.clientPrivateKey = PKI_FOLDER + '/client/private/client.pem' clientSettings.certificateTrustListLocation = PKI_FOLDER + '/trusted/certs/' clientSettings.certificateRevocationListLocation = PKI_FOLDER + '/trusted/crl/' clientSettings.issuersCertificatesLocation = PKI_FOLDER + '/issuers/certs/' clientSettings.issuersRevocationListLocation = PKI_FOLDER + '/issuers/crl/' # make sure the above directories are created clientSettings.createSecurityLocations() # create the client myClient = Client(clientSettings) print("") print( "===========================================================================================" ) print("STEP 3: Store the client certificate and private key") print( "===========================================================================================" ) print("") # store the certificate result = certificate.toDERFile(clientSettings.clientCertificate) if result == -1: raise Exception("Could not save the client certificate!")
# examples/pyuaf/client/easiest_client_example.py # Start the demo server ($SDK/bin/uaservercpp) of Unified Automation before running this script! import pyuaf from pyuaf.util import Address, NodeId from pyuaf.client import Client from pyuaf.client.settings import ClientSettings # create a client named "myClient", and provide the discovery URL of the server (uaservercpp): myClient = Client(ClientSettings("myClient", ["opc.tcp://localhost:48010"])) # specify the address of the node of which we would like to read its Value attribute: # (here we're using an absolute address, i.e. a NodeId(<identifier>, <namespace URI>) and a <server URI>) someAddress = Address( NodeId( "Demo.SimulationSpeed", # NodeId identifier "http://www.unifiedautomation.com/DemoServer"), # NodeId namespace URI "urn:UnifiedAutomation:UaServerCpp") # server URI # read the Value attribute of the node that we just addressed: result = myClient.read([someAddress]) print("The value is %d" % result.targets[0].data.value)
settings = ClientSettings() settings.discoveryUrls.append("opc.tcp://localhost:4841") settings.applicationName = "myClient" settings.logToStdOutLevel = loglevels.Debug settings.logToCallbackLevel = loglevels.Error # define the callback for the logging def myLoggingCallback(msg): print("************ CALLBACK SAYS: ************") if msg.level == loglevels.Error: print("Error message received: %s" %str(msg)) elif msg.level == loglevels.Warning: print("Warning message received: %s" %str(msg)) else: print("Info or debug message received: %s" %str(msg)) # create the client myClient = Client(settings, myLoggingCallback) # try to read the Value attribute of some non-existing node (so errors will be sent to the callback) try: nodeId = NodeId("NonExistingIdentifier","NonExistingNameSpace") address = Address(nodeId, "NonExistingServerURI") myClient.read( [address] ) except pyuaf.util.errors.UafError, e: print("UAF error raised: %s" %e) # alternatively: myClient2 = Client() myClient2.registerLoggingCallback(myLoggingCallback) myClient2.setClientSettings(settings)
# Subscriptions will be created silently in the background by the UAF, based on the # settings we provided via the 'cfg' object. # If subscriptions need to be created to the embedded device or the fast PLC, they will be # created according to the specified settings. # If subscriptions need to be created to other servers, they will be created according to the # defaultSubscriptionSettings settings. # First of all, configure a client ... clientSettings = ClientSettings() clientSettings.applicationName = "MyClient" clientSettings.discoveryUrls.append("opc.tcp://10.133.78.42") clientSettings.discoveryUrls.append("opc.tcp://10.133.78.81") clientSettings.discoveryUrls.append("opc.tcp://10.134.25.16") # ... and create the client myClient = Client(clientSettings) # define some node addresses temperature1 = Address(NodeId("temperature1" , "MyCompanyNamespace"), "Some/OPCUA/Server") temperature2 = Address(NodeId("temperature2" , "MyCompanyNamespace"), "Some/OPCUA/Server") pressure0005 = Address(NodeId("pressure0005" , "MyCompanyNamespace"), "My/Slow/Device/Server") motorStatus3 = Address(NodeId("motorStatus3" , "MyCompanyNamespace"), "My/Fast/PLC/Server") safetyValve5 = Address(NodeId("safetyValve5" , "MyCompanyNamespace"), "My/Fast/PLC/Server") # now we can monitor any variables or events without worrying about the settings of the subscriptions! # monitor the 4 variables myCreateMonitoredDataResult = myClient.createMonitoredData([temperature1, temperature2, pressure0005, motorStatus3], subscriptionConfig=cfg) # monitor the valve object that may send events
from pyuaf.util import Matrix from pyuaf.util import primitives from pyuaf.util import opcuaidentifiers, attributeids, opcuatypes from pyuaf.util.errors import UafError # define the namespace URI and server URI of the UaServerCPP demo server demoServerUri = "urn:UnifiedAutomation:UaServerCpp" demoNamespaceUri = "http://www.unifiedautomation.com/DemoServer/" # define the ClientSettings: settings = ClientSettings() settings.applicationName = "MyClient" settings.discoveryUrls.append("opc.tcp://localhost:48010") # create the client myClient = Client(settings) print( "#******************************************************************************#" ) print( "# #" ) print( "# 1) To understand matrices, let's define the function below to print one: #" ) print( "# #" ) print( "#******************************************************************************#"
from pyuaf.util import primitives from pyuaf.util import opcuaidentifiers, attributeids, opcuatypes from pyuaf.util.errors import UafError # define the namespace URI and server URI of the UaServerCPP demo server demoServerUri = "urn:UnifiedAutomation:UaServerCpp" demoNamespaceUri = "http://www.unifiedautomation.com/DemoServer/" # define the ClientSettings: settings = ClientSettings() settings.applicationName = "MyClient" settings.discoveryUrls.append("opc.tcp://localhost:48010") # create the client myClient = Client(settings) print("#******************************************************************************#") print("# #") print("# 1) To understand matrices, let's define the function below to print one: #") print("# #") print("#******************************************************************************#") def printMatrix(matrix): """ Print a matrix. Parameters: structure: a pyuaf.util.Matrix instance.
from pyuaf.client import Client from pyuaf.client.settings import ClientSettings, SessionSettings from pyuaf.util import Address, NodeId, opcuaidentifiers import uao server_uri = 'urn:CERN:QuasarOpcUaServer' # needs to match the factual server URI server_address = 'opc.tcp://127.0.0.1:4841' cs = ClientSettings("myClient", [server_address]) client = Client(cs) # next 2 lines are not necessary but help to ensure good state of OPC-UA connectivity rootNode = Address(NodeId(opcuaidentifiers.OpcUaId_RootFolder, 0), server_uri) result = client.browse([rootNode]) session = uao.Session(client, server_uri) obj = session.get_object('anObject', 2) # needs to match factuall existing object
from pyuaf.util import primitives from pyuaf.util import opcuaidentifiers, attributeids, opcuatypes, structurefielddatatypes from pyuaf.util.errors import UafError # define the namespace URI and server URI of the UaServerCPP demo server demoServerUri = "urn:UnifiedAutomation:UaServerCpp" demoNamespaceUri = "http://www.unifiedautomation.com/DemoServer/" # define the ClientSettings: settings = ClientSettings() settings.applicationName = "MyClient" settings.discoveryUrls.append("opc.tcp://localhost:48010") # create the client myClient = Client(settings) print("#**************************************************************************************************#") print("# #") print("# 1) To understand a GenericStructureValue instance, let's define the function below to print one: #") print("# #") print("#**************************************************************************************************#") def printStructure(structure, indentation=""): """ Print a structure. Parameters: structure: a pyuaf.util.GenericStructureValue instance. May represent a structure
def connect( ): global client cs = ClientSettings("myClient", [server_address]) client = Client(cs) rootNode = Address( NodeId(opcuaidentifiers.OpcUaId_RootFolder, 0), server_uri ) result=client.browse ([ rootNode ])
# will take care of the Discovery process and the connection process for you. A background thread will check # every 20 seconds (configurable, see above) the URLs you provided, and keep an inventory of all discovered # endpoints. If at some point the UAF thinks it's necessary to connect to one of these servers (e.g. because # you want to read a variable on a particular server), it will automatically create the necessary session # for you. # -> Bottomline: just provide the discovery URLs to the UAF, and afterwards you can directly start # reading data or monitoring events or calling methods or whatever. No need to manage connections yourself! # -> All OPC UA servers have such a Discovery endpoint, but additionally there are also "dedicated" discovery servers # that do nothing more than provide endpoints to other servers. Most people will never have to deal with such a # server, however. # -> In the (advanced!) scenario where a hierarchy of dedicated discovery servers is used, you only need to specify # the top discovery server. The UAF will automatically discover the discovery servers that are lower in the # hierarchy. # create the client myClient = Client(settings) print("") print( "################################################################################################################" ) print( "Step 3: Specify the addresses to some nodes which we would like to read/write/browse/monitor/call/..." ) print( "################################################################################################################" ) print("") # There are *many* ways how you can identify (address) a node, see the examples below: # 1) absolute address to the standard OPC UA "RootFolder" node (notice the standard OPC UA index 0)
import time, os, sys import pyuaf from pyuaf.client import Client from pyuaf.client.settings import ClientSettings from pyuaf.util import Address, NodeId from pyuaf.util.errors import UafError, ConnectionError # define the ClientSettings (note that we do NOT provide a discoveryUrl!!!): settings = ClientSettings() settings.applicationName = "MyClient" # settings.logToStdOutLevel = pyuaf.util.loglevels.Debug # uncomment to see the full UAF logging # create the client myClient = Client(settings) # Now manually connect to an endpoint of the demo server using 'manuallyConnectToEndpoint()'. # - The first argument (endpointUrl) is the URL of the endpoint you want to connect to # - The optional (!) second argument (sessionSettings) a SessionSettings instance. # If you don't provide one, then a default SessionSettings instance will be used. # A default SessionSettings instance has: # - no security policy (pyuaf.util.securitypolicies.UA_None) # - no security mode (pyuaf.util.messagesecuritymodes.Mode_None) # - no authentication (pyuaf.util.usertokentypes.Anonymous) try: print("") print("Now connecting") clientConnectionId = myClient.manuallyConnectToEndpoint("opc.tcp://localhost:48010") except ConnectionError, e: # if an error was raised, then no Session has been created!
# Subscriptions will be created silently in the background by the UAF, based on the # settings we provided via the 'cfg' object. # If subscriptions need to be created to the embedded device or the fast PLC, they will be # created according to the specified settings. # If subscriptions need to be created to other servers, they will be created according to the # defaultSubscriptionSettings settings. # First of all, configure a client ... clientSettings = ClientSettings() clientSettings.applicationName = "MyClient" clientSettings.discoveryUrls.append("opc.tcp://10.133.78.42") clientSettings.discoveryUrls.append("opc.tcp://10.133.78.81") clientSettings.discoveryUrls.append("opc.tcp://10.134.25.16") # ... and create the client myClient = Client(clientSettings) # define some node addresses temperature1 = Address(NodeId("temperature1", "MyCompanyNamespace"), "Some/OPCUA/Server") temperature2 = Address(NodeId("temperature2", "MyCompanyNamespace"), "Some/OPCUA/Server") pressure0005 = Address(NodeId("pressure0005", "MyCompanyNamespace"), "My/Slow/Device/Server") motorStatus3 = Address(NodeId("motorStatus3", "MyCompanyNamespace"), "My/Fast/PLC/Server") safetyValve5 = Address(NodeId("safetyValve5", "MyCompanyNamespace"), "My/Fast/PLC/Server") # now we can monitor any variables or events without worrying about the settings of the subscriptions!
# msg.message may contain multiple lines, so we prepend the other logging details in # front of each line: for line in msg.message.splitlines(): f.write("%s: %s\n" %(logDetailsString, line)) # Example 0: create a client with the default settings and no logging callback # -------------------------------------------------------------------------------------------------- client0 = Client() # Example 1: create a client by specifying the settings # -------------------------------------------------------------------------------------------------- client1 = Client(settings) # Example 2: create a client by specifying the settings # -------------------------------------------------------------------------------------------------- client2 = Client(settings, callback) # Example 3: create a client by specifying only the logging callback # -------------------------------------------------------------------------------------------------- client3 = Client(loggingCallback=callback) # you can still provide settings and register a logging callback afterwards, but you'll need to use: # client0.setClientSettings(settings) # client0.registerLoggingCallback(callback) # read the Value attribute of some non-existing node in order to have some Error output sent to the callback: client2.read([Address(NodeId("InvalidIdentifier","InvalidNamespace"),"InvalidServerURI")]) f.close()
from pyuaf.util.errors import UafError # define the namespace URI and server URI of the UaServerCPP demo server demoServerUri = "urn:UnifiedAutomation:UaServerCpp" # define the address of the Root node which we would like to start browsing rootNode = Address( NodeId(opcuaidentifiers.OpcUaId_RootFolder, 0), demoServerUri ) # define the ClientSettings: settings = ClientSettings() settings.applicationName = "MyClient" settings.discoveryUrls.append("opc.tcp://localhost:48010") # create the client myClient = Client(settings) try: print("") print("First option: use the convenience function \"browse()\"") print("===================================================") # now browse the root node # (notice that there is also an argument called 'maxAutoBrowseNext', which we don't mention # here because we can leave it at the default value (100), to make sure that BrowseNext is # automatically being called for us as much as needed!) firstLevelBrowseResult = myClient.browse([rootNode]) # Notice too that you can optionally provide a BrowseSettings and/or a SessionSettings argument
demoNsUri = "http://www.unifiedautomation.com/DemoServer" demoServerUri = "urn:UnifiedAutomation:UaServerCpp" # define some addresses which will be used later on address_Server = Address( NodeId(opcuaidentifiers.OpcUaId_Server , 0), demoServerUri ) address_Dynamic = Address( NodeId("Demo.DynamicNodes" , demoNsUri), demoServerUri ) address_Create = Address( NodeId("Demo.DynamicNodes.CreateDynamicNode", demoNsUri), demoServerUri ) address_Delete = Address( NodeId("Demo.DynamicNodes.DeleteDynamicNode", demoNsUri), demoServerUri ) # define the ClientSettings: settings = ClientSettings() settings.applicationName = "MyClient" settings.discoveryUrls.append("opc.tcp://localhost:48010") # create the client myClient = Client(settings) # define the event filter to only receive the GeneralModelChangeEventType events eventFilter = EventFilter() eventFilter.selectClauses.resize(1) eventFilter.selectClauses[0].attributeId = pyuaf.util.attributeids.Value eventFilter.selectClauses[0].browsePath.append(QualifiedName("Changes", 0)) eventFilter.selectClauses[0].typeId = NodeId(opcuaidentifiers.OpcUaId_GeneralModelChangeEventType, 0) # define a callback function to handle the events def myCallback(notification): print("Notification received!") changes = notification.fields[0] print("Changes:") for i in xrange(len(changes)): change = changes[i]
# Sessions will be created silently in the background by the UAF, based on the # settings we provided via the 'cfg' object. # If sessions need to be created to the "My/Unreliable/Device/Uri" or "My/Reliable/PLC/Uri" # servers, they will be created according to the specified settings. # If sessions need to be created to other servers, they will be created according to the # defaultSessionSettings settings. # configure a client ... clientSettings = ClientSettings() clientSettings.applicationName = "MyClient" clientSettings.discoveryUrls.append("opc.tcp://10.133.78.42") clientSettings.discoveryUrls.append("opc.tcp://10.133.78.81") clientSettings.discoveryUrls.append("opc.tcp://10.134.25.16") # ... and create the client myClient = Client(clientSettings) # define some addresses temperature1 = Address(NodeId("temperature1", "MyCompanyNamespace"), "Some/OPCUA/Server") temperature2 = Address(NodeId("temperature2", "MyCompanyNamespace"), "Some/OPCUA/Server") pressure0005 = Address(NodeId("pressure0005", "MyCompanyNamespace"), "My/Unreliable/Device/Server") motorStatus3 = Address(NodeId("motorStatus3", "MyCompanyNamespace"), "My/Reliable/PLC/Server") # now we can read, write, ... any address(es) without worrying about the settings of the sessions! # read the Value attribute of the 4 nodes myReadResult = myClient.read(
# We configure the PKI folder structure (set the PKI_FOLDER to 'PKI' and you get the defaults). # Note that paths must ALWAYS be specified using '/', also on Windows! # You cannot use os.path.join or similar, since these will introduce platform-dependent separators! clientSettings.clientCertificate = PKI_FOLDER + "/client/certs/client.der" clientSettings.clientPrivateKey = PKI_FOLDER + "/client/private/client.pem" clientSettings.certificateTrustListLocation = PKI_FOLDER + "/trusted/certs/" clientSettings.certificateRevocationListLocation = PKI_FOLDER + "/trusted/crl/" clientSettings.issuersCertificatesLocation = PKI_FOLDER + "/issuers/certs/" clientSettings.issuersRevocationListLocation = PKI_FOLDER + "/issuers/crl/" # make sure the above directories are created clientSettings.createSecurityLocations() # create the client myClient = Client(clientSettings) print("") print("===========================================================================================") print("STEP 3: Store the client certificate and private key") print("===========================================================================================") print("") # store the certificate result = certificate.toDERFile(clientSettings.clientCertificate) if result == -1: raise Exception("Could not save the client certificate!") # store the private key: result = keyPair.toPEMFile(clientSettings.clientPrivateKey) if result == -1:
# target 4: status = readResult.targets[4].status # 'status' has type pyuaf.util.Status data = readResult.targets[4].data # 'data' is a list of pyuaf.util.primitives.SByte if status.isGood() and isinstance(data, list): print("The array is:") for i in xrange(len(data)): print(" - array[%d] = %d" %(i, data[i].value)) # define the ClientSettings: settings = ClientSettings() settings.applicationName = "MyClient" settings.discoveryUrls.append("opc.tcp://localhost:4841") # create the client myClient = Client(settings) # read the node attributes all at once try: print("") print("First option: use the convenience function \"read()\"") print("===================================================") # OPTIONAL: You could also provide a ReadConfig to configure a call timeout, # or maximum age of the values, or ... serviceConfig = ReadConfig() serviceConfig.serviceSettings.callTimeoutSec = 0.5 serviceConfig.serviceSettings.maxAgeSec = 1.0
# Sessions will be created silently in the background by the UAF, based on the # settings we provided via the 'cfg' object. # If sessions need to be created to the "My/Unreliable/Device/Uri" or "My/Reliable/PLC/Uri" # servers, they will be created according to the specified settings. # If sessions need to be created to other servers, they will be created according to the # defaultSessionSettings settings. # configure a client ... clientSettings = ClientSettings() clientSettings.applicationName = "MyClient"; clientSettings.discoveryUrls.append("opc.tcp://10.133.78.42") clientSettings.discoveryUrls.append("opc.tcp://10.133.78.81") clientSettings.discoveryUrls.append("opc.tcp://10.134.25.16") # ... and create the client myClient = Client(clientSettings) # define some addresses temperature1 = Address(NodeId("temperature1" , "MyCompanyNamespace"), "Some/OPCUA/Server") temperature2 = Address(NodeId("temperature2" , "MyCompanyNamespace"), "Some/OPCUA/Server") pressure0005 = Address(NodeId("pressure0005" , "MyCompanyNamespace"), "My/Unreliable/Device/Server") motorStatus3 = Address(NodeId("motorStatus3" , "MyCompanyNamespace"), "My/Reliable/PLC/Server") # now we can read, write, ... any address(es) without worrying about the settings of the sessions! # read the Value attribute of the 4 nodes myReadResult = myClient.read([temperature1, temperature2, pressure0005, motorStatus3], sessionConfig=cfg) # write a new motor status myWriteResult = myClient.write([motorStatus3], [Byte(0x3)], sessionConfig=cfg)
# every 20 seconds (configurable, see above) the URLs you provided, and keep an inventory of all discovered # endpoints. If at some point the UAF thinks it's necessary to connect to one of these servers (e.g. because # you want to read a variable on a particular server), it will automatically create the necessary session # for you. # -> Bottomline: just provide the discovery URLs to the UAF, and afterwards you can directly start # reading data or monitoring events or calling methods or whatever. No need to manage connections yourself! # -> All OPC UA servers have such a Discovery endpoint, but additionally there are also "dedicated" discovery servers # that do nothing more than provide endpoints to other servers. Most people will never have to deal with such a # server, however. # -> In the (advanced!) scenario where a hierarchy of dedicated discovery servers is used, you only need to specify # the top discovery server. The UAF will automatically discover the discovery servers that are lower in the # hierarchy. # create the client myClient = Client(settings) print("") print("################################################################################################################") print("Step 3: Specify the addresses to some nodes which we would like to read/write/browse/monitor/call/...") print("################################################################################################################") print("") # There are *many* ways how you can identify (address) a node, see the examples below: # 1) absolute address to the standard OPC UA "RootFolder" node (notice the standard OPC UA index 0) # 2) absolute address to the non-standard "Demo" node (notice the demo server namespace URI) # 3) absolute address to the non-standard "BoilerDemo" node (notice that we use an ExpandedNodeId this time) # 4) relative address to the "Boiler1" node (relative to the previous address)
from pyuaf.util.errors import UafError # define the namespace URI and server URI of the UaServerCPP demo server demoServerUri = "urn:UnifiedAutomation:UaServerCpp" # define the address of the Root node which we would like to start browsing rootNode = Address(NodeId(opcuaidentifiers.OpcUaId_RootFolder, 0), demoServerUri) # define the ClientSettings: settings = ClientSettings() settings.applicationName = "MyClient" settings.discoveryUrls.append("opc.tcp://localhost:48010") # create the client myClient = Client(settings) try: print("") print("First option: use the convenience function \"browse()\"") print("===================================================") # now browse the root node # (notice that there is also an argument called 'maxAutoBrowseNext', which we don't mention # here because we can leave it at the default value (100), to make sure that BrowseNext is # automatically being called for us as much as needed!) # (notice too that you can optionally provide a BrowseConfig and a SessionConfig for # more detailed configuration) firstLevelBrowseResult = myClient.browse([rootNode]) # print the result
# When trying to interact with a third-party server (i.e. any server of which you don't know all details # from), you must dynamically discover some "details". # This example will show you how to connect and interact with such an "unknown" server. # # In general, what you *do* know is the IP address and port of the server. Together they are known as # the "discoveryURL". # You can provide a discovery URL like this: import pyuaf from pyuaf.util import Address, NodeId from pyuaf.util import opcuaidentifiers from pyuaf.client import Client from pyuaf.client.settings import ClientSettings # create a client named "myClient", and provide the discovery URL of the server (uaservercpp): myClient = Client(ClientSettings("myClient", ["opc.tcp://localhost:48010"])) # The client now discovers the "opc.tcp://localhost:48010", and fetches the application description # of the UaServerCpp demo server. # Let's print out what the client discovered: listOfApplicationDescriptions = myClient.serversFound() print(listOfApplicationDescriptions) # It's a list of one server description (the demo server). It tells us the application URI, or in # this case, the server uri: SERVER_URI = listOfApplicationDescriptions[0].applicationUri # Okay now that we know the server URI of the demo server, we can connect to it. # We'll just dynamically browse the address space, and let the UAF do the connection for us: rootNode = Address(NodeId(opcuaidentifiers.OpcUaId_RootFolder, 0), SERVER_URI)