svghmi/hmi_tree.ysl2
author Edouard Tisserant
Wed, 01 Mar 2023 10:54:54 +0100
changeset 3740 ac0e6de439b5
parent 3579 c5070b6973ba
permissions -rw-r--r--
Linux runtime: overrun detection for real-time timers and for plc execution.

If real-time timer wakes-up PLC thread too late (10% over period), then
warning is logged.

If PLC code (IO retreive, execution, IO publish) takes longer than requested
PLC execution cycle, then warning is logged, and CPU hoogging is mitigated
by delaying next PLC execution a few cylces more until having at least
1ms minimal idle time.
// hmi_tree.ysl2

// Location identifies uniquely SVGHMI instance
param "instance_name";

// HMI Tree computed from VARIABLES.CSV in svghmi.py
const "hmitree", "ns:GetHMITree()";

const "_categories" {
    noindex > HMI_PLC_STATUS
    noindex > HMI_CURRENT_PAGE
}
const "categories", "exsl:node-set($_categories)";

// HMI Tree Index
const "_indexed_hmitree" apply "$hmitree", mode="index";
const "indexed_hmitree", "exsl:node-set($_indexed_hmitree)";

emit "preamble:hmi-tree" {
    | var hmi_hash = [«$hmitree/@hash»];
    |
    | var heartbeat_index = «$indexed_hmitree/*[@hmipath = '/HEARTBEAT']/@index»;
    |
    | var current_page_var_index = «$indexed_hmitree/*[@hmipath = concat('/CURRENT_PAGE_', $instance_name)]/@index»;
    |
    | var hmitree_types = [

    foreach "$indexed_hmitree/*" 
    |     "«substring(local-name(), 5)»"`if "position()!=last()" > ,`

    | ];
    |
    | var hmitree_paths = [

    foreach "$indexed_hmitree/*" 
    |     "«@hmipath»"`if "position()!=last()" > ,`

    | ];
    |
    | var hmitree_nodes = {

    foreach "$indexed_hmitree/*[local-name() = 'HMI_NODE']" 
    |     "«@hmipath»" : [«@index», "«@class»"]`if "position()!=last()" > ,`
    | };
    |
}

template "*", mode="index" {
    param "index", "0";
    param "parentpath", "''";
    const "content" {
        const "path"
            choose {
                when "count(ancestor::*)=0" > /
                when "count(ancestor::*)=1" > /«@name»
                otherwise > «$parentpath»/«@name»
            }
        choose {
            when "not(local-name() = $categories/noindex)" {
                xsl:copy {
                    attrib "index" > «$index»
                    attrib "hmipath" > «$path»
                    foreach "@*" xsl:copy;
                }
                apply "*[1]", mode="index"{
                     with "index", "$index + 1";
                     with "parentpath" > «$path»
                }
            }
            otherwise {
                apply "*[1]", mode="index"{
                    with "index", "$index";
                    with "parentpath" > «$path»
                }
            }
        }
    }

    copy "$content";
    apply "following-sibling::*[1]", mode="index" {
        with "index", "$index + count(exsl:node-set($content)/*)";
        with "parentpath" > «$parentpath»
    }
}

include parse_labels.ysl2

const "_parsed_widgets" {
    widget type="VarInitPersistent" {
        arg value="0";
        path value="lang";
    }
    apply "$hmi_elements", mode="parselabel";
}

const "parsed_widgets","exsl:node-set($_parsed_widgets)";

def "func:widget" {
    param "id";
    result "$parsed_widgets/widget[@id = $id]";
}

def "func:is_descendant_path" {
    param "descend";
    param "ancest";
    // TODO : use HMI tree to answer more accurately
    result "string-length($ancest) > 0 and starts-with($descend,$ancest)";
}

def "func:same_class_paths" {
    param "a";
    param "b";
    const "class_a", "$indexed_hmitree/*[@hmipath = $a]/@class";
    const "class_b", "$indexed_hmitree/*[@hmipath = $b]/@class";
    result "$class_a and $class_b and $class_a = $class_b";
}

// Debug data
template "*", mode="testtree"{
    param "indent", "''";
    > «$indent» «local-name()» 
    foreach "@*" > «local-name()»="«.»" 
    > \n
    if "text()" > «text()»\n
    apply "*", mode="testtree" {
        with "indent" value "concat($indent,'>')"
    };
}

emit "debug:hmi-tree" {
    | Raw HMI tree
    apply "$hmitree", mode="testtree";
    |
    | Indexed HMI tree
    apply "$indexed_hmitree", mode="testtree";
    |
    | Parsed Widgets
    copy "_parsed_widgets";
    apply "$parsed_widgets", mode="testtree";
}