Files
nr-flow-validator/flows/zigbee-monitor.yaml
T
david b9c53c1a23 generator: auto-expand declarative plug lists with per-channel mapper
Add build_plugs() to flow2json.py: a flow can declare a plugs: table
({id, name, channels?}) plus single_plugs/hold_plugs lists and the
generator emits all plumbing automatically — state-in node, /set out node,
dashboard widget, and (for multi-channel devices) a mapper function that
toggles each channel (state_1/state_2) instead of the ignored shared
{state:TOGGLE} payload.

Rewrite zigbee-monitor.yaml to the declarative form; Dual Outlet - Couch
is multi-channel (channels: [1,2]). Adding a plug is one line, no manual
node/wire duplication. Single press toggles 5 devices (couch via mapper
verified E2E ON/OFF), hold-release still DJ Booth only.

Refs: david/nr-flow-validator#2
2026-08-15 02:55:29 -07:00

106 lines
2.7 KiB
YAML

version: 1
brokers:
mosquitto:
host: mosquitto
port: 1883
dashboards:
- base: Dashboard
pages:
- page: Home
icon: home
path: /home
groups:
- name: Plugs
width: 6
flows:
- tab: Zigbee Monitor
description: Button dispatches single vs hold-release to different plug sets.
Plug plumbing (state-in, /set out, dashboard widget, per-channel mapper)
is generated by flow2json.py from the plugs lists below.
# Declarative plug set. channels:[] marks a multi-channel device, which gets
# a mapper that toggles each channel and a widget showing each state_N.
plugs:
- id: squiggle
name: Squiggle
- id: sideboard
name: Sideboard Lamp
- id: bamboo
name: Bamboo Lights
- id: djbooth
name: DJ Booth
- id: couch
name: Dual Outlet - Couch
channels: [1, 2]
# Device ids toggled on brief single press (driven by single_filter)
single_plugs: [squiggle, sideboard, bamboo, couch]
# Device ids toggled on press-hold-release (driven by hold_filter)
hold_plugs: [djbooth]
single_filter: single-filter
hold_filter: hold-filter
nodes:
- id: button-in
type: mqtt in
broker: mosquitto
topic: zigbee2mqtt/Door Button
qos: 0
- id: single-filter
type: function
name: Single click
code: |
const now = Date.now();
const last = context.get('lastTime') || 0;
if (now - last < 50) return null;
context.set('lastTime', now);
try {
const p = JSON.parse(msg.payload);
if (p.action === 'single') {
msg.payload = { state: 'TOGGLE' };
return msg;
}
} catch (e) {}
return null;
- id: hold-filter
type: function
name: Hold release
code: |
const now = Date.now();
const last = context.get('lastTime') || 0;
if (now - last < 50) return null;
context.set('lastTime', now);
try {
const p = JSON.parse(msg.payload);
if (p.action === 'release') {
msg.payload = { state: 'TOGGLE' };
return msg;
}
} catch (e) {}
return null;
- id: permit-btn
type: ui-button
group: Plugs
label: Permit Join (60s)
topic: zigbee2mqtt/bridge/request/permit_join
payload:
value: true
time: 60
order: 9
- id: mqtt-out
type: mqtt out
broker: mosquitto
wires:
button-in: [single-filter, hold-filter]
permit-btn: [mqtt-out]