Skip to content
Snippets Groups Projects
Commit da3a4aab authored by Jan David Mol's avatar Jan David Mol
Browse files

Only reconnect once if connection fails -- we only want to catch exotic...

Only reconnect once if connection fails -- we only want to catch exotic errors, not cover up hardware/infra failure
parent b51a57ff
No related branches found
No related tags found
No related merge requests found
...@@ -74,38 +74,34 @@ class OPCUAConnection(Thread): ...@@ -74,38 +74,34 @@ class OPCUAConnection(Thread):
Run a connector function in the background, until it succeeds. Run a connector function in the background, until it succeeds.
""" """
def __init__(self, client, init_func, fault_func, streams, try_interval=2): def __init__(self, client, on_func, fault_func, streams, try_interval=2):
super().__init__(daemon=True) super().__init__(daemon=True)
self.client = client self.client = client
self.init_func = init_func self.on_func = on_func
self.fault_func = fault_func self.fault_func = fault_func
self.try_interval = try_interval self.try_interval = try_interval
self.streams = streams self.streams = streams
self.stopping = False self.stopping = False
self.connected = False
self.start()
def _servername(self): def _servername(self):
return self.client.server_url.geturl() return self.client.server_url.geturl()
def try_connect(self): def connect(self):
try: try:
self.streams.debug_stream("Connecting to server %s", self._servername()) self.streams.debug_stream("Connecting to server %s", self._servername())
self.client.connect() self.client.connect()
self.connected = True
self.streams.debug_stream("Connected to server. Initialising.") self.streams.debug_stream("Connected to server. Initialising.")
self.init_func()
return True return True
except socket.error as e: except socket.error as e:
self.streams.error_stream("Could not connect to server %s: %s", self._servername(), e) self.streams.error_stream("Could not connect to server %s: %s", self._servername(), e)
# signal that we're disconnected
self.fault_func()
return False return False
def try_disconnect(self): def disconnect(self):
self.connected = False # always force a reconnect, regardless of a successful disconnect
try: try:
self.client.disconnect() self.client.disconnect()
except Exception as e: except Exception as e:
...@@ -114,8 +110,14 @@ class OPCUAConnection(Thread): ...@@ -114,8 +110,14 @@ class OPCUAConnection(Thread):
def run(self): def run(self):
while not self.stopping: while not self.stopping:
# keep trying to connect # keep trying to connect
while not self.stopping and not self.try_connect(): if not self.connected:
time.sleep(self.try_interval) if self.connect():
self.on_func()
else:
# we retry only once, to catch exotic network issues. if the infra or hardware is down,
# our device cannot help, and must be reinitialised after the infra or hardware is fixed.
self.fault_func()
return
# keep checking if the connection is still alive # keep checking if the connection is still alive
try: try:
...@@ -126,7 +128,7 @@ class OPCUAConnection(Thread): ...@@ -126,7 +128,7 @@ class OPCUAConnection(Thread):
self.streams.error_stream("Lost connection to server %s: %s", self._servername(), e) self.streams.error_stream("Lost connection to server %s: %s", self._servername(), e)
# technically, we may not have dropped the connection, but encounter a different error. so explicitly disconnect. # technically, we may not have dropped the connection, but encounter a different error. so explicitly disconnect.
self.try_disconnect() self.disconnect()
# signal that we're disconnected # signal that we're disconnected
self.fault_func() self.fault_func()
...@@ -139,7 +141,7 @@ class OPCUAConnection(Thread): ...@@ -139,7 +141,7 @@ class OPCUAConnection(Thread):
self.stopping = True self.stopping = True
self.join() self.join()
self.try_disconnect() self.disconnect()
class RCUSCC(Device): class RCUSCC(Device):
""" """
...@@ -262,7 +264,7 @@ class RCUSCC(Device): ...@@ -262,7 +264,7 @@ class RCUSCC(Device):
return DummyNode() return DummyNode()
def _init_opcua(self): def _map_attributes(self):
try: try:
self.name_space_index = self.client.get_namespace_index("http://lofar.eu") self.name_space_index = self.client.get_namespace_index("http://lofar.eu")
except Exception as e: except Exception as e:
...@@ -367,7 +369,21 @@ class RCUSCC(Device): ...@@ -367,7 +369,21 @@ class RCUSCC(Device):
self.client = opcua.Client("opc.tcp://{}:{}/".format(self.OPC_Server_Name, self.OPC_Server_Port), self.OPC_Time_Out) # timeout in seconds self.client = opcua.Client("opc.tcp://{}:{}/".format(self.OPC_Server_Name, self.OPC_Server_Port), self.OPC_Time_Out) # timeout in seconds
# Connect to OPC-UA -- will set ON state on success # Connect to OPC-UA -- will set ON state on success
self.opcua_connection = OPCUAConnection(self.client, self._init_opcua, self.Fault, self) self.opcua_connection = OPCUAConnection(self.client, self.On, self.Fault, self)
if not self.opcua_connection.connect():
# hardware or infra is down -- needs fixing first
self.Fault()
return
# Retrieve and map server attributes
self._map_attributes()
# Start keep-alive
self.opcua_connection.start()
# Everything went ok -- go online
self.On()
# PROTECTED REGION END # // RCUSCC.init_device # PROTECTED REGION END # // RCUSCC.init_device
...@@ -568,11 +584,15 @@ class RCUSCC(Device): ...@@ -568,11 +584,15 @@ class RCUSCC(Device):
:return:None :return:None
""" """
# Turn off
self.set_state(DevState.OFF) self.set_state(DevState.OFF)
# stop reconnecting before disconnect # Stop keep-alive
self.opcua_connection.stop() self.opcua_connection.stop()
# Turn off again, in case of race conditions through reconnecting
self.set_state(DevState.OFF)
# PROTECTED REGION END # // RCUSCC.Off # PROTECTED REGION END # // RCUSCC.Off
@command( @command(
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment