Skip to main content
Version: 1.0.4

Timer New in 1.0.4

Puts time between messages. It can hold a message back, pulse a value and put it back, repeat a message on a cadence, count down to a deadline, or say something when a message that should have arrived did not.

Type: timer · Category: Common · Ports: one input · one output

The Timer node as it appears on the pipeline canvas.The Timer node as it appears on the pipeline canvas.

When to use it

  • Watching a heartbeat, so silence raises an alarm instead of passing unnoticed
  • Pulsing a tag — set it to 1, then back to 0 five seconds later — from one message
  • Waiting until a burst of messages settles before writing anything
  • Counting down a permit, a cure time or a hold, with a warning before it expires
Reach for something else when

To start a flow on a schedule, use Inject — a Timer needs an input message and Inject needs none. To drop repeats of a value that has not moved, use RBE, which compares values where a Timer only measures time.

The Timer is the only node that defers. It never blocks the pipeline: it hands a deadline to the runtime and returns, and when that deadline matures the runtime re-enters the pipeline at this node and the message goes out. Every fire is its own independent run, which is why a repeating timer needs no loop in a graph that does not allow them.

Modes

ModeOn input it…Later it…
Pulse (oneshot)sends the first payload straight awaysends the second payload after the duration
Watch for silence (watchdog)sends nothing, and restarts the clocksends an alert only if the duration passes with no message
Wait until quiet (debounce)holds the newest message and restarts the clocksends that one message once things go quiet
Delay every message (delay)queues the messagesends each one, in order, after its own wait — nothing is discarded
Count down / stopwatch (counter)starts countingsends a warning at the threshold, then zero — or, counting up, the elapsed time when stopped
Repeat until stopped (loop)starts repeatingre-sends the incoming message every duration, until a STOP or a limit

Every mode except Delay holds at most one pending timer per key, so a fast input cannot accumulate work — a new message replaces the pending timer rather than adding to it. Delay is the exception because letting every message through is the whole point of it, which is also why it is the only mode with a queue depth to cap.

Settings

Timing

SettingKeyDefaultPurpose
ModemodeoneshotOne of the six above.
Durationduration / durationUnit5 secondsHow long the timer waits. Milliseconds, seconds, minutes or hours.
First payloadinitialPayload1Pulse only. Sent immediately.
Second payloadfinalPayload0Pulse only. Sent after the duration.
Keep alerting while silentrepeatWhileSilentoffWatchdog only. On, it alerts every duration until traffic resumes; off, once per silent period.
Most messages held per topicmaxQueue1000Delay only.
DirectiondirectiondownCounter only. Count down to zero, or up as a stopwatch.
Warn with this many seconds leftwarningAt0Counter only. 0 = no warning.
Stop after this many repeatsmaxIterations0Loop only. 0 = unlimited.
Stop after this long (seconds)loopTimeout0Loop only. 0 = unlimited.

A literal payload is converted on the way out: 1 becomes the number 1 and true becomes a boolean, so a pulse can drive a numeric tag with no cast node in between. Anything else stays text.

Duration is not Timeout

Every node has a Timeout, which bounds how long that node may run. A Timer runs in microseconds and then waits, so the two are unrelated — a one-hour timer does not need a one-hour timeout.

Topics

SettingKeyDefaultPurpose
Separate timer per topicseptopicstrueEach topic gets its own independent timer. Off, every message shares one.
Topic fromtopicPropertytopicWhat identifies a timer. A dotted path such as payload.device keys on something other than the topic.
Maximum topicsmaxTopics1000The node refuses a new key past this, rather than quietly evicting one it is already watching.

Control

A message can command the timer instead of feeding it. The command is read from a named property and is consumed — it never travels downstream, and a watchdog never counts it as activity.

SettingKeyDefaultPurpose
Command read fromcontrolPropertymetadata.timerCmdWhere a command is read from.
Command target read fromtargetProperty(empty)Which timer a command addresses. Empty = the command's own topic. A path such as payload.target lets a command name another one; the value * clears every timer on the node.
Duration read fromdurationProperty(empty)Optional. A path such as payload.seconds lets a message set its own wait, read in the unit chosen under Timing.
Accept that duration ondurationOverrideOnSTART commands onlyOr any message, for a feed that carries its own cadence.
Longest allowed duration (seconds)maxDuration86400The ceiling any message-supplied duration is held to.

The five commands are START, STOP, RESET, PAUSE and CONTINUE. Rename any of them in the config and the old name stops working — which is what makes the word safe to send as ordinary data once you have. PAUSE holds the time remaining and CONTINUE resumes that; it never starts a fresh full-length wait.

Do not read commands from the payload

The default is metadata.timerCmd, not payload, on purpose. The payload is your data channel: a device that happens to publish the literal text STOP would stop the timer instead of feeding it — which lets a device silently switch off the watchdog monitoring it. The property panel warns you if you point the command at the payload.

Example — a watchdog on a pump heartbeat

Each pump publishes to its own topic every few seconds. If one goes quiet for 30 seconds, raise it.

Mode: Watch for silence
Duration: 30 seconds
Keep alerting while silent: off
Separate timer per topic: on
Topic from: topic
Industrial I/O (subscribe Pumps/*) → Timer (watchdog 30s) → Alarm (raise) → Send Email

In — normal traffic. Each message restarts that pump's own clock, and the node emits nothing:

{ "topic": "Pumps/PMP-01", "payload": { "rpm": 1480 } }
{ "topic": "Pumps/PMP-02", "payload": { "rpm": 1502 } }
{ "topic": "Pumps/PMP-01", "payload": { "rpm": 1477 } }

Out — 30 seconds after PMP-01's last message, with PMP-02 still reporting normally:

{
"topic": "Pumps/PMP-01",
"payload": { "event": "elapsed", "durationSec": 30, "topic": "Pumps/PMP-01" },
"metadata": { "timerEvent": "elapsed" }
}

PMP-02 is untouched — its own timer is still running, because Separate timer per topic gives each pump an independent one. The alert synthesises a message rather than replaying the last good reading, which is the point: the interesting fact is that nothing arrived.

With Keep alerting while silent off that is one alert per silent period. The next real message from PMP-01 re-arms the watchdog, and the next silence alerts again.

Example — pulsing a tag for five seconds

Mode: Pulse (send, wait, send again)
Duration: 5 seconds
First payload: 1
Second payload: 0
Inject → Timer (pulse 5s) → Industrial I/O (write Line1/Horn)

Out — two messages from one input, five seconds apart:

{ "payload": 1, "metadata": { "timerEvent": "initial" } }
{ "payload": 0, "metadata": { "timerEvent": "final" } }

Both are numbers, not the strings "1" and "0", so the write lands on a numeric tag with no conversion step in between.

Reading the output

Every emitted message carries metadata.timerEvent, saying why it fired. The node has one output port, so route on that value with a Switch rather than looking for a second socket.

timerEventModeMeans
initialpulseThe leading edge, sent on input.
finalpulseThe trailing edge, after the duration.
elapsedwatchdogNothing arrived in time.
releasedebounce, delayA held message is being let through.
warningcounterThe countdown reached the warning threshold.
zerocounterThe countdown reached zero.
stoppedcounter (up)The stopwatch stopped, carrying the elapsed time.
repeatloopOne iteration. Also carries metadata.iteration, and metadata.loopEnded on the last one.

Watching a timer on the canvas

An armed timer sends the Designer its deadline once, and the node card counts down locally from there. That costs one message per arm and nothing per second — there is no server-side tick, so a node watching 500 topics is as cheap as one watching a single tag.

Gotchas

  • A watchdog needs traffic to arm it. It starts watching only once a first message arrives, so a device that never reports at all after a restart is not caught by a watchdog alone — pair it with a scheduled read if you need to detect that.
  • CONTINUE only resumes a paused timer. If nothing was paused the node says so and does nothing. It deliberately never falls back to starting a fresh full-length timer, which would look like it worked and then wait the wrong amount of time.
  • Watch maxTopics when you key on a value rather than a topic. Keying on something high-cardinality — an order number, a batch id — reaches the limit, and the node then refuses new keys with a warning rather than quietly forgetting one it is already watching.
  • An unusable duration from a message is ignored and the configured duration is used instead. Refusing to arm because a payload was malformed would stop the monitoring, which is the failure the node exists to prevent. A duration that was clamped or rejected says so in the message metadata.
  • A loop is the one mode that produces work with no further input. Set maxIterations or loopTimeout unless you genuinely mean "until someone sends STOP".

See also