Appearance
Variables and Data ()
Last updated
Nodes do not hand values to each other along the wires. Instead, every run has one shared set of named variables. A node that produces something stores it under the name in its Output variable field; a later node reads it by writing {{name}} in one of its text fields.
Writing {{name}}
{{name}}can sit anywhere in a text field:Oven {{oven}} at {{temp}} °C.- Spaces inside the braces are ignored:
{{ temp }}works. - The lookup order is: run variables first, then the data the trigger supplied.
- If the name is not found, the text stays as it is — you will see a literal
{{temp}}in the email or tag. - A dotted name reads a field of an object:
{{fromPeer.name}},{{response.temp}}. It is used only when no variable is called exactly that. List positions ({{rows[0]}}) are not understood and stay literal; use an Expression node for those. - Every substitution produces text. A number 21.5 becomes
21.5; a list becomes its items joined with commas; an object becomes its JSON, such as{"lot":42}. {{…}}is replaced in text fields only. Number fields (Threshold, Delay (ms), Preset count…) and on/off boxes take a fixed value.
Where variables come from
| Source | Variable name |
|---|---|
| Output variable field of Read Tag, Math, Expression, Convert, Concat/Split String, Decode JSON, Reformat Date/Time, Random Number, Count Up/Down, Read DB, Call URL, Get Variable | Whatever you type there (each has a sensible default such as value, result, rows, response) |
| Set Variable | Its Variable name |
| Compare Value, String Compare, Date/Time Compare | Always result (true or false) |
| Check Network | Always networkConnected |
| Send Message | recipients (a send), or its Reply variable (default reply) when it waits for a reply |
| Loop | loopIndex (0, 1, 2…), loopCount, and loopItem in for-each mode |
| Parameters passed to the run (dashboard button, Run Workflow node, script, API) | Each parameter's name |
Output variables are shared across the whole run, so two Math nodes both left at result overwrite each other. Give each one a meaningful name: tempF, scrapPct.
Trigger data
The trigger's own data can be read the same way. It is looked up after the variables, so a variable of the same name wins.
| Started by | Names you can use |
|---|---|
| Tag Change | trigger (= tag_change), deviceId, tagPath, value |
| Tag Value | trigger (= tag_value), deviceId, tagPath, value (as a number; true/false become 1/0), threshold |
| Machine Online / Machine Offline | trigger, deviceId, status (connected / disconnected) |
| Schedule node | trigger (= schedule), scheduleType, and cron or time |
| Network Event | trigger (= network), connected (true/false), state |
| User Login / User Logout | trigger, userId, email |
| Message Received | Every field of the message's payload ({{lot}}), then trigger (= message), messageName, messageHops, and fromPeer ({{fromPeer.name}}, {{fromPeer.id}}) when it came from a paired appliance |
| Run Now, dashboard button, REST call | trigger (= manual), userId, plus any parameters |
| Run Workflow node in another workflow | Every variable of the calling run, the node's parameters, trigger (= workflow), parentWorkflowId, depth |
A script (workflows.run / workflows.trigger) | The parameters, trigger (= script), depth |
| The Schedules page | trigger (= schedule) only |
| An alarm pipeline step | trigger (= alarm_pipeline), alarmRuleId (holds the rule's name), severity, message, deviceId, tagPath, value |
Note: A few nodes read a variable by name rather than through
{{ }}: Read DB's Where value variable, Encode JSON's Source variable and Loop's Array variable. These look only at run variables, not at trigger data. To use the trigger'svaluethere, copy it first with a Set Variable node (Variable namepartNo, Value{{value}}).
Text versus numbers
Because {{…}} always produces text, a value copied with Set Variable is text too. That matters in a few places:
- Condition with
==or!=compares the two texts as typed:5equals5, but5.0does not equal5. Use Compare Value, which compares as numbers, or use>=/<=. - Condition and Compare Value with
>,<,>=,<=convert both sides to numbers. Text that is not a number never matches. - Lists and objects survive only when a node stores them directly (Split String, Read DB, Decode JSON, Call URL with a JSON reply, Expression). Get at their contents with an Expression:
return vars.rows[0].batch;.
Text boxes and the Headers box
Expression, Send Email Body and Call URL Body keep exactly what you type — no quotes, no escaping. {{variables}} in an email or Call URL body are replaced when the node runs.
| You want | Type this |
|---|---|
| Expression code | return Number(vars.value) * 1.8 + 32; |
| An email body with variables | Oven 3 is at {{value}} °C. Check the burner. |
| A Call URL header | {"Authorization": "Bearer {{token}}"} in Headers (JSON) |
| A Call URL JSON body with variables | {"line": {{line}}, "state": "{{state}}"} |
Headers (JSON) must be a JSON object. Text that isn't valid JSON is kept, marked Not valid JSON, and fails the run with Headers are not valid JSON until you correct it.
Hidden per-node values
After a node runs, its outputs are also stored under <nodeId>_<output>. Node ids are generated and not shown anywhere in the editor, so you cannot use these in practice.