# This file is part of Beremiz
# Copyright (C) 2019: Edouard TISSERANT
# See COPYING file for copyrights details.
from __future__ import absolute_import
from twisted.web.server import Site
from twisted.web.resource import Resource
from twisted.internet import reactor
from twisted.web.static import File
from autobahn.twisted.websocket import WebSocketServerFactory, WebSocketServerProtocol
from autobahn.twisted.resource import WebSocketResource
svghmi_send_collect = PLCBinary.svghmi_send_collect
svghmi_send_collect.restype = ctypes.c_int # error or 0
svghmi_send_collect.argtypes = [
ctypes.POINTER(ctypes.c_uint32), # size
ctypes.POINTER(ctypes.c_char_p)] # data ptr
# TODO multiclient : switch to arrays
svghmi_recv_dispatch = PLCBinary.svghmi_recv_dispatch
svghmi_recv_dispatch.restype = ctypes.c_int # error or 0
svghmi_recv_dispatch.argtypes = [
ctypes.c_char_p] # data ptr
# TODO multiclient : switch to arrays
class HMISession(object):
def __init__(self, protocol_instance):
# TODO: kill existing session for robustness
assert(svghmi_session is None)
self.protocol_instance = protocol_instance
# svghmi_sessions.append(self)
# get a unique bit index amont other svghmi_sessions,
# so that we can match flags passed by C->python callback
# svghmi_sessions.remove(self)
def onMessage(self, msg):
# pass message to the C side recieve_message()
c_string = ctypes.c_char_p(msg)
c_string_pointer = ctypes.c_void_p(ctypes.addressof(c_string))
svghmi_recv_dispatch(len(msg), msg)
# TODO multiclient : pass client index as well
def sendMessage(self, msg):
self.sendMessage(msg, True)
class HMIProtocol(WebSocketServerProtocol):
def __init__(self, *args, **kwargs):
WebSocketServerProtocol.__init__(self, *args, **kwargs)
self._hmi_session = HMISession(self)
def onClose(self, wasClean, code, reason):
def onMessage(self, msg, isBinary):
self._hmi_session.onMessage(msg)
#self.sendMessage(msg, binary)
class HMIWebSocketServerFactory(WebSocketServerFactory):
svghmi_send_thread = None
while svghmi_send_collect(ctypes.byref(size), ctypes.byref(ptr)) == 0 and \
svghmi_session is not None and \
svghmi_session.sendMessage(ctypes.string_at(ptr,size)) == 0:
# TODO multiclient : dispatch to sessions
# Called by PLCObject at start
def _runtime_svghmi0_start():
global svghmi_listener, svghmi_root, svghmi_send_thread
svghmi_root.putChild("ws", WebSocketResource(HMIWebSocketServerFactory()))
svghmi_listener = reactor.listenTCP(8008, Site(svghmi_root))
# start a thread that call the C part of SVGHMI
svghmi_send_thread = Thread(target=SendThreadProc, name="SVGHMI Send")
svghmi_send_thread.start()
# Called by PLCObject at stop
def _runtime_svghmi0_stop():
global svghmi_listener, svghmi_root, svghmi_send_thread
svghmi_root.delEntity("ws")
svghmi_listener.stopListening()
# plc cleanup calls svghmi_(locstring)_cleanup and unlocks send thread
svghmi_send_thread.join()
svghmi_send_thread = None