--- a/svghmi/gen_index_xhtml.xslt Wed Sep 18 11:03:56 2019 +0200
+++ b/svghmi/gen_index_xhtml.xslt Wed Sep 18 11:09:35 2019 +0200
@@ -1,6 +1,6 @@
-<xsl:stylesheet xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns:exsl="http://exslt.org/common" xmlns:ns="beremiz" xmlns:cc="http://creativecommons.org/ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dc="http://purl.org/dc/elements/1.1/" extension-element-prefixes="ns" version="1.0" exclude-result-prefixes="ns">
- <xsl:output method="xml"/>
+<xsl:stylesheet xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/1999/xhtml" xmlns:exsl="http://exslt.org/common" xmlns:ns="beremiz" xmlns:cc="http://creativecommons.org/ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dc="http://purl.org/dc/elements/1.1/" extension-element-prefixes="ns" version="1.0" exclude-result-prefixes="ns"> + <xsl:output method="xml" cdata-section-elements="script"/> <xsl:variable name="geometry" select="ns:GetSVGGeometry()"/>
<xsl:variable name="hmitree" select="ns:GetHMITree()"/>
<xsl:template match="@* | node()">
@@ -9,17 +9,44 @@
- <xsl:apply-templates mode="testgeo" select="$geometry"/>
+ <html xmlns="http://www.w3.org/1999/xhtml"> + <body style="margin:0;"> + <xsl:apply-templates mode="testgeo" select="$geometry"/> + <xsl:apply-templates mode="testtree" select="$hmitree"/> + <xsl:apply-templates select="@* | node()"/> + <xsl:text> var relative_URI = window.location.href.replace(/^http(s?:\/\/[^\/]*)\/.*$/, 'ws$1/ws'); + <xsl:text> var ws = new WebSocket(relative_URI); - <xsl:apply-templates mode="testtree" select="$hmitree"/>
- <xsl:apply-templates select="@* | node()"/>
+ <xsl:text> ws.onmessage = function (evt) { + <xsl:text> var received_msg = evt.data; + <xsl:text> alert("Message is received..."+received_msg); + <xsl:text> ws.onopen = function (evt) { + <xsl:text> ws.send("test"); <xsl:template mode="testgeo" match="bbox">
<xsl:text>ID: </xsl:text>
--- a/svghmi/gen_index_xhtml.ysl2 Wed Sep 18 11:03:56 2019 +0200
+++ b/svghmi/gen_index_xhtml.ysl2 Wed Sep 18 11:09:35 2019 +0200
@@ -1,4 +1,7 @@
include yslt_noindent.yml2
+// overrides yslt's output function to set CDATA +decl output(method, cdata-section-elements="script"); xmlns:dc="http://purl.org/dc/elements/1.1/"
@@ -7,6 +10,7 @@
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns="http://www.w3.org/1999/xhtml" /* Our namespace to invoke python code */
@@ -30,17 +34,34 @@
/* copy root node and add geometry as comment for a test */
- apply "$geometry", mode="testgeo";
+ html xmlns="http://www.w3.org/1999/xhtml" { + body style="margin:0;" { + apply "$geometry", mode="testgeo"; + apply "$hmitree", mode="testtree"; + var relative_URI = window.location.href.replace(/^http(s?:\/\/[^\/]*)\/.*$/, 'ws$1/ws'); + var ws = new WebSocket(relative_URI); + ws.onmessage = function (evt) { + var received_msg = evt.data; + alert("Message is received..."+received_msg); + ws.onopen = function (evt) {
- apply "$hmitree", mode="testtree";
template "bbox", mode="testgeo"{
--- a/svghmi/svghmi.c Wed Sep 18 11:03:56 2019 +0200
+++ b/svghmi/svghmi.c Wed Sep 18 11:09:35 2019 +0200
@@ -179,7 +179,7 @@
-int svghmi_send_collect(uint32_t *size, void *ptr){
+int svghmi_send_collect(uint32_t *size, char **ptr){ pthread_mutex_lock(&svghmi_send_WakeCondLock);
@@ -202,7 +202,7 @@
-int svghmi_recv_dispatch(uint32_t size, void* ptr){
+int svghmi_recv_dispatch(uint32_t size, char *ptr){ /* TODO something with ptr and size
--- a/svghmi/svghmi.py Wed Sep 18 11:03:56 2019 +0200
+++ b/svghmi/svghmi.py Wed Sep 18 11:09:35 2019 +0200
@@ -165,8 +165,6 @@
new_node = HMITreeNode(path, path[-1], v["derived"], v["type"], v["vartype"])
hmi_tree_root.place_node(new_node)
- print(hmi_tree_root.pprint())
extern_variables_declarations = []
@@ -366,6 +364,9 @@
def _runtime_svghmi1_%(location)s_start():
svghmi_root.putChild('%(view_name)s',File('%(xhtml)s'))
+def _runtime_svghmi1_%(location)s_stop(): + svghmi_root.delEntity('%(view_name)s') """ % {"location": location_str,
--- a/svghmi/svghmi_server.py Wed Sep 18 11:03:56 2019 +0200
+++ b/svghmi/svghmi_server.py Wed Sep 18 11:09:35 2019 +0200
@@ -25,14 +25,14 @@
svghmi_send_collect.restype = ctypes.c_int # error or 0
svghmi_send_collect.argtypes = [
ctypes.POINTER(ctypes.c_uint32), # size
- ctypes.POINTER(ctypes.c_void_p)] # data ptr
+ 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_uint32, # size
- ctypes.POINTER(ctypes.c_void_p)] # data ptr
+ ctypes.c_uint32, # size + ctypes.c_char_p] # data ptr # TODO multiclient : switch to arrays
class HMISession(object):
@@ -59,15 +59,13 @@
# svghmi_sessions.remove(self)
def onMessage(self, msg):
- # TODO : pass it to the C side recieve_message()
- # - refresh rates / subsriptions
+ # 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
- svghmi_recv_dispatch(len(msg), ctypes.c_void_p.from_buffer_copy(msg))
def sendMessage(self, msg):
self.sendMessage(msg, True)
@@ -92,6 +90,9 @@
#self.sendMessage(msg, binary)
+class HMIWebSocketServerFactory(WebSocketServerFactory): svghmi_send_thread = None
@@ -99,7 +100,7 @@
- ptr = ctypes.c_void_p()
+ ptr = ctypes.c_char_p() while svghmi_send_collect(ctypes.byref(size), ctypes.byref(ptr)) == 0 and \
svghmi_session is not None and \
@@ -109,20 +110,15 @@
# TODO multiclient : dispatch to sessions
# Called by PLCObject at start
def _runtime_svghmi0_start():
global svghmi_listener, svghmi_root, svghmi_send_thread
- wsfactory = WebSocketServerFactory()
- wsfactory.protocol = HMIProtocol
+ svghmi_root.putChild("ws", WebSocketResource(HMIWebSocketServerFactory())) - svghmi_root.putChild("ws", WebSocketResource(wsfactory))
- sitefactory = Site(svghmi_root)
- svghmi_listener = reactor.listenTCP(8008, sitefactory)
+ 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")