From 32d38b11e1a6c43fd0a082faf3d58d6a1661e769 Mon Sep 17 00:00:00 2001
From: Jan David Mol <mol@astron.nl>
Date: Wed, 2 Dec 2020 10:07:09 +0100
Subject: [PATCH] Move reconnect functionality to separate class

---
 RCUSCC/RCUSCC/RCUSCC.py | 91 +++++++++++++++++++++++------------------
 1 file changed, 52 insertions(+), 39 deletions(-)

diff --git a/RCUSCC/RCUSCC/RCUSCC.py b/RCUSCC/RCUSCC/RCUSCC.py
index 62824eb73..68a2184ac 100644
--- a/RCUSCC/RCUSCC/RCUSCC.py
+++ b/RCUSCC/RCUSCC/RCUSCC.py
@@ -46,7 +46,7 @@ def fault_on_opcua_error(func):
         except Exception as e:
             self.error_stream("Communication with the OPC-UA server %s:%d failed. Reconnecting. Trace: %s" % (self.OPC_Server_Name, self.OPC_Server_Port, traceback.format_exc()))
             self.set_state(DevState.FAULT)
-            self._reconnect_opcua()
+            self.opcua_connector.reconnect()
 
             return None
 
@@ -57,7 +57,7 @@ __all__ = ["RCUSCC", "main"]
 
 class BackgroundConnector(Thread):
     """
-      Run a function in the background, until it succeeds.
+      Run a connector function in the background, until it succeeds.
     """
 
     def __init__(self, connect_func, try_interval=2, debug_stream=print):
@@ -84,6 +84,53 @@ class BackgroundConnector(Thread):
             if not self.connected:
                 time.sleep(self.try_interval)
 
+class BackgroundReconnector(object):
+    """
+      Keeps a connection attempt going.
+    """
+
+    def __init__(self, connect_func, disconnect_func, debug_stream=print):
+        self.connect_func = connect_func
+        self.disconnect_func = disconnect_func
+        self.debug_stream = debug_stream
+
+        self._connect()
+
+    def _connect(self):
+        self.connector = BackgroundConnector(self.connect_func, debug_stream=self.debug_stream)
+        self.connector.start()
+
+    def reconnect(self):
+        """
+          Connect or reconnect to the OPC-UA server.
+        """
+
+        if self.connector.connecting:
+            # don't try twice in parallel
+            return
+        
+        # reap previous instance
+        self.debug_stream("reaping previous connector")
+        self.connector.join()
+
+        # disconnect if necessary
+        self.debug_stream("disconnecting (if connected)")
+        self.disconnect_func()
+
+        # connect in the background
+        self.debug_stream("connecting")
+        self._connect()
+
+    def wait_connected(self):
+        """
+          Wait until a connection is established.
+        """
+
+        # wait for attempt to finish
+        self.connector.join()
+
+        if not self.connector.connected:
+            raise Exception("Could not connect to server")
 
 class RCUSCC(Device):
     """
@@ -205,39 +252,6 @@ class RCUSCC(Device):
 
             return DummyNode()
 
-    def _reconnect_opcua(self):
-        """
-          Connect or reconnect to the OPC-UA server.
-        """
-
-        if self.opcua_connector:
-            if self.opcua_connector.connecting:
-              # don't try twice in parallel
-              return
-            
-            # reap previous instance
-            self.debug_stream("reaping previous connector")
-            self.opcua_connector.join()
-
-        self.debug_stream("disconnecting (if connected)")
-        self._disconnect()
-        self.debug_stream("connecting")
-        self.opcua_connector = BackgroundConnector(self._init_opcua)
-        self.opcua_connector.start()
-
-    def _wait_opcua_connect(self):
-        """
-          Wait until an OPC-UA connection is established.
-        """
-
-        if not self.opcua_connector:
-            # start connecting if not already
-            self._reconnect_opcua()
-
-        self.opcua_connector.join()
-
-        if not self.opcua_connector.connected:
-            raise Exception("Could not connect to OPC-UA server")
 
     def _init_opcua(self):
         self.debug_stream("Connecting to OPC-UA server %s:%d...", self.OPC_Server_Name, self.OPC_Server_Port)
@@ -305,9 +319,6 @@ class RCUSCC(Device):
         # PROTECTED REGION ID(RCUSCC.init_device) ENABLED START #
         self.set_state(DevState.INIT)
 
-        # Thread to connect to OPC-UA in the background
-        self.opcua_connector = None
-
         # Init the dict that contains attribute to OPC-UA MP/CP mappings.
         self.attribute_mapping = {}
 
@@ -350,7 +361,9 @@ class RCUSCC(Device):
         # Set defaults to property values.
 
         try:
-            self._wait_opcua_connect()
+            # Connect to OPC-UA
+            self.opcua_connector = BackgroundReconnector(self._init_opcua, self._disconnect, self.debug_stream)
+            self.opcua_connector.wait_connected()
 
             self.set_state(DevState.ON)
         except Exception as e:
-- 
GitLab