svghmi/svghmi.js
author Edouard Tisserant
Thu, 24 Nov 2022 11:47:56 +0100
changeset 3690 f41733be17a8
parent 3685 570a738239f4
child 3837 efe0b5b21842
permissions -rw-r--r--
SVGHMI: move declaration of "xmlns" javascript const so that widgets can use it.

This was broken in earlier commit, when changing initial execution order because of implementing websocket reconnect.
2783
5ee6967f721d SVGHMI: Starting to define JS side more in details.
Edouard Tisserant
parents: 2780
diff changeset
     1
// svghmi.js
5ee6967f721d SVGHMI: Starting to define JS side more in details.
Edouard Tisserant
parents: 2780
diff changeset
     2
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
     3
function dispatch_value(index, value) {
3022
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
     4
    let widgets = subscribers(index);
2800
68cee1366b9c SVGHMI: dispatching data to minimalist "Display" text widget.
Edouard Tisserant
parents: 2799
diff changeset
     5
2805
e521e0d133d5 SVGHMI: fixed HMI->PLC dataflow : not updates as expected, and not initialized properly after subscribe.
Edouard Tisserant
parents: 2803
diff changeset
     6
    let oldval = cache[index];
e521e0d133d5 SVGHMI: fixed HMI->PLC dataflow : not updates as expected, and not initialized properly after subscribe.
Edouard Tisserant
parents: 2803
diff changeset
     7
    cache[index] = value;
e521e0d133d5 SVGHMI: fixed HMI->PLC dataflow : not updates as expected, and not initialized properly after subscribe.
Edouard Tisserant
parents: 2803
diff changeset
     8
2800
68cee1366b9c SVGHMI: dispatching data to minimalist "Display" text widget.
Edouard Tisserant
parents: 2799
diff changeset
     9
    if(widgets.size > 0) {
68cee1366b9c SVGHMI: dispatching data to minimalist "Display" text widget.
Edouard Tisserant
parents: 2799
diff changeset
    10
        for(let widget of widgets){
3006
bbffdefd2eed SVGHMI: JS refactoring continued : "dispatch_value_to_widget" becomes widget class member "new_hmi_value" (was also broken by previous relativeness commit)
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3005
diff changeset
    11
            widget.new_hmi_value(index, value, oldval);
2800
68cee1366b9c SVGHMI: dispatching data to minimalist "Display" text widget.
Edouard Tisserant
parents: 2799
diff changeset
    12
        }
68cee1366b9c SVGHMI: dispatching data to minimalist "Display" text widget.
Edouard Tisserant
parents: 2799
diff changeset
    13
    }
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
    14
};
2783
5ee6967f721d SVGHMI: Starting to define JS side more in details.
Edouard Tisserant
parents: 2780
diff changeset
    15
2801
390acff12755 SVGHMI: Added init call to all widgets at startup to bind events. More features in Input widget : Edit and Change buttons. WIP HMI->PLC value update, incoherent data detected in C part on update.
Edouard Tisserant
parents: 2800
diff changeset
    16
function init_widgets() {
390acff12755 SVGHMI: Added init call to all widgets at startup to bind events. More features in Input widget : Edit and Change buttons. WIP HMI->PLC value update, incoherent data detected in C part on update.
Edouard Tisserant
parents: 2800
diff changeset
    17
    Object.keys(hmi_widgets).forEach(function(id) {
390acff12755 SVGHMI: Added init call to all widgets at startup to bind events. More features in Input widget : Edit and Change buttons. WIP HMI->PLC value update, incoherent data detected in C part on update.
Edouard Tisserant
parents: 2800
diff changeset
    18
        let widget = hmi_widgets[id];
3455
2716cd8e498d SVGHMI: Add support for forcing widget update frequency with period longer than a second. As an example, "HMI:Display|10s@/myvar" updates variable every 10 seconds.
Edouard Tisserant
parents: 3451
diff changeset
    19
        widget.do_init();
2801
390acff12755 SVGHMI: Added init call to all widgets at startup to bind events. More features in Input widget : Edit and Change buttons. WIP HMI->PLC value update, incoherent data detected in C part on update.
Edouard Tisserant
parents: 2800
diff changeset
    20
    });
390acff12755 SVGHMI: Added init call to all widgets at startup to bind events. More features in Input widget : Edit and Change buttons. WIP HMI->PLC value update, incoherent data detected in C part on update.
Edouard Tisserant
parents: 2800
diff changeset
    21
};
390acff12755 SVGHMI: Added init call to all widgets at startup to bind events. More features in Input widget : Edit and Change buttons. WIP HMI->PLC value update, incoherent data detected in C part on update.
Edouard Tisserant
parents: 2800
diff changeset
    22
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
    23
// Open WebSocket to relative "/ws" address
3381
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
    24
var has_watchdog = window.location.hash == "#watchdog";
3268
d22782b9591f SVGHMI: Added a way to distinguish watchdog-enabled HMI from multi-client HMI in URL.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3206
diff changeset
    25
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
    26
const dvgetters = {
2826
1e5abecc3cde SVGHMI : support for HMI_STRING and HMI_BOOL
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2822
diff changeset
    27
    INT: (dv,offset) => [dv.getInt16(offset, true), 2],
1e5abecc3cde SVGHMI : support for HMI_STRING and HMI_BOOL
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2822
diff changeset
    28
    BOOL: (dv,offset) => [dv.getInt8(offset, true), 1],
2890
ae8063127e95 SVGHMI: make root HMI tree node a HMI_NODE, droped HMI_ROOT node type
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2889
diff changeset
    29
    NODE: (dv,offset) => [dv.getInt8(offset, true), 1],
3068
81758c94f3df SVGHMI: Fix HMI_REAL support, and add a HMI_REAL use case in tests/svghmi.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3035
diff changeset
    30
    REAL: (dv,offset) => [dv.getFloat32(offset, true), 4],
2826
1e5abecc3cde SVGHMI : support for HMI_STRING and HMI_BOOL
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2822
diff changeset
    31
    STRING: (dv, offset) => {
3080
e5fa1f49f0b9 SVGHMI: WIP trying to reduce memory usage : use .onclick onstead of SetAttribute, avoid useless closure and object creation when possible, etc.
Edouard Tisserant
parents: 3078
diff changeset
    32
        const size = dv.getInt8(offset);
2826
1e5abecc3cde SVGHMI : support for HMI_STRING and HMI_BOOL
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2822
diff changeset
    33
        return [
1e5abecc3cde SVGHMI : support for HMI_STRING and HMI_BOOL
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2822
diff changeset
    34
            String.fromCharCode.apply(null, new Uint8Array(
1e5abecc3cde SVGHMI : support for HMI_STRING and HMI_BOOL
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2822
diff changeset
    35
                dv.buffer, /* original buffer */
1e5abecc3cde SVGHMI : support for HMI_STRING and HMI_BOOL
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2822
diff changeset
    36
                offset + 1, /* string starts after size*/
1e5abecc3cde SVGHMI : support for HMI_STRING and HMI_BOOL
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2822
diff changeset
    37
                size /* size of string */
1e5abecc3cde SVGHMI : support for HMI_STRING and HMI_BOOL
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2822
diff changeset
    38
            )), size + 1]; /* total increment */
1e5abecc3cde SVGHMI : support for HMI_STRING and HMI_BOOL
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2822
diff changeset
    39
    }
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
    40
};
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
    41
2865
545902730141 SVGHMI: cosmetic code moving
Edouard Tisserant
parents: 2864
diff changeset
    42
// Called on requestAnimationFrame, modifies DOM
545902730141 SVGHMI: cosmetic code moving
Edouard Tisserant
parents: 2864
diff changeset
    43
var requestAnimationFrameID = null;
545902730141 SVGHMI: cosmetic code moving
Edouard Tisserant
parents: 2864
diff changeset
    44
function animate() {
3553
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    45
    let rearm = true;
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    46
    do{
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    47
        if(page_fading == "pending" || page_fading == "forced"){
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    48
            if(page_fading == "pending")
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    49
                svg_root.classList.add("fade-out-page");
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    50
            page_fading = "in_progress";
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    51
            if(page_fading_args.length)
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    52
                setTimeout(function(){
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    53
                    switch_page(...page_fading_args);
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    54
                },1);
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    55
            break;
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    56
        }
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    57
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    58
        // Do the page swith if pending
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    59
        if(page_switch_in_progress){
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    60
            if(current_subscribed_page != current_visible_page){
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    61
                switch_visible_page(current_subscribed_page);
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    62
            }
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    63
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    64
            page_switch_in_progress = false;
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    65
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    66
            if(page_fading == "in_progress"){
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    67
                svg_root.classList.remove("fade-out-page");
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    68
                page_fading = "off";
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    69
            }
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    70
        }
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    71
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    72
        if(jumps_need_update) update_jumps();
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    73
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    74
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    75
        pending_widget_animates.forEach(widget => widget._animate());
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    76
        pending_widget_animates = [];
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    77
        rearm = false;
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    78
    } while(0);
3019
497aac6522a3 SVGHMI: provide request_animate() to Widget authors so that they can register redraw code when events lead to redraw. Widget member animate() is called when it is time to update DOM.
Edouard Tisserant
parents: 3018
diff changeset
    79
2864
36f78f6cfabd SVGHMI: split page switch into switching subscription and switching elements in the DOM, to ensure that subscriptions have been send before changing DOM, and avoid some flicker.
Edouard Tisserant
parents: 2860
diff changeset
    80
    requestAnimationFrameID = null;
3553
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    81
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
    82
    if(rearm) requestHMIAnimation();
2859
517583e21bfd SVGHMI: use requestAnimationFrame to delegate rendering of updates from network. Should help prevent browser collapse leading to watchdog in case of overload.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2850
diff changeset
    83
}
517583e21bfd SVGHMI: use requestAnimationFrame to delegate rendering of updates from network. Should help prevent browser collapse leading to watchdog in case of overload.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2850
diff changeset
    84
2860
b7650c6abeda SVGHMI: more decoupling in between UI related and the rest of JS code, still in the aim of enhancing robustness under heavy load.
Edouard Tisserant
parents: 2859
diff changeset
    85
function requestHMIAnimation() {
2864
36f78f6cfabd SVGHMI: split page switch into switching subscription and switching elements in the DOM, to ensure that subscriptions have been send before changing DOM, and avoid some flicker.
Edouard Tisserant
parents: 2860
diff changeset
    86
    if(requestAnimationFrameID == null){
36f78f6cfabd SVGHMI: split page switch into switching subscription and switching elements in the DOM, to ensure that subscriptions have been send before changing DOM, and avoid some flicker.
Edouard Tisserant
parents: 2860
diff changeset
    87
        requestAnimationFrameID = window.requestAnimationFrame(animate);
36f78f6cfabd SVGHMI: split page switch into switching subscription and switching elements in the DOM, to ensure that subscriptions have been send before changing DOM, and avoid some flicker.
Edouard Tisserant
parents: 2860
diff changeset
    88
    }
2860
b7650c6abeda SVGHMI: more decoupling in between UI related and the rest of JS code, still in the aim of enhancing robustness under heavy load.
Edouard Tisserant
parents: 2859
diff changeset
    89
}
b7650c6abeda SVGHMI: more decoupling in between UI related and the rest of JS code, still in the aim of enhancing robustness under heavy load.
Edouard Tisserant
parents: 2859
diff changeset
    90
2859
517583e21bfd SVGHMI: use requestAnimationFrame to delegate rendering of updates from network. Should help prevent browser collapse leading to watchdog in case of overload.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2850
diff changeset
    91
// Message reception handler
517583e21bfd SVGHMI: use requestAnimationFrame to delegate rendering of updates from network. Should help prevent browser collapse leading to watchdog in case of overload.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2850
diff changeset
    92
// Hash is verified and HMI values updates resulting from binary parsing
517583e21bfd SVGHMI: use requestAnimationFrame to delegate rendering of updates from network. Should help prevent browser collapse leading to watchdog in case of overload.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2850
diff changeset
    93
// are stored until browser can compute next frame, DOM is left untouched
3648
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
    94
function ws_onmessage(evt) {
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
    95
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
    96
    let data = evt.data;
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
    97
    let dv = new DataView(data);
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
    98
    let i = 0;
2799
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
    99
    try {
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   100
        for(let hash_int of hmi_hash) {
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   101
            if(hash_int != dv.getUint8(i)){
2800
68cee1366b9c SVGHMI: dispatching data to minimalist "Display" text widget.
Edouard Tisserant
parents: 2799
diff changeset
   102
                throw new Error("Hash doesn't match");
2799
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   103
            };
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   104
            i++;
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   105
        };
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   106
2799
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   107
        while(i < data.byteLength){
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   108
            let index = dv.getUint32(i, true);
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   109
            i += 4;
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   110
            let iectype = hmitree_types[index];
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   111
            if(iectype != undefined){
2826
1e5abecc3cde SVGHMI : support for HMI_STRING and HMI_BOOL
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2822
diff changeset
   112
                let dvgetter = dvgetters[iectype];
1e5abecc3cde SVGHMI : support for HMI_STRING and HMI_BOOL
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2822
diff changeset
   113
                let [value, bytesize] = dvgetter(dv,i);
3624
770c613c424f SVGHMI: remove intermediate "updates" Map and apply_updates()
Edouard Tisserant
parents: 3603
diff changeset
   114
                dispatch_value(index, value);
2799
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   115
                i += bytesize;
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   116
            } else {
2859
517583e21bfd SVGHMI: use requestAnimationFrame to delegate rendering of updates from network. Should help prevent browser collapse leading to watchdog in case of overload.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2850
diff changeset
   117
                throw new Error("Unknown index "+index);
2799
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   118
            }
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   119
        };
3602
1bd8e077894e SVGHMI: re-arrange Animate and data Dispath code paths.
Edouard Tisserant
parents: 3553
diff changeset
   120
2859
517583e21bfd SVGHMI: use requestAnimationFrame to delegate rendering of updates from network. Should help prevent browser collapse leading to watchdog in case of overload.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2850
diff changeset
   121
        // register for rendering on next frame, since there are updates
2799
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   122
    } catch(err) {
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   123
        // 1003 is for "Unsupported Data"
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   124
        // ws.close(1003, err.message);
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   125
2799
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   126
        // TODO : remove debug alert ?
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   127
        alert("Error : "+err.message+"\\\\nHMI will be reloaded.");
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   128
2799
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   129
        // force reload ignoring cache
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   130
        location.reload(true);
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   131
    }
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   132
};
2783
5ee6967f721d SVGHMI: Starting to define JS side more in details.
Edouard Tisserant
parents: 2780
diff changeset
   133
3080
e5fa1f49f0b9 SVGHMI: WIP trying to reduce memory usage : use .onclick onstead of SetAttribute, avoid useless closure and object creation when possible, etc.
Edouard Tisserant
parents: 3078
diff changeset
   134
hmi_hash_u8 = new Uint8Array(hmi_hash);
2788
2ed9ff826d03 SVGHMI: Work in progress. C side mostly implemented, neither built nor tested.
Edouard Tisserant
parents: 2783
diff changeset
   135
3648
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   136
var ws = null;
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   137
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   138
function send_blob(data) {
3648
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   139
    if(ws && data.length > 0) {
3080
e5fa1f49f0b9 SVGHMI: WIP trying to reduce memory usage : use .onclick onstead of SetAttribute, avoid useless closure and object creation when possible, etc.
Edouard Tisserant
parents: 3078
diff changeset
   140
        ws.send(new Blob([hmi_hash_u8].concat(data)));
2780
e468f18df200 SVGHMI: moved static JS code to a separate file included at xhtml generation time
Edouard Tisserant
parents:
diff changeset
   141
    };
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   142
};
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   143
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   144
const typedarray_types = {
2829
4c2c50f60730 SVGHMI : HMI_STRING now also supported from HMI to PLC
Edouard Tisserant
parents: 2827
diff changeset
   145
    INT: (number) => new Int16Array([number]),
3645
82882a9f91ce SVGHMI: cosmetic fixes
Edouard Tisserant
parents: 3625
diff changeset
   146
    BOOL: (truth) => new Int8Array([truth]),
82882a9f91ce SVGHMI: cosmetic fixes
Edouard Tisserant
parents: 3625
diff changeset
   147
    NODE: (truth) => new Int8Array([truth]),
3145
80ebb88cf7b7 SVGHMI: Fixed sending HMI_REAL to PLC. Added a svghmi_real test that illustrates using printf style formating in HMI:Display to control precision of Float number display.
Edouard Tisserant
parents: 3142
diff changeset
   148
    REAL: (number) => new Float32Array([number]),
2829
4c2c50f60730 SVGHMI : HMI_STRING now also supported from HMI to PLC
Edouard Tisserant
parents: 2827
diff changeset
   149
    STRING: (str) => {
4c2c50f60730 SVGHMI : HMI_STRING now also supported from HMI to PLC
Edouard Tisserant
parents: 2827
diff changeset
   150
        // beremiz default string max size is 128
4c2c50f60730 SVGHMI : HMI_STRING now also supported from HMI to PLC
Edouard Tisserant
parents: 2827
diff changeset
   151
        str = str.slice(0,128);
4c2c50f60730 SVGHMI : HMI_STRING now also supported from HMI to PLC
Edouard Tisserant
parents: 2827
diff changeset
   152
        binary = new Uint8Array(str.length + 1);
4c2c50f60730 SVGHMI : HMI_STRING now also supported from HMI to PLC
Edouard Tisserant
parents: 2827
diff changeset
   153
        binary[0] = str.length;
3080
e5fa1f49f0b9 SVGHMI: WIP trying to reduce memory usage : use .onclick onstead of SetAttribute, avoid useless closure and object creation when possible, etc.
Edouard Tisserant
parents: 3078
diff changeset
   154
        for(let i = 0; i < str.length; i++){
2829
4c2c50f60730 SVGHMI : HMI_STRING now also supported from HMI to PLC
Edouard Tisserant
parents: 2827
diff changeset
   155
            binary[i+1] = str.charCodeAt(i);
4c2c50f60730 SVGHMI : HMI_STRING now also supported from HMI to PLC
Edouard Tisserant
parents: 2827
diff changeset
   156
        }
4c2c50f60730 SVGHMI : HMI_STRING now also supported from HMI to PLC
Edouard Tisserant
parents: 2827
diff changeset
   157
        return binary;
4c2c50f60730 SVGHMI : HMI_STRING now also supported from HMI to PLC
Edouard Tisserant
parents: 2827
diff changeset
   158
    }
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   159
    /* TODO */
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   160
};
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   161
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   162
function send_reset() {
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   163
    send_blob(new Uint8Array([1])); /* reset = 1 */
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   164
};
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   165
3022
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   166
var subscriptions = [];
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   167
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   168
function subscribers(index) {
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   169
    let entry = subscriptions[index];
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   170
    let res;
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   171
    if(entry == undefined){
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   172
        res = new Set();
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   173
        subscriptions[index] = [res,0];
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   174
    }else{
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   175
        [res, _ign] = entry;
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   176
    }
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   177
    return res
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   178
}
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   179
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   180
function get_subscription_period(index) {
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   181
    let entry = subscriptions[index];
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   182
    if(entry == undefined)
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   183
        return 0;
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   184
    let [_ign, period] = entry;
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   185
    return period;
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   186
}
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   187
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   188
function set_subscription_period(index, period) {
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   189
    let entry = subscriptions[index];
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   190
    if(entry == undefined){
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   191
        subscriptions[index] = [new Set(), period];
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   192
    } else {
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   193
        entry[1] = period;
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   194
    }
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   195
}
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   196
3648
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   197
function reset_subscription_periods() {
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   198
    for(let index in subscriptions)
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   199
        subscriptions[index][1] = 0;
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   200
}
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   201
3381
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   202
if(has_watchdog){
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   203
    // artificially subscribe the watchdog widget to "/heartbeat" hmi variable
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   204
    // Since dispatch directly calls change_hmi_value,
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   205
    // PLC will periodically send variable at given frequency
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   206
    subscribers(heartbeat_index).add({
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   207
        /* type: "Watchdog", */
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   208
        frequency: 1,
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   209
        indexes: [heartbeat_index],
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   210
        new_hmi_value: function(index, value, oldval) {
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   211
            apply_hmi_value(heartbeat_index, value+1);
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   212
        }
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   213
    });
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   214
}
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   215
3512
fce3d407bb46 SVGHMI: add fading transition to make page switch feel more responsive on slow machines.
Edouard Tisserant
parents: 3455
diff changeset
   216
3553
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
   217
var page_fading = "off";
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
   218
var page_fading_args = "off";
3512
fce3d407bb46 SVGHMI: add fading transition to make page switch feel more responsive on slow machines.
Edouard Tisserant
parents: 3455
diff changeset
   219
function fading_page_switch(...args){
3553
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
   220
    if(page_fading == "in_progress")
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
   221
        page_fading = "forced";
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
   222
    else
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
   223
        page_fading = "pending";
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
   224
    page_fading_args = args;
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
   225
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
   226
    requestHMIAnimation();
406eb8a13648 SVGHMI: re-organize animate() to ensure that page fade-out is always visible, also make fade-out curve more aggressive to enhance visual feedback.
Edouard Tisserant
parents: 3535
diff changeset
   227
3512
fce3d407bb46 SVGHMI: add fading transition to make page switch feel more responsive on slow machines.
Edouard Tisserant
parents: 3455
diff changeset
   228
}
fce3d407bb46 SVGHMI: add fading transition to make page switch feel more responsive on slow machines.
Edouard Tisserant
parents: 3455
diff changeset
   229
document.body.style.backgroundColor = "black";
fce3d407bb46 SVGHMI: add fading transition to make page switch feel more responsive on slow machines.
Edouard Tisserant
parents: 3455
diff changeset
   230
3381
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   231
// subscribe to per instance current page hmi variable
3385
18621ce81f5f SVGHMI: Changes /CURRENT_PAGE_* behaviour to prevent problem whith multiclient : all clients were switching page when one was jumping.
Edouard Tisserant
parents: 3381
diff changeset
   232
// PLC must prefix page name with "!" for page switch to happen
3381
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   233
subscribers(current_page_var_index).add({
2822
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2811
diff changeset
   234
    frequency: 1,
3381
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   235
    indexes: [current_page_var_index],
3006
bbffdefd2eed SVGHMI: JS refactoring continued : "dispatch_value_to_widget" becomes widget class member "new_hmi_value" (was also broken by previous relativeness commit)
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3005
diff changeset
   236
    new_hmi_value: function(index, value, oldval) {
3385
18621ce81f5f SVGHMI: Changes /CURRENT_PAGE_* behaviour to prevent problem whith multiclient : all clients were switching page when one was jumping.
Edouard Tisserant
parents: 3381
diff changeset
   237
        if(value.startsWith("!"))
3512
fce3d407bb46 SVGHMI: add fading transition to make page switch feel more responsive on slow machines.
Edouard Tisserant
parents: 3455
diff changeset
   238
            fading_page_switch(value.slice(1));
2822
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2811
diff changeset
   239
    }
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2811
diff changeset
   240
});
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2811
diff changeset
   241
3142
2637bb6a6bb0 SVGHMI: allow i18n of formated strings of HMI:Messages. This was by construction impossible since formating was given as an argument. Now added optional "format" labelled element in HMI:Display, so that it can be translated, when labelled "_format".
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3137
diff changeset
   242
function svg_text_to_multiline(elt) {
2637bb6a6bb0 SVGHMI: allow i18n of formated strings of HMI:Messages. This was by construction impossible since formating was given as an argument. Now added optional "format" labelled element in HMI:Display, so that it can be translated, when labelled "_format".
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3137
diff changeset
   243
    return(Array.prototype.map.call(elt.children, x=>x.textContent).join("\\\\n")); 
2637bb6a6bb0 SVGHMI: allow i18n of formated strings of HMI:Messages. This was by construction impossible since formating was given as an argument. Now added optional "format" labelled element in HMI:Display, so that it can be translated, when labelled "_format".
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3137
diff changeset
   244
}
2637bb6a6bb0 SVGHMI: allow i18n of formated strings of HMI:Messages. This was by construction impossible since formating was given as an argument. Now added optional "format" labelled element in HMI:Display, so that it can be translated, when labelled "_format".
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3137
diff changeset
   245
3524
27d298c6f961 SVGHMI: force initial state of Display widget to empty string.
Edouard Tisserant
parents: 3514
diff changeset
   246
function multiline_to_svg_text(elt, str, blank) {
27d298c6f961 SVGHMI: force initial state of Display widget to empty string.
Edouard Tisserant
parents: 3514
diff changeset
   247
    str.split('\\\\n').map((line,i) => {elt.children[i].textContent = blank?"":line;});
3142
2637bb6a6bb0 SVGHMI: allow i18n of formated strings of HMI:Messages. This was by construction impossible since formating was given as an argument. Now added optional "format" labelled element in HMI:Display, so that it can be translated, when labelled "_format".
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3137
diff changeset
   248
}
3129
f2709923c82c SVGHMI: Add "lang" permament persistent HMI_LOCAL variable to reflect selected language, apply stored language choice at startup and make it always subscribed to a pseudo widget (as for hearbeat) that apply language choice when it changes.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3128
diff changeset
   249
f2709923c82c SVGHMI: Add "lang" permament persistent HMI_LOCAL variable to reflect selected language, apply stored language choice at startup and make it always subscribed to a pseudo widget (as for hearbeat) that apply language choice when it changes.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3128
diff changeset
   250
function switch_langnum(langnum) {
3144
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   251
    langnum = Math.max(0, Math.min(langs.length - 1, langnum));
3129
f2709923c82c SVGHMI: Add "lang" permament persistent HMI_LOCAL variable to reflect selected language, apply stored language choice at startup and make it always subscribed to a pseudo widget (as for hearbeat) that apply language choice when it changes.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3128
diff changeset
   252
f2709923c82c SVGHMI: Add "lang" permament persistent HMI_LOCAL variable to reflect selected language, apply stored language choice at startup and make it always subscribed to a pseudo widget (as for hearbeat) that apply language choice when it changes.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3128
diff changeset
   253
    for (let translation of translations) {
3144
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   254
        let [objs, msgs] = translation;
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   255
        let msg = msgs[langnum];
3129
f2709923c82c SVGHMI: Add "lang" permament persistent HMI_LOCAL variable to reflect selected language, apply stored language choice at startup and make it always subscribed to a pseudo widget (as for hearbeat) that apply language choice when it changes.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3128
diff changeset
   256
        for (let obj of objs) {
3142
2637bb6a6bb0 SVGHMI: allow i18n of formated strings of HMI:Messages. This was by construction impossible since formating was given as an argument. Now added optional "format" labelled element in HMI:Display, so that it can be translated, when labelled "_format".
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3137
diff changeset
   257
            multiline_to_svg_text(obj, msg);
2637bb6a6bb0 SVGHMI: allow i18n of formated strings of HMI:Messages. This was by construction impossible since formating was given as an argument. Now added optional "format" labelled element in HMI:Display, so that it can be translated, when labelled "_format".
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3137
diff changeset
   258
            obj.setAttribute("lang",langnum);
3129
f2709923c82c SVGHMI: Add "lang" permament persistent HMI_LOCAL variable to reflect selected language, apply stored language choice at startup and make it always subscribed to a pseudo widget (as for hearbeat) that apply language choice when it changes.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3128
diff changeset
   259
        }
f2709923c82c SVGHMI: Add "lang" permament persistent HMI_LOCAL variable to reflect selected language, apply stored language choice at startup and make it always subscribed to a pseudo widget (as for hearbeat) that apply language choice when it changes.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3128
diff changeset
   260
    }
3144
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   261
    return langnum;
3129
f2709923c82c SVGHMI: Add "lang" permament persistent HMI_LOCAL variable to reflect selected language, apply stored language choice at startup and make it always subscribed to a pseudo widget (as for hearbeat) that apply language choice when it changes.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3128
diff changeset
   262
}
3142
2637bb6a6bb0 SVGHMI: allow i18n of formated strings of HMI:Messages. This was by construction impossible since formating was given as an argument. Now added optional "format" labelled element in HMI:Display, so that it can be translated, when labelled "_format".
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3137
diff changeset
   263
2637bb6a6bb0 SVGHMI: allow i18n of formated strings of HMI:Messages. This was by construction impossible since formating was given as an argument. Now added optional "format" labelled element in HMI:Display, so that it can be translated, when labelled "_format".
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3137
diff changeset
   264
// backup original texts
2637bb6a6bb0 SVGHMI: allow i18n of formated strings of HMI:Messages. This was by construction impossible since formating was given as an argument. Now added optional "format" labelled element in HMI:Display, so that it can be translated, when labelled "_format".
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3137
diff changeset
   265
for (let translation of translations) {
3144
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   266
    let [objs, msgs] = translation;
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   267
    msgs.unshift(svg_text_to_multiline(objs[0])); 
3142
2637bb6a6bb0 SVGHMI: allow i18n of formated strings of HMI:Messages. This was by construction impossible since formating was given as an argument. Now added optional "format" labelled element in HMI:Display, so that it can be translated, when labelled "_format".
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3137
diff changeset
   268
}
2637bb6a6bb0 SVGHMI: allow i18n of formated strings of HMI:Messages. This was by construction impossible since formating was given as an argument. Now added optional "format" labelled element in HMI:Display, so that it can be translated, when labelled "_format".
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3137
diff changeset
   269
3129
f2709923c82c SVGHMI: Add "lang" permament persistent HMI_LOCAL variable to reflect selected language, apply stored language choice at startup and make it always subscribed to a pseudo widget (as for hearbeat) that apply language choice when it changes.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3128
diff changeset
   270
var lang_local_index = hmi_local_index("lang");
3144
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   271
var langcode_local_index = hmi_local_index("lang_code");
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   272
var langname_local_index = hmi_local_index("lang_name");
3129
f2709923c82c SVGHMI: Add "lang" permament persistent HMI_LOCAL variable to reflect selected language, apply stored language choice at startup and make it always subscribed to a pseudo widget (as for hearbeat) that apply language choice when it changes.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3128
diff changeset
   273
subscribers(lang_local_index).add({
f2709923c82c SVGHMI: Add "lang" permament persistent HMI_LOCAL variable to reflect selected language, apply stored language choice at startup and make it always subscribed to a pseudo widget (as for hearbeat) that apply language choice when it changes.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3128
diff changeset
   274
    indexes: [lang_local_index],
f2709923c82c SVGHMI: Add "lang" permament persistent HMI_LOCAL variable to reflect selected language, apply stored language choice at startup and make it always subscribed to a pseudo widget (as for hearbeat) that apply language choice when it changes.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3128
diff changeset
   275
    new_hmi_value: function(index, value, oldval) {
3144
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   276
        let current_lang =  switch_langnum(value);
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   277
        let [langname,langcode] = langs[current_lang];
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   278
        apply_hmi_value(langcode_local_index, langcode);
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   279
        apply_hmi_value(langname_local_index, langname);
3142
2637bb6a6bb0 SVGHMI: allow i18n of formated strings of HMI:Messages. This was by construction impossible since formating was given as an argument. Now added optional "format" labelled element in HMI:Display, so that it can be translated, when labelled "_format".
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3137
diff changeset
   280
        switch_page();
3129
f2709923c82c SVGHMI: Add "lang" permament persistent HMI_LOCAL variable to reflect selected language, apply stored language choice at startup and make it always subscribed to a pseudo widget (as for hearbeat) that apply language choice when it changes.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3128
diff changeset
   281
    }
f2709923c82c SVGHMI: Add "lang" permament persistent HMI_LOCAL variable to reflect selected language, apply stored language choice at startup and make it always subscribed to a pseudo widget (as for hearbeat) that apply language choice when it changes.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3128
diff changeset
   282
});
3144
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   283
3451
302efcf746e0 SVGHMI: add localized Date and Time support to sprintf.js. Use with "%D" or "%2.1D" format style.
Edouard Tisserant
parents: 3417
diff changeset
   284
// returns en_US, fr_FR or en_UK depending on selected language
302efcf746e0 SVGHMI: add localized Date and Time support to sprintf.js. Use with "%D" or "%2.1D" format style.
Edouard Tisserant
parents: 3417
diff changeset
   285
function get_current_lang_code(){
302efcf746e0 SVGHMI: add localized Date and Time support to sprintf.js. Use with "%D" or "%2.1D" format style.
Edouard Tisserant
parents: 3417
diff changeset
   286
    return cache[langcode_local_index];
302efcf746e0 SVGHMI: add localized Date and Time support to sprintf.js. Use with "%D" or "%2.1D" format style.
Edouard Tisserant
parents: 3417
diff changeset
   287
}
302efcf746e0 SVGHMI: add localized Date and Time support to sprintf.js. Use with "%D" or "%2.1D" format style.
Edouard Tisserant
parents: 3417
diff changeset
   288
3144
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   289
function setup_lang(){
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   290
    let current_lang = cache[lang_local_index];
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   291
    let new_lang = switch_langnum(current_lang);
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   292
    if(current_lang != new_lang){
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   293
        apply_hmi_value(lang_local_index, new_lang);
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   294
    }
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   295
}
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   296
2af6afaccaf2 SVGHMI: i18n: ensure langs always appea in same order, and add two variables that are updated automatically when selecting a new language : lang_name and lang_code. Also fixed i18n startup, prevent wrong lang numer to crash loading.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3142
diff changeset
   297
setup_lang();
3022
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   298
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   299
function update_subscriptions() {
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   300
    let delta = [];
3648
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   301
    if(!ws)
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   302
        // dont' change subscriptions if not connected
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   303
        return;
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   304
3022
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   305
    for(let index in subscriptions){
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   306
        let widgets = subscribers(index);
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   307
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   308
        // periods are in ms
3022
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   309
        let previous_period = get_subscription_period(index);
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   310
2822
9101a72a1da0 SVGHMI: added a watchdog. To ensure that the whole chain is checked, watchdog use a periodic echo of a hearteat variable. JS client code systematically register /HEARTBEAT at 1s update freq, and reacts on updates of /HEARTBEAT by systematically incrementing it. C code catch /HEARTBEAT update and feeds python-implemented watchdog. For now, watchdog does nothing when tiggered
Edouard Tisserant
parents: 2811
diff changeset
   311
        // subscribing with a zero period is unsubscribing
2799
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   312
        let new_period = 0;
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   313
        if(widgets.size > 0) {
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   314
            let maxfreq = 0;
2960
5ad82541b46e SVGHMI: explicit handling of undefined maximum widget update frequency
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2951
diff changeset
   315
            for(let widget of widgets){
5ad82541b46e SVGHMI: explicit handling of undefined maximum widget update frequency
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2951
diff changeset
   316
                let wf = widget.frequency;
5ad82541b46e SVGHMI: explicit handling of undefined maximum widget update frequency
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2951
diff changeset
   317
                if(wf != undefined && maxfreq < wf)
5ad82541b46e SVGHMI: explicit handling of undefined maximum widget update frequency
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2951
diff changeset
   318
                    maxfreq = wf;
5ad82541b46e SVGHMI: explicit handling of undefined maximum widget update frequency
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2951
diff changeset
   319
            }
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   320
2799
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   321
            if(maxfreq != 0)
f5da343b9b63 SVGHMI: Many fixes. Subscriptions to HMItree seems to be working, and dispatch function is called in JS with good data. Bidirectional communication now really working.
Edouard Tisserant
parents: 2798
diff changeset
   322
                new_period = 1000/maxfreq;
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   323
        }
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   324
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   325
        if(previous_period != new_period) {
3022
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   326
            set_subscription_period(index, new_period);
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   327
            if(index <= last_remote_index){
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   328
                delta.push(
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   329
                    new Uint8Array([2]), /* subscribe = 2 */
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   330
                    new Uint32Array([index]),
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   331
                    new Uint16Array([new_period]));
f6fe42b7ce60 SVGHMI: finished initial implementation of PAGE_LOCAL and HMI_LOCAL variables.
Edouard Tisserant
parents: 3017
diff changeset
   332
            }
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   333
        }
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   334
    }
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   335
    send_blob(delta);
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   336
};
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   337
2801
390acff12755 SVGHMI: Added init call to all widgets at startup to bind events. More features in Input widget : Edit and Change buttons. WIP HMI->PLC value update, incoherent data detected in C part on update.
Edouard Tisserant
parents: 2800
diff changeset
   338
function send_hmi_value(index, value) {
3017
15e2df3e5610 SVGHMI: Intermediate state while implementing local HMI variables. Now write to cache only (no send), still need to implement dispatch on change.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3006
diff changeset
   339
    if(index > last_remote_index){
3602
1bd8e077894e SVGHMI: re-arrange Animate and data Dispath code paths.
Edouard Tisserant
parents: 3553
diff changeset
   340
        dispatch_value(index, value);
3128
32a4675af377 SVGHMI: Added HMI:VarInitPersistent to initialize persistent HMI_LOCAL and PAGE_LOCAL variables, stored as cookies in browser.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3126
diff changeset
   341
32a4675af377 SVGHMI: Added HMI:VarInitPersistent to initialize persistent HMI_LOCAL and PAGE_LOCAL variables, stored as cookies in browser.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3126
diff changeset
   342
        if(persistent_indexes.has(index)){
32a4675af377 SVGHMI: Added HMI:VarInitPersistent to initialize persistent HMI_LOCAL and PAGE_LOCAL variables, stored as cookies in browser.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3126
diff changeset
   343
            let varname = persistent_indexes.get(index);
32a4675af377 SVGHMI: Added HMI:VarInitPersistent to initialize persistent HMI_LOCAL and PAGE_LOCAL variables, stored as cookies in browser.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3126
diff changeset
   344
            document.cookie = varname+"="+value+"; max-age=3153600000";
32a4675af377 SVGHMI: Added HMI:VarInitPersistent to initialize persistent HMI_LOCAL and PAGE_LOCAL variables, stored as cookies in browser.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3126
diff changeset
   345
        }
32a4675af377 SVGHMI: Added HMI:VarInitPersistent to initialize persistent HMI_LOCAL and PAGE_LOCAL variables, stored as cookies in browser.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3126
diff changeset
   346
3017
15e2df3e5610 SVGHMI: Intermediate state while implementing local HMI variables. Now write to cache only (no send), still need to implement dispatch on change.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3006
diff changeset
   347
        return;
15e2df3e5610 SVGHMI: Intermediate state while implementing local HMI variables. Now write to cache only (no send), still need to implement dispatch on change.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3006
diff changeset
   348
    }
15e2df3e5610 SVGHMI: Intermediate state while implementing local HMI variables. Now write to cache only (no send), still need to implement dispatch on change.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3006
diff changeset
   349
2802
64e6f73b9859 SVGHMI - Fixed svghmi.{c,js} about HMI -> PLC data unpack.
Edouard Tisserant
parents: 2801
diff changeset
   350
    let iectype = hmitree_types[index];
2829
4c2c50f60730 SVGHMI : HMI_STRING now also supported from HMI to PLC
Edouard Tisserant
parents: 2827
diff changeset
   351
    let tobinary = typedarray_types[iectype];
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   352
    send_blob([
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   353
        new Uint8Array([0]),  /* setval = 0 */
2829
4c2c50f60730 SVGHMI : HMI_STRING now also supported from HMI to PLC
Edouard Tisserant
parents: 2827
diff changeset
   354
        new Uint32Array([index]),
4c2c50f60730 SVGHMI : HMI_STRING now also supported from HMI to PLC
Edouard Tisserant
parents: 2827
diff changeset
   355
        tobinary(value)]);
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   356
2921
2670f5c53caf SVGHMI: HMI is not speculating on PLC variable update anymore when sending new variable value.
Edouard Tisserant
parents: 2920
diff changeset
   357
    // DON'T DO THAT unless read_iterator in svghmi.c modifies wbuf as well, not only rbuf
2670f5c53caf SVGHMI: HMI is not speculating on PLC variable update anymore when sending new variable value.
Edouard Tisserant
parents: 2920
diff changeset
   358
    // cache[index] = value;
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   359
};
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   360
2911
211d6a185e31 SVGHMI: More infrastructure for editing values with a keypad.
Edouard Tisserant
parents: 2905
diff changeset
   361
function apply_hmi_value(index, new_val) {
3413
2e84a2782295 SVGHMI: Add pushbutton widget, that can take reflect short press in variable, but has no garantee on consistency.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3385
diff changeset
   362
    // Similarly to previous comment, taking decision to update based 
2e84a2782295 SVGHMI: Add pushbutton widget, that can take reflect short press in variable, but has no garantee on consistency.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3385
diff changeset
   363
    // on cache content is bad and can lead to inconsistency
2e84a2782295 SVGHMI: Add pushbutton widget, that can take reflect short press in variable, but has no garantee on consistency.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3385
diff changeset
   364
    /*let old_val = cache[index];*/
2e84a2782295 SVGHMI: Add pushbutton widget, that can take reflect short press in variable, but has no garantee on consistency.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3385
diff changeset
   365
    if(new_val != undefined /*&& old_val != new_val*/)
2911
211d6a185e31 SVGHMI: More infrastructure for editing values with a keypad.
Edouard Tisserant
parents: 2905
diff changeset
   366
        send_hmi_value(index, new_val);
211d6a185e31 SVGHMI: More infrastructure for editing values with a keypad.
Edouard Tisserant
parents: 2905
diff changeset
   367
    return new_val;
211d6a185e31 SVGHMI: More infrastructure for editing values with a keypad.
Edouard Tisserant
parents: 2905
diff changeset
   368
}
211d6a185e31 SVGHMI: More infrastructure for editing values with a keypad.
Edouard Tisserant
parents: 2905
diff changeset
   369
3078
d345673610b0 SVGHMI: use const when applicable
Edouard Tisserant
parents: 3075
diff changeset
   370
const quotes = {"'":null, '"':null};
2970
4a9b0df0602a SVGHMI: stop using eval in change_hmi_value, apparently slowly leaking memory.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2960
diff changeset
   371
3098
5823b73b132f SVGHMI: decoupled operation string evaluation from HMI variable uptdate in change_hmi_variable(), paving the way for min/max boundaries enforcement
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3082
diff changeset
   372
function eval_operation_string(old_val, opstr) {
2801
390acff12755 SVGHMI: Added init call to all widgets at startup to bind events. More features in Input widget : Edit and Change buttons. WIP HMI->PLC value update, incoherent data detected in C part on update.
Edouard Tisserant
parents: 2800
diff changeset
   373
    let op = opstr[0];
2970
4a9b0df0602a SVGHMI: stop using eval in change_hmi_value, apparently slowly leaking memory.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2960
diff changeset
   374
    let given_val;
4a9b0df0602a SVGHMI: stop using eval in change_hmi_value, apparently slowly leaking memory.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2960
diff changeset
   375
    if(opstr.length < 2) 
3098
5823b73b132f SVGHMI: decoupled operation string evaluation from HMI variable uptdate in change_hmi_variable(), paving the way for min/max boundaries enforcement
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3082
diff changeset
   376
        return undefined;
2970
4a9b0df0602a SVGHMI: stop using eval in change_hmi_value, apparently slowly leaking memory.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2960
diff changeset
   377
    if(opstr[1] in quotes){
4a9b0df0602a SVGHMI: stop using eval in change_hmi_value, apparently slowly leaking memory.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2960
diff changeset
   378
        if(opstr.length < 3) 
3098
5823b73b132f SVGHMI: decoupled operation string evaluation from HMI variable uptdate in change_hmi_variable(), paving the way for min/max boundaries enforcement
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3082
diff changeset
   379
            return undefined;
2970
4a9b0df0602a SVGHMI: stop using eval in change_hmi_value, apparently slowly leaking memory.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2960
diff changeset
   380
        if(opstr[opstr.length-1] == opstr[1]){
4a9b0df0602a SVGHMI: stop using eval in change_hmi_value, apparently slowly leaking memory.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2960
diff changeset
   381
            given_val = opstr.slice(2,opstr.length-1);
4a9b0df0602a SVGHMI: stop using eval in change_hmi_value, apparently slowly leaking memory.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2960
diff changeset
   382
        }
4a9b0df0602a SVGHMI: stop using eval in change_hmi_value, apparently slowly leaking memory.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2960
diff changeset
   383
    } else {
4a9b0df0602a SVGHMI: stop using eval in change_hmi_value, apparently slowly leaking memory.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2960
diff changeset
   384
        given_val = Number(opstr.slice(1));
4a9b0df0602a SVGHMI: stop using eval in change_hmi_value, apparently slowly leaking memory.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2960
diff changeset
   385
    }
2803
f48121cf31b6 SVGHMI: Added relative changes of HMI value from widgets.
Edouard Tisserant
parents: 2802
diff changeset
   386
    let new_val;
f48121cf31b6 SVGHMI: Added relative changes of HMI value from widgets.
Edouard Tisserant
parents: 2802
diff changeset
   387
    switch(op){
f48121cf31b6 SVGHMI: Added relative changes of HMI value from widgets.
Edouard Tisserant
parents: 2802
diff changeset
   388
      case "=":
2970
4a9b0df0602a SVGHMI: stop using eval in change_hmi_value, apparently slowly leaking memory.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2960
diff changeset
   389
        new_val = given_val;
2803
f48121cf31b6 SVGHMI: Added relative changes of HMI value from widgets.
Edouard Tisserant
parents: 2802
diff changeset
   390
        break;
f48121cf31b6 SVGHMI: Added relative changes of HMI value from widgets.
Edouard Tisserant
parents: 2802
diff changeset
   391
      case "+":
2970
4a9b0df0602a SVGHMI: stop using eval in change_hmi_value, apparently slowly leaking memory.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2960
diff changeset
   392
        new_val = old_val + given_val;
4a9b0df0602a SVGHMI: stop using eval in change_hmi_value, apparently slowly leaking memory.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2960
diff changeset
   393
        break;
2803
f48121cf31b6 SVGHMI: Added relative changes of HMI value from widgets.
Edouard Tisserant
parents: 2802
diff changeset
   394
      case "-":
2970
4a9b0df0602a SVGHMI: stop using eval in change_hmi_value, apparently slowly leaking memory.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2960
diff changeset
   395
        new_val = old_val - given_val;
4a9b0df0602a SVGHMI: stop using eval in change_hmi_value, apparently slowly leaking memory.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2960
diff changeset
   396
        break;
2803
f48121cf31b6 SVGHMI: Added relative changes of HMI value from widgets.
Edouard Tisserant
parents: 2802
diff changeset
   397
      case "*":
2970
4a9b0df0602a SVGHMI: stop using eval in change_hmi_value, apparently slowly leaking memory.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2960
diff changeset
   398
        new_val = old_val * given_val;
4a9b0df0602a SVGHMI: stop using eval in change_hmi_value, apparently slowly leaking memory.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2960
diff changeset
   399
        break;
2803
f48121cf31b6 SVGHMI: Added relative changes of HMI value from widgets.
Edouard Tisserant
parents: 2802
diff changeset
   400
      case "/":
2970
4a9b0df0602a SVGHMI: stop using eval in change_hmi_value, apparently slowly leaking memory.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2960
diff changeset
   401
        new_val = old_val / given_val;
2803
f48121cf31b6 SVGHMI: Added relative changes of HMI value from widgets.
Edouard Tisserant
parents: 2802
diff changeset
   402
        break;
f48121cf31b6 SVGHMI: Added relative changes of HMI value from widgets.
Edouard Tisserant
parents: 2802
diff changeset
   403
    }
3098
5823b73b132f SVGHMI: decoupled operation string evaluation from HMI variable uptdate in change_hmi_variable(), paving the way for min/max boundaries enforcement
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3082
diff changeset
   404
    return new_val;
5823b73b132f SVGHMI: decoupled operation string evaluation from HMI variable uptdate in change_hmi_variable(), paving the way for min/max boundaries enforcement
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3082
diff changeset
   405
}
5823b73b132f SVGHMI: decoupled operation string evaluation from HMI variable uptdate in change_hmi_variable(), paving the way for min/max boundaries enforcement
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3082
diff changeset
   406
2864
36f78f6cfabd SVGHMI: split page switch into switching subscription and switching elements in the DOM, to ensure that subscriptions have been send before changing DOM, and avoid some flicker.
Edouard Tisserant
parents: 2860
diff changeset
   407
var current_visible_page;
36f78f6cfabd SVGHMI: split page switch into switching subscription and switching elements in the DOM, to ensure that subscriptions have been send before changing DOM, and avoid some flicker.
Edouard Tisserant
parents: 2860
diff changeset
   408
var current_subscribed_page;
2903
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   409
var current_page_index;
3206
4fd7bd10e606 SVGHMI: added "page_node" variable that reflects the HMI tree path of current relative page
Edouard Tisserant
parents: 3190
diff changeset
   410
var page_node_local_index = hmi_local_index("page_node");
3535
770fcb344f50 SVGHMI: better handling of page switch fade-out.
Edouard Tisserant
parents: 3524
diff changeset
   411
var page_switch_in_progress = false;
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   412
3299
8b45d8494fae SVGHMI: Allow toggling fulscreen mode my right click or long press.
Edouard Tisserant
parents: 3268
diff changeset
   413
function toggleFullscreen() {
8b45d8494fae SVGHMI: Allow toggling fulscreen mode my right click or long press.
Edouard Tisserant
parents: 3268
diff changeset
   414
  let elem = document.documentElement;
8b45d8494fae SVGHMI: Allow toggling fulscreen mode my right click or long press.
Edouard Tisserant
parents: 3268
diff changeset
   415
8b45d8494fae SVGHMI: Allow toggling fulscreen mode my right click or long press.
Edouard Tisserant
parents: 3268
diff changeset
   416
  if (!document.fullscreenElement) {
8b45d8494fae SVGHMI: Allow toggling fulscreen mode my right click or long press.
Edouard Tisserant
parents: 3268
diff changeset
   417
    elem.requestFullscreen().catch(err => {
8b45d8494fae SVGHMI: Allow toggling fulscreen mode my right click or long press.
Edouard Tisserant
parents: 3268
diff changeset
   418
      console.log("Error attempting to enable full-screen mode: "+err.message+" ("+err.name+")");
8b45d8494fae SVGHMI: Allow toggling fulscreen mode my right click or long press.
Edouard Tisserant
parents: 3268
diff changeset
   419
    });
8b45d8494fae SVGHMI: Allow toggling fulscreen mode my right click or long press.
Edouard Tisserant
parents: 3268
diff changeset
   420
  } else {
8b45d8494fae SVGHMI: Allow toggling fulscreen mode my right click or long press.
Edouard Tisserant
parents: 3268
diff changeset
   421
    document.exitFullscreen();
8b45d8494fae SVGHMI: Allow toggling fulscreen mode my right click or long press.
Edouard Tisserant
parents: 3268
diff changeset
   422
  }
8b45d8494fae SVGHMI: Allow toggling fulscreen mode my right click or long press.
Edouard Tisserant
parents: 3268
diff changeset
   423
}
8b45d8494fae SVGHMI: Allow toggling fulscreen mode my right click or long press.
Edouard Tisserant
parents: 3268
diff changeset
   424
3648
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   425
// prevents context menu from appearing on right click and long touch
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   426
document.body.addEventListener('contextmenu', e => {
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   427
    toggleFullscreen();
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   428
    e.preventDefault();
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   429
});
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   430
3664
7e8db0b44e42 SVGHMI: fix HMI freeze at load when no screen saver is defined
Edouard Tisserant
parents: 3661
diff changeset
   431
if(screensaver_delay){
7e8db0b44e42 SVGHMI: fix HMI freeze at load when no screen saver is defined
Edouard Tisserant
parents: 3661
diff changeset
   432
    var screensaver_timer = null;
7e8db0b44e42 SVGHMI: fix HMI freeze at load when no screen saver is defined
Edouard Tisserant
parents: 3661
diff changeset
   433
    function reset_screensaver_timer() {
7e8db0b44e42 SVGHMI: fix HMI freeze at load when no screen saver is defined
Edouard Tisserant
parents: 3661
diff changeset
   434
        if(screensaver_timer){
7e8db0b44e42 SVGHMI: fix HMI freeze at load when no screen saver is defined
Edouard Tisserant
parents: 3661
diff changeset
   435
            window.clearTimeout(screensaver_timer);
7e8db0b44e42 SVGHMI: fix HMI freeze at load when no screen saver is defined
Edouard Tisserant
parents: 3661
diff changeset
   436
        }
7e8db0b44e42 SVGHMI: fix HMI freeze at load when no screen saver is defined
Edouard Tisserant
parents: 3661
diff changeset
   437
        screensaver_timer = window.setTimeout(() => {
7e8db0b44e42 SVGHMI: fix HMI freeze at load when no screen saver is defined
Edouard Tisserant
parents: 3661
diff changeset
   438
            switch_page("ScreenSaver");
7e8db0b44e42 SVGHMI: fix HMI freeze at load when no screen saver is defined
Edouard Tisserant
parents: 3661
diff changeset
   439
            screensaver_timer = null;
7e8db0b44e42 SVGHMI: fix HMI freeze at load when no screen saver is defined
Edouard Tisserant
parents: 3661
diff changeset
   440
        }, screensaver_delay*1000);
7e8db0b44e42 SVGHMI: fix HMI freeze at load when no screen saver is defined
Edouard Tisserant
parents: 3661
diff changeset
   441
    }
3653
d5ff60e906b0 SVGHMI: add ScreenSaver feature. Automatically jumps to a page named "ScreenSaver" after timeout defined in page arguments.
Edouard Tisserant
parents: 3650
diff changeset
   442
    document.body.addEventListener('pointerdown', reset_screensaver_timer);
3664
7e8db0b44e42 SVGHMI: fix HMI freeze at load when no screen saver is defined
Edouard Tisserant
parents: 3661
diff changeset
   443
    // initialize screensaver
7e8db0b44e42 SVGHMI: fix HMI freeze at load when no screen saver is defined
Edouard Tisserant
parents: 3661
diff changeset
   444
    reset_screensaver_timer();
7e8db0b44e42 SVGHMI: fix HMI freeze at load when no screen saver is defined
Edouard Tisserant
parents: 3661
diff changeset
   445
}
7e8db0b44e42 SVGHMI: fix HMI freeze at load when no screen saver is defined
Edouard Tisserant
parents: 3661
diff changeset
   446
3653
d5ff60e906b0 SVGHMI: add ScreenSaver feature. Automatically jumps to a page named "ScreenSaver" after timeout defined in page arguments.
Edouard Tisserant
parents: 3650
diff changeset
   447
3648
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   448
function detach_detachables() {
3082
20a5eb6a02e6 SVGHMI: prevent unwnted context menu and pinch zoom
Edouard Tisserant
parents: 3080
diff changeset
   449
2850
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   450
    for(let eltid in detachable_elements){
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   451
        let [element,parent] = detachable_elements[eltid];
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   452
        parent.removeChild(element);
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   453
    }
2843
94696b3f69fb SVGHMI : still trying to optimize. Added xslt code to identitfy minimum set of elements needed by a particular page. Plan is to remove unseen/unused elements from the DOM, and re-appending them later when used, on page switch. Disabled previous optimization.
Edouard Tisserant
parents: 2841
diff changeset
   454
};
94696b3f69fb SVGHMI : still trying to optimize. Added xslt code to identitfy minimum set of elements needed by a particular page. Plan is to remove unseen/unused elements from the DOM, and re-appending them later when used, on page switch. Disabled previous optimization.
Edouard Tisserant
parents: 2841
diff changeset
   455
2870
634b43d69897 SVGHMI: relative pages and page jumps
Edouard Tisserant
parents: 2869
diff changeset
   456
function switch_page(page_name, page_index) {
3535
770fcb344f50 SVGHMI: better handling of page switch fade-out.
Edouard Tisserant
parents: 3524
diff changeset
   457
    if(page_switch_in_progress){
2864
36f78f6cfabd SVGHMI: split page switch into switching subscription and switching elements in the DOM, to ensure that subscriptions have been send before changing DOM, and avoid some flicker.
Edouard Tisserant
parents: 2860
diff changeset
   458
        /* page switch already going */
36f78f6cfabd SVGHMI: split page switch into switching subscription and switching elements in the DOM, to ensure that subscriptions have been send before changing DOM, and avoid some flicker.
Edouard Tisserant
parents: 2860
diff changeset
   459
        /* TODO LOG ERROR */
2902
1fcb50af0335 SVGHMI: added Back widget.
Edouard Tisserant
parents: 2899
diff changeset
   460
        return false;
2895
89c02b452717 SVGHMI: ForEach now has working (un)subscribe. Fixed PageSwitch that wasn't behaving when jumping to current page with another path.
Edouard Tisserant
parents: 2890
diff changeset
   461
    }
3535
770fcb344f50 SVGHMI: better handling of page switch fade-out.
Edouard Tisserant
parents: 3524
diff changeset
   462
    page_switch_in_progress = true;
2895
89c02b452717 SVGHMI: ForEach now has working (un)subscribe. Fixed PageSwitch that wasn't behaving when jumping to current page with another path.
Edouard Tisserant
parents: 2890
diff changeset
   463
89c02b452717 SVGHMI: ForEach now has working (un)subscribe. Fixed PageSwitch that wasn't behaving when jumping to current page with another path.
Edouard Tisserant
parents: 2890
diff changeset
   464
    if(page_name == undefined)
89c02b452717 SVGHMI: ForEach now has working (un)subscribe. Fixed PageSwitch that wasn't behaving when jumping to current page with another path.
Edouard Tisserant
parents: 2890
diff changeset
   465
        page_name = current_subscribed_page;
3381
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   466
    else if(page_index == undefined){
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   467
        [page_name, page_index] = page_name.split('@')
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   468
    }
2903
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   469
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   470
    let old_desc = page_desc[current_subscribed_page];
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   471
    let new_desc = page_desc[page_name];
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   472
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   473
    if(new_desc == undefined){
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   474
        /* TODO LOG ERROR */
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   475
        return false;
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   476
    }
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   477
3381
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   478
    if(page_index == undefined)
2903
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   479
        page_index = new_desc.page_index;
3381
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   480
    else if(typeof(page_index) == "string") {
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   481
        let hmitree_node = hmitree_nodes[page_index];
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   482
        if(hmitree_node !== undefined){
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   483
            let [int_index, hmiclass] = hmitree_node;
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   484
            if(hmiclass == new_desc.page_class)
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   485
                page_index = int_index;
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   486
            else
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   487
                page_index = new_desc.page_index;
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   488
        } else {
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   489
            page_index = new_desc.page_index;
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   490
        }
2903
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   491
    }
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   492
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   493
    if(old_desc){
3005
ff9ae4f4e3be SVGHMI: widgets are not anymore binary relative or absolute, but have a "relativeness".
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3000
diff changeset
   494
        old_desc.widgets.map(([widget,relativeness])=>widget.unsub());
ff9ae4f4e3be SVGHMI: widgets are not anymore binary relative or absolute, but have a "relativeness".
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3000
diff changeset
   495
    }
3080
e5fa1f49f0b9 SVGHMI: WIP trying to reduce memory usage : use .onclick onstead of SetAttribute, avoid useless closure and object creation when possible, etc.
Edouard Tisserant
parents: 3078
diff changeset
   496
    const new_offset = page_index == undefined ? 0 : page_index - new_desc.page_index;
e5fa1f49f0b9 SVGHMI: WIP trying to reduce memory usage : use .onclick onstead of SetAttribute, avoid useless closure and object creation when possible, etc.
Edouard Tisserant
parents: 3078
diff changeset
   497
e5fa1f49f0b9 SVGHMI: WIP trying to reduce memory usage : use .onclick onstead of SetAttribute, avoid useless closure and object creation when possible, etc.
Edouard Tisserant
parents: 3078
diff changeset
   498
    const container_id = page_name + (page_index != undefined ? page_index : "");
3017
15e2df3e5610 SVGHMI: Intermediate state while implementing local HMI variables. Now write to cache only (no send), still need to implement dispatch on change.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3006
diff changeset
   499
15e2df3e5610 SVGHMI: Intermediate state while implementing local HMI variables. Now write to cache only (no send), still need to implement dispatch on change.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3006
diff changeset
   500
    new_desc.widgets.map(([widget,relativeness])=>widget.sub(new_offset,relativeness,container_id));
2903
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   501
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   502
    update_subscriptions();
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   503
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   504
    current_subscribed_page = page_name;
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   505
    current_page_index = page_index;
3206
4fd7bd10e606 SVGHMI: added "page_node" variable that reflects the HMI tree path of current relative page
Edouard Tisserant
parents: 3190
diff changeset
   506
    let page_node;
4fd7bd10e606 SVGHMI: added "page_node" variable that reflects the HMI tree path of current relative page
Edouard Tisserant
parents: 3190
diff changeset
   507
    if(page_index != undefined){
4fd7bd10e606 SVGHMI: added "page_node" variable that reflects the HMI tree path of current relative page
Edouard Tisserant
parents: 3190
diff changeset
   508
        page_node = hmitree_paths[page_index];
4fd7bd10e606 SVGHMI: added "page_node" variable that reflects the HMI tree path of current relative page
Edouard Tisserant
parents: 3190
diff changeset
   509
    }else{
4fd7bd10e606 SVGHMI: added "page_node" variable that reflects the HMI tree path of current relative page
Edouard Tisserant
parents: 3190
diff changeset
   510
        page_node = "";
4fd7bd10e606 SVGHMI: added "page_node" variable that reflects the HMI tree path of current relative page
Edouard Tisserant
parents: 3190
diff changeset
   511
    }
4fd7bd10e606 SVGHMI: added "page_node" variable that reflects the HMI tree path of current relative page
Edouard Tisserant
parents: 3190
diff changeset
   512
    apply_hmi_value(page_node_local_index, page_node);
2903
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   513
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   514
    jumps_need_update = true;
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   515
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   516
    requestHMIAnimation();
3653
d5ff60e906b0 SVGHMI: add ScreenSaver feature. Automatically jumps to a page named "ScreenSaver" after timeout defined in page arguments.
Edouard Tisserant
parents: 3650
diff changeset
   517
    let [last_page_name, last_page_index] = jump_history[jump_history.length-1];
d5ff60e906b0 SVGHMI: add ScreenSaver feature. Automatically jumps to a page named "ScreenSaver" after timeout defined in page arguments.
Edouard Tisserant
parents: 3650
diff changeset
   518
    if(last_page_name != page_name || last_page_index != page_index){
d5ff60e906b0 SVGHMI: add ScreenSaver feature. Automatically jumps to a page named "ScreenSaver" after timeout defined in page arguments.
Edouard Tisserant
parents: 3650
diff changeset
   519
        jump_history.push([page_name, page_index]);
d5ff60e906b0 SVGHMI: add ScreenSaver feature. Automatically jumps to a page named "ScreenSaver" after timeout defined in page arguments.
Edouard Tisserant
parents: 3650
diff changeset
   520
        if(jump_history.length > 42)
d5ff60e906b0 SVGHMI: add ScreenSaver feature. Automatically jumps to a page named "ScreenSaver" after timeout defined in page arguments.
Edouard Tisserant
parents: 3650
diff changeset
   521
            jump_history.shift();
d5ff60e906b0 SVGHMI: add ScreenSaver feature. Automatically jumps to a page named "ScreenSaver" after timeout defined in page arguments.
Edouard Tisserant
parents: 3650
diff changeset
   522
    }
2903
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   523
3385
18621ce81f5f SVGHMI: Changes /CURRENT_PAGE_* behaviour to prevent problem whith multiclient : all clients were switching page when one was jumping.
Edouard Tisserant
parents: 3381
diff changeset
   524
    apply_hmi_value(current_page_var_index, page_index == undefined
18621ce81f5f SVGHMI: Changes /CURRENT_PAGE_* behaviour to prevent problem whith multiclient : all clients were switching page when one was jumping.
Edouard Tisserant
parents: 3381
diff changeset
   525
        ? page_name
18621ce81f5f SVGHMI: Changes /CURRENT_PAGE_* behaviour to prevent problem whith multiclient : all clients were switching page when one was jumping.
Edouard Tisserant
parents: 3381
diff changeset
   526
        : page_name + "@" + hmitree_paths[page_index]);
3381
3a0908b0319d SVGHMI: add CURRENT_PAGE_{location} global variable to reflect currently visible page. If PLC wites some valid page reference in that variable, it triggers page switch. Additionally, fixed /HEARTBEAT being subscribed systematically by JS code even when wtchdog is not enabled.
Edouard Tisserant
parents: 3299
diff changeset
   527
3685
570a738239f4 SVGHMI: Add arbitrary variable assignment when entering Pages
Edouard Tisserant
parents: 3683
diff changeset
   528
    // when entering a page, assignments are evaluated
570a738239f4 SVGHMI: Add arbitrary variable assignment when entering Pages
Edouard Tisserant
parents: 3683
diff changeset
   529
    new_desc.widgets[0][0].assign();
570a738239f4 SVGHMI: Add arbitrary variable assignment when entering Pages
Edouard Tisserant
parents: 3683
diff changeset
   530
2903
881d0248b3ce SVGHMI: Jump widget can now display as active or inactive, if corresponfing "active" and "inactive labeled elements are provided.
Edouard Tisserant
parents: 2902
diff changeset
   531
    return true;
2864
36f78f6cfabd SVGHMI: split page switch into switching subscription and switching elements in the DOM, to ensure that subscriptions have been send before changing DOM, and avoid some flicker.
Edouard Tisserant
parents: 2860
diff changeset
   532
};
36f78f6cfabd SVGHMI: split page switch into switching subscription and switching elements in the DOM, to ensure that subscriptions have been send before changing DOM, and avoid some flicker.
Edouard Tisserant
parents: 2860
diff changeset
   533
36f78f6cfabd SVGHMI: split page switch into switching subscription and switching elements in the DOM, to ensure that subscriptions have been send before changing DOM, and avoid some flicker.
Edouard Tisserant
parents: 2860
diff changeset
   534
function switch_visible_page(page_name) {
36f78f6cfabd SVGHMI: split page switch into switching subscription and switching elements in the DOM, to ensure that subscriptions have been send before changing DOM, and avoid some flicker.
Edouard Tisserant
parents: 2860
diff changeset
   535
36f78f6cfabd SVGHMI: split page switch into switching subscription and switching elements in the DOM, to ensure that subscriptions have been send before changing DOM, and avoid some flicker.
Edouard Tisserant
parents: 2860
diff changeset
   536
    let old_desc = page_desc[current_visible_page];
36f78f6cfabd SVGHMI: split page switch into switching subscription and switching elements in the DOM, to ensure that subscriptions have been send before changing DOM, and avoid some flicker.
Edouard Tisserant
parents: 2860
diff changeset
   537
    let new_desc = page_desc[page_name];
36f78f6cfabd SVGHMI: split page switch into switching subscription and switching elements in the DOM, to ensure that subscriptions have been send before changing DOM, and avoid some flicker.
Edouard Tisserant
parents: 2860
diff changeset
   538
36f78f6cfabd SVGHMI: split page switch into switching subscription and switching elements in the DOM, to ensure that subscriptions have been send before changing DOM, and avoid some flicker.
Edouard Tisserant
parents: 2860
diff changeset
   539
    if(old_desc){
2850
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   540
        for(let eltid in old_desc.required_detachables){
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   541
            if(!(eltid in new_desc.required_detachables)){
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   542
                let [element, parent] = old_desc.required_detachables[eltid];
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   543
                parent.removeChild(element);
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   544
            }
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   545
        }
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   546
        for(let eltid in new_desc.required_detachables){
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   547
            if(!(eltid in old_desc.required_detachables)){
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   548
                let [element, parent] = new_desc.required_detachables[eltid];
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   549
                parent.appendChild(element);
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   550
            }
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   551
        }
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   552
    }else{
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   553
        for(let eltid in new_desc.required_detachables){
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   554
            let [element, parent] = new_desc.required_detachables[eltid];
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   555
            parent.appendChild(element);
e38654ec6281 SVGHMI: detach/re-attach elements required by pages on page switch
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2843
diff changeset
   556
        }
2843
94696b3f69fb SVGHMI : still trying to optimize. Added xslt code to identitfy minimum set of elements needed by a particular page. Plan is to remove unseen/unused elements from the DOM, and re-appending them later when used, on page switch. Disabled previous optimization.
Edouard Tisserant
parents: 2841
diff changeset
   557
    }
94696b3f69fb SVGHMI : still trying to optimize. Added xslt code to identitfy minimum set of elements needed by a particular page. Plan is to remove unseen/unused elements from the DOM, and re-appending them later when used, on page switch. Disabled previous optimization.
Edouard Tisserant
parents: 2841
diff changeset
   558
2895
89c02b452717 SVGHMI: ForEach now has working (un)subscribe. Fixed PageSwitch that wasn't behaving when jumping to current page with another path.
Edouard Tisserant
parents: 2890
diff changeset
   559
    svg_root.setAttribute('viewBox',new_desc.bbox.join(" "));
89c02b452717 SVGHMI: ForEach now has working (un)subscribe. Fixed PageSwitch that wasn't behaving when jumping to current page with another path.
Edouard Tisserant
parents: 2890
diff changeset
   560
    current_visible_page = page_name;
89c02b452717 SVGHMI: ForEach now has working (un)subscribe. Fixed PageSwitch that wasn't behaving when jumping to current page with another path.
Edouard Tisserant
parents: 2890
diff changeset
   561
};
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   562
3625
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   563
/* From https://jsfiddle.net/ibowankenobi/1mmh7rs6/6/ */
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   564
function getAbsoluteCTM(element){
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   565
	var height = svg_root.height.baseVal.value,
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   566
		width = svg_root.width.baseVal.value,
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   567
		viewBoxRect = svg_root.viewBox.baseVal,
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   568
		vHeight = viewBoxRect.height,
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   569
		vWidth = viewBoxRect.width;
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   570
	if(!vWidth || !vHeight){
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   571
		return element.getCTM();
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   572
	}
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   573
	var sH = height/vHeight,
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   574
		sW = width/vWidth,
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   575
		matrix = svg_root.createSVGMatrix();
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   576
	matrix.a = sW;
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   577
	matrix.d = sH
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   578
	var realCTM = element.getCTM().multiply(matrix.inverse());
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   579
	realCTM.e = realCTM.e/sW + viewBoxRect.x;
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   580
	realCTM.f = realCTM.f/sH + viewBoxRect.y;
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   581
	return realCTM;
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   582
}
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   583
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   584
function apply_reference_frames(){
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   585
    const matches = svg_root.querySelectorAll("g[svghmi_x_offset]");
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   586
    matches.forEach((group) => {
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   587
        let [x,y] = ["x", "y"].map((axis) => Number(group.getAttribute("svghmi_"+axis+"_offset")));
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   588
        let ctm = getAbsoluteCTM(group);
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   589
        // zero translation part of CTM
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   590
        // to only apply rotation/skewing to offset vector
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   591
        ctm.e = 0;
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   592
        ctm.f = 0;
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   593
        let invctm = ctm.inverse();
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   594
        let vect = new DOMPoint(x, y);
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   595
        let newvect = vect.matrixTransform(invctm);
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   596
        let transform = svg_root.createSVGTransform();
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   597
        transform.setTranslate(newvect.x, newvect.y);
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   598
        group.transform.baseVal.appendItem(transform);
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   599
        ["x", "y"].forEach((axis) => group.removeAttribute("svghmi_"+axis+"_offset"));
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   600
    });
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   601
}
bb1eff4091ab SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
Edouard Tisserant
parents: 3624
diff changeset
   602
3648
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   603
// prepare SVG
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   604
apply_reference_frames();
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   605
init_widgets();
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   606
detach_detachables();
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   607
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   608
// show main page
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   609
switch_page(default_page);
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   610
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   611
var reconnect_delay = 0;
3650
9256c344c2da SVGHMI: enable periodical reconnect when browser is QtWebengine, working around memory leak with websocket on Qt's embedded Chromium.
Edouard Tisserant
parents: 3648
diff changeset
   612
var periodic_reconnect_timer;
3683
bbcbb1bba9f1 SVGHMI: fix periodic reconnect triggering watchdog
Edouard Tisserant
parents: 3680
diff changeset
   613
var force_reconnect = false;
3648
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   614
2798
ddb2c4668a6b SVGHMI : many details about communication implemented in JS, with side effects.
Edouard Tisserant
parents: 2788
diff changeset
   615
// Once connection established
3648
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   616
function ws_onopen(evt) {
3650
9256c344c2da SVGHMI: enable periodical reconnect when browser is QtWebengine, working around memory leak with websocket on Qt's embedded Chromium.
Edouard Tisserant
parents: 3648
diff changeset
   617
    // Work around memory leak with websocket on QtWebEngine
9256c344c2da SVGHMI: enable periodical reconnect when browser is QtWebengine, working around memory leak with websocket on Qt's embedded Chromium.
Edouard Tisserant
parents: 3648
diff changeset
   618
    // reconnect every hour to force deallocate websocket garbage
9256c344c2da SVGHMI: enable periodical reconnect when browser is QtWebengine, working around memory leak with websocket on Qt's embedded Chromium.
Edouard Tisserant
parents: 3648
diff changeset
   619
    if(window.navigator.userAgent.includes("QtWebEngine")){
9256c344c2da SVGHMI: enable periodical reconnect when browser is QtWebengine, working around memory leak with websocket on Qt's embedded Chromium.
Edouard Tisserant
parents: 3648
diff changeset
   620
        if(periodic_reconnect_timer){
9256c344c2da SVGHMI: enable periodical reconnect when browser is QtWebengine, working around memory leak with websocket on Qt's embedded Chromium.
Edouard Tisserant
parents: 3648
diff changeset
   621
            window.clearTimeout(periodic_reconnect_timer);
9256c344c2da SVGHMI: enable periodical reconnect when browser is QtWebengine, working around memory leak with websocket on Qt's embedded Chromium.
Edouard Tisserant
parents: 3648
diff changeset
   622
        }
9256c344c2da SVGHMI: enable periodical reconnect when browser is QtWebengine, working around memory leak with websocket on Qt's embedded Chromium.
Edouard Tisserant
parents: 3648
diff changeset
   623
        periodic_reconnect_timer = window.setTimeout(() => {
3683
bbcbb1bba9f1 SVGHMI: fix periodic reconnect triggering watchdog
Edouard Tisserant
parents: 3680
diff changeset
   624
            force_reconnect = true;
3650
9256c344c2da SVGHMI: enable periodical reconnect when browser is QtWebengine, working around memory leak with websocket on Qt's embedded Chromium.
Edouard Tisserant
parents: 3648
diff changeset
   625
            ws.close();
9256c344c2da SVGHMI: enable periodical reconnect when browser is QtWebengine, working around memory leak with websocket on Qt's embedded Chromium.
Edouard Tisserant
parents: 3648
diff changeset
   626
            periodic_reconnect_timer = null;
9256c344c2da SVGHMI: enable periodical reconnect when browser is QtWebengine, working around memory leak with websocket on Qt's embedded Chromium.
Edouard Tisserant
parents: 3648
diff changeset
   627
        }, 3600000);
9256c344c2da SVGHMI: enable periodical reconnect when browser is QtWebengine, working around memory leak with websocket on Qt's embedded Chromium.
Edouard Tisserant
parents: 3648
diff changeset
   628
    }
3648
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   629
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   630
    // forget earlier subscriptions locally
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   631
    reset_subscription_periods();
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   632
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   633
    // update PLC about subscriptions and current page
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   634
    switch_page();
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   635
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   636
    // at first try reconnect immediately
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   637
    reconnect_delay = 1;
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   638
};
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   639
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   640
function ws_onclose(evt) {
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   641
    console.log("Connection closed. code:"+evt.code+" reason:"+evt.reason+" wasClean:"+evt.wasClean+" Reload in "+reconnect_delay+"ms.");
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   642
    ws = null;
3683
bbcbb1bba9f1 SVGHMI: fix periodic reconnect triggering watchdog
Edouard Tisserant
parents: 3680
diff changeset
   643
    // Do not attempt to reconnect immediately in case:
bbcbb1bba9f1 SVGHMI: fix periodic reconnect triggering watchdog
Edouard Tisserant
parents: 3680
diff changeset
   644
    //    - connection was closed by server (PLC stop)
bbcbb1bba9f1 SVGHMI: fix periodic reconnect triggering watchdog
Edouard Tisserant
parents: 3680
diff changeset
   645
    //    - connection was closed locally with an intention to reconnect
bbcbb1bba9f1 SVGHMI: fix periodic reconnect triggering watchdog
Edouard Tisserant
parents: 3680
diff changeset
   646
    if(evt.code=1000 && !force_reconnect){
3680
20f9f0c36ad6 SVGHMI: do not try to reconnect websocket if closed properly by server.
Edouard Tisserant
parents: 3664
diff changeset
   647
        window.alert("Connection closed by server");
20f9f0c36ad6 SVGHMI: do not try to reconnect websocket if closed properly by server.
Edouard Tisserant
parents: 3664
diff changeset
   648
        location.reload();
20f9f0c36ad6 SVGHMI: do not try to reconnect websocket if closed properly by server.
Edouard Tisserant
parents: 3664
diff changeset
   649
    }
3648
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   650
    window.setTimeout(create_ws, reconnect_delay);
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   651
    reconnect_delay += 500;
3683
bbcbb1bba9f1 SVGHMI: fix periodic reconnect triggering watchdog
Edouard Tisserant
parents: 3680
diff changeset
   652
    force_reconnect = false;
3648
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   653
};
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   654
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   655
var ws_url =
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   656
    window.location.href.replace(/^http(s?:\/\/[^\/]*)\/.*$/, 'ws$1/ws')
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   657
    + '?mode=' + (has_watchdog ? "watchdog" : "multiclient");
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   658
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   659
function create_ws(){
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   660
    ws = new WebSocket(ws_url);
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   661
    ws.binaryType = 'arraybuffer';
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   662
    ws.onmessage = ws_onmessage;
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   663
    ws.onclose = ws_onclose;
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   664
    ws.onopen = ws_onopen;
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   665
}
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   666
ff42600fddd7 SVGHMI: add automatic reconnection of websocket with 1s reconnection delay after first attempt.
Edouard Tisserant
parents: 3645
diff changeset
   667
create_ws()
2911
211d6a185e31 SVGHMI: More infrastructure for editing values with a keypad.
Edouard Tisserant
parents: 2905
diff changeset
   668
211d6a185e31 SVGHMI: More infrastructure for editing values with a keypad.
Edouard Tisserant
parents: 2905
diff changeset
   669
var edit_callback;
3075
2f9dbd3ee445 SVGHMI: Fix: on screen keyboard wasn't showing up when editing local variables through Input widget.
Edouard Tisserant
parents: 3068
diff changeset
   670
const localtypes = {"PAGE_LOCAL":null, "HMI_LOCAL":null}
3118
e704b0487515 SVGHMI : removed support for changing keyboard position and showing at user defined location. Feature was problematic in many respect.
Edouard Tisserant
parents: 3098
diff changeset
   671
function edit_value(path, valuetype, callback, initial) {
3075
2f9dbd3ee445 SVGHMI: Fix: on screen keyboard wasn't showing up when editing local variables through Input widget.
Edouard Tisserant
parents: 3068
diff changeset
   672
    if(valuetype in localtypes){
2f9dbd3ee445 SVGHMI: Fix: on screen keyboard wasn't showing up when editing local variables through Input widget.
Edouard Tisserant
parents: 3068
diff changeset
   673
        valuetype = (typeof initial) == "number" ? "HMI_REAL" : "HMI_STRING";
2f9dbd3ee445 SVGHMI: Fix: on screen keyboard wasn't showing up when editing local variables through Input widget.
Edouard Tisserant
parents: 3068
diff changeset
   674
    }
2913
ac4328e69079 SVGHMI: Keypad: added code to re-attach keypad when starting edit.
Edouard Tisserant
parents: 2912
diff changeset
   675
    let [keypadid, xcoord, ycoord] = keypads[valuetype];
2911
211d6a185e31 SVGHMI: More infrastructure for editing values with a keypad.
Edouard Tisserant
parents: 2905
diff changeset
   676
    edit_callback = callback;
2917
c8d923dd707f SVGHMI: Keypad working for HMI_STRING, still Shift/CapsLock not finished.
Edouard Tisserant
parents: 2916
diff changeset
   677
    let widget = hmi_widgets[keypadid];
3118
e704b0487515 SVGHMI : removed support for changing keyboard position and showing at user defined location. Feature was problematic in many respect.
Edouard Tisserant
parents: 3098
diff changeset
   678
    widget.start_edit(path, valuetype, callback, initial);
2917
c8d923dd707f SVGHMI: Keypad working for HMI_STRING, still Shift/CapsLock not finished.
Edouard Tisserant
parents: 2916
diff changeset
   679
};
c8d923dd707f SVGHMI: Keypad working for HMI_STRING, still Shift/CapsLock not finished.
Edouard Tisserant
parents: 2916
diff changeset
   680
c8d923dd707f SVGHMI: Keypad working for HMI_STRING, still Shift/CapsLock not finished.
Edouard Tisserant
parents: 2916
diff changeset
   681
var current_modal; /* TODO stack ?*/
c8d923dd707f SVGHMI: Keypad working for HMI_STRING, still Shift/CapsLock not finished.
Edouard Tisserant
parents: 2916
diff changeset
   682
3118
e704b0487515 SVGHMI : removed support for changing keyboard position and showing at user defined location. Feature was problematic in many respect.
Edouard Tisserant
parents: 3098
diff changeset
   683
function show_modal() {
2917
c8d923dd707f SVGHMI: Keypad working for HMI_STRING, still Shift/CapsLock not finished.
Edouard Tisserant
parents: 2916
diff changeset
   684
    let [element, parent] = detachable_elements[this.element.id];
c8d923dd707f SVGHMI: Keypad working for HMI_STRING, still Shift/CapsLock not finished.
Edouard Tisserant
parents: 2916
diff changeset
   685
2916
4f3b130fd197 SVGHMI: fix keyboard not showing
Edouard Tisserant
parents: 2913
diff changeset
   686
    tmpgrp = document.createElementNS(xmlns,"g");
2913
ac4328e69079 SVGHMI: Keypad: added code to re-attach keypad when starting edit.
Edouard Tisserant
parents: 2912
diff changeset
   687
    tmpgrpattr = document.createAttribute("transform");
2917
c8d923dd707f SVGHMI: Keypad working for HMI_STRING, still Shift/CapsLock not finished.
Edouard Tisserant
parents: 2916
diff changeset
   688
    let [xcoord,ycoord] = this.coordinates;
2913
ac4328e69079 SVGHMI: Keypad: added code to re-attach keypad when starting edit.
Edouard Tisserant
parents: 2912
diff changeset
   689
    let [xdest,ydest] = page_desc[current_visible_page].bbox;
3118
e704b0487515 SVGHMI : removed support for changing keyboard position and showing at user defined location. Feature was problematic in many respect.
Edouard Tisserant
parents: 3098
diff changeset
   690
    tmpgrpattr.value = "translate("+String(xdest-xcoord)+","+String(ydest-ycoord)+")";
3010
893cc309f5e2 Changed keyboard to show on defined position.
usveticic
parents: 3000
diff changeset
   691
2913
ac4328e69079 SVGHMI: Keypad: added code to re-attach keypad when starting edit.
Edouard Tisserant
parents: 2912
diff changeset
   692
    tmpgrp.setAttributeNode(tmpgrpattr);
ac4328e69079 SVGHMI: Keypad: added code to re-attach keypad when starting edit.
Edouard Tisserant
parents: 2912
diff changeset
   693
ac4328e69079 SVGHMI: Keypad: added code to re-attach keypad when starting edit.
Edouard Tisserant
parents: 2912
diff changeset
   694
    tmpgrp.appendChild(element);
ac4328e69079 SVGHMI: Keypad: added code to re-attach keypad when starting edit.
Edouard Tisserant
parents: 2912
diff changeset
   695
    parent.appendChild(tmpgrp);
ac4328e69079 SVGHMI: Keypad: added code to re-attach keypad when starting edit.
Edouard Tisserant
parents: 2912
diff changeset
   696
2917
c8d923dd707f SVGHMI: Keypad working for HMI_STRING, still Shift/CapsLock not finished.
Edouard Tisserant
parents: 2916
diff changeset
   697
    current_modal = [this.element.id, tmpgrp];
c8d923dd707f SVGHMI: Keypad working for HMI_STRING, still Shift/CapsLock not finished.
Edouard Tisserant
parents: 2916
diff changeset
   698
};
c8d923dd707f SVGHMI: Keypad working for HMI_STRING, still Shift/CapsLock not finished.
Edouard Tisserant
parents: 2916
diff changeset
   699
c8d923dd707f SVGHMI: Keypad working for HMI_STRING, still Shift/CapsLock not finished.
Edouard Tisserant
parents: 2916
diff changeset
   700
function end_modal() {
c8d923dd707f SVGHMI: Keypad working for HMI_STRING, still Shift/CapsLock not finished.
Edouard Tisserant
parents: 2916
diff changeset
   701
    let [eltid, tmpgrp] = current_modal;
c8d923dd707f SVGHMI: Keypad working for HMI_STRING, still Shift/CapsLock not finished.
Edouard Tisserant
parents: 2916
diff changeset
   702
    let [element, parent] = detachable_elements[this.element.id];
c8d923dd707f SVGHMI: Keypad working for HMI_STRING, still Shift/CapsLock not finished.
Edouard Tisserant
parents: 2916
diff changeset
   703
c8d923dd707f SVGHMI: Keypad working for HMI_STRING, still Shift/CapsLock not finished.
Edouard Tisserant
parents: 2916
diff changeset
   704
    parent.removeChild(tmpgrp);
c8d923dd707f SVGHMI: Keypad working for HMI_STRING, still Shift/CapsLock not finished.
Edouard Tisserant
parents: 2916
diff changeset
   705
c8d923dd707f SVGHMI: Keypad working for HMI_STRING, still Shift/CapsLock not finished.
Edouard Tisserant
parents: 2916
diff changeset
   706
    current_modal = undefined;
c8d923dd707f SVGHMI: Keypad working for HMI_STRING, still Shift/CapsLock not finished.
Edouard Tisserant
parents: 2916
diff changeset
   707
};
2920
3ee337c8c769 SVGHMI: finished shift and capslock support n keypad widget. Added a helper in widgets_common to collect subelements likle active/inactive/disabled...
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2917
diff changeset
   708