SVGHMI: Added parsing of min and max value that can be given as @path,min,max in widget description
--- a/svghmi/gen_index_xhtml.xslt Tue Dec 22 14:57:59 2020 +0100
+++ b/svghmi/gen_index_xhtml.xslt Thu Dec 24 16:56:19 2020 +0100
@@ -55,7 +55,27 @@
<xsl:text>
</xsl:text>
</xsl:for-each>
- <xsl:text>]
+ <xsl:text>];
+</xsl:text>
+ <xsl:text>
+</xsl:text>
+ <xsl:text>var hmitree_paths = [
+</xsl:text>
+ <xsl:for-each select="$indexed_hmitree/*">
+ <xsl:text> /* </xsl:text>
+ <xsl:value-of select="@index"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="substring(local-name(), 5)"/>
+ <xsl:text> */ "</xsl:text>
+ <xsl:value-of select="@hmipath"/>
+ <xsl:text>"</xsl:text>
+ <xsl:if test="position()!=last()">
+ <xsl:text>,</xsl:text>
+ </xsl:if>
+ <xsl:text>
+</xsl:text>
+ </xsl:for-each>
+ <xsl:text>];
</xsl:text>
<xsl:text>
</xsl:text>
@@ -122,6 +142,7 @@
</xsl:template>
<xsl:template mode="parselabel" match="*">
<xsl:variable name="label" select="@inkscape:label"/>
+ <xsl:variable name="id" select="@id"/>
<xsl:variable name="description" select="substring-after($label,'HMI:')"/>
<xsl:variable name="_args" select="substring-before($description,'@')"/>
<xsl:variable name="args">
@@ -148,7 +169,7 @@
<xsl:if test="$type">
<widget>
<xsl:attribute name="id">
- <xsl:value-of select="@id"/>
+ <xsl:value-of select="$id"/>
</xsl:attribute>
<xsl:attribute name="type">
<xsl:value-of select="$type"/>
@@ -164,33 +185,65 @@
<xsl:for-each select="str:split($paths, '@')">
<xsl:if test="string-length(.) > 0">
<path>
+ <xsl:variable name="pathminmax" select="str:split(.,',')"/>
+ <xsl:variable name="path" select="$pathminmax[1]"/>
+ <xsl:variable name="pathminmaxcount" select="count($pathminmax)"/>
<xsl:attribute name="value">
- <xsl:value-of select="."/>
+ <xsl:value-of select="$path"/>
</xsl:attribute>
- <xsl:variable name="path" select="."/>
- <xsl:variable name="item" select="$indexed_hmitree/*[@hmipath = $path]"/>
<xsl:choose>
- <xsl:when test="count($item) = 1">
- <xsl:attribute name="index">
- <xsl:value-of select="$item/@index"/>
+ <xsl:when test="$pathminmaxcount = 3">
+ <xsl:attribute name="min">
+ <xsl:value-of select="$pathminmax[2]"/>
</xsl:attribute>
+ <xsl:attribute name="max">
+ <xsl:value-of select="$pathminmax[3]"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$pathminmaxcount = 2">
+ <xsl:message terminate="yes">
+ <xsl:text>Widget id:</xsl:text>
+ <xsl:value-of select="$id"/>
+ <xsl:text> label:</xsl:text>
+ <xsl:value-of select="$label"/>
+ <xsl:text> has wrong syntax of path section </xsl:text>
+ <xsl:value-of select="$pathminmax"/>
+ </xsl:message>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="regexp:test($path,'^\.[a-zA-Z0-9_]+')">
<xsl:attribute name="type">
- <xsl:value-of select="local-name($item)"/>
+ <xsl:text>PAGE_LOCAL</xsl:text>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="regexp:test($path,'^[a-zA-Z0-9_]+')">
+ <xsl:attribute name="type">
+ <xsl:text>HMI_LOCAL</xsl:text>
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
- <xsl:choose>
- <xsl:when test="regexp:test($path,'^\.[a-zA-Z0-9_]+')">
- <xsl:attribute name="type">
- <xsl:text>PAGE_LOCAL</xsl:text>
- </xsl:attribute>
- </xsl:when>
- <xsl:when test="regexp:test($path,'^[a-zA-Z0-9_]+')">
- <xsl:attribute name="type">
- <xsl:text>HMI_LOCAL</xsl:text>
- </xsl:attribute>
- </xsl:when>
- </xsl:choose>
+ <xsl:variable name="item" select="$indexed_hmitree/*[@hmipath = $path]"/>
+ <xsl:variable name="pathtype" select="local-name($item)"/>
+ <xsl:if test="$pathminmaxcount = 3 and not($pathtype = 'HMI_INT' or $pathtype = 'HMI_REAL')">
+ <xsl:message terminate="yes">
+ <xsl:text>Widget id:</xsl:text>
+ <xsl:value-of select="$id"/>
+ <xsl:text> label:</xsl:text>
+ <xsl:value-of select="$label"/>
+ <xsl:text> path section </xsl:text>
+ <xsl:value-of select="$pathminmax"/>
+ <xsl:text> use min and max on non mumeric value</xsl:text>
+ </xsl:message>
+ </xsl:if>
+ <xsl:if test="count($item) = 1">
+ <xsl:attribute name="index">
+ <xsl:value-of select="$item/@index"/>
+ </xsl:attribute>
+ <xsl:attribute name="type">
+ <xsl:value-of select="$pathtype"/>
+ </xsl:attribute>
+ </xsl:if>
</xsl:otherwise>
</xsl:choose>
</path>
@@ -1223,6 +1276,8 @@
</xsl:text>
<xsl:text> if(typeof(index) == "string"){
</xsl:text>
+ <xsl:text> /* XXX return index as path */
+</xsl:text>
<xsl:text> index = page_local_index(index, this.container_id);
</xsl:text>
<xsl:text> } else {
@@ -1233,19 +1288,27 @@
</xsl:text>
<xsl:text> }
</xsl:text>
+ <xsl:text> /* XXX check for hmi_paths and return path */
+</xsl:text>
<xsl:text> }
</xsl:text>
<xsl:text> return index;
</xsl:text>
<xsl:text> }
</xsl:text>
+ <xsl:text>
+</xsl:text>
<xsl:text> change_hmi_value(index, opstr) {
</xsl:text>
<xsl:text> let realindex = this.get_variable_index(index);
</xsl:text>
<xsl:text> if(realindex == undefined) return undefined;
</xsl:text>
- <xsl:text> return change_hmi_value(realindex, opstr);
+ <xsl:text> let old_val = cache[realindex];
+</xsl:text>
+ <xsl:text> let new_val = eval_operation_string(old_val, opstr);
+</xsl:text>
+ <xsl:text> return apply_hmi_value(realindex, new_val);
</xsl:text>
<xsl:text> }
</xsl:text>
@@ -3995,7 +4058,7 @@
</xsl:text>
<xsl:text> on_op_click(opstr) {
</xsl:text>
- <xsl:text> let new_val = this.change_hmi_value(0, opstr);
+ <xsl:text> this.change_hmi_value(0, opstr);
</xsl:text>
<xsl:text> }
</xsl:text>
@@ -6827,71 +6890,83 @@
</xsl:text>
<xsl:text>
</xsl:text>
+ <xsl:text>function eval_operation_string(old_val, opstr) {
+</xsl:text>
+ <xsl:text> let op = opstr[0];
+</xsl:text>
+ <xsl:text> let given_val;
+</xsl:text>
+ <xsl:text> if(opstr.length < 2)
+</xsl:text>
+ <xsl:text> return undefined;
+</xsl:text>
+ <xsl:text> if(opstr[1] in quotes){
+</xsl:text>
+ <xsl:text> if(opstr.length < 3)
+</xsl:text>
+ <xsl:text> return undefined;
+</xsl:text>
+ <xsl:text> if(opstr[opstr.length-1] == opstr[1]){
+</xsl:text>
+ <xsl:text> given_val = opstr.slice(2,opstr.length-1);
+</xsl:text>
+ <xsl:text> }
+</xsl:text>
+ <xsl:text> } else {
+</xsl:text>
+ <xsl:text> given_val = Number(opstr.slice(1));
+</xsl:text>
+ <xsl:text> }
+</xsl:text>
+ <xsl:text> let new_val;
+</xsl:text>
+ <xsl:text> switch(op){
+</xsl:text>
+ <xsl:text> case "=":
+</xsl:text>
+ <xsl:text> new_val = given_val;
+</xsl:text>
+ <xsl:text> break;
+</xsl:text>
+ <xsl:text> case "+":
+</xsl:text>
+ <xsl:text> new_val = old_val + given_val;
+</xsl:text>
+ <xsl:text> break;
+</xsl:text>
+ <xsl:text> case "-":
+</xsl:text>
+ <xsl:text> new_val = old_val - given_val;
+</xsl:text>
+ <xsl:text> break;
+</xsl:text>
+ <xsl:text> case "*":
+</xsl:text>
+ <xsl:text> new_val = old_val * given_val;
+</xsl:text>
+ <xsl:text> break;
+</xsl:text>
+ <xsl:text> case "/":
+</xsl:text>
+ <xsl:text> new_val = old_val / given_val;
+</xsl:text>
+ <xsl:text> break;
+</xsl:text>
+ <xsl:text> }
+</xsl:text>
+ <xsl:text> return new_val;
+</xsl:text>
+ <xsl:text>}
+</xsl:text>
+ <xsl:text>
+</xsl:text>
+ <xsl:text>/*
+</xsl:text>
<xsl:text>function change_hmi_value(index, opstr) {
</xsl:text>
- <xsl:text> let op = opstr[0];
-</xsl:text>
- <xsl:text> let given_val;
-</xsl:text>
- <xsl:text> if(opstr.length < 2)
-</xsl:text>
- <xsl:text> return undefined; // TODO raise
-</xsl:text>
- <xsl:text> if(opstr[1] in quotes){
-</xsl:text>
- <xsl:text> if(opstr.length < 3)
-</xsl:text>
- <xsl:text> return undefined; // TODO raise
-</xsl:text>
- <xsl:text> if(opstr[opstr.length-1] == opstr[1]){
-</xsl:text>
- <xsl:text> given_val = opstr.slice(2,opstr.length-1);
-</xsl:text>
- <xsl:text> }
-</xsl:text>
- <xsl:text> } else {
-</xsl:text>
- <xsl:text> given_val = Number(opstr.slice(1));
-</xsl:text>
- <xsl:text> }
-</xsl:text>
<xsl:text> let old_val = cache[index];
</xsl:text>
- <xsl:text> let new_val;
-</xsl:text>
- <xsl:text> switch(op){
-</xsl:text>
- <xsl:text> case "=":
-</xsl:text>
- <xsl:text> new_val = given_val;
-</xsl:text>
- <xsl:text> break;
-</xsl:text>
- <xsl:text> case "+":
-</xsl:text>
- <xsl:text> new_val = old_val + given_val;
-</xsl:text>
- <xsl:text> break;
-</xsl:text>
- <xsl:text> case "-":
-</xsl:text>
- <xsl:text> new_val = old_val - given_val;
-</xsl:text>
- <xsl:text> break;
-</xsl:text>
- <xsl:text> case "*":
-</xsl:text>
- <xsl:text> new_val = old_val * given_val;
-</xsl:text>
- <xsl:text> break;
-</xsl:text>
- <xsl:text> case "/":
-</xsl:text>
- <xsl:text> new_val = old_val / given_val;
-</xsl:text>
- <xsl:text> break;
-</xsl:text>
- <xsl:text> }
+ <xsl:text> let new_val = eval_operation_string(old_val, opstr);
</xsl:text>
<xsl:text> if(new_val != undefined && old_val != new_val)
</xsl:text>
@@ -6903,6 +6978,8 @@
</xsl:text>
<xsl:text>}
</xsl:text>
+ <xsl:text>*/
+</xsl:text>
<xsl:text>
</xsl:text>
<xsl:text>var current_visible_page;
--- a/svghmi/hmi_tree.ysl2 Tue Dec 22 14:57:59 2020 +0100
+++ b/svghmi/hmi_tree.ysl2 Thu Dec 24 16:56:19 2020 +0100
@@ -24,7 +24,7 @@
foreach "$indexed_hmitree/*"
| /* «@index» «@hmipath» */ "«substring(local-name(), 5)»"`if "position()!=last()" > ,`
- | ]
+ | ];
|
}
@@ -67,19 +67,20 @@
}
// Parses:
-// "HMI:WidgetType:param1:param2@path1@path2"
+// "HMI:WidgetType:param1:param2@path1,path1min,path1max@path2"
//
// Into:
// widget type="WidgetType" id="blah456" {
// arg value="param1";
// arg value="param2";
-// path value=".path1" index=".path1" type="PAGE_LOCAL";
+// path value=".path1" index=".path1" min="path1min" max="path1max" type="PAGE_LOCAL";
// path value="/path1" index="348" type="HMI_INT";
// path value="path4" index="path4" type="HMI_LOCAL";
// }
//
template "*", mode="parselabel" {
const "label","@inkscape:label";
+ const "id","@id";
const "description", "substring-after($label,'HMI:')";
const "_args", "substring-before($description,'@')";
@@ -95,7 +96,7 @@
}
if "$type" widget {
- attrib "id" > «@id»
+ attrib "id" > «$id»
attrib "type" > «$type»
foreach "str:split(substring-after($args, ':'), ':')" {
arg {
@@ -105,22 +106,35 @@
const "paths", "substring-after($description,'@')";
foreach "str:split($paths, '@')" {
if "string-length(.) > 0" path {
- attrib "value" > «.»
- const "path", ".";
- const "item", "$indexed_hmitree/*[@hmipath = $path]";
+ const "pathminmax", "str:split(.,',')";
+ const "path", "$pathminmax[1]";
+ const "pathminmaxcount", "count($pathminmax)";
+ attrib "value" > «$path»
choose {
- when "count($item) = 1" {
- attrib "index" > «$item/@index»
- attrib "type" > «local-name($item)»
+ when "$pathminmaxcount = 3" {
+ attrib "min" > «$pathminmax[2]»
+ attrib "max" > «$pathminmax[3]»
+ }
+ when "$pathminmaxcount = 2" {
+ error > Widget id:«$id» label:«$label» has wrong syntax of path section «$pathminmax»
+ }
+ }
+ choose {
+ when "regexp:test($path,'^\.[a-zA-Z0-9_]+')" {
+ attrib "type" > PAGE_LOCAL
+ }
+ when "regexp:test($path,'^[a-zA-Z0-9_]+')" {
+ attrib "type" > HMI_LOCAL
}
otherwise {
- choose {
- when "regexp:test($path,'^\.[a-zA-Z0-9_]+')" {
- attrib "type" > PAGE_LOCAL
- }
- when "regexp:test($path,'^[a-zA-Z0-9_]+')" {
- attrib "type" > HMI_LOCAL
- }
+ const "item", "$indexed_hmitree/*[@hmipath = $path]";
+ const "pathtype", "local-name($item)";
+ if "$pathminmaxcount = 3 and not($pathtype = 'HMI_INT' or $pathtype = 'HMI_REAL')" {
+ error > Widget id:«$id» label:«$label» path section «$pathminmax» use min and max on non mumeric value
+ }
+ if "count($item) = 1" {
+ attrib "index" > «$item/@index»
+ attrib "type" > «$pathtype»
}
}
}
--- a/tests/svghmi/svghmi_0@svghmi/svghmi.svg Tue Dec 22 14:57:59 2020 +0100
+++ b/tests/svghmi/svghmi_0@svghmi/svghmi.svg Thu Dec 24 16:56:19 2020 +0100
@@ -304,7 +304,7 @@
</g>
<g
id="g84"
- inkscape:label="HMI:Input@/TARGETPRESSURE"
+ inkscape:label="HMI:Input@/TARGETPRESSURE,0,100"
transform="matrix(0.35865594,0,0,0.35865594,22.072155,63.074421)">
<text
inkscape:label="value"