Early beta (0.1.0), not yet for critical processes. See the roadmap
PNeX logo

Controls

Switches, sliders and buttons on your surfaces, acted on by a flow

PNeX follows one rule for anything you press on a screen: a surface reads, a flow acts. A dashboard, a mobile card or an annotation on a panorama never drives a device pin. Pressing a switch writes a control value; a deployed flow that listens to that control decides what happens: write a pin on one or several devices, send a notification, store a value, or anything else a flow can do.

Behaviour therefore lives in one visible, versioned place — the flow — and the same switch can drive a relay today and a scene of ten devices tomorrow without touching the dashboard.

Controls are created when you save

You never pick a control before saving. Add a switch, a slider or a home card to a dashboard and save: each control widget, and each command of a home card, receives its own control in the same transaction. The inspector shows the reference it will get, for example #w-0001 or #w-0001.power for the On / off role of a Light card.

Delete the card and its control is released: removed if nothing uses it, kept as a standalone control if a flow still listens to it. To share one control between two surfaces (a dashboard and a panorama, say), use Link to an existing control… in the inspector.

Inspector after save: each command has its reference
Inspector after save: each command has its reference

Kinds

KindSendsNotes
Switch1 / 0Values editable
SliderA number, 0–100 by defaultSent on release; plugs straight into a PWM duty
ButtonOne fixed value
Number inputThe typed number
List of choicesThe numeric value of the chosen optionSegments up to 4 options, a list above
Stepper (− / +)The new valueMin, max and step
CommandsThe numeric value of the pressed buttonOpen / Stop / Close = 1 / 0 / −1 by default
Colour0xRRGGBB as an integer, or a white temperature in K2200–6500 K by default

Tick Ask for a confirmation before sending (sensitive actuator) for gates, locks and alarms. Presses closer than 250 ms on the same control are refused (Too fast). Viewers see controls disabled, and public shares are read-only.

What the flow receives

The Control source node (palette Triggers) has no input and one output per control you tick. Every message carries:

FieldContent
msg.payloadAlways a number, ready for Device (write)
msg.topicThe control key, e.g. dash-1a2b3c4d.w-0001.power
msg.control.optionThe option key of a choice or a command (heat, open…), or #rrggbb for a colour
msg.control.by / via / ts_msWho pressed, from which surface, when

Sources are listed grouped by surface (Dashboard · Living room, …), then Standalone controls; a search box filters them. Resend the last value at start replays the current value when the flow is deployed. A node with nothing ticked can be saved as a draft, but the deploy refuses it.

Control source node: sources grouped by dashboard
Control source node: sources grouped by dashboard

Create the flow from the dashboard

A control widget, and each command of a home card, has a Create the flow… section in the inspector: pick a Target device… and an Output pin… (digital or PWM outputs only), then Create and open the flow. PNeX creates a draft Control — <label> wired Control source → Device (write) and opens it in the flow editor. It is never deployed for you: review it, then deploy.

Create the flow… from a Light card
Create the flow… from a Light card

The Controls page

Data → Controls lists every control of the organization: who declared it (a dashboard, annotations, or standalone), its kind, its last value, and the flows listening to it. A control no deployed flow listens to carries a No effect badge. New control creates a standalone control, useful for a value shared by several surfaces. A control used by a deployed flow cannot be deleted.

Controls page: declared by, last value, listened by
Controls page: declared by, last value, listened by

The guarantee is enforced in the code: continuous-integration guards fail the build if a dashboard or annotation component ever references a device command, OTA or flash path.

On this page