# HG changeset patch # User Edouard Tisserant # Date 1613276550 -3600 # Node ID 1f5ca646ce6eed28ad44f27d49ea437f0eba9da0 # Parent 1d724e8d5592339c888c212a67dd7e22cf7cc4aa SVGHMI: Add inhibition to widget's apply_hmi_value() so that it does not change variable more frquently than given widget's frequency. This prevents flooding network with many update if browser is producing events at high rate, as for exemple when dragging ScrollBar's cursor. diff -r 1d724e8d5592 -r 1f5ca646ce6e svghmi/widget_scrollbar.ysl2 --- a/svghmi/widget_scrollbar.ysl2 Sun Feb 14 05:17:25 2021 +0100 +++ b/svghmi/widget_scrollbar.ysl2 Sun Feb 14 05:22:30 2021 +0100 @@ -3,7 +3,7 @@ template "widget[@type='ScrollBar']", mode="widget_class"{ || class ScrollBarWidget extends Widget{ - frequency = 5; + frequency = 10; position = undefined; range = undefined; size = undefined; diff -r 1d724e8d5592 -r 1f5ca646ce6e svghmi/widgets_common.ysl2 --- a/svghmi/widgets_common.ysl2 Sun Feb 14 05:17:25 2021 +0100 +++ b/svghmi/widgets_common.ysl2 Sun Feb 14 05:22:30 2021 +0100 @@ -144,12 +144,23 @@ this.indexes = indexes; this.minmaxes = minmaxes; Object.keys(members).forEach(prop => this[prop]=members[prop]); + this.lastapply = indexes.map(() => undefined); + this.inhibit = indexes.map(() => undefined); + this.pending = indexes.map(() => undefined); + this.bound_unhinibit = this.unhinibit.bind(this); } unsub(){ /* remove subsribers */ if(!this.unsubscribable) for(let i = 0; i < this.indexes.length; i++) { + /* flush updates pending because of inhibition */ + let inhibition = this.inhibit[index]; + if(inhibition != undefined){ + clearTimeout(inhibition); + this.lastapply[index] = undefined; + this.unhinibit(index); + } let index = this.indexes[i]; if(this.relativeness[i]) index += this.offset; @@ -227,13 +238,41 @@ return apply_hmi_value(realindex, new_val); } - apply_hmi_value(index, new_val) { + _apply_hmi_value(index, new_val) { let realindex = this.get_variable_index(index); if(realindex == undefined) return undefined; new_val = this.clip_min_max(index, new_val); return apply_hmi_value(realindex, new_val); } + unhinibit(index){ + this.inhibit[index] = undefined; + let new_val = this.pending[index]; + this.pending[index] = undefined; + return this.apply_hmi_value(index, new_val); + } + + apply_hmi_value(index, new_val) { + if(this.inhibit[index] == undefined){ + let now = Date.now(); + let min_interval = 1000/this.frequency; + let lastapply = this.lastapply[index]; + if(lastapply == undefined || now > lastapply + min_interval){ + this.lastapply[index] = now; + return this._apply_hmi_value(index, new_val); + } + else { + let elapsed = now - lastapply; + this.pending[index] = new_val; + this.inhibit[index] = setTimeout(this.bound_unhinibit, min_interval - elapsed, index); + } + } + else { + this.pending[index] = new_val; + return new_val; + } + } + new_hmi_value(index, value, oldval) { // TODO avoid searching, store index at sub() for(let i = 0; i < this.indexes.length; i++) {