SVGHMI: use requestAnimationFrame to delegate rendering of updates from network. Should help prevent browser collapse leading to watchdog in case of overload.
--- a/svghmi/gen_index_xhtml.xslt Thu Mar 05 13:54:29 2020 +0100
+++ b/svghmi/gen_index_xhtml.xslt Fri Mar 06 09:35:08 2020 +0100
@@ -623,6 +623,8 @@
</xsl:text>
<xsl:text>var cache = hmitree_types.map(_ignored => undefined);
</xsl:text>
+ <xsl:text>var updates = {};
+</xsl:text>
<xsl:text>
</xsl:text>
<xsl:text>function dispatch_value_to_widget(widget, index, value, oldval) {
@@ -749,7 +751,33 @@
</xsl:text>
<xsl:text>
</xsl:text>
- <xsl:text>// Register message reception handler
+ <xsl:text>// Apply updates recieved through ws.onmessage to subscribed widgets
+</xsl:text>
+ <xsl:text>// Called on requestAnimationFram, modifies DOM
+</xsl:text>
+ <xsl:text>function apply_pending_updates() {
+</xsl:text>
+ <xsl:text> for(let index in updates){
+</xsl:text>
+ <xsl:text> // serving as a key, index becomes a string
+</xsl:text>
+ <xsl:text> // -> pass Number(index) instead
+</xsl:text>
+ <xsl:text> dispatch_value(Number(index), updates[index]);
+</xsl:text>
+ <xsl:text> delete updates[index];
+</xsl:text>
+ <xsl:text> }
+</xsl:text>
+ <xsl:text>}
+</xsl:text>
+ <xsl:text>
+</xsl:text>
+ <xsl:text>// Message reception handler
+</xsl:text>
+ <xsl:text>// Hash is verified and HMI values updates resulting from binary parsing
+</xsl:text>
+ <xsl:text>// are stored until browser can compute next frame, DOM is left untouched
</xsl:text>
<xsl:text>ws.onmessage = function (evt) {
</xsl:text>
@@ -791,18 +819,22 @@
</xsl:text>
<xsl:text> let [value, bytesize] = dvgetter(dv,i);
</xsl:text>
- <xsl:text> dispatch_value(index, value);
+ <xsl:text> updates[index] = value;
</xsl:text>
<xsl:text> i += bytesize;
</xsl:text>
<xsl:text> } else {
</xsl:text>
- <xsl:text> throw new Error("Unknown index "+index)
+ <xsl:text> throw new Error("Unknown index "+index);
</xsl:text>
<xsl:text> }
</xsl:text>
<xsl:text> };
</xsl:text>
+ <xsl:text> // register for rendering on next frame, since there are updates
+</xsl:text>
+ <xsl:text> window.requestAnimationFrame(apply_pending_updates);
+</xsl:text>
<xsl:text> } catch(err) {
</xsl:text>
<xsl:text> // 1003 is for "Unsupported Data"
--- a/svghmi/svghmi.js Thu Mar 05 13:54:29 2020 +0100
+++ b/svghmi/svghmi.js Fri Mar 06 09:35:08 2020 +0100
@@ -1,6 +1,7 @@
// svghmi.js
var cache = hmitree_types.map(_ignored => undefined);
+var updates = {};
function dispatch_value_to_widget(widget, index, value, oldval) {
try {
@@ -64,7 +65,20 @@
}
};
-// Register message reception handler
+// Apply updates recieved through ws.onmessage to subscribed widgets
+// Called on requestAnimationFrame, modifies DOM
+function apply_pending_updates() {
+ for(let index in updates){
+ // serving as a key, index becomes a string
+ // -> pass Number(index) instead
+ dispatch_value(Number(index), updates[index]);
+ delete updates[index];
+ }
+}
+
+// Message reception handler
+// Hash is verified and HMI values updates resulting from binary parsing
+// are stored until browser can compute next frame, DOM is left untouched
ws.onmessage = function (evt) {
let data = evt.data;
@@ -85,12 +99,14 @@
if(iectype != undefined){
let dvgetter = dvgetters[iectype];
let [value, bytesize] = dvgetter(dv,i);
- dispatch_value(index, value);
+ updates[index] = value;
i += bytesize;
} else {
- throw new Error("Unknown index "+index)
+ throw new Error("Unknown index "+index);
}
};
+ // register for rendering on next frame, since there are updates
+ window.requestAnimationFrame(apply_pending_updates);
} catch(err) {
// 1003 is for "Unsupported Data"
// ws.close(1003, err.message);