svghmi/svghmi_server.py
branchsvghmi
changeset 2822 9101a72a1da0
parent 2819 3b99c908f43b
child 2823 d631f8671c75
--- a/svghmi/svghmi_server.py	Wed Dec 18 13:31:22 2019 +0100
+++ b/svghmi/svghmi_server.py	Fri Jan 10 13:15:07 2020 +0100
@@ -7,6 +7,7 @@
 
 from __future__ import absolute_import
 import errno
+from threading import RLock, Timer
 
 from twisted.web.server import Site
 from twisted.web.resource import Resource
@@ -20,8 +21,10 @@
 # TODO multiclient :
 # session list lock
 # svghmi_sessions = []
+# svghmi_watchdogs = []
 
 svghmi_session = None
+svghmi_watchdog = None
 
 svghmi_send_collect = PLCBinary.svghmi_send_collect
 svghmi_send_collect.restype = ctypes.c_int # error or 0
@@ -61,15 +64,45 @@
 
     def onMessage(self, msg):
         # pass message to the C side recieve_message()
-        svghmi_recv_dispatch(len(msg), msg)
+        return svghmi_recv_dispatch(len(msg), msg)
 
         # TODO multiclient : pass client index as well
 
-
     def sendMessage(self, msg):
         self.protocol_instance.sendMessage(msg, True)
         return 0
 
+class Watchdog(object):
+    def __init__(self, initial_timeout, callback):
+        self._callback = callback
+        self.lock = RLock()
+        self.initial_timeout = initial_timeout
+        self.callback = callback
+        with self.lock:
+            self._start()
+
+    def _start(self):
+        self.timer = Timer(self.initial_timeout, self.trigger)
+        self.timer.start()
+
+    def _stop(self):
+        if self.timer is not None:
+            self.timer.cancel()
+            self.timer = None
+
+    def cancel(self):
+        with self.lock:
+            self._stop()
+
+    def feed(self):
+        with self.lock:
+            self._stop()
+            self._start()
+
+    def trigger(self):
+        self._callback()
+        self.feed()
+
 class HMIProtocol(WebSocketServerProtocol):
 
     def __init__(self, *args, **kwargs):
@@ -85,7 +118,11 @@
 
     def onMessage(self, msg, isBinary):
         assert(self._hmi_session is not None)
-        self._hmi_session.onMessage(msg)
+
+        result = self._hmi_session.onMessage(msg)
+        if result == 1 :  # was heartbeat
+            if svghmi_watchdog is not None:
+                svghmi_watchdog.feed()
 
 class HMIWebSocketServerFactory(WebSocketServerFactory):
     protocol = HMIProtocol
@@ -114,11 +151,13 @@
             break
 
 
-
+def watchdog_trigger():
+    print("SVGHMI watchdog trigger")
+    
 
 # Called by PLCObject at start
 def _runtime_svghmi0_start():
-    global svghmi_listener, svghmi_root, svghmi_send_thread
+    global svghmi_listener, svghmi_root, svghmi_send_thread, svghmi_watchdog
 
     svghmi_root = Resource()
     svghmi_root.putChild("ws", WebSocketResource(HMIWebSocketServerFactory()))
@@ -129,10 +168,16 @@
     svghmi_send_thread = Thread(target=SendThreadProc, name="SVGHMI Send")
     svghmi_send_thread.start()
 
+    svghmi_watchdog = Watchdog(5, watchdog_trigger)
 
 # Called by PLCObject at stop
 def _runtime_svghmi0_stop():
-    global svghmi_listener, svghmi_root, svghmi_send_thread, svghmi_session
+    global svghmi_listener, svghmi_root, svghmi_send_thread, svghmi_session, svghmi_watchdog
+
+    if svghmi_watchdog is not None:
+        svghmi_watchdog.cancel()
+        svghmi_watchdog = None
+
     if svghmi_session is not None:
         svghmi_session.close()
     svghmi_root.delEntity("ws")