Skip to content

Output Messages

mchristegh edited this page Jul 10, 2026 · 2 revisions

The three outputs

# Output Carries
1 Trigger Genuine Triggers only — the count reached the limit. Never a blocked or redundant message.
2 Query State snapshots only — responses to a query command, and Heartbeat ticks.
3 Events Everything else, plus a duplicate copy of every Trigger. The only output where msg.ignored can be true.

The routing rule is absolute: anything that didn't truly happen only ever appears on output 3. A flow wired to output 1 can treat every message as a real Trigger without checking anything.

What message arrives

Every output message is a clone of the message that caused the event, with the envelope properties below layered on top:

  • A counted candidate's events clone that candidate.
  • A command's events clone that command message.
  • The Trigger clones the final counted message — the one that completed the count — so its payload and topic carry through to downstream nodes.
  • Events with no live triggering message of their own — windowexpired, cooldownstarted, cooldownended, Heartbeat ticks — clone the last counted message as their base. (One special case: a Trigger caused by lowering the count limit also clones the last counted message, since no candidate completed it.)

This lineage means a Trigger wired straight into an action node (a notification, a switch actuation) delivers the original sensor message's payload, not a synthetic one.

The envelope

Added to every message on every output. Property names deliberately match the sibling timer-events node, so downstream function and switch nodes can process both nodes' output with the same code.

Property Description
msg.timerEvent The event type — see Events for the full vocabulary
msg.timerState idle, counting, or cooldown — see States
msg.count The current live count
msg.countLimit The effective count limit (configuration, or a setcountlimit override)
msg.windowMode fixed or sliding
msg.windowDuration The effective window length in milliseconds
msg.windowRemaining Fixed mode: ms until the window expires. Sliding mode: ms until the oldest live message ages out. During cooldown: cooldown time remaining. 0 when idle.
msg.cooldownRemaining ms left in the cooldown, 0 in every other state
msg.ignoredCount Candidates blocked (not counted) during the current cooldown/disabled period
msg.lastIgnoredTime ISO 8601 timestamp of the last blocked candidate, or null
msg.disabled The disabled flag (boolean) — a flag, not a state; see States
msg.ignored true if this message was received but did not take effect. Always false on outputs 1 and 2.
msg.source "external" — a live incoming message caused this event. "internal" — the node itself did: window expiry, sliding decay to zero, cooldown transitions, a Heartbeat tick.

Event-specific extras

Property Present on Contains
msg.countLimitSet countlimitset events The applied value — or, on an ignored: true event, the rejected attempted value
msg.windowSet windowset events Same, in milliseconds

Echoing rejected values lets a downstream flow log or alert on invalid runtime configuration attempts without any other channel.

The Trigger message reports the settled state

The envelope on a triggered message describes the post-trigger state: count is 0, windowRemaining is 0, and timerState is idle — not a mid-transition snapshot. If a Cooldown follows, the subsequent cooldownstarted event (output 3) is what reports the cooldown state. The Trigger's payload still carries the completing message's content, per the lineage rules above.

Reading a query snapshot

A query response (or Heartbeat tick) is the same envelope with timerEvent: "query". The most useful reads:

  • "How close is it to triggering?" — count vs. countLimit.
  • "When will something next change?" — windowRemaining (in sliding mode this is when the count next decays; in fixed mode, when the whole cycle expires).
  • "Why isn't it counting?" — check timerState for cooldown and the disabled flag; ignoredCount tells you how many candidates have bounced off.
  • "Did someone change the configuration at runtime?" — compare countLimit / windowDuration against the values in the edit dialog.

Clone this wiki locally