Summary
| Task name | demo-Thermostat01 |
| Input topic | demo/showcase/thermostat/01/in |
| Output topic | demo/showcase/thermostat/01/out |
| Operations used | mqtt.MqttTrigger, core.JsonParser, core.Hysteresis, core.Boolean, mqtt.MqttAction |
The Smart Thermostat task is the canonical introductory example: a
sensor stream in, a cooling command out, and a Hysteresis node in the
middle that keeps the relay from chattering when the temperature sits
on the boundary. Five nodes end-to-end — the simplest task that tells a
complete “rules engine replacement” story.
A temperature sensor publishes readings to the demo slot. We want a cooling controller that:
Summary
| Task name | demo-Thermostat01 |
| Input topic | demo/showcase/thermostat/01/in |
| Output topic | demo/showcase/thermostat/01/out |
| Operations used | mqtt.MqttTrigger, core.JsonParser, core.Hysteresis, core.Boolean, mqtt.MqttAction |
MqttTrigger ─► JsonParser ─► Hysteresis ─► Boolean ─► MqttActionJsonParser pulls /temp out of the incoming payload.Hysteresis is configured with Threshold High = 24.0, Threshold
Low = 22.0. It outputs true when the input rises above 24, false
when it falls below 22, and stops the execution path on every reading
in between — so downstream nodes run only on state changes.Boolean is an AND over a single Data input (which is the
identity for one boolean) and its output format is set to String,
with the true text COOL ON and the false text COOL OFF. The
node serves as a typed projection from the Hysteresis bool directly to
the string the dashboard wants to see — no Const/Condition/Report
wiring required.MqttAction publishes the string payload to the output topic.Every Node that carries On Error leaves it at Stop this branch — the default. Error handling is the subject of later Thermostat variants; this task is the on-ramp where the happy path is the whole story.
Input
Topic: demo/showcase/thermostat/01/in
{"temp": 24.5}Output
Topic: demo/showcase/thermostat/01/out
COOL ONA representative sequence:
Reading (/temp) | Hysteresis edge | Output |
|---|---|---|
23.0 | none (first value inside dead band) | nothing |
24.5 | false → true | COOL ON |
23.5 | none (above low threshold, still high) | nothing |
21.5 | true → false | COOL OFF |
Make sure the demo slot is running — either on the public demo server or in your own Nonbl instance with an equivalent task defined.
Subscribe to the output topic in one shell:
mosquitto_sub -h <broker> -t demo/showcase/thermostat/01/outPublish a few readings from another shell:
mosquitto_pub -h <broker> -t demo/showcase/thermostat/01/in -m '{"temp":23.0}'mosquitto_pub -h <broker> -t demo/showcase/thermostat/01/in -m '{"temp":24.5}'mosquitto_pub -h <broker> -t demo/showcase/thermostat/01/in -m '{"temp":23.5}'mosquitto_pub -h <broker> -t demo/showcase/thermostat/01/in -m '{"temp":21.5}'You should see COOL ON for reading 24.5 and COOL OFF for
21.5. The other two readings sit inside the dead band and are
silently absorbed.
Dead-banded control is the textbook fix for the “relay flapping on the
threshold” problem. Expressing it as a single node — instead of a pair
of Compares plus state juggling — keeps the graph readable and makes
the dead band visible at a glance. Hysteresis also is one of the few
operations whose output is preserved across restarts, so the
controller resumes in the same state it left off in.