1 // svghmi.js |
1 // svghmi.js |
2 |
2 |
3 var cache = hmitree_types.map(_ignored => undefined); |
|
4 var updates = {}; |
3 var updates = {}; |
5 var need_cache_apply = []; |
4 var need_cache_apply = []; |
6 |
5 |
7 |
6 |
8 function dispatch_value(index, value) { |
7 function dispatch_value(index, value) { |
9 let widgets = subscribers[index]; |
8 let widgets = subscribers(index); |
10 |
9 |
11 let oldval = cache[index]; |
10 let oldval = cache[index]; |
12 cache[index] = value; |
11 cache[index] = value; |
13 |
12 |
14 if(widgets.size > 0) { |
13 if(widgets.size > 0) { |
154 |
153 |
155 function send_reset() { |
154 function send_reset() { |
156 send_blob(new Uint8Array([1])); /* reset = 1 */ |
155 send_blob(new Uint8Array([1])); /* reset = 1 */ |
157 }; |
156 }; |
158 |
157 |
159 // subscription state, as it should be in hmi server |
158 var subscriptions = []; |
160 // hmitree indexed array of integers |
159 |
161 var subscriptions = hmitree_types.map(_ignored => 0); |
160 function subscribers(index) { |
162 |
161 let entry = subscriptions[index]; |
163 // subscription state as needed by widget now |
162 let res; |
164 // hmitree indexed array of Sets of widgets objects |
163 if(entry == undefined){ |
165 var subscribers = hmitree_types.map(_ignored => new Set()); |
164 res = new Set(); |
|
165 subscriptions[index] = [res,0]; |
|
166 }else{ |
|
167 [res, _ign] = entry; |
|
168 } |
|
169 return res |
|
170 } |
|
171 |
|
172 function get_subscription_period(index) { |
|
173 let entry = subscriptions[index]; |
|
174 if(entry == undefined) |
|
175 return 0; |
|
176 let [_ign, period] = entry; |
|
177 return period; |
|
178 } |
|
179 |
|
180 function set_subscription_period(index, period) { |
|
181 let entry = subscriptions[index]; |
|
182 if(entry == undefined){ |
|
183 subscriptions[index] = [new Set(), period]; |
|
184 } else { |
|
185 entry[1] = period; |
|
186 } |
|
187 } |
166 |
188 |
167 // artificially subscribe the watchdog widget to "/heartbeat" hmi variable |
189 // artificially subscribe the watchdog widget to "/heartbeat" hmi variable |
168 // Since dispatch directly calls change_hmi_value, |
190 // Since dispatch directly calls change_hmi_value, |
169 // PLC will periodically send variable at given frequency |
191 // PLC will periodically send variable at given frequency |
170 subscribers[heartbeat_index].add({ |
192 subscribers(heartbeat_index).add({ |
171 /* type: "Watchdog", */ |
193 /* type: "Watchdog", */ |
172 frequency: 1, |
194 frequency: 1, |
173 indexes: [heartbeat_index], |
195 indexes: [heartbeat_index], |
174 new_hmi_value: function(index, value, oldval) { |
196 new_hmi_value: function(index, value, oldval) { |
175 apply_hmi_value(heartbeat_index, value+1); |
197 apply_hmi_value(heartbeat_index, value+1); |
176 } |
198 } |
177 }); |
199 }); |
178 |
200 |
|
201 |
179 function update_subscriptions() { |
202 function update_subscriptions() { |
180 let delta = []; |
203 let delta = []; |
181 for(let index = 0; index < subscribers.length; index++){ |
204 for(let index in subscriptions){ |
182 let widgets = subscribers[index]; |
205 let widgets = subscribers(index); |
183 |
206 |
184 // periods are in ms |
207 // periods are in ms |
185 let previous_period = subscriptions[index]; |
208 let previous_period = get_subscription_period(index); |
186 |
209 |
187 // subscribing with a zero period is unsubscribing |
210 // subscribing with a zero period is unsubscribing |
188 let new_period = 0; |
211 let new_period = 0; |
189 if(widgets.size > 0) { |
212 if(widgets.size > 0) { |
190 let maxfreq = 0; |
213 let maxfreq = 0; |
197 if(maxfreq != 0) |
220 if(maxfreq != 0) |
198 new_period = 1000/maxfreq; |
221 new_period = 1000/maxfreq; |
199 } |
222 } |
200 |
223 |
201 if(previous_period != new_period) { |
224 if(previous_period != new_period) { |
202 subscriptions[index] = new_period; |
225 set_subscription_period(index, new_period); |
203 delta.push( |
226 if(index <= last_remote_index){ |
204 new Uint8Array([2]), /* subscribe = 2 */ |
227 delta.push( |
205 new Uint32Array([index]), |
228 new Uint8Array([2]), /* subscribe = 2 */ |
206 new Uint16Array([new_period])); |
229 new Uint32Array([index]), |
|
230 new Uint16Array([new_period])); |
|
231 } |
207 } |
232 } |
208 } |
233 } |
209 send_blob(delta); |
234 send_blob(delta); |
210 }; |
235 }; |
211 |
236 |
212 function send_hmi_value(index, value) { |
237 function send_hmi_value(index, value) { |
213 if(index > last_remote_index){ |
238 if(index > last_remote_index){ |
214 cache[index] = value; |
|
215 console.log("updated local variable ",index,value); |
239 console.log("updated local variable ",index,value); |
216 /* TODO : dispatch value ASAP */ |
240 updates[index] = value; |
|
241 requestHMIAnimation(); |
217 return; |
242 return; |
218 } |
243 } |
219 |
244 |
220 let iectype = hmitree_types[index]; |
245 let iectype = hmitree_types[index]; |
221 let tobinary = typedarray_types[iectype]; |
246 let tobinary = typedarray_types[iectype]; |
313 if(old_desc){ |
338 if(old_desc){ |
314 old_desc.widgets.map(([widget,relativeness])=>widget.unsub()); |
339 old_desc.widgets.map(([widget,relativeness])=>widget.unsub()); |
315 } |
340 } |
316 var new_offset = page_index == undefined ? 0 : page_index - new_desc.page_index; |
341 var new_offset = page_index == undefined ? 0 : page_index - new_desc.page_index; |
317 |
342 |
318 container_id = String([page_name, page_index]); |
343 container_id = page_name + (page_index != undefined ? page_index : ""); |
319 |
344 |
320 new_desc.widgets.map(([widget,relativeness])=>widget.sub(new_offset,relativeness,container_id)); |
345 new_desc.widgets.map(([widget,relativeness])=>widget.sub(new_offset,relativeness,container_id)); |
321 |
346 |
322 update_subscriptions(); |
347 update_subscriptions(); |
323 |
348 |