Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

get client connection state #521

Open
daniel-brosche opened this issue Nov 20, 2017 · 13 comments
Open

get client connection state #521

daniel-brosche opened this issue Nov 20, 2017 · 13 comments

Comments

@daniel-brosche
Copy link

I did not find a possibility to check that a client connection has been successfully established like client.is_connected.

@DaEwe
Copy link

DaEwe commented Feb 15, 2018

What worked for me as a workaround is
client.uaclient._uasocket._thread.isAlive()

@oroulet
Copy link
Member

oroulet commented Feb 15, 2018

I think that with the current implementation, you get a crash is connection is not succesfull. BUT as with any networking system, things may hang for along time depending on timeouts.
If there is a case where the connection is not succefull and you do not get a crash, let me know

@DaEwe
Copy link

DaEwe commented Feb 15, 2018

Thing is, yes, I get a crash, but how can I react to it programmatically? The exception occurs in another thread..

@oroulet
Copy link
Member

oroulet commented Feb 15, 2018

I do not know you application, but usually, people have a kind of ua thread that fetch/push data under a big try/except and restart connection if there is any exception

is_connected = False
while not self._stop:
    try:
        client.connect()
        is_connected = True
       # subscribe or whaterver
        node=  client.nodes.server_state    
        while True:
              node.get_value()
              time.sleep(1)
    except:
        is_connected = False  
        # clean up, disconnect completely from server  
        client.disconnect() 
        logger.exception("something happent, reconnecting in 5s")
        time.sleep(5)

I know that some libraries do that kind of things for you, but from my experience this is very fragile so I thought it was better to let people do what works for them

@DaEwe
Copy link

DaEwe commented Feb 15, 2018

I am working with subscriptions. In your example the exception would be raised from get_value(), right? I can catch that, since it occurred in my own thread.
How would that work with subscriptions? Just pack my whole application in a try/except-block?

@oroulet
Copy link
Member

oroulet commented Feb 15, 2018

for the subscriptions callback this should not change anything, but you need to recreate your subscritions after connecting, since they are lost when disconnecting (ua does allow to reconnect to a subcription, but we do not support that currently, we close them when disconnecting)

@oroulet
Copy link
Member

oroulet commented Feb 15, 2018

but if you want to know is connection is lost, you need a kind of polling anyway. This is what clients like uaexpert do. We could have added it into the KeepAlice class, although it is probably more complicated to configure it than just just implementing it

@DaEwe
Copy link

DaEwe commented Feb 15, 2018

for the subscriptions callback this should not change anything

Yes it does. The exception is raised within your thread, which is then ended. The rest of my program doesn't notice and so I am not able to handle the situation. Just as in the example below. The prgram will run to it's end and not react to the raised exception.

from threading import Thread


def some_internal_ua_stuff():
    time.sleep(5)
    raise Exception("Something!")


if __name__ == "__main__":
    try:
        t = Thread(target=some_internal_ua_stuff)
        t.start()
        for i in range(10):
            print("doing sth else")
            time.sleep(1)
        print("done")
    except Exception as e:
        print(" caught exception: " + str(e))

but if you want to know is connection is lost, you need a kind of polling anyway.

What I am doing right now is checking if your internal thread is alive. If there was some exception as described above it will have died and I can try to reconnect. However, that's a hacky solution. Much nicer would be either a method of the client as requested by @daniel-brosche, or maybe the possiblity to register a callback.

@oroulet
Copy link
Member

oroulet commented Feb 15, 2018

This is a general issue in multi processing. If a thread dies you need a way to communicate the info to the others, isn'it?

Much nicer would be either a method of the client as requested by @daniel-brosche, or maybe the possiblity to register a callback.

I know a lot of people seems to want that kind of things. I think it is broken since it is much easier to have my own thread as shown above that monitors the connection and clean up things if necessary. But is someone make a class for that I am open to merge it (It migth be possible to add that functionnality to the "KeepAlive" class). it should simply be a class started with a polling interval and the possibility to register callbacks to be called if connection is lost, and maybe if connection is remade. It could also have a is_connected attribute if some people want to add one more layer of polling

It has also been propose once to make a ClientForDummies class that automatically reconnects. It iis more work since it needs to keep track of all subscriptions, etc,...

@oroulet
Copy link
Member

oroulet commented Feb 15, 2018

and if someone has even more time: The entire client/server API should be ported to the async module to offer an async api. This is more work... an attempte started there: #558

OptrixAU added a commit to OptrixAU/python-opcua that referenced this issue Feb 25, 2020
@OptrixAU
Copy link

This issue is ancient, but still a legitimate concern. Suggested a small update to include a simple connection test (based on the thread check shown above) to check for dropped connections.

This is particularly useful when you are only subscribing to the OPC - you don't get the opportunity to catch exceptions on connection failure if you're not actively polling. I also considered sending 'hello' requests occasionally, but Hello doesn't appear to be supported by some OPCUA servers.

@GLmontanari
Copy link

Hi!
Any updates about this? I can't find the function "is_connected" in the latest release (0.98.12 from PyPI)

@AlexanderSkachkov
Copy link

AlexanderSkachkov commented Aug 10, 2022

I use this in my solution:
opc_ua_client.keepalive.is_alive()
And also probably need to add this:

opc_ua_client.secure_channel_timeout = 5000 # 5 secconds just for example
opc_ua_client.session_timeout = 5000 # 5 secconds just for example

because default timeout is 1 hour.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants