406 lines
18 KiB
Plaintext
406 lines
18 KiB
Plaintext
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta name="generator" content="HTML Tidy for HTML5 for Apple macOS version 5.8.0">
|
|
<title>LogixNG Reference - Chapter 8</title>
|
|
<meta name="author" content="Daniel Bergqvist">
|
|
<meta name="author" content="Dave Sand">
|
|
<meta name="keywords" content="jmri LogixNG reference local variables">
|
|
<!--#include virtual="/help/en/parts/Style.shtml" -->
|
|
</head>
|
|
<body>
|
|
<!--#include virtual="/help/en/parts/Header.shtml" -->
|
|
|
|
<div id="mBody">
|
|
<div id="mainContent" class="no-sidebar">
|
|
<h1>LogixNG Reference - Chapter 8</h1>
|
|
|
|
<h2>Local Variables</h2>
|
|
|
|
<p>JMRI has memories that can store data. And that's great. But there is a problem with
|
|
memories. They are global, which means that anyone can change them. Lets assume you want to
|
|
count something so you create a memory IMCOUNTER. You create a LogixNG that does the counting
|
|
and everything works fine.</p>
|
|
|
|
<p>A year passes and you need to count something else. You create a new LogixNG that does the
|
|
new counting and you need a memory, so you decide to use the memory IMCOUNTER. And your new
|
|
LogixNG works fine. But then you suddenly realize that something else on the layout stops
|
|
working. Why? What has happen? Well, the problem is that you use the same memory IMCOUNTER
|
|
for two different things in two different places. And when that happens, you get into
|
|
trouble.</p>
|
|
|
|
<p>LogixNG has a simple solution to this problem, <strong>local variables</strong>. A local
|
|
variable is similar to a memory, but it only exists in a very limited context and nothing
|
|
outside that context can interfere with the variable. The local variable is also transient. It
|
|
is only available during the execution of the ConditionalNG and it goes away when the
|
|
execution is finished. This protects the local variable from being changed in an
|
|
unpredictable way.</p>
|
|
|
|
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
|
|
|
<h3>Defining local variables</h3>
|
|
|
|
<p>Local variables are created in the ConditionalNG editor. Open the editor of a
|
|
ConditionalNG and right-click on an action or expression and select <strong>Local
|
|
variables</strong>.</p>
|
|
|
|
<div style="margin-left: 2em;">
|
|
<a href="images/chapter8/local_variables_menu.png"><img class="image-border" src=
|
|
"images/chapter8/local_variables_menu.png" alt="Chapter 8 local variable menu item"></a>
|
|
</div>
|
|
|
|
<p>The local variable dialog window will open.</p>
|
|
|
|
<div style="margin-left: 2em;">
|
|
<a href="images/chapter8/local_variables_dialog.png"><img src=
|
|
"images/chapter8/local_variables_dialog.png" alt="Chapter 8 local variables dialog"></a>
|
|
</div>
|
|
|
|
<p>To create a local variable, click on the <strong>Add variable</strong> button. A new row
|
|
will be added. Double click in the <strong>Name</strong> field and give it a name. Select the
|
|
<strong>Type</strong> and provide an initial value if desired. The <strong>Select</strong>
|
|
menu is used to <strong>Delete</strong> a local variable and has <strong>Move Up</strong> and
|
|
<strong>Move Down</strong> options if there is more than one variable.</p>
|
|
|
|
<p>Click on <strong>OK</strong> to finish. The local variable will be added to the tree. See
|
|
the editor image below.</p>
|
|
|
|
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
|
|
|
<h3 id="variableTypes">Local variable types</h3>
|
|
|
|
<div style="margin-left: 2em;">
|
|
<a href="images/chapter8/local_variable_types.png"><img src=
|
|
"images/chapter8/local_variable_types.png" alt="Chapter 8 local variable types"></a>
|
|
</div>
|
|
|
|
<dl>
|
|
<dt>None</dt>
|
|
<dd>The initial value will be <code>null</code>.</dd>
|
|
|
|
<dt>Boolean <span class="since">since 5.7.5</span></dt>
|
|
<dd>Contains the boolean value <strong>true</strong> or <strong>false</strong>. The state
|
|
is set or referenced by using the words <strong><em>true</em></strong> and
|
|
<strong><em>false</em></strong>. The words are case insensitive. Setting an initial value
|
|
is recommended.</dd>
|
|
|
|
<dt>Integer</dt>
|
|
<dd>A whole number such as 123</dd>
|
|
|
|
<dt>Floating number</dt>
|
|
<dd>A number such as 123.4</dd>
|
|
|
|
<dt>String</dt>
|
|
<dd>A series of characters, such as ABC123def</dd>
|
|
|
|
<dt>Array</dt>
|
|
<dd>A list of items. This is implemented using the Java ArrayList. This is similar to the
|
|
Python List.</dd>
|
|
|
|
<dt>Map</dt>
|
|
<dd>A list of kev/value items. This is implemented using the Java HashMap. This is similar
|
|
to the Python Dictionary.</dd>
|
|
|
|
<dt>Local Variable</dt>
|
|
<dd>Use the value from another local variable.</dd>
|
|
|
|
<dt>Memory</dt>
|
|
<dd>Use the value from a memory variable.</dd>
|
|
|
|
<dt>Reference</dt>
|
|
<dd>Use the value from an indirect reference.</dd>
|
|
|
|
<dt>Formula</dt>
|
|
<dd>Use the value from a formula</dd>
|
|
|
|
<dt>Script expression</dt>
|
|
<dd>Use a one line script command to set the value of the variable. For example:
|
|
<code>sensors.getSensor("BlinkSensor")</code>. This gets a sensor object which can then
|
|
be set active or inactive. For details on accessing LogixNG objects from a script see
|
|
<a href="chapter13.shtml">Chapter 13 - Jython Scripting Support</a>.</dd>
|
|
|
|
<dt>Script file</dt>
|
|
<dd>For more complex logic, a script file can be used to set the value. There are sample
|
|
scripts at the <strong>jython/LogixNG</strong> directory within the JMRI install location.
|
|
Note: The results of the script are passed back to LogixNG using
|
|
<code>variable.set(<em>some_python_variable</em>)</code>. This is a Python global variable
|
|
that is added by the LogixNG scripting support. For details on accessing LogixNG objects
|
|
from a script see <a href="chapter13.shtml">Chapter 13 - Jython Scripting Support</a>.</dd>
|
|
|
|
<dt>LogixNG Table</dt>
|
|
<dd>Load the contents of a specified LogixNG table into a variable. The table name is
|
|
specified in the data column when creating the local variable. For global variables, use
|
|
the initial value field. Here is an example that creates the local variable and provides
|
|
access to the table rows and columns:
|
|
|
|
<div style="margin-left: 2em;">
|
|
<a href="images/chapter8/local_variable_table_type.png"><img src=
|
|
"images/chapter8/local_variable_table_type.png" alt="Chapter 8 local variable table_type"></a>
|
|
</div>
|
|
|
|
</dd>
|
|
|
|
</dl>
|
|
|
|
<p>Note: The type of a variable can change based on the last assignment. For example, a
|
|
local variable with the name <code>index</code> defined as integer would change to string if
|
|
"XVZ" was assigned to <code>index</code>.</p>
|
|
|
|
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
|
|
|
<h5>Array<span class="since">since 4.25.8</span></h5>
|
|
|
|
<p>When an <strong>Array</strong> Local Variable is defined, it will default to empty. Rows
|
|
can be added to the Array using the <strong>add</strong> method. The rows can also be
|
|
defined by providing a value in the data column, in this example 5 rows for Array2.</p>
|
|
|
|
<div style="margin-left: 2em;">
|
|
<a href="images/chapter8/local_variable_array.png"><img src=
|
|
"images/chapter8/local_variable_array.png" alt="Chapter 8 local variable array"></a>
|
|
</div>
|
|
|
|
<p>Some examples of setting the initial Array values. <strong>size</strong> is another local
|
|
variable that contains the row count, such as 23.</p>
|
|
|
|
<div style="margin-left: 2em;">
|
|
<table>
|
|
<tr><th>Example</th><th>Result</th></tr>
|
|
<tr><td>Data field is empty</td><td>The array is empty</td></tr>
|
|
<tr><td>12</td><td>12 empty strings in the array</td></tr>
|
|
<tr><td>size</td><td>23 empty strings in the array</td></tr>
|
|
|
|
<tr><td>12:"Hello world"</td><td>12 "Hello world" strings in the array</td></tr>
|
|
<tr><td>size:"Hello world"</td><td>23 "Hello world" strings in the array</td></tr>
|
|
|
|
<tr><td>12:233</td><td>12 items with the number 233 in the array</td></tr>
|
|
<tr><td>size:233</td><td>23 items with the number 233 in the array</td></tr>
|
|
|
|
<tr><td>12:43.323</td><td>12 items with the number 43.323 in the array</td></tr>
|
|
<tr><td>size:43.323</td><td>23 items with the number 43.323 in the array</td></tr>
|
|
</table>
|
|
</div>
|
|
|
|
<p>The rows in the array are accessed by using the row number. The first row has a row number
|
|
of zero. The last row number is the size of the array minus 1. To set the value of a row:
|
|
<code>array[1] = value</code>. To get the value: <code>value = array[1]</code>.</p>
|
|
|
|
<p>The following list has the common ArrayList methods using the Java syntax.</p>
|
|
|
|
<ul>
|
|
<li>add(value) — Append a row to the array with the specified value.</li>
|
|
<li>clear() — Remove all of the rows from the array.</li>
|
|
<li>get(row) — Get the value of a row using a row number.</li>
|
|
<li>set(row, value) — Set the value of a row using a row number and the new value.</li>
|
|
<li>size() — Return the number of rows in the array</li>
|
|
</ul>
|
|
|
|
<p>The following image shows some of the options for working with an array.</p>
|
|
|
|
<div style="margin-left: 2em;">
|
|
<a href="images/chapter8/array_sample.png"><img src=
|
|
"images/chapter8/array_sample.png" alt="Chapter 8 local variable array sample"></a>
|
|
</div>
|
|
|
|
<ul>
|
|
<li>A1
|
|
<pre>
|
|
Log local variables:
|
|
Name: size1, value: 0
|
|
Name: size2, value: 0
|
|
Name: Array1, value: []
|
|
Name: Array2, value: [, , , , ]
|
|
Log local variables done
|
|
</pre>
|
|
</li>
|
|
<li>A2 and A3 changes two of the rows of Array2 to new values. The array was set with five
|
|
rows. The rows are referenced using the row numbers.</li>
|
|
<li>A5 and A6 copy the two rows from Array2 and <strong>adds</strong> them to Array1. The
|
|
Array2 rows are referenced by row number, but the rows are appended to Array1. The
|
|
corresponding row numbers in Array1 will be 0 and 1.</li>
|
|
<li>A8
|
|
<pre>
|
|
Log local variables: (A8)
|
|
Name: size1, value: 2
|
|
Name: size2, value: 5
|
|
Name: Array1, value: [Zero, XYZ]
|
|
Name: Array2, value: [Zero, , , XYZ, ]
|
|
Log local variables done
|
|
</pre>
|
|
</li>
|
|
<li>A9 removes all of the rows from Array2.</li>
|
|
<li>A10
|
|
<pre>
|
|
Log local variables: (A8)
|
|
Name: size1, value: 2
|
|
Name: size2, value: 5
|
|
Name: Array1, value: [Zero, XYZ]
|
|
Name: Array2, value: [] <== Note zero length
|
|
Log local variables done
|
|
</pre>
|
|
</li>
|
|
</ul>
|
|
|
|
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
|
|
|
<h5 id="lv_map">Map<span class="since">since 4.25.8</span></h5>
|
|
|
|
<p>When a <strong>Map</strong> Local Variable is defined, it is empty. Rows are added as
|
|
shown in the example.</p>
|
|
|
|
<div style="margin-left: 2em;">
|
|
<a href="images/chapter8/local_variable_map.png"><img src=
|
|
"images/chapter8/local_variable_map.png" alt="Chapter 8 local variable map"></a>
|
|
</div>
|
|
|
|
<p>The rows in the map are accessed by using the key for the row. To add a new key/value pair:
|
|
<code>map{key} = value</code>. The same syntax will replace the value for an existing key.
|
|
To get the value for a key: <code>value = map{key}</code>.</p>
|
|
|
|
<p>The following list has the common HashMap methods using the Java syntax.</p>
|
|
|
|
<ul>
|
|
<li>get("key") — Get the value for the key.</li>
|
|
<li>put("key", "value") — Assign a value to the key. If a value already exists
|
|
it is replaced with the new value.</li>
|
|
<li>clear() — Remove all of the rows from the map.</li>
|
|
<li>size() — Return the number of key/value pairs in the map</li>
|
|
</ul>
|
|
|
|
<p>The following image shows some of the options for working with an array.</p>
|
|
|
|
<div style="margin-left: 2em;">
|
|
<a href="images/chapter8/map_sample.png"><img src=
|
|
"images/chapter8/map_sample.png" alt="Chapter 8 local variable map sample"></a>
|
|
</div>
|
|
|
|
<div style="margin-left: 2em;">
|
|
<pre>
|
|
Log local variables:
|
|
Name: Map1, value: {key=value}
|
|
Name: Map2, value: {new=value, abc=xyz}
|
|
Name: Size2, value: 2
|
|
Name: Size1, value: 1
|
|
Log local variables done
|
|
</pre>
|
|
</div>
|
|
|
|
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
|
|
|
<h3>Order of local variables</h3>
|
|
|
|
<p>The order of the local variables that are defined in an action or expression matters if
|
|
you use one variable in the initialization of another. Lets say you define two variables "a"
|
|
and "b", and that you define "a" to be initialized to the formula "34 * 4" and you define "b"
|
|
to be initialized to "a * 3". This will work if "a" is defined before "b". You can define
|
|
both variables in the same action or expression, but "a" needs to be before "b" since "b"
|
|
uses "a" in its initialization.</p>
|
|
|
|
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
|
|
|
<h3>Local variables are local</h3>
|
|
|
|
<p>This may seem obvious, but when writing scripts that uses local variables, it's important
|
|
to remember this. A script can access the symbol table if it has access to the ConditionalNG,
|
|
but the symbol table is dependent on which action or expression that's currently running.</p>
|
|
|
|
<p>The <strong>scope</strong> of a local variable depends on where it is defined in the tree.
|
|
This a contrived example to show scope behavior.</p>
|
|
|
|
<p>There are two local variables defined. One at the root of the tree and a second one part
|
|
way up the first branch.</p>
|
|
|
|
<div style="margin-left: 2em;">
|
|
<a href="images/chapter8/local_variables_scope.png"><img src=
|
|
"images/chapter8/local_variables_scope.png" alt="Chapter 8 local variables scope"></a>
|
|
</div>
|
|
|
|
<p>The output on the JMRI system console shows the result when the ConditionalNG is
|
|
executed.</p>
|
|
|
|
<div style="margin-left: 2em;">
|
|
<pre>
|
|
in if trees
|
|
WARN - Log local variables: [JMRI LogixNGThread]
|
|
WARN - Name: rootlevel, value: null [JMRI LogixNGThread]
|
|
WARN - Name: iftree, value: null [JMRI LogixNGThread]
|
|
WARN - Log local variables done [JMRI LogixNGThread]
|
|
|
|
root level
|
|
WARN - Log local variables: [JMRI LogixNGThread]
|
|
WARN - Name: rootlevel, value: null [JMRI LogixNGThread]
|
|
WARN - Log local variables done [JMRI LogixNGThread]
|
|
</pre>
|
|
</div>
|
|
|
|
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
|
|
|
<h3>Initialization of local variables</h3>
|
|
|
|
<p>When an action or expression is executed that defines local variables, these local
|
|
variables are created with an initial value. When you create the local variable, you define
|
|
what the initial value should be. 'None' means that the value will be 'null'. Reference means
|
|
that the value will be the value that the reference is pointing at. Formula means the result
|
|
of the formula.</p>
|
|
<a id="LogLocalVariables"></a>
|
|
<h3>Debugging local variables</h3>
|
|
|
|
<p>What to do if the ConditionalNG doesn't do the expected? The debugger provides one tool,
|
|
but another tool is the action <strong>Log local variables</strong>. Each time it's executed,
|
|
it prints all the local variables and their values to the JMRI Sytem Console.</p>
|
|
|
|
<div style="margin-left: 2em;">
|
|
<a href="images/chapter8/log_variables.png"><img src=
|
|
"images/chapter8/log_variables.png" alt="Chapter 8 log variables"></a>
|
|
</div>
|
|
|
|
<p>Options:</p>
|
|
|
|
<ul>
|
|
<li><strong>Include global variables</strong> — The global variables will be
|
|
listed after the local variables.</li>
|
|
|
|
<li><strong>Expand arrays and maps</strong> — The contents of each array and map
|
|
will be listed.</li>
|
|
|
|
<li><strong>Show class name</strong> — The name of the Java class will be included
|
|
for each item. Sometimes it is useful for debugging to know the actual type of the value.</li>
|
|
</ul>
|
|
|
|
<p>Example:</p>
|
|
|
|
<div style="margin-left: 2em;">
|
|
<pre>
|
|
WARN - Log local variables: [JMRI LogixNGThread]
|
|
WARN - Name: time, Value: Time is 13:02 [JMRI LogixNGThread]
|
|
WARN - Global variables: [JMRI LogixNGThread]
|
|
WARN - Global Name: gHour, value: 13 [JMRI LogixNGThread]
|
|
WARN - Global Name: gMin, value: 2 [JMRI LogixNGThread]
|
|
WARN - Global Name: timeMap, [JMRI LogixNGThread]
|
|
WARN - theHour -> 13, [JMRI LogixNGThread]
|
|
WARN - theMin -> 2, [JMRI LogixNGThread]
|
|
WARN - theTime -> The map time is 13:02, [JMRI LogixNGThread]
|
|
WARN - Global Name: timeArray, [JMRI LogixNGThread]
|
|
WARN - 0: 13, [JMRI LogixNGThread]
|
|
WARN - 1: 2, [JMRI LogixNGThread]
|
|
WARN - 2: The array time is 13:02, [JMRI LogixNGThread]
|
|
WARN - Global Name: null, value: null [JMRI LogixNGThread]
|
|
WARN - Log local variables done [JMRI LogixNGThread]
|
|
</pre>
|
|
</div>
|
|
|
|
<hr>
|
|
|
|
<p><a href="chapter9.shtml">Chapter 9 - Formula</a>
|
|
</p>
|
|
|
|
<p><a href="index.shtml">Return to the Reference TOC</a>
|
|
</p>
|
|
<!--#include virtual="/help/en/parts/Footer.shtml" -->
|
|
</div>
|
|
<!-- closes #mainContent-->
|
|
</div>
|
|
<!-- closes #mBody-->
|
|
<script src="/js/help.js"></script>
|
|
</body>
|
|
</html>
|