Can not establish connection to OPC UA server

Hi, I am running an async OPC UA server on Python which I am trying to connect to Visual Components. However, I’m getting an error which doesn’t allow me to connect to the server for some reason.

Here is the code:

 > /usr/bin/env python3
> 
> # This file contains a set of classes and methods to handle
> 
> # running a OPC UA server on a raspberry pi.
> 
> import asyncio
> 
> import random
> 
> import time
> 
> from asyncua import ua, uamethod, Server, Client
> 
> import announce_service as sa
> 
> SERVER_NAME = "RaspPI OPC UA Server"
> 
> FLAT_NAME = SERVER_NAME.replace(" ", "")
> 
> SERVER_PORT = 9000
> 
> SERVER_ENDPOINT = "opc.tcp://0.0.0.0:"+str(SERVER_PORT)
> 
> UA_NAMESPACE = "hvproj:ua:"+FLAT_NAME
> 
> DISCOVERY_NAME="_"+FLAT_NAME[:10]+"."
> 
> TEMP = 19
> 
> class SubHandler():
> 
>     """
> 
>     Subscription Handler. To receive events from server for a subscription
> 
>     data_change and event methods are called directly from receiving thread.
> 
>     Do not do expensive, slow or network operation there. Create another 
> 
>     thread if you need to do such a thing
> 
>     """
> 
>     def datachange_notification(self, node, val, data):
> 
>         print("Python: New data change event", node, val)
> 
>     def event_notification(self, event):
> 
>         print("Python: New event", event)
> 
> client = None
> 
> handler = SubHandler()
> 
> sub = None
> 
> handle = None
> 
> class ServerPI:
> 
>     def __init__(self):
> 
>         self.temp = TEMP
> 
>         self.clients = {}
> 
>     
> 
>     # This ua method is used to subscribe to a variable on
> 
>     # another server.
> 
>     # Inputs:
> 
>     # endpoint(Server url as string): the path to server to subscribe from.
> 
>     # qx(NodeId in string format): The variable to subscribe to
> 
>     # ix(NodeId in string fromat): The variable to connect subscription to
> 
>     # Returns void.
> 
>     @uamethod
> 
>     async def subscribe(self, parent, endpoint, qx, ix):
> 
>         server = str(endpoint)
> 
>         if server not in self.clients:
> 
>             try:
> 
>                 client = Client(server)
> 
>                 await client.connect()
> 
>                 await client.load_data_type_definitions()
> 
>                 self.clients[server] = (client,set())
> 
>             except:
> 
>                 return "Could not reach the server specified."
> 
>         else:
> 
>             client = self.clients[server][0]
> 
>         #root = client.get_root_node(
> 
>         #uri = "http://examples.freeopcua.github.io"
> 
>         #idx = client.get_namespace_index(uri)
> 
>         qxvar = client.get_node(qx)
> 
>         if qx not in self.clients[server][1]:
> 
>             self.clients[server][1].add(qx)
> 
>             print(len(self.clients[server][1]))
> 
>             sub = await client.create_subscription(50, handler)
> 
>             handle = await sub.subscribe_data_change(qxvar)
> 
>         time.sleep(0.1)
> 
>         return "Successfully subscribed to the specified variable!"
> 
>             
> 
>     def method_var(self, name, description):
> 
>         arg = ua.Argument()
> 
>         arg.Name = name
> 
>         arg.DataType = ua.NodeId(ua.ObjectIds.Int64) #NodeId, and not datatype of value. We use Int64 ID's.
> 
>         arg.ValueRank = -1
> 
>         arg.ArrayDimensions = []
> 
>         arg.Description = ua.LocalizedText(description)
> 
>         return arg
> 
>     async def go(self):
> 
>         server = Server()
> 
>         await server.init()
> 
>         server.set_endpoint(SERVER_ENDPOINT)
> 
>         server.set_server_name(SERVER_NAME)
> 
>         '''
> 
>         server.set_security_policy([
> 
>             ua.SecurityPolicyType.NoSecurity,
> 
>             ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
> 
>             ua.SecurityPolicyType.Basic256Sha256_Sign
> 
>         ])
> 
>         '''
> 
>         idx = await server.register_namespace(UA_NAMESPACE)
> 
>         objects = server.nodes.objects
> 
>         #dev = await server.nodes.base_object_type.add_object_type(idx, FLAT_NAME)
> 
>         lFolder = await objects.add_folder(idx, "Sensors")
> 
>         print("Sensors folder: ", lFolder)
> 
>         zobj = await objects.add_object(idx, "Methods")
> 
>         print("Methods object:", zobj)
> 
>         zvar = await lFolder.add_variable(idx, "ixTemperature", self.temp)
> 
>         print("Temp var: ", zvar)
> 
>         endp = self.method_var("Endpoint", "Address to tendpoint")
> 
>         qxvar = self.method_var("qx", "Output variable to connect to server.")
> 
>         ixvar = self.method_var("ix", "Input variable that is to be connected to.")
> 
>         ret = self.method_var("ret", "Return message for information of what happend.")
> 
>         await zobj.add_method(idx, "subscribe", self.subscribe, [endp, qxvar, ixvar], [ret])
> 
>         async with server:
> 
>             while True:
> 
>                 await asyncio.sleep(0.1)
> 
>                 await zvar.write_value(self.temp)
> 
>                 self.temp = 19 + random.random()
> 
> if __name__ == "__main__":
> 
>     print(DISCOVERY_NAME)
> 
>     sa.start_service_announcement(device_name=DISCOVERY_NAME, iport=SERVER_PORT)
> 
>     sp = ServerPI()
> 
>     asyncio.run(sp.go())

Now if I change to a regular OPC UA Server the connection actually works. But with an async server it doesn’t? I don’t understand what the issue is here

Error message:

Connection failed.

Following error and warning message(s) were received from the Connection Plugin:

[ERROR] Failed to load endpoint descriptions from the server and select one that matches the specified security and protocol criteria.
[ERROR] Connecting to server failed: An unexpected error occurred while connecting to the server.

Why have you commented out this call?

1 Like

uncommented or commented, doesn’t matter the issue is still prevalent. I tried with and without, I don’t understand what the issue is really…

1 Like

yes, I got same problem, it seems we can not use python OPC UA server. or is there any demo we could use?

Are there any relevant errors logged in the VC application log file when the connection fails?

It can be found from e.g.:
C:\Users\%USERNAME%\AppData\Local\Visual Components\Visual Components Premium 4.4\Logs\log-file-VisualComponents.Engine.txt

2021-12-15 19:56:20,766 ERROR - Connecting to server failed. Message: An unexpected error occurred while connecting to the server., StatusCode: BadUnexpectedError
Additional info:
[StatusException] An unexpected error occurred while connecting to the server.
在 UnifiedAutomation.UaBase.TcpAsyncOperation1.End(Int32 timeout) 在 UnifiedAutomation.UaBase.TcpClientChannel.EndSendRequest(IAsyncResult result) 在 UnifiedAutomation.UaBase.DiscoveryClient.EndGetEndpoints(IAsyncResult result, EndpointDescriptionCollection& endpoints) 在 UnifiedAutomation.UaClient.Discovery.OnGetEndpointsComplete(IAsyncResult result) 2021-12-15 21:04:51,495 ERROR - Failed to find suitable endpoint from the server at url: opc.tcp://0.0.0.0:4840/freeopcua/server1/ UnifiedAutomation.UaBase.StatusException: An unexpected error occurred while connecting to the server. ---> UnifiedAutomation.UaBase.StatusException: An unexpected error occurred while connecting to the server. 在 UnifiedAutomation.UaBase.TcpAsyncOperation1.End(Int32 timeout)
在 UnifiedAutomation.UaBase.TcpClientChannel.EndSendRequest(IAsyncResult result)
在 UnifiedAutomation.UaBase.DiscoveryClient.EndGetEndpoints(IAsyncResult result, EndpointDescriptionCollection& endpoints)
在 UnifiedAutomation.UaClient.Discovery.OnGetEndpointsComplete(IAsyncResult result)
— 内部异常堆栈跟踪的结尾 —
在 UnifiedAutomation.UaBase.AsyncResultBase.ThrowOnError()
在 UnifiedAutomation.UaBase.AsyncResultBase.WaitForComplete()
在 UnifiedAutomation.UaBase.AsyncResultBase.WaitForComplete(IAsyncResult ar)
在 UnifiedAutomation.UaClient.Discovery.EndGetEndpoints(IAsyncResult result)
在 VisualComponents.Connectivity.OpcUA.Server.FindServerEndpoint(String discoveryUrl, Boolean useSecureEndpoint, Boolean replaceHost)

when I change path “opc.tcp://0.0.0.0:4840/freeopcua/server1/” to " opc.tcp://localhost:4840" . the log is as below:
2021-12-15 21:35:20,994 ERROR - Exception thrown during server connection test.
System.NullReferenceException: 未将对象引用设置到对象的实例。
在 VisualComponents.Connectivity.OpcUA.Server.GetServerLimits()
在 VisualComponents.Connectivity.OpcUA.Server.Connect(IServerConnectionSettings connectionSettings)
在 VisualComponents.Connectivity.OpcUA.UI.ServerConnectionEditorUI.TestConnection(ServerConnectionSettings settings)

Seems to me that the Python server doesn’t implement the GetEndpoints service correctly. That is required functionality on any OPC UA server.

I don’t know how to fix that, but probably it is just a configuration issue on the server side. The endpoints the server returns should also be valid URIs, so e.g. an empty string is an error.

That issue is probably this one:

Could you try with the following? I remember having similar problems and setting the endpoint IP address and port to these values solved it.

server.set_endpoint(“opc.tcp://127.0.0.1:4841”)

1 Like

thanks for fast reply,
my server code is as below:

if name == “main”:
# setup our server
server = Server()
server.set_endpoint(“opc.tcp://localhost:4840”)

# setup our own namespace, not really necessary but should as spec
uri = "http://examples.freeopcua.github.io"
idx = server.register_namespace(uri)

# get Objects node, this is where we should put our nodes
objects = server.get_objects_node()

# populating our address space
myobj = objects.add_object(idx, "MyObject")
myvar = myobj.add_variable(idx, "MyVariable", 6.7)
myvar.set_writable()    # Set MyVariable to be writable by clients

# starting!
server.start()

try:
    count = 0
    while True:
        time.sleep(1)
        count += 0.1
        myvar.set_value(count)
finally:
    #close connection, remove subcsriptions, etc
    server.stop()

I tried it , not work. :joy:

But,but but when i force start the server, I can see the data of the OPC server. it works???

Yes, I had a similar experience. Testing the connection does not work, but when you start the server anyways you can see and pair the variables.

From the screenshot I can see that your server doesn’t have the “Server” object and other mandatory stuff under it. It needs to have those server capabilities etc. in the hierarchy. I don’t know anything about this specific Python library, so you’ll need to research how to fix that yourself.

The GitHub issue I linked is about defining these server capability objects that VC expects each OPC UA server to have.

Also see this other topic about the same issue.