# HG changeset patch # User Edouard Tisserant <edouard.tisserant@gmail.com> # Date 1583483708 -3600 # Node ID 517583e21bfdc25b8e6c599bec15ee0bf5319353 # Parent 39c8d6079f0f6fd4b7f5e99d2b096347c291a8a3 SVGHMI: use requestAnimationFrame to delegate rendering of updates from network. Should help prevent browser collapse leading to watchdog in case of overload. diff -r 39c8d6079f0f -r 517583e21bfd svghmi/gen_index_xhtml.xslt --- 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" diff -r 39c8d6079f0f -r 517583e21bfd svghmi/svghmi.js --- 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);