Local Home Automation
A RUAL node is the gateway itself, not a client of somebody else's cloud. Zigbee, Thread/Matter, Z-Wave, Philips Hue, Daikin and UniFi devices become one vocabulary that blueprints automate, and it keeps working when the internet does not.
This section is the working reference. New here? Start at Setting Up a RUAL Nano, or read the shorter Local Home Automation tutorial first.
The node is the gateway
The ordinary way to reach a smart device from software is the vendor's cloud API: your flow talks to a server in another country, that server talks to a bridge in your hallway, and the bridge talks to a lamp two metres away. That costs hundreds of milliseconds, an account and a rate limit, and it fails whenever any hop does.
Here the devices talk to the node. Radios are attached to the machine, the protocol daemons run beside the node, and a motion event reaches your flow over a loopback socket.
| Vendor cloud integration | Local, on the node | |
|---|---|---|
| A motion event reaching a flow | Sensor to bridge to vendor cloud to your cluster | Sensor to radio to node, in process |
| Internet down | Nothing works | Everything works |
| Vendor retires the API | Your automation stops | Unaffected: the radio protocol has not changed |
| Who can see your floor plan | The vendor, by construction | Nobody outside the LAN |
Aqara is the clearest case. Aqara devices are Zigbee devices. Reached through Aqara's cloud API, turning on a lamp is a request to Germany and back; paired to a coordinator on your own machine, they are just devices on your mesh. That is why the older aqaraconnection_* blocks are deprecated in favour of these.
The node does not drive the radios itself
A native Zigbee stack means owning EZSP and Z-Stack framing, the ZCL cluster library, mesh routing, OTA updates and a device quirks database. So the node sits behind the reference daemon for each protocol and translates.
| Protocol | Runs beside the node | The node reaches it over |
|---|---|---|
| Zigbee | Zigbee2MQTT, against a USB coordinator | MQTT |
| Z-Wave | Z-Wave JS UI, against a Z-Wave stick | MQTT, gateway type ValueID topics |
| Thread and Matter | Matter Server, plus a Thread Border Router for Thread devices | WebSocket |
| Philips Hue | the bridge you already own | HTTPS and its event stream, on the LAN |
| Daikin | the BRP WiFi adapter in the unit | HTTP, on the LAN, polled |
| Daikin Onecta cloud | nothing: for units with no local API, such as the BRP069C4x family | Daikin's cloud API, polled. The one adapter that needs the internet. |
| UniFi Access and Protect | the UniFi console you already own | Ubiquiti's integration APIs and their event streams, on the LAN |
There is no device list inside RUAL to update. Zigbee2MQTT publishes a complete machine-readable description of every device on your mesh: every attribute it reports, with type, unit and range, for roughly 4,000 devices. The node reads that directly, so pairing a sensor released after your RUAL version still gives you a fully described device.
Hue is a separate adapter from Zigbee, even though a Hue bridge is a Zigbee coordinator. Re-pairing bulbs to your own stick breaks the Hue app, the dimmer switches and the scenes the household already uses; talking to the bridge leaves all of that working. A bulb paired directly to your own coordinator arrives through the Zigbee adapter instead, and neither path knows about the other.
One vocabulary, whatever the radio
Four vendors describe the same physical event four different ways. A motion sensor is occupancy: true on Zigbee2MQTT, a Notification command class carrying "Home Security, Motion sensor status" on Z-Wave JS, motion.motion: true on a Hue bridge, and bit 0 of an OccupancySensing bitmap on Matter.
So every adapter funnels into one closed set of capabilities, and a flow is written against those. A sensor activated trigger behaves identically whether the sensor is an Aqara on Zigbee, a Fibaro on Z-Wave or an Eve on Thread, because by the time the trigger sees it, all of them are occupancy = true.
A capability earns its place by being something an automation would branch on. Anything not listed here still survives on the device's raw map, so it is readable without being promoted into the vocabulary.
Binary capabilities: true is always the active state
A blueprint never has to ask whether true means open or closed.
| Capability | True means | Counts as a sensor |
|---|---|---|
occupancy | Someone is there | Yes |
contact | The door or window is open | Yes |
water_leak | Water is present | Yes |
smoke | Smoke detected | Yes |
gas | Gas or carbon monoxide detected | Yes |
vibration | Moved, tilted or dropped | Yes |
tamper | The anti-tamper switch opened | No, device health |
power | The bulb, plug or relay is on | No, it has its own triggers |
battery_low | The device raised its own low-battery flag | No, device health |
The "counts as a sensor" column is what sensor activated and get active sensors mean by a sensor: the binary capabilities that describe the world, minus the ones that describe the device.
poweris excluded because a bulb turning on is not a sensor activating. Folding it in would make every whole-house sensor flow fire on its own lighting changes and livelock.tamperandbattery_loware excluded because an author asking about presence does not want a flat battery in the same stream.
Numeric capabilities
| Capability | Unit | Notes |
|---|---|---|
temperature | °C | Ambient reading |
target_temperature | °C | The setpoint somebody chose |
humidity | % | Relative |
pressure | hPa | Atmospheric |
illuminance | lux | Hue and Matter both report a log scale on the wire; converted here |
brightness | 0 to 100 % | Vendors use 0 to 254 or 0 to 99; adapters scale |
color_temp | kelvin | Not mireds. 2200 candle, 2700 warm white, 4000 neutral, 6500 daylight |
position | 0 to 100 % | Blinds and valves, percent open |
power_watts | W | Instantaneous draw |
energy_kwh | kWh | Cumulative lifetime meter |
co2 | ppm | |
voc | ppb | |
pm25 | µg/m³ | |
aqi | none | The console's own composite air-quality index. Vendor-defined: comparable over time on one device, not between vendors |
battery | % | Remaining charge |
link_quality | 0 to 255 | The radio's own signal metric |
Text and enum capabilities
| Capability | Values |
|---|---|
color_hex | #rrggbb |
hvac_mode | off, auto, cool, heat, dry, fan |
fan_mode | auto, silent, low, medium, high, turbo |
lock_state | locked, unlocked, jammed |
action | A momentary button pulse: single, double, hold, release, and whatever else the device emits |
Access control and cameras
These come with the UniFi adapter. A door controller is a lock, a position sensor, a card reader and a doorbell at once, and "the front door" is one thing people automate rather than four.
| Capability | Carries | Behaves like |
|---|---|---|
door_position | true means the door or gate is open. The physical position, not the lock: a door can be unlocked and shut. | An alarm: stored on transitions, charted as a timeline |
alarm | true means the security controller's own alarm is active. Distinct from the smoke, gas and leak sensors, which are individual detectors. | An alarm |
doorbell | Somebody rang. The value is the moment it happened. | An event: every occurrence is recorded |
access_entry | An entry decision, as an object: actor, method, granted, door. Method is nfc, pin, wave, mobile, touchpass or manual. | An event |
nfc | A card or fob was presented, whether or not it was accepted. The value is the token or actor. | An event |
motion_event | A camera detected motion. The value is the moment it happened. | An event |
nfcis separate fromaccess_entrybecause "a card was swiped" and "entry was granted" are different automations: a swipe may be refused.motion_eventis separate fromoccupancybecause a camera reports motion as discrete detections, while a PIR or radar sensor reports a state that stays true while somebody is there. Usecamera motion detectedfor the first andpresence detectedfor the second.
Two vendor quirks are corrected for you
contact = true means open, everywhere above the adapter. Device types are derived from capabilities
Every device is classified into one of ten types from the capabilities it exposes, not from what the vendor calls it. Vendor device classes are frequently wrong: Zigbee plugs that meter power routinely announce themselves as lights.
| Type | Recognised by |
|---|---|
climate | hvac_mode or target_temperature |
door | doorbell, access_entry, nfc or door_position |
camera | motion_event |
lock | lock_state |
cover | position |
light | brightness, color_temp or color_hex |
sensor | Any sensor capability, or any environment reading |
button | action |
switch | power, with none of the above |
unknown | Nothing recognisable yet |
The order in that table is the order the checks run, because capabilities overlap:
- A Hue bulb has
powerandbrightness, a metering plug haspowerandpower_watts. Testing brightness before plain power keeps the plug out of the lights list. - Testing climate first keeps a thermostat with a display backlight from being classified as a lamp.
- A UniFi door has a lock state, a door-position sensor and usually a reader and a bell, so any access-control capability wins and the whole thing classifies as one
door.
Type decides what fires: light turned on fires only for devices classified as lights, switch turned on only for switches, and the studio's device picker offers only the right type per block.
Nothing is in service until you adopt it
Devices appear on their own: a coordinator hears everything ever paired to its network, and the node records each one as it reports. But a discovered device fires no triggers and refuses every command until you adopt it.
Without that gate, "when any sensor activates" means "when anything within thirty metres twitches", including the sensor somebody paired to test three years ago and whatever a second-hand Z-Wave stick inherited from its previous owner. The full onboarding loop is on Discovering and Adopting Devices.
What you need to own
- A machine. A RUAL Core Nano: one box in the building, wired, on an SSD. 16 GB of RAM is the comfortable number once the radio daemons are running beside the node. See RUAL Core Nano for the specifications and the reference builds.
- A radio per protocol. Zigbee, Thread and Z-Wave are three radios on different frequency bands. Nothing bridges them and no single dongle does all three at once. The tutorial covers which to buy.
- The daemons. Redis and an MQTT broker for the node itself, plus Zigbee2MQTT, Z-Wave JS UI or Matter Server depending on what you own. Setting Up a RUAL Nano is the runbook.
- The devices. Hue, Aqara, IKEA, Eve, Fibaro, Aeotec, Shelly Wave, a Daikin air conditioner and a UniFi console running Access or Protect are all covered. Anything Zigbee2MQTT supports works, which is most of what is sold.
The blocks arrive with Core v15.0.0, and the feature is opt-in.
[homeassist] enabled = true starts no radio goroutine, creates no device store, and every home-automation block reports HOMEASSIST_NOT_AVAILABLE, so a cloud node pays nothing for these blocks existing. What to know before you commit
- Restored state is a belief, not an observation. Last-known device state survives a restart, but
availablestays false andlast_seenis untouched until the device actually reports. - Triggers are not durable. Device triggers dispatch in process rather than through the queue, which is what makes a light come on before you have finished walking through the door. A restart drops anything in flight.
- Smoke, gas and leak triggers are a supplement, not a certified alarm. They depend on a mesh, a broker and a node all being up.
- Daikin is polled. Its local API has no event channel, so
poll_interval(30s by default) is the resolution of every climate trigger. - Matter endpoints collapse. A Matter device with two endpoints, such as a two-gang switch, currently appears as one device whose power state is whichever endpoint reported last.
- UniFi emergency controls are not exposed. Siren, lockdown and evacuation have no capability and no command. A flow can react to the console's
alarmstate; it cannot raise one. - Daikin Onecta temperatures are best-effort. Power on and off is reliable; the temperature and mode decoding follows community reverse engineering, the hex encoding varies by model, and it is unverified against a live unit. The full raw
/dsiottree is on the device'srawmap. - The Daikin Onecta cloud allows 200 requests a day, writes included. One poll covers every unit, and the 15 minute default spends 96.
- History is sampled by design. It answers trends and totals well and forensic questions poorly. See Device History and Energy.
A restart does not re-fire everything
Without care, a window that was open all night would announce itself as "just opened" at 03:00, run the alarm flow and switch the lights on. Two mechanisms prevent that.
An unknown previous value seeds silently rather than firing. When the node has never seen a capability before, an incoming reading is recorded without counting as a transition. The exceptions are:
smoke,gasandwater_leak, where a missed event is worse than a repeated one. A node that comes back up to an alarm already sounding says so.- Buttons, because a press is an event with no persistent state to seed.
Last-known state is persisted and restored before the adapters connect, so the first real report has something to compare against and an unchanged re-announce stays unchanged.
- It lives in Redis, because it is hot, small, rewritten constantly and worthless once stale.
- Writes coalesce per device on a two-second flush (one Zigbee message carrying four capabilities is one write), and a clean shutdown flushes.
- Entries expire after 30 days, so a node restored from a backup does not seed year-old beliefs.
- Momentary capabilities are excluded: replaying the last button press as current state would make it look freshly pressed.
Next steps
Setting Up a RUAL Nano The runbook: broker, Zigbee2MQTT against a ZBT-2, config.toml and first boot. Discovering and Adopting Devices Pairing, adoption, rooms and naming. Example Flows Nine worked automations, block by block.Frequently asked
Can RUAL control smart home devices without a cloud?
Yes. A RUAL node is the gateway itself: the radios are attached to the machine, the protocol daemons run beside the node, and a motion event reaches a blueprint over a loopback socket. Zigbee, Thread and Matter, Z-Wave, a Philips Hue bridge and Daikin air conditioning are all reached on the local network, so the automations keep working when the internet does not.
Does a RUAL flow have to know whether a sensor is Zigbee or Z-Wave?
No. Every adapter translates into one closed set of capabilities, so a motion sensor is occupancy whether it is an Aqara on Zigbee, a Fibaro on Z-Wave or an Eve on Thread. A flow written against one works against the others without an edit.
Does a RUAL contact sensor report true when the door is open or closed?
True means OPEN. Zigbee and Matter both report the opposite on the wire, because their contact attribute is true when the magnet is present, and RUAL inverts it at the adapter so that true always means the active, noteworthy state.