142 this.element = id(elt_id); |
142 this.element = id(elt_id); |
143 this.args = args; |
143 this.args = args; |
144 this.indexes = indexes; |
144 this.indexes = indexes; |
145 this.minmaxes = minmaxes; |
145 this.minmaxes = minmaxes; |
146 Object.keys(members).forEach(prop => this[prop]=members[prop]); |
146 Object.keys(members).forEach(prop => this[prop]=members[prop]); |
|
147 this.lastapply = indexes.map(() => undefined); |
|
148 this.inhibit = indexes.map(() => undefined); |
|
149 this.pending = indexes.map(() => undefined); |
|
150 this.bound_unhinibit = this.unhinibit.bind(this); |
147 } |
151 } |
148 |
152 |
149 unsub(){ |
153 unsub(){ |
150 /* remove subsribers */ |
154 /* remove subsribers */ |
151 if(!this.unsubscribable) |
155 if(!this.unsubscribable) |
152 for(let i = 0; i < this.indexes.length; i++) { |
156 for(let i = 0; i < this.indexes.length; i++) { |
|
157 /* flush updates pending because of inhibition */ |
|
158 let inhibition = this.inhibit[index]; |
|
159 if(inhibition != undefined){ |
|
160 clearTimeout(inhibition); |
|
161 this.lastapply[index] = undefined; |
|
162 this.unhinibit(index); |
|
163 } |
153 let index = this.indexes[i]; |
164 let index = this.indexes[i]; |
154 if(this.relativeness[i]) |
165 if(this.relativeness[i]) |
155 index += this.offset; |
166 index += this.offset; |
156 subscribers(index).delete(this); |
167 subscribers(index).delete(this); |
157 } |
168 } |
225 let new_val = eval_operation_string(old_val, opstr); |
236 let new_val = eval_operation_string(old_val, opstr); |
226 new_val = this.clip_min_max(index, new_val); |
237 new_val = this.clip_min_max(index, new_val); |
227 return apply_hmi_value(realindex, new_val); |
238 return apply_hmi_value(realindex, new_val); |
228 } |
239 } |
229 |
240 |
230 apply_hmi_value(index, new_val) { |
241 _apply_hmi_value(index, new_val) { |
231 let realindex = this.get_variable_index(index); |
242 let realindex = this.get_variable_index(index); |
232 if(realindex == undefined) return undefined; |
243 if(realindex == undefined) return undefined; |
233 new_val = this.clip_min_max(index, new_val); |
244 new_val = this.clip_min_max(index, new_val); |
234 return apply_hmi_value(realindex, new_val); |
245 return apply_hmi_value(realindex, new_val); |
|
246 } |
|
247 |
|
248 unhinibit(index){ |
|
249 this.inhibit[index] = undefined; |
|
250 let new_val = this.pending[index]; |
|
251 this.pending[index] = undefined; |
|
252 return this.apply_hmi_value(index, new_val); |
|
253 } |
|
254 |
|
255 apply_hmi_value(index, new_val) { |
|
256 if(this.inhibit[index] == undefined){ |
|
257 let now = Date.now(); |
|
258 let min_interval = 1000/this.frequency; |
|
259 let lastapply = this.lastapply[index]; |
|
260 if(lastapply == undefined || now > lastapply + min_interval){ |
|
261 this.lastapply[index] = now; |
|
262 return this._apply_hmi_value(index, new_val); |
|
263 } |
|
264 else { |
|
265 let elapsed = now - lastapply; |
|
266 this.pending[index] = new_val; |
|
267 this.inhibit[index] = setTimeout(this.bound_unhinibit, min_interval - elapsed, index); |
|
268 } |
|
269 } |
|
270 else { |
|
271 this.pending[index] = new_val; |
|
272 return new_val; |
|
273 } |
235 } |
274 } |
236 |
275 |
237 new_hmi_value(index, value, oldval) { |
276 new_hmi_value(index, value, oldval) { |
238 // TODO avoid searching, store index at sub() |
277 // TODO avoid searching, store index at sub() |
239 for(let i = 0; i < this.indexes.length; i++) { |
278 for(let i = 0; i < this.indexes.length; i++) { |