b9c53c1a23
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
106 lines
2.7 KiB
YAML
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]
|