SVGHMI: dispatching data to minimalist "Display" text widget.
--- a/svghmi/gen_index_xhtml.xslt Thu Oct 17 15:48:09 2019 +0200
+++ b/svghmi/gen_index_xhtml.xslt Sat Oct 19 01:23:30 2019 +0200
@@ -198,10 +198,6 @@
<xsl:value-of select="$widget/@type"/>
<xsl:text>",
</xsl:text>
- <xsl:text> frequency: </xsl:text>
- <xsl:apply-templates mode="refresh_frequency" select="$widget"/>
- <xsl:text>,
-</xsl:text>
<xsl:text> args: [
</xsl:text>
<xsl:for-each select="$widget/arg">
@@ -236,8 +232,15 @@
<xsl:text>
</xsl:text>
</xsl:for-each>
- <xsl:text> ]
-</xsl:text>
+ <xsl:text> ],
+</xsl:text>
+ <xsl:text> element: document.getElementById("</xsl:text>
+ <xsl:value-of select="@id"/>
+ <xsl:text>"),
+</xsl:text>
+ <xsl:apply-templates mode="widget_defs" select="$widget">
+ <xsl:with-param name="hmi_element" select="."/>
+ </xsl:apply-templates>
<xsl:text>}</xsl:text>
<xsl:if test="position()!=last()">
<xsl:text>,</xsl:text>
@@ -319,7 +322,43 @@
</xsl:text>
<xsl:text>function dispatch_value(index, value) {
</xsl:text>
- <xsl:text> console.log("dispatch_value("+index+", "+value+")");
+ <xsl:text> let widgets = subscribers[index];
+</xsl:text>
+ <xsl:text>
+</xsl:text>
+ <xsl:text> if(widgets.size > 0) {
+</xsl:text>
+ <xsl:text> for(let widget of widgets){
+</xsl:text>
+ <xsl:text> let idxidx = widget.indexes.indexOf(index);
+</xsl:text>
+ <xsl:text> if(idxidx == -1){
+</xsl:text>
+ <xsl:text> throw new Error("Dispatching to widget not interested, should not happen.");
+</xsl:text>
+ <xsl:text> }
+</xsl:text>
+ <xsl:text> let d = widget.dispatch;
+</xsl:text>
+ <xsl:text> if(typeof(d) == "function" && idxidx == 0){
+</xsl:text>
+ <xsl:text> return d.call(widget,value);
+</xsl:text>
+ <xsl:text> }else if(typeof(d) == "object" && d.length >= idxidx){
+</xsl:text>
+ <xsl:text> d[idxidx].call(widget,value);
+</xsl:text>
+ <xsl:text> }/* else dispatch_0, ..., dispatch_n ? */
+</xsl:text>
+ <xsl:text> /*else {
+</xsl:text>
+ <xsl:text> throw new Error("Dunno how to dispatch to widget at index = " + index);
+</xsl:text>
+ <xsl:text> }*/
+</xsl:text>
+ <xsl:text> }
+</xsl:text>
+ <xsl:text> }
</xsl:text>
<xsl:text>};
</xsl:text>
@@ -357,7 +396,7 @@
</xsl:text>
<xsl:text> let i = 0;
</xsl:text>
- <xsl:text> console.log("Recv something.");
+ <xsl:text> //console.log("Recv something.");
</xsl:text>
<xsl:text> try {
</xsl:text>
@@ -365,7 +404,7 @@
</xsl:text>
<xsl:text> if(hash_int != dv.getUint8(i)){
</xsl:text>
- <xsl:text> throw new Error("Hash doesn't match")
+ <xsl:text> throw new Error("Hash doesn't match");
</xsl:text>
<xsl:text> };
</xsl:text>
@@ -375,7 +414,7 @@
</xsl:text>
<xsl:text>
</xsl:text>
- <xsl:text> console.log("Recv something GOOD.");
+ <xsl:text> //console.log("Recv something GOOD.");
</xsl:text>
<xsl:text>
</xsl:text>
@@ -383,7 +422,7 @@
</xsl:text>
<xsl:text> let index = dv.getUint32(i, true);
</xsl:text>
- <xsl:text> console.log("Recv something index is "+index);
+ <xsl:text> //console.log("Recv something index is "+index);
</xsl:text>
<xsl:text> i += 4;
</xsl:text>
@@ -722,16 +761,30 @@
</xsl:with-param>
</xsl:apply-templates>
</xsl:template>
- <xsl:template mode="refresh_frequency" match="widget">
- <xsl:text>10</xsl:text>
- </xsl:template>
- <xsl:template mode="refresh_frequency" match="widget[@type='Meter']">
- <xsl:text>10</xsl:text>
- </xsl:template>
- <xsl:template mode="refresh_frequency" match="widget[@type='Display']">
- <xsl:text>5</xsl:text>
- </xsl:template>
- <xsl:template mode="refresh_frequency" match="widget[@type='Input']">
- <xsl:text>5</xsl:text>
+ <xsl:template mode="widget_defs" match="widget[@type='Display']">
+ <xsl:param name="hmi_element"/>
+ <xsl:text>frequency: 5,
+</xsl:text>
+ <xsl:text>dispatch: function(value) {
+</xsl:text>
+ <xsl:choose>
+ <xsl:when test="$hmi_element[self::svg:text]">
+ <xsl:text> this.element.textContent = String(value);
+</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">Display widget as a group not implemented</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>},
+</xsl:text>
+ </xsl:template>
+ <xsl:template mode="widget_defs" match="widget[@type='Meter']">
+ <xsl:text> frequency: 10,
+</xsl:text>
+ </xsl:template>
+ <xsl:template mode="widget_defs" match="widget[@type='Input']">
+ <xsl:text> frequency: 5,
+</xsl:text>
</xsl:template>
</xsl:stylesheet>
--- a/svghmi/gen_index_xhtml.ysl2 Thu Oct 17 15:48:09 2019 +0200
+++ b/svghmi/gen_index_xhtml.ysl2 Sat Oct 19 01:23:30 2019 +0200
@@ -191,7 +191,6 @@
const "widget", "func:parselabel(@inkscape:label)/widget";
| «@id»: {
| type: "«$widget/@type»",
- | frequency: `apply "$widget", mode="refresh_frequency"`,
| args: [
foreach "$widget/arg"
| "«@value»"`if "position()!=last()" > ,`
@@ -204,7 +203,9 @@
error > No match for HMI «$hmipath»;
| «$hmitree_match/@index»`if "position()!=last()" > ,`
}
- | ]
+ | ],
+ | element: document.getElementById("«@id»"),
+ apply "$widget", mode="widget_defs" with "hmi_element",".";
| }`if "position()!=last()" > ,`
}
| }
@@ -306,8 +307,33 @@
};
}
- template "widget", mode="refresh_frequency" > 10
+ template "widget[@type='Display']", mode="widget_defs" {
+ param "hmi_element";
+ | frequency: 5,
+ | dispatch: function(value) {
+ choose {
+ when "$hmi_element[self::svg:text]"{
+ // TODO : care about <tspan> ?
+ | this.element.textContent = String(value);
+ }
+ otherwise {
+ error "Display widget as a group not implemented";
+ }
+ }
+ | },
+
+ }
+ template "widget[@type='Meter']", mode="widget_defs" {
+ | frequency: 10,
+ }
+ template "widget[@type='Input']", mode="widget_defs" {
+ | frequency: 5,
+ }
+ // | frequency: 10`apply ".", mode="refresh_frequency"`,
+ // template "widget", mode="refresh_frequency" > 10
+ /*
template "widget[@type='Meter']", mode="refresh_frequency" > 10
template "widget[@type='Display']", mode="refresh_frequency" > 5
template "widget[@type='Input']", mode="refresh_frequency" > 5
+ */
}
--- a/svghmi/svghmi.js Thu Oct 17 15:48:09 2019 +0200
+++ b/svghmi/svghmi.js Sat Oct 19 01:23:30 2019 +0200
@@ -1,7 +1,25 @@
// svghmi.js
function dispatch_value(index, value) {
- console.log("dispatch_value("+index+", "+value+")");
+ let widgets = subscribers[index];
+
+ if(widgets.size > 0) {
+ for(let widget of widgets){
+ let idxidx = widget.indexes.indexOf(index);
+ if(idxidx == -1){
+ throw new Error("Dispatching to widget not interested, should not happen.");
+ }
+ let d = widget.dispatch;
+ if(typeof(d) == "function" && idxidx == 0){
+ return d.call(widget,value);
+ }else if(typeof(d) == "object" && d.length >= idxidx){
+ d[idxidx].call(widget,value);
+ }/* else dispatch_0, ..., dispatch_n ? */
+ /*else {
+ throw new Error("Dunno how to dispatch to widget at index = " + index);
+ }*/
+ }
+ }
};
// Open WebSocket to relative "/ws" address
@@ -23,14 +41,13 @@
try {
for(let hash_int of hmi_hash) {
if(hash_int != dv.getUint8(i)){
- throw new Error("Hash doesn't match")
+ throw new Error("Hash doesn't match");
};
i++;
};
while(i < data.byteLength){
let index = dv.getUint32(i, true);
- console.log("Recv something index is "+index);
i += 4;
let iectype = hmitree_types[index];
if(iectype != undefined){