28 } |
28 } |
29 }); |
29 }); |
30 }; |
30 }; |
31 |
31 |
32 // Open WebSocket to relative "/ws" address |
32 // Open WebSocket to relative "/ws" address |
|
33 var has_watchdog = window.location.hash == "#watchdog"; |
33 |
34 |
34 var ws_url = |
35 var ws_url = |
35 window.location.href.replace(/^http(s?:\/\/[^\/]*)\/.*$/, 'ws$1/ws') |
36 window.location.href.replace(/^http(s?:\/\/[^\/]*)\/.*$/, 'ws$1/ws') |
36 + '?mode=' + (window.location.hash == "#watchdog" |
37 + '?mode=' + (has_watchdog ? "watchdog" : "multiclient"); |
37 ? "watchdog" |
38 |
38 : "multiclient"); |
|
39 var ws = new WebSocket(ws_url); |
39 var ws = new WebSocket(ws_url); |
40 ws.binaryType = 'arraybuffer'; |
40 ws.binaryType = 'arraybuffer'; |
41 |
41 |
42 const dvgetters = { |
42 const dvgetters = { |
43 INT: (dv,offset) => [dv.getInt16(offset, true), 2], |
43 INT: (dv,offset) => [dv.getInt16(offset, true), 2], |
193 } else { |
193 } else { |
194 entry[1] = period; |
194 entry[1] = period; |
195 } |
195 } |
196 } |
196 } |
197 |
197 |
198 // artificially subscribe the watchdog widget to "/heartbeat" hmi variable |
198 if(has_watchdog){ |
199 // Since dispatch directly calls change_hmi_value, |
199 // artificially subscribe the watchdog widget to "/heartbeat" hmi variable |
200 // PLC will periodically send variable at given frequency |
200 // Since dispatch directly calls change_hmi_value, |
201 subscribers(heartbeat_index).add({ |
201 // PLC will periodically send variable at given frequency |
202 /* type: "Watchdog", */ |
202 subscribers(heartbeat_index).add({ |
|
203 /* type: "Watchdog", */ |
|
204 frequency: 1, |
|
205 indexes: [heartbeat_index], |
|
206 new_hmi_value: function(index, value, oldval) { |
|
207 apply_hmi_value(heartbeat_index, value+1); |
|
208 } |
|
209 }); |
|
210 } |
|
211 |
|
212 // subscribe to per instance current page hmi variable |
|
213 // PLC must prefix page name with "!" for page switch to happen |
|
214 subscribers(current_page_var_index).add({ |
203 frequency: 1, |
215 frequency: 1, |
204 indexes: [heartbeat_index], |
216 indexes: [current_page_var_index], |
205 new_hmi_value: function(index, value, oldval) { |
217 new_hmi_value: function(index, value, oldval) { |
206 apply_hmi_value(heartbeat_index, value+1); |
218 if(value.startsWith("!")) |
|
219 switch_page(value.slice(1)); |
207 } |
220 } |
208 }); |
221 }); |
209 |
222 |
210 function svg_text_to_multiline(elt) { |
223 function svg_text_to_multiline(elt) { |
211 return(Array.prototype.map.call(elt.children, x=>x.textContent).join("\\\\n")); |
224 return(Array.prototype.map.call(elt.children, x=>x.textContent).join("\\\\n")); |
399 return false; |
412 return false; |
400 } |
413 } |
401 |
414 |
402 if(page_name == undefined) |
415 if(page_name == undefined) |
403 page_name = current_subscribed_page; |
416 page_name = current_subscribed_page; |
404 |
417 else if(page_index == undefined){ |
|
418 [page_name, page_index] = page_name.split('@') |
|
419 } |
405 |
420 |
406 let old_desc = page_desc[current_subscribed_page]; |
421 let old_desc = page_desc[current_subscribed_page]; |
407 let new_desc = page_desc[page_name]; |
422 let new_desc = page_desc[page_name]; |
408 |
423 |
409 if(new_desc == undefined){ |
424 if(new_desc == undefined){ |
410 /* TODO LOG ERROR */ |
425 /* TODO LOG ERROR */ |
411 return false; |
426 return false; |
412 } |
427 } |
413 |
428 |
414 if(page_index == undefined){ |
429 if(page_index == undefined) |
415 page_index = new_desc.page_index; |
430 page_index = new_desc.page_index; |
|
431 else if(typeof(page_index) == "string") { |
|
432 let hmitree_node = hmitree_nodes[page_index]; |
|
433 if(hmitree_node !== undefined){ |
|
434 let [int_index, hmiclass] = hmitree_node; |
|
435 if(hmiclass == new_desc.page_class) |
|
436 page_index = int_index; |
|
437 else |
|
438 page_index = new_desc.page_index; |
|
439 } else { |
|
440 page_index = new_desc.page_index; |
|
441 } |
416 } |
442 } |
417 |
443 |
418 if(old_desc){ |
444 if(old_desc){ |
419 old_desc.widgets.map(([widget,relativeness])=>widget.unsub()); |
445 old_desc.widgets.map(([widget,relativeness])=>widget.unsub()); |
420 } |
446 } |
441 requestHMIAnimation(); |
467 requestHMIAnimation(); |
442 jump_history.push([page_name, page_index]); |
468 jump_history.push([page_name, page_index]); |
443 if(jump_history.length > 42) |
469 if(jump_history.length > 42) |
444 jump_history.shift(); |
470 jump_history.shift(); |
445 |
471 |
|
472 apply_hmi_value(current_page_var_index, page_index == undefined |
|
473 ? page_name |
|
474 : page_name + "@" + hmitree_paths[page_index]); |
|
475 |
446 return true; |
476 return true; |
447 }; |
477 }; |
448 |
478 |
449 function switch_visible_page(page_name) { |
479 function switch_visible_page(page_name) { |
450 |
480 |