Linux runtime: overrun detection for real-time timers and for plc execution.
If real-time timer wakes-up PLC thread too late (10% over period), then
warning is logged.
If PLC code (IO retreive, execution, IO publish) takes longer than requested
PLC execution cycle, then warning is logged, and CPU hoogging is mitigated
by delaying next PLC execution a few cylces more until having at least
1ms minimal idle time.
// widget_meter.ysl2
widget_desc("Meter") {
longdesc
||
Meter widget moves the end of "needle" labeled path along "range" labeled
path, according to value of the single accepted variable.
Needle is reduced to a single segment. If "min" a "max" labeled texts
are provided, or if first and second argument are given, then they are used
as respective minimum and maximum value. Otherwise, value is expected to be
in between 0 and 100.
||
shortdesc > Moves "needle" along "range"
arg name="min" count="optional" accepts="int,real" > minimum value
arg name="max" count="optional" accepts="int,real" > maximum value
path name="value" accepts="HMI_INT,HMI_REAL" > Value to display
}
widget_class("Meter"){
||
frequency = 10;
origin = undefined;
range = undefined;
dispatch(value) {
this.display_val = value;
this.request_animate();
}
animate(){
if(this.value_elt)
this.value_elt.textContent = String(this.display_val);
let [min,max,totallength] = this.range;
let length = Math.max(0,Math.min(totallength,(Number(this.display_val)-min)*totallength/(max-min)));
let tip = this.range_elt.getPointAtLength(length);
this.needle_elt.setAttribute('d', "M "+this.origin.x+","+this.origin.y+" "+tip.x+","+tip.y);
}
init() {
let [min,max] = [[this.min_elt,0],[this.max_elt,100]].map(([elt,def],i)=>elt?
Number(elt.textContent) :
this.args.length >= i+1 ? this.args[i] : def);
this.range = [min, max, this.range_elt.getTotalLength()]
this.origin = this.needle_elt.getPointAtLength(0);
}
||
}
widget_defs("Meter") {
labels("needle range");
optional_labels("min max");
}