Skip to content

Logic & Control Nodes ​

Last updated

Logic nodes decide which way a run goes and reshape values. Fields ending in (or {{var}}) or (if no input) accept {{name}} — or a wired data dot, which now overrides the field the same way a value typed into it would. A dot only carries a value once its own node has actually run earlier in that execution; wire it from something upstream in the same path, not a sibling branch.

Condition ​

If/else. Continues from True or False.

FieldDefaultNotes
Left value / {{var}}—e.g. {{value}}
Operator====, !=, >, <, >=, <=
Right value / {{var}}—e.g. 85

== and != compare the texts as typed (true = true, but 1.0 ≠ 1). The other four compare as numbers. Condition does not set any variable.

Compare Value ​

Compares a tag, or a value / {{var}}, with a value as numbers, stores true/false in result, and continues from True or False. Out also fires whatever the answer — workflows built before the True/False outputs existed keep working. When several outputs are wired, Out runs first, then True or False.

FieldDefaultNotes
CompareA value or {{var}}A value or {{var}}, or A tag
Left value—With A value or {{var}}: a number or {{var}}
Tag—With A tag: the tag's live value is read when the node runs
Operator==Same six as Condition
Right value—A number or {{var}}

On/off values count as numbers: true and on are 1, false and off are 0. A value that is not a number never matches.

String Compare ​

Continues from True or False and stores result. Case-sensitive.

FieldDefaultOptions
Left string—
OperatorEqualsEquals, Not equals, Contains, Starts with, Ends with, Regex
Right string / pattern—For Regex, a JavaScript pattern without slashes, e.g. ^LOT-\d{6}$. An invalid pattern is treated as no match

Math ​

FieldDefaultNotes
OperationAdd (+)Add, Subtract, Multiply, Divide, Modulo, Power, Absolute value, Round, Floor, Ceiling, Square root, Sin, Cos, Tan, Average, Min, Max
A (if no input)0Number or {{var}}
B (if no input)0Ignored by the one-value operations (Absolute value … Tan)
Decimal placesblankRounds the result
Output variableresult
  • Text that is not a number counts as 0.
  • Divide and Modulo by 0 divide by 1 instead — 25 ÷ 0 gives 25, with no error.
  • Sin, Cos and Tan work in radians.
  • Average, Min and Max use A and B.

Expression ​

Runs a line or two of JavaScript and stores the returned value.

FieldDefaultNotes
Expression (return value)return vars.myVar * 2;JavaScript, typed as-is
Output variableresult

Inside the code you have vars (the run's variables — you can also assign to them, vars.limit = 90;), triggerData, and Math, Date, JSON, Number, String, Boolean, Array, Object. There is no access to tags, the database or the network — use a script for that. The code must return something. An exception fails the run with Expression error: ….

The code runs in the same locked-down sandbox as scripts, with a 2-second time limit of its own, so a mistake like while (true) {} fails just this step (Expression error: timed out after 2s) instead of freezing the appliance. Keep an Expression to a quick calculation; anything longer or heavier belongs in a script run from a Run Script node.

Examples:

javascript
return Math.round((Number(vars.good) / Number(vars.total)) * 1000) / 10;
javascript
return vars.rows.length > 0 ? vars.rows[0].batch : 'none';

{{variables}} are not replaced inside the code — read them from vars instead.

Fork ​

FieldDefault
Number of branches2

Starts Branch 1, Branch 2 and Branch 3 at the same time — in parallel, unlike several wires from one output, which run one after another. Only branches up to Number of branches run: with the default 2, a wire from Branch 3 is ignored. Values above 3 add no more dots. If any branch fails, the run fails and the other branches stop at their next node. Gather the branches with a Join. See Parallel branches.

Join ​

FieldDefaultOptions
Continue whenAll branches have arrivedAll branches have arrived, or The first branch arrives

Wire the end of each Fork branch into the Join's In. With All, every branch stops at the Join until the last one arrives, and that one continues from Out — exactly once. With The first branch arrives, the first continues and the rest stop there. The Join counts the wires into it, so a branch that does not reach it (because a Condition sent it elsewhere) leaves an All Join waiting; History then says Join (all) never continued.

Loop ​

FieldDefaultNotes
TypeCountCount or For-each array
Count (if type=count)5Accepts {{var}}
Array variable (if type=each)itemsThe name of a variable holding a list — no braces

Runs the chain wired to Loop body once per pass, then the chain wired to After loop. On each pass loopIndex is 0, 1, 2…, loopCount is the total, and in for-each mode loopItem is the current item. Lists come from Split String, Read DB, Decode JSON, Call URL or Expression. If the variable is not a list, the body runs zero times.

{{loopItem}} of a database row shows [object Object]; take a field with an Expression: return vars.loopItem.weight;.

Jump To ​

FieldDefault
Target label—

Continues the run at the node whose Node Label matches Target label. Case and surrounding spaces are ignored. The run fails with Jump To: no node is labeled "…" if none matches, or if more than one node has that label — give the target a label no other node uses.

A jump back to an earlier node counts toward the 1,000-step limit like a wire loop does; use the Loop node for repetition.

Convert ​

FieldDefaultOptions
From typeNumberNumber, String, Hex, Binary, Octal
To typeStringNumber, String, Hex, Binary, Octal, Boolean
Value (if no input)—
Output variableresult
  • To Hex / Binary / Octal: gives 0xFF, 0b1010, 0o17. The From type is not used.
  • To Number from Hex: FF or 0xFF → 255. From Binary: 1010 or 0b1010 → 10.
  • To Boolean: empty, 0 and false → false; anything else → true.

Encode JSON / Decode JSON ​

NodeFieldDefault
Encode JSONSource variable (name, no braces)data
Encode JSONOutput variablejson
Decode JSONJSON input (or {{var}}){{json}}
Decode JSONOutput variabledata

Decode JSON fails the run with Invalid JSON: … if the text is not JSON.

Reformat Date/Time ​

Formats a date and time: the value wired into Timestamp, else Value, else the current time.

FieldDefaultOptions
Value (or {{var}})—An ISO date such as 2026-09-15T13:05:00Z, or a Unix time in seconds or milliseconds. Empty means now. Anything that isn't a date fails the run
FormatISO 8601ISO 8601 (UTC, e.g. 2026-09-15T13:05:00.000Z), Date only, Time only, Date + Time, Unix timestamp (seconds), Custom
Custom (YYYY-MM-DD HH:mm:ss)YYYY-MM-DD HH:mm:ssUsed when Format is Custom. Tokens: YYYY year, MM month, DD day, HH hour (24 h), mm minute, ss second; anything else is kept as typed, e.g. DD/MM/YYYY HH:mm
Localeen-USControls Date only / Time only / Date + Time, e.g. en-GB → 15/09/2026
Output variableresult

Date only, Time only, Date + Time and Custom use the appliance's time zone.

Date/Time Compare ​

Continues from True or False and stores result.

FieldDefaultOptions
Date A (or {{var}})—Any date text JavaScript understands: 2026-09-15T06:00:00, ISO strings
OperatorBeforeBefore, After, Equal, Same day
Date B (or {{var}})—

A date that cannot be read makes every comparison false.

Concat String ​

FieldDefault
Input count2
Separatorempty
String 1 (if no input) / String 2 (if no input)—
Output variableresult

Only two string fields are offered, so raise the count only if you are happy with empty extra parts. You can usually skip this node: a text field such as Line {{line}} – {{state}} does the same.

Split String ​

FieldDefault
Input (or {{var}})—
Delimiter,
Number of outputs3
Output variableparts

Stores the whole list of parts in the output variable, and also on the Part 1–Part 3, Remainder and Parts[] dots — wire one of those directly into a downstream field instead of writing an Expression, unless you need an index the fixed dots don't cover.

Example: a barcode reader sends LOT-4471;PN-2230;QTY-48. Split with Delimiter ; into parts, then an Expression return vars.parts[2].replace('QTY-', ''); into qty.

See also ​

Scada.Ink Help Center