OPC-UA: only support the encryption policy selected in config.
By default open62541 client accepts all supported policies, but in makes problem
when negociating with some servers while most clients seems to only support
one policy at a time.
// detachable_pages.ysl2
//
// compute what elements are required by pages
// and decide where to cut when removing/attaching
// pages elements on page switch
const "hmi_pages_descs", "$parsed_widgets/widget[@type = 'Page']";
const "hmi_pages", "$hmi_elements[@id = $hmi_pages_descs/@id]";
const "default_page" choose {
when "count($hmi_pages) > 1" {
choose {
when "$hmi_pages_descs/arg[1]/@value = 'Home'" > Home
otherwise {
error > No Home page defined!
}
}
}
when "count($hmi_pages) = 0" {
error > No page defined!
}
otherwise > «func:widget($hmi_pages/@id)/arg[1]/@value»
}
emit "preamble:default-page" {
|
| var default_page = "«$default_page»";
const "screensaverpage", "$hmi_pages_descs[arg[1]/@value = 'ScreenSaver']";
const "delay" choose {
when "$screensaverpage" {
const "delaystr", "$screensaverpage/arg[2]/@value";
if "not(regexp:test($delaystr,'^[0-9]+$'))"
error > ScreenSaver page has missing or malformed delay argument.
value "$delaystr";
}
otherwise > null
}
| var screensaver_delay = «$delay»;
}
const "keypads_descs", "$parsed_widgets/widget[@type = 'Keypad']";
const "keypads", "$hmi_elements[@id = $keypads_descs/@id]";
// returns all directly or indirectly refered elements
def "func:refered_elements" {
param "elems";
const "descend", "$elems/descendant-or-self::svg:*";
const "clones", "$descend[self::svg:use]";
const "originals", "//svg:*[concat('#',@id) = $clones/@xlink:href]";
choose {
when "$originals"
result "$descend | func:refered_elements($originals)";
otherwise
result "$descend";
}
}
// variable "overlapping_geometry" was added for optimization.
// It avoids calling func:overlapping_geometry 3 times for each page
// (apparently libxml doesn't cache exslt function results)
// in order to optimize further, func:overlapping_geometry
// should be implemented in python or even C,
// as this is still the main bottleneck here
const "_overlapping_geometry" {
foreach "$hmi_pages | $keypads" {
const "k", "concat('overlapping:', @id)";
value "ns:ProgressStart($k, concat('collecting membership of ', @inkscape:label))";
elt {
attrib "id" > «@id»
copy "func:overlapping_geometry(.)";
}
value "ns:ProgressEnd($k)";
}
}
const "overlapping_geometry", "exsl:node-set($_overlapping_geometry)";
def "func:all_related_elements" {
param "page";
const "page_overlapping_geometry", "$overlapping_geometry/elt[@id = $page/@id]/*";
const "page_overlapping_elements", "//svg:*[@id = $page_overlapping_geometry/@Id]";
const "page_widgets_elements", """
$hmi_elements[not(@id=$page/@id)
and descendant-or-self::svg:*/@id = $page_overlapping_elements/@id]
/descendant-or-self::svg:*""";
const "page_sub_elements", "func:refered_elements($page | $page_overlapping_elements | $page_widgets_elements)";
result "$page_sub_elements";
}
def "func:required_elements" {
param "pages";
choose{
when "$pages"{
result """func:all_related_elements($pages[1])
| func:required_elements($pages[position()!=1])""";
}otherwise{
result "/..";
}
}
}
const "required_page_elements",
"func:required_elements($hmi_pages | $keypads)/ancestor-or-self::svg:*";
const "required_list_elements", "func:refered_elements(($hmi_lists | $hmi_textlists)[@id = $required_page_elements/@id])/ancestor-or-self::svg:*";
const "required_elements", "$defs | $required_list_elements | $required_page_elements";
const "discardable_elements", "//svg:*[not(@id = $required_elements/@id)]";
def "func:sumarized_elements" {
param "elements";
const "short_list", "$elements[not(ancestor::*/@id = $elements/@id)]";
const "filled_groups", """$short_list/parent::*[
not(child::*[
not(@id = $discardable_elements/@id) and
not(@id = $short_list/@id)
])]""";
const "groups_to_add", "$filled_groups[not(ancestor::*/@id = $filled_groups/@id)]";
result "$groups_to_add | $short_list[not(ancestor::*/@id = $filled_groups/@id)]";
}
def "func:detachable_elements" {
param "pages";
choose{
when "$pages"{
result """func:sumarized_elements(func:all_related_elements($pages[1]))
| func:detachable_elements($pages[position()!=1])""";
}otherwise{
result "/..";
}
}
}
// Avoid nested detachables
const "_detachable_elements", "func:detachable_elements($hmi_pages | $keypads)";
const "detachable_elements", "$_detachable_elements[not(ancestor::*/@id = $_detachable_elements/@id)]";
emit "declarations:detachable-elements" {
|
| var detachable_elements = {
foreach "$detachable_elements"{
| "«@id»":[id("«@id»"), id("«../@id»")]`if "position()!=last()" > ,`
}
| }
}
const "forEach_widgets_ids", "$parsed_widgets/widget[@type = 'ForEach']/@id";
const "forEach_widgets", "$hmi_widgets[@id = $forEach_widgets_ids]";
const "in_forEach_widget_ids", "func:refered_elements($forEach_widgets)[not(@id = $forEach_widgets_ids)]/@id";
template "svg:*", mode="page_desc" {
if "ancestor::*[@id = $hmi_pages/@id]" error > HMI:Page «@id» is nested in another HMI:Page
const "desc", "func:widget(@id)";
const "pagename", "$desc/arg[1]/@value";
const "msg", "concat('generating page description ', $pagename)";
value "ns:ProgressStart($pagename, $msg)";
const "page", ".";
const "p", "$geometry[@Id = $page/@id]";
const "page_all_elements", "func:all_related_elements($page)";
const "all_page_widgets","$hmi_widgets[@id = $page_all_elements/@id and @id != $page/@id]";
const "page_managed_widgets","$all_page_widgets[not(@id=$in_forEach_widget_ids)]";
const "page_relative_widgets",
"$page_managed_widgets[func:is_descendant_path(func:widget(@id)/path/@value, $desc/path/@value)]";
// Take closest ancestor in detachable_elements
// since nested detachable elements are filtered out
const "sumarized_page",
"""func:sumarized_elements($page_all_elements)""";
const "required_detachables",
"""$sumarized_page/
ancestor-or-self::*[@id = $detachable_elements/@id]""";
| "«$pagename»": {
//| widget: hmi_widgets["«@id»"],
| bbox: [«$p/@x», «$p/@y», «$p/@w», «$p/@h»],
if "$desc/path/@value" {
if "count($desc/path/@index)=0"
warning > Page id="«$page/@id»" : No match for path "«$desc/path/@value»" in HMI tree
| page_index: «$desc/path/@index»,
| page_class: "«$indexed_hmitree/*[@hmipath = $desc/path/@value]/@class»",
}
| widgets: [
foreach "$page_managed_widgets" {
const "widget_paths_relativeness"
foreach "func:widget(@id)/path" {
value "func:is_descendant_path(@value, $desc/path/@value)";
if "position()!=last()" > ,
}
| [hmi_widgets["«@id»"], [«$widget_paths_relativeness»]]`if "position()!=last()" > ,`
}
| ],
| jumps: [
foreach "$parsed_widgets/widget[@id = $all_page_widgets/@id and @type='Jump']" {
| hmi_widgets["«@id»"]`if "position()!=last()" > ,`
}
| ],
| required_detachables: {
foreach "$required_detachables" {
| "«@id»": detachable_elements["«@id»"]`if "position()!=last()" > ,`
}
| }
apply "$parsed_widgets/widget[@id = $all_page_widgets/@id]", mode="widget_page"{
with "page_desc", "$desc";
}
| }`if "position()!=last()" > ,`
value "ns:ProgressEnd($pagename)";
}
emit "definitions:page-desc" {
|
| var page_desc = {
apply "$hmi_pages", mode="page_desc";
| }
}
template "*", mode="widget_page";
emit "debug:detachable-pages" {
|
| DETACHABLES:
foreach "$detachable_elements"{
| «@id»
}
| DISCARDABLES:
foreach "$discardable_elements"{
| «@id»
}
| In Foreach:
foreach "$in_forEach_widget_ids"{
| «.»
}
| Overlapping
apply "$overlapping_geometry", mode="testtree";
}