svghmi/svghmi_server.py
author Edouard Tisserant
Fri, 09 Jul 2021 15:47:43 +0200
branchsvghmi
changeset 3271 561dbd1e3e04
parent 3270 38f7122ccbf9
child 3272 c8182e066545
permissions -rw-r--r--
SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
2771
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
     1
#!/usr/bin/env python
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
     2
# -*- coding: utf-8 -*-
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
     3
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
     4
# This file is part of Beremiz
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
     5
# Copyright (C) 2019: Edouard TISSERANT
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
     6
# See COPYING file for copyrights details.
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
     7
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
     8
from __future__ import absolute_import
2799
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
     9
import errno
2822
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
    10
from threading import RLock, Timer
2771
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
    11
2823
d631f8671c75 SVGHMI : add on Start, Stop and Watchdog command fields to configuration
Edouard Tisserant
parents: 2822
diff changeset
    12
try:
d631f8671c75 SVGHMI : add on Start, Stop and Watchdog command fields to configuration
Edouard Tisserant
parents: 2822
diff changeset
    13
    from runtime.spawn_subprocess import Popen
d631f8671c75 SVGHMI : add on Start, Stop and Watchdog command fields to configuration
Edouard Tisserant
parents: 2822
diff changeset
    14
except ImportError:
d631f8671c75 SVGHMI : add on Start, Stop and Watchdog command fields to configuration
Edouard Tisserant
parents: 2822
diff changeset
    15
    from subprocess import Popen
d631f8671c75 SVGHMI : add on Start, Stop and Watchdog command fields to configuration
Edouard Tisserant
parents: 2822
diff changeset
    16
2771
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
    17
from twisted.web.server import Site
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
    18
from twisted.web.resource import Resource
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
    19
from twisted.internet import reactor
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
    20
from twisted.web.static import File
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
    21
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
    22
from autobahn.twisted.websocket import WebSocketServerFactory, WebSocketServerProtocol
2799
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
    23
from autobahn.websocket.protocol import WebSocketProtocol
2771
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
    24
from autobahn.twisted.resource import  WebSocketResource
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
    25
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    26
max_svghmi_sessions = None
2822
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
    27
svghmi_watchdog = None
2771
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
    28
3271
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
    29
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
    30
svghmi_wait = PLCBinary.svghmi_wait
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
    31
svghmi_wait.restype = ctypes.c_int # error or 0
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
    32
svghmi_wait.argtypes = []
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
    33
2774
9857b4b0d979 SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2773
diff changeset
    34
svghmi_send_collect = PLCBinary.svghmi_send_collect
9857b4b0d979 SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2773
diff changeset
    35
svghmi_send_collect.restype = ctypes.c_int # error or 0
9857b4b0d979 SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2773
diff changeset
    36
svghmi_send_collect.argtypes = [
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    37
    ctypes.c_uint32,  # index
2774
9857b4b0d979 SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2773
diff changeset
    38
    ctypes.POINTER(ctypes.c_uint32),  # size
2799
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
    39
    ctypes.POINTER(ctypes.c_void_p)]  # data ptr
2774
9857b4b0d979 SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2773
diff changeset
    40
3271
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
    41
svghmi_reset = PLCBinary.svghmi_reset
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
    42
svghmi_reset.restype = ctypes.c_int # error or 0
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
    43
svghmi_reset.argtypes = [
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
    44
    ctypes.c_uint32]  # index
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
    45
2774
9857b4b0d979 SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2773
diff changeset
    46
svghmi_recv_dispatch = PLCBinary.svghmi_recv_dispatch
9857b4b0d979 SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2773
diff changeset
    47
svghmi_recv_dispatch.restype = ctypes.c_int # error or 0
9857b4b0d979 SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2773
diff changeset
    48
svghmi_recv_dispatch.argtypes = [
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    49
    ctypes.c_uint32,  # index
2788
2ed9ff826d03 SVGHMI: Work in progress. C side mostly implemented, neither built nor tested.
Edouard Tisserant
parents: 2779
diff changeset
    50
    ctypes.c_uint32,  # size
2779
75c6a31caca6 SVGHMI: Work In Progress : fixed pointer types in ctypes interface, cleaned up server startup and cleanup code, changed document type to XHTML, cleaner JS script : encapsulated in a function and in CDATA.
Edouard Tisserant
parents: 2777
diff changeset
    51
    ctypes.c_char_p]  # data ptr
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    52
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    53
class HMISessionMgr(object):
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    54
    def __init__(self):
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    55
        self.multiclient_sessions = set()
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    56
        self.watchdog_session = None
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    57
        self.session_count = 0
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    58
        self.lock = RLock()
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    59
        self.indexes = set()
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    60
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    61
    def next_index(self):
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    62
        if self.indexes:
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    63
            greatest = max(self.indexes)
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    64
            holes = set(range(greatest)) - self.indexes
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    65
            index = min(holes) if holes else greatest+1
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    66
        else:
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    67
            index = 0
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    68
        self.indexes.add(index)
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    69
        return index
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    70
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    71
    def free_index(self, index):
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    72
        self.indexes.remove(index)
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    73
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    74
    def register(self, session):
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    75
        global max_svghmi_sessions
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    76
        with self.lock:
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    77
            if session.is_watchdog_session:
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    78
                # Creating a new watchdog session closes pre-existing one
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    79
                if self.watchdog_session is not None:
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    80
                    self.unregister(self.watchdog_session)
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    81
                else:
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    82
                    assert(self.session_count < max_svghmi_sessions)
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    83
                    self.session_count += 1
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    84
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    85
                self.watchdog_session = session
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    86
            else:
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    87
                assert(self.session_count < max_svghmi_sessions)
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    88
                self.multiclient_sessions.add(session)
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    89
                self.session_count += 1
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    90
            session.session_index = self.next_index()
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    91
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    92
    def unregister(self, session):
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    93
        with self.lock:
3271
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
    94
            if session.is_watchdog_session :
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
    95
                if self.watchdog_session != session:
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
    96
                    return
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    97
                self.watchdog_session = None
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
    98
            else:
3271
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
    99
                try:
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   100
                    self.multiclient_sessions.remove(self)
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   101
                except KeyError:
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   102
                    return
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   103
            self.free_index(session.session_index)
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   104
            self.session_count -= 1
3271
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   105
        session.kill()
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   106
        
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   107
    def close_all(self):
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   108
        with self.lock:
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   109
            close_list = list(self.multiclient_sessions)
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   110
            if self.watchdog_session:
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   111
                close_list.append(self.watchdog_session)
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   112
            for session in close_list:
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   113
                self.unregister(session)
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   114
        
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   115
    def iter_sessions(self):
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   116
        with self.lock:
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   117
            nxt_session = self.watchdog_session
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   118
        if nxt_session is not None:
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   119
            yield nxt_session
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   120
        idx = 0
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   121
        while True:
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   122
            with self.lock:
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   123
                if idx >= len(self.multiclient_sessions):
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   124
                    return
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   125
                nxt_session = self.multiclient_sessions[idx]
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   126
            yield nxt_session
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   127
            idx += 1
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   128
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   129
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   130
svghmi_session_manager = HMISessionMgr()
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   131
2774
9857b4b0d979 SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2773
diff changeset
   132
2771
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   133
class HMISession(object):
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   134
    def __init__(self, protocol_instance):
2773
6e5e752372c8 SVGHMI: single session for now
Edouard Tisserant
parents: 2772
diff changeset
   135
        self.protocol_instance = protocol_instance
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   136
        self._session_index = None
3271
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   137
        self.closed = False
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   138
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   139
    @property
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   140
    def is_watchdog_session(self):
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   141
        return self.protocol_instance.has_watchdog
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   142
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   143
    @property
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   144
    def session_index(self):
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   145
        return self._session_index
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   146
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   147
    @session_index.setter
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   148
    def session_index(self, value):
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   149
        self._session_index = value
2775
3b93409ba22c SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2774
diff changeset
   150
3271
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   151
    def reset(self):
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   152
        return svghmi_reset(self.session_index)
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   153
2799
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   154
    def close(self):
3271
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   155
        if self.closed: return
2799
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   156
        self.protocol_instance.sendClose(WebSocketProtocol.CLOSE_STATUS_CODE_NORMAL)
2771
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   157
3271
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   158
    def notify_closed(self):
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   159
        self.closed = True
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   160
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   161
    def kill(self):
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   162
        self.close()
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   163
        self.reset()
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   164
2772
3f1dd8312710 SVGHMI: few fixes on serving
Edouard Tisserant
parents: 2771
diff changeset
   165
    def onMessage(self, msg):
2779
75c6a31caca6 SVGHMI: Work In Progress : fixed pointer types in ctypes interface, cleaned up server startup and cleanup code, changed document type to XHTML, cleaner JS script : encapsulated in a function and in CDATA.
Edouard Tisserant
parents: 2777
diff changeset
   166
        # pass message to the C side recieve_message()
3271
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   167
        if self.closed: return
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   168
        return svghmi_recv_dispatch(self.session_index, len(msg), msg)
2777
cdf6584953a0 SVGHMI: WIP for python<->C data exchange : message from browser hit the C side.
Edouard Tisserant
parents: 2776
diff changeset
   169
2774
9857b4b0d979 SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2773
diff changeset
   170
    def sendMessage(self, msg):
3271
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   171
        if self.closed: return
2799
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   172
        self.protocol_instance.sendMessage(msg, True)
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   173
        return 0
2771
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   174
2822
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   175
class Watchdog(object):
2831
6c9cfdbe94dc SVGHMI : watchdog is now taking an initial and interval duration as CTN fields.
Edouard Tisserant
parents: 2830
diff changeset
   176
    def __init__(self, initial_timeout, interval, callback):
2822
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   177
        self._callback = callback
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   178
        self.lock = RLock()
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   179
        self.initial_timeout = initial_timeout
2831
6c9cfdbe94dc SVGHMI : watchdog is now taking an initial and interval duration as CTN fields.
Edouard Tisserant
parents: 2830
diff changeset
   180
        self.interval = interval
2822
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   181
        self.callback = callback
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   182
        with self.lock:
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   183
            self._start()
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   184
2831
6c9cfdbe94dc SVGHMI : watchdog is now taking an initial and interval duration as CTN fields.
Edouard Tisserant
parents: 2830
diff changeset
   185
    def _start(self, rearm=False):
6c9cfdbe94dc SVGHMI : watchdog is now taking an initial and interval duration as CTN fields.
Edouard Tisserant
parents: 2830
diff changeset
   186
        duration = self.interval if rearm else self.initial_timeout
6c9cfdbe94dc SVGHMI : watchdog is now taking an initial and interval duration as CTN fields.
Edouard Tisserant
parents: 2830
diff changeset
   187
        if duration:
6c9cfdbe94dc SVGHMI : watchdog is now taking an initial and interval duration as CTN fields.
Edouard Tisserant
parents: 2830
diff changeset
   188
            self.timer = Timer(duration, self.trigger)
6c9cfdbe94dc SVGHMI : watchdog is now taking an initial and interval duration as CTN fields.
Edouard Tisserant
parents: 2830
diff changeset
   189
            self.timer.start()
2835
bc666f020ab3 SVGHMI : fix watchdog exception when timeout null
Edouard Tisserant
parents: 2832
diff changeset
   190
        else:
bc666f020ab3 SVGHMI : fix watchdog exception when timeout null
Edouard Tisserant
parents: 2832
diff changeset
   191
            self.timer = None
2822
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   192
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   193
    def _stop(self):
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   194
        if self.timer is not None:
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   195
            self.timer.cancel()
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   196
            self.timer = None
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   197
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   198
    def cancel(self):
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   199
        with self.lock:
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   200
            self._stop()
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   201
2832
e9ba4dee6ffb SVGHMI : wait for initial timeout after watchdog is triggered, since it generaly induces HMI restart
Edouard Tisserant
parents: 2831
diff changeset
   202
    def feed(self, rearm=True):
2822
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   203
        with self.lock:
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   204
            self._stop()
2832
e9ba4dee6ffb SVGHMI : wait for initial timeout after watchdog is triggered, since it generaly induces HMI restart
Edouard Tisserant
parents: 2831
diff changeset
   205
            self._start(rearm)
2822
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   206
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   207
    def trigger(self):
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   208
        self._callback()
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   209
        # Don't repeat trigger periodically
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   210
        # # wait for initial timeout on re-start
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   211
        # self.feed(rearm=False)
2822
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   212
2771
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   213
class HMIProtocol(WebSocketServerProtocol):
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   214
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   215
    def __init__(self, *args, **kwargs):
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   216
        self._hmi_session = None
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   217
        self.has_watchdog = False
2771
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   218
        WebSocketServerProtocol.__init__(self, *args, **kwargs)
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   219
3268
d22782b9591f SVGHMI: Added a way to distinguish watchdog-enabled HMI from multi-client HMI in URL.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3200
diff changeset
   220
    def onConnect(self, request):
d22782b9591f SVGHMI: Added a way to distinguish watchdog-enabled HMI from multi-client HMI in URL.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3200
diff changeset
   221
        self.has_watchdog = request.params.get("mode", [None])[0] == "watchdog"
d22782b9591f SVGHMI: Added a way to distinguish watchdog-enabled HMI from multi-client HMI in URL.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3200
diff changeset
   222
        return WebSocketServerProtocol.onConnect(self, request)
d22782b9591f SVGHMI: Added a way to distinguish watchdog-enabled HMI from multi-client HMI in URL.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3200
diff changeset
   223
2771
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   224
    def onOpen(self):
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   225
        global svghmi_session_manager
2799
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   226
        assert(self._hmi_session is None)
2771
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   227
        self._hmi_session = HMISession(self)
3271
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   228
        registered = svghmi_session_manager.register(self._hmi_session)
2771
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   229
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   230
    def onClose(self, wasClean, code, reason):
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   231
        global svghmi_session_manager
3271
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   232
        self._hmi_session.notify_closed()
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   233
        svghmi_session_manager.unregister(self._hmi_session)
2771
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   234
        self._hmi_session = None
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   235
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   236
    def onMessage(self, msg, isBinary):
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   237
        global svghmi_watchdog
2799
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   238
        assert(self._hmi_session is not None)
2822
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   239
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   240
        result = self._hmi_session.onMessage(msg)
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   241
        if result == 1 and self.has_watchdog:  # was heartbeat
2822
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   242
            if svghmi_watchdog is not None:
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   243
                svghmi_watchdog.feed()
2775
3b93409ba22c SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2774
diff changeset
   244
2779
75c6a31caca6 SVGHMI: Work In Progress : fixed pointer types in ctypes interface, cleaned up server startup and cleanup code, changed document type to XHTML, cleaner JS script : encapsulated in a function and in CDATA.
Edouard Tisserant
parents: 2777
diff changeset
   245
class HMIWebSocketServerFactory(WebSocketServerFactory):
75c6a31caca6 SVGHMI: Work In Progress : fixed pointer types in ctypes interface, cleaned up server startup and cleanup code, changed document type to XHTML, cleaner JS script : encapsulated in a function and in CDATA.
Edouard Tisserant
parents: 2777
diff changeset
   246
    protocol = HMIProtocol
75c6a31caca6 SVGHMI: Work In Progress : fixed pointer types in ctypes interface, cleaned up server startup and cleanup code, changed document type to XHTML, cleaner JS script : encapsulated in a function and in CDATA.
Edouard Tisserant
parents: 2777
diff changeset
   247
3269
5d174cdf4d98 SVGHMI: More configuration parameters : network interface, TCP port, URL path and watchdog enabling.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3268
diff changeset
   248
svghmi_servers = {}
2775
3b93409ba22c SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2774
diff changeset
   249
svghmi_send_thread = None
3b93409ba22c SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2774
diff changeset
   250
2776
246ae685ab65 SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2775
diff changeset
   251
def SendThreadProc():
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   252
    global svghmi_session_manager
2819
3b99c908f43b SVGHMI: change collect/send thread looping condition to fix infinite loop in some cases
Edouard Tisserant
parents: 2799
diff changeset
   253
    size = ctypes.c_uint32()
3b99c908f43b SVGHMI: change collect/send thread looping condition to fix infinite loop in some cases
Edouard Tisserant
parents: 2799
diff changeset
   254
    ptr = ctypes.c_void_p()
3b99c908f43b SVGHMI: change collect/send thread looping condition to fix infinite loop in some cases
Edouard Tisserant
parents: 2799
diff changeset
   255
    res = 0
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   256
    finished = False
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   257
    while not(finished):
3271
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   258
        svghmi_wait()
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   259
        for svghmi_session in svghmi_session_manager.iter_sessions():
3271
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   260
            # TODO make svghmi_send_collect waiting only once per
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   261
            # svghmi_session_manager.iter_sessions cycle
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   262
            res = svghmi_send_collect(
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   263
                svghmi_session.session_index,
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   264
                ctypes.byref(size), ctypes.byref(ptr))
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   265
            if res == 0:
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   266
                svghmi_session.sendMessage(
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   267
                    ctypes.string_at(ptr.value,size.value))
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   268
            elif res == errno.ENODATA:
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   269
                # this happens when there is no data after wakeup
3271
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   270
                # because of hmi data refresh period longer than
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   271
                # PLC common ticktime
3271
561dbd1e3e04 SVGHMI: Fixing last commit's multiclient implementation, in case of watchdog. To be continued, since multiclient still fail...
Edouard Tisserant
parents: 3270
diff changeset
   272
                pass
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   273
            else:
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   274
                # this happens when finishing
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   275
                finished = True
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   276
                break
2776
246ae685ab65 SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2775
diff changeset
   277
3269
5d174cdf4d98 SVGHMI: More configuration parameters : network interface, TCP port, URL path and watchdog enabling.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3268
diff changeset
   278
def AddPathToSVGHMIServers(path, factory):
5d174cdf4d98 SVGHMI: More configuration parameters : network interface, TCP port, URL path and watchdog enabling.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3268
diff changeset
   279
    for k,v in svghmi_servers.iteritems():
5d174cdf4d98 SVGHMI: More configuration parameters : network interface, TCP port, URL path and watchdog enabling.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3268
diff changeset
   280
        svghmi_root, svghmi_listener, path_list = v
5d174cdf4d98 SVGHMI: More configuration parameters : network interface, TCP port, URL path and watchdog enabling.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3268
diff changeset
   281
        svghmi_root.putChild(path, factory())
2779
75c6a31caca6 SVGHMI: Work In Progress : fixed pointer types in ctypes interface, cleaned up server startup and cleanup code, changed document type to XHTML, cleaner JS script : encapsulated in a function and in CDATA.
Edouard Tisserant
parents: 2777
diff changeset
   282
2771
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   283
# Called by PLCObject at start
2993
b76f303ffce6 Python Runtime: order of execution of extension's init() and cleanup() now reflects order of appearance of extensions in configuration tree.
Edouard Tisserant
parents: 2835
diff changeset
   284
def _runtime_00_svghmi_start():
3269
5d174cdf4d98 SVGHMI: More configuration parameters : network interface, TCP port, URL path and watchdog enabling.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3268
diff changeset
   285
    global svghmi_send_thread
2771
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   286
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   287
    # start a thread that call the C part of SVGHMI
2775
3b93409ba22c SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2774
diff changeset
   288
    svghmi_send_thread = Thread(target=SendThreadProc, name="SVGHMI Send")
3b93409ba22c SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2774
diff changeset
   289
    svghmi_send_thread.start()
2771
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   290
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   291
361366b891ca WIP on svghmi, now builds and runs. HTTP serving + WS transport ready, missing actual data to transmit and thread to collect it.
Edouard Tisserant
parents:
diff changeset
   292
# Called by PLCObject at stop
2993
b76f303ffce6 Python Runtime: order of execution of extension's init() and cleanup() now reflects order of appearance of extensions in configuration tree.
Edouard Tisserant
parents: 2835
diff changeset
   293
def _runtime_00_svghmi_stop():
3269
5d174cdf4d98 SVGHMI: More configuration parameters : network interface, TCP port, URL path and watchdog enabling.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3268
diff changeset
   294
    global svghmi_send_thread, svghmi_session
2822
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2819
diff changeset
   295
3270
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   296
    svghmi_session_manager.close_all()
38f7122ccbf9 SVGHMI: Implemented multiserver+multiclient, but only tested with single client and single server for now. To be continued...
Edouard Tisserant
parents: 3269
diff changeset
   297
2775
3b93409ba22c SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2774
diff changeset
   298
    # plc cleanup calls svghmi_(locstring)_cleanup and unlocks send thread
3b93409ba22c SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2774
diff changeset
   299
    svghmi_send_thread.join()
3b93409ba22c SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2774
diff changeset
   300
    svghmi_send_thread = None
3b93409ba22c SVGHMI: WIP for python<->C data exchange
Edouard Tisserant
parents: 2774
diff changeset
   301
2830
15d7bd79d9e8 SVGHMI : avoid caching of xhtml file by forcing cache-control header in http response.
Edouard Tisserant
parents: 2823
diff changeset
   302
15d7bd79d9e8 SVGHMI : avoid caching of xhtml file by forcing cache-control header in http response.
Edouard Tisserant
parents: 2823
diff changeset
   303
class NoCacheFile(File):
15d7bd79d9e8 SVGHMI : avoid caching of xhtml file by forcing cache-control header in http response.
Edouard Tisserant
parents: 2823
diff changeset
   304
    def render_GET(self, request):
15d7bd79d9e8 SVGHMI : avoid caching of xhtml file by forcing cache-control header in http response.
Edouard Tisserant
parents: 2823
diff changeset
   305
        request.setHeader(b"Cache-Control", b"no-cache, no-store")
15d7bd79d9e8 SVGHMI : avoid caching of xhtml file by forcing cache-control header in http response.
Edouard Tisserant
parents: 2823
diff changeset
   306
        return File.render_GET(self, request)
15d7bd79d9e8 SVGHMI : avoid caching of xhtml file by forcing cache-control header in http response.
Edouard Tisserant
parents: 2823
diff changeset
   307
    render_HEAD = render_GET
15d7bd79d9e8 SVGHMI : avoid caching of xhtml file by forcing cache-control header in http response.
Edouard Tisserant
parents: 2823
diff changeset
   308
15d7bd79d9e8 SVGHMI : avoid caching of xhtml file by forcing cache-control header in http response.
Edouard Tisserant
parents: 2823
diff changeset
   309