Skip to content

Tags and scripts

Everything in JasperNode is a tag: a named value in one live tree. A tag’s id is its path and its name joined by /, like plant/tank/level.

Value typeFor
numberreadings, setpoints, counts (64-bit)
booleanon/off, run/stop, alarms
stringstates, labels, short text
bytesbinary payloads

A tag’s props are valueType, description and, for a number, decimals (the value is rounded before the controller decides whether it changed). Writing the same value again changes nothing and triggers nothing.

Your programme is every tag outside __sys, plus the connectors under __sys/node/user/connectors/. The rest of __sys is the controller’s own: __sys/host/ (clock, OS, network), __sys/node/about/ (version), __sys/node/service/ (connector status and diagnostics) and __sys/node/user/config (the controller’s settings).

A tag can carry a script: an async JavaScript function body that computes that tag’s value. A script sets only its own tag, by returning a value or calling self.setValue(v).

It reads other tags with two helpers, each given a tag id as a plain string:

  • on("path/name") returns the tag’s value and runs the script whenever that tag changes.
  • read("path/name") returns the tag’s value without triggering anything.
// Tag: plant/pump/run — true while the level is above the limit
return on("plant/tank/level") > on("plant/tank/high_limit");
// Tag: plant/counter — counts 0–15, once a second
on("__sys/host/clock/second");
if (typeof cache.count !== "number") cache.count = -1;
cache.count = (cache.count + 1) & 0xf;
return cache.count;
  • The wiring is read from the code. Every on(...) and read(...) is found when the script is saved, so the path must be a string literal: on(someVariable) is refused, with the line named. For a choice, put a literal in each branch: cond ? on("a/b") : on("c/d").
  • A script may not on() its own tag; that would re-run it on its own write.
  • Inputs are a snapshot. Every value a run reads is taken once, when the run starts.
  • In scope: self (this tag), on, read, script (script.caller is the tag that fired the run), cache (an object kept between runs, in memory), fn (fn.sleep(ms), fn.timerOn(ms, valueWhenElapsed, defaultValue) as an on-delay timer) and console.
  • Event-driven. Nothing runs on a fixed scan: a script runs when one of its on() tags changes. A run longer than 30 seconds is stopped.