Step control
A control for a value that moves in steps: a column of dots filling from a button, one dot per step. Wheel over it or click a step, and the change goes out as a one-way RPC command or an attribute write — with the payload shaped by you if the device wants something of its own. A wide range is grouped, so 0 to 50 becomes ten dots of five, and a rejected change returns the control to the value the device reports.
Step control
A control for a value that moves in steps: a column of dots that fills from a button outwards, one dot per step. Turn the mouse wheel over it, or click the step you want. Each change goes to the device as a one-way RPC command or as an attribute write.
It arrives configured as a fan speed — four speeds, a fan icon, setFanSpeed — because that is the case
everyone has. It is not limited to it: a range, a step, an icon and a caption make it a heater level, a
damper position, a pump rate or a dimmer.
Features
- Mouse wheel steps one at a time; a click on any dot jumps straight to it
- The button switches off and back on at the last step used
- One gesture, one change: crossing four steps sends the fourth, not all four
- A rejected change is not pretended away — the control returns to the value the device reports, and says why
- Opens on the value the device already holds, reading the attribute itself when that is what it writes
- Reads the value back from telemetry, so a change made anywhere else shows up here
- A wide range is grouped: 0 to 50 becomes ten dots of five, and one click moves by five
- Vertical or horizontal, any icon from the platform’s picker, and colours to match the dashboard
What a change does
Send a one-way RPC command reaches the device directly. The value travels as a number, either wrapped or on its own:
| What the device receives | Setting |
|---|---|
{ "value": 30 } | An object, parameter name value — the default |
{ "speed": 30 } | An object, parameter name speed |
30 | The number alone |
| anything at all | A function of yours |
Payload function(value) receives value, the number the control is sending, and ctx, the widget
context. Whatever
it returns becomes the command parameters, so a device with a shape of its own is one line away:
return { fan: { speed: value }, source: 'dashboard' };It can scale the value, wrap it, nest it, or turn it into a list. If it throws or returns nothing, nothing is sent: the change is treated as failed, the reason appears on the card, and the control goes back to the value the device reports. A malformed command is worse than no command.
The method name must match the handler on the device. Queue the command for an offline device uses the platform’s persistent RPC, so a device that is asleep gets the change when it wakes.
Write an attribute puts the value in a shared attribute, which the device reads the next time it looks and which survives a reboot on both sides. Choose server scope when the value is meant for a rule chain rather than for the device.
Either way the widget learns only that the platform accepted the change: a one-way command carries no reply and an attribute write is not a conversation with the device. What actually happened comes from the feedback key, which is why it is worth setting.
The range, and grouping
Lowest value, Highest value and Step between values define what the control can send. The lowest value is what it sits on when it is off.
Fifty values would be fifty dots, which is not a control anyone can hit. Most dots to draw caps them, and the step is widened to fit — to a number a person would have chosen, not to whatever divides evenly:
| Range | Step | Cap | What you get |
|---|---|---|---|
| 0 – 4 | 1 | 10 | four dots, one per speed |
| 0 – 50 | 1 | 10 | ten dots of five |
| 0 – 50 | 1 | 5 | five dots of ten |
| 0 – 100 | 5 | 10 | ten dots of ten |
Once a dot stands for more than one value, turn on Show the value — the number appears under the control, with units if you set them. A value read back from the device that falls between two dots snaps to the nearest.
The widened step is always a round number, which means the cap is a ceiling rather than a target: fifty values with a cap of twenty-four become ten dots of five, because dots of two would need twenty-five of them. Raising the cap past what the range needs changes nothing.
One gesture, one change
A wheel gesture crosses several steps on the way to the one you want. One notch of a mouse wheel is one
step, whatever the browser reports for it, and a trackpad’s smaller movements accumulate to the same. The
dots follow your hand immediately and the change goes out once you stop — Wait before sending is that
pause, 350 ms by default. Set it to 0 if the device is happy to receive every step.
When a change fails
The control shows the value you chose while the change is in flight, then either keeps it or gives it up. If the platform rejects it — no permission, target device not set, device unreachable for a queued command — the value returns to what the device last reported, or to the lowest value if it has never reported anything, and the reason is printed under the control. It is a control, not an indicator: showing a value the device is not holding would be worse than showing nothing.
Settings
| Group | Description |
|---|---|
| Command | Whether a change sends a command or writes an attribute, and the details of whichever you pick — method and payload shape, or attribute key and scope — plus the request timeout, persistent queueing with retries, and the pause before sending. |
| Range | Lowest and highest value, the step, the cap on dots, whether off is allowed, the value line and its units. |
| Appearance | Layout, size, icon, caption, and the colours of the button, dots, icon, caption and a failed change. |
Title, background and padding come from the widget’s own Appearance settings. The caption under the control is a setting of its own, and falls back to the data key’s label when you clear it.
Colours
One accent and neutrals, which is what keeps a wall of these calm: an indigo button and indigo dots for the steps reached, light grey rings for the ones not reached, a near-black value and a grey caption. Every pair that carries meaning clears 4.5:1 against its surface.
The icon has no colour of its own by default — it takes white or near-black to suit whatever the button is,
so a pale button still reads. Set Icon colour to override that. The icon itself comes from the
platform’s picker and starts as mdi:fan; clearing the field brings that back rather than leaving the
button bare.
For a dark dashboard, three values do it: steps not reached #3A4250, the button at its lowest value
#39414F, and the caption #8A93A5. The accent, the icon and the value look after themselves.
How the column is drawn
Each dot is a little smaller than the one below it, down to a third of the largest at the far end, which is what makes the column read as something coming off the button rather than as a list of dots. The gap between them stays the same the whole way up, so the rhythm reads as even rather than as loosening. The taper is derived from the number of dots, so the smallest is never an odd size of its own.
Layout turns the column on its side: vertical puts the steps above the button, horizontal to the right of it. Either way the largest dot is the one next to the button, and they taper away from it.
Size is a percentage of the space the widget has, not an abstract multiplier: 100 fills it edge to edge, 70 — the default — leaves a comfortable margin. Because it is measured against the widget rather than against a fixed reference, a narrow card gets a control sized for it instead of a shrunken one.
Tips
- Two steps with Allow switching off on gives an off / low / high control in three dots.
- Put the feedback key in even when you do not need it on screen: a control that disagrees with the machine is the one thing worse than no control.
- A device that is often offline is a better fit for an attribute than for a command — the attribute waits for it, and nothing has to be queued.
- Horizontal layout suits a row of controls under a chart, where a vertical column would stretch the row.
- The icon comes from the platform’s picker, so anything it offers works — including the
mdi:set.
Share Your Widget with the Community
Built a custom widget? Export it as a JSON from ThingsBoard and publish it to the IoT Hub through a simple 4-step wizard (Upload, Listing, Readme, Review & Submit). Share it with thousands of ThingsBoard developers worldwide and get featured in the catalog.