Add multi-plug toggle, debounce via unique topic subscriptions
Button (Door Button) now toggles Squiggle, Sideboard Lamp, and Bamboo Lights
via three parallel mqtt-out publishes.
Key fix: avoid subscribing to a wildcard '#' topic alongside a specific topic
in the same Node-RED instance. The mqtt-broker re-adds its handler as an
EventEmitter listener on each subscribe call (file:
/usr/src/node-red/node_modules/@node-red/nodes/core/network/10-mqtt.js
_clientOn('message', subscription.handler) is unconditional), so after
each deploy/restart the same message arrives N times to internal listeners.
Each mqtt-in node now uses a unique topic (zigbee2mqtt/<device>).
Removed zigbee-in # wildcard and plug-state ui-text widgets (state now
displayed via per-plug ui-text widgets).
Added function node support to flow2json.py for msg filtering logic.
Added ui-text format/width/height defaults support.
Added dashboard 2.0 config node defaults matching reference flow:
ui-base, ui-theme, ui-page, ui-group with full property set.
This commit is contained in:
+34
-26
@@ -4,8 +4,8 @@ import future.keywords.contains
|
||||
import future.keywords.in
|
||||
|
||||
# helpers
|
||||
config_node(typ) if typ in {"mqtt-broker", "ui_tab", "ui_base"}
|
||||
welcome_isolated(typ) if typ in {"debug", "mqtt-broker", "ui_tab", "ui_group", "ui_text", "ui_chart", "ui_gauge", "ui_button", "ui_slider", "ui_switch", "inject", "comment", "mqtt in", "catch", "status", "link in"}
|
||||
config_node(typ) if typ in {"mqtt-broker", "ui-base", "ui-page", "ui-group"}
|
||||
welcome_isolated(typ) if typ in {"debug", "mqtt-broker", "ui-base", "ui-page", "ui-group", "ui-text", "ui-chart", "ui-gauge", "ui-button", "ui-switch", "ui-slider", "inject", "comment", "mqtt in", "catch", "status", "link in"}
|
||||
|
||||
broker_node(id) if {
|
||||
some node in input
|
||||
@@ -13,18 +13,6 @@ broker_node(id) if {
|
||||
node.id == id
|
||||
}
|
||||
|
||||
ui_group(id) if {
|
||||
some node in input
|
||||
node.type == "ui_group"
|
||||
node.id == id
|
||||
}
|
||||
|
||||
ui_tab(id) if {
|
||||
some node in input
|
||||
node.type == "ui_tab"
|
||||
node.id == id
|
||||
}
|
||||
|
||||
node_exists(id) if {
|
||||
some node in input
|
||||
node.id == id
|
||||
@@ -89,7 +77,7 @@ deny_missing_field contains msg if {
|
||||
|
||||
deny_missing_field contains msg if {
|
||||
some node in input
|
||||
node.type in {"ui_text", "ui_button", "ui_chart", "ui_gauge", "ui_slider", "ui_switch"}
|
||||
node.type in {"ui-text", "ui-button", "ui-chart", "ui-gauge", "ui-switch", "ui-slider", "ui-dropdown"}
|
||||
required := {"type", "group", "z"}
|
||||
some f in required
|
||||
not node[f]
|
||||
@@ -98,20 +86,29 @@ deny_missing_field contains msg if {
|
||||
|
||||
deny_missing_field contains msg if {
|
||||
some node in input
|
||||
node.type == "ui_group"
|
||||
required := {"type", "tab", "name"}
|
||||
node.type == "ui-group"
|
||||
required := {"type", "page", "name"}
|
||||
some f in required
|
||||
not node[f]
|
||||
msg := sprintf("node %s (ui_group): missing %s", [node.id, f])
|
||||
msg := sprintf("node %s (ui-group): missing %s", [node.id, f])
|
||||
}
|
||||
|
||||
deny_missing_field contains msg if {
|
||||
some node in input
|
||||
node.type == "ui_tab"
|
||||
node.type == "ui-page"
|
||||
required := {"type", "name", "ui"}
|
||||
some f in required
|
||||
not node[f]
|
||||
msg := sprintf("node %s (ui-page): missing %s", [node.id, f])
|
||||
}
|
||||
|
||||
deny_missing_field contains msg if {
|
||||
some node in input
|
||||
node.type == "ui-base"
|
||||
required := {"type", "name"}
|
||||
some f in required
|
||||
not node[f]
|
||||
msg := sprintf("node %s (ui_tab): missing %s", [node.id, f])
|
||||
msg := sprintf("node %s (ui-base): missing %s", [node.id, f])
|
||||
}
|
||||
|
||||
deny_broker_ref contains msg if {
|
||||
@@ -121,18 +118,30 @@ deny_broker_ref contains msg if {
|
||||
msg := sprintf("node %s (%s): references unknown broker %s", [node.id, node.type, node.broker])
|
||||
}
|
||||
|
||||
ui_page(id) if {
|
||||
some node in input
|
||||
node.type == "ui-page"
|
||||
node.id == id
|
||||
}
|
||||
|
||||
ui_group(id) if {
|
||||
some node in input
|
||||
node.type == "ui-group"
|
||||
node.id == id
|
||||
}
|
||||
|
||||
deny_group_ref contains msg if {
|
||||
some node in input
|
||||
node.type in {"ui_text", "ui_button", "ui_chart", "ui_gauge", "ui_slider", "ui_switch"}
|
||||
node.type in {"ui-text", "ui-button", "ui-chart", "ui-gauge", "ui-switch", "ui-slider", "ui-dropdown"}
|
||||
not ui_group(node.group)
|
||||
msg := sprintf("node %s (%s): references unknown group %s", [node.id, node.type, node.group])
|
||||
}
|
||||
|
||||
deny_tab_ref contains msg if {
|
||||
deny_page_ref contains msg if {
|
||||
some node in input
|
||||
node.type == "ui_group"
|
||||
not ui_tab(node.tab)
|
||||
msg := sprintf("node %s (ui_group): references unknown tab %s", [node.id, node.tab])
|
||||
node.type == "ui-group"
|
||||
not ui_page(node.page)
|
||||
msg := sprintf("node %s (ui-group): references unknown page %s", [node.id, node.page])
|
||||
}
|
||||
|
||||
deny_wire_ref contains msg if {
|
||||
@@ -158,7 +167,6 @@ deny_isolated_node contains msg if {
|
||||
msg := sprintf("node %s (%s): has no wires", [node.id, node.type])
|
||||
}
|
||||
|
||||
# MQTT brokers must have valid port
|
||||
deny_broker_port contains msg if {
|
||||
some node in input
|
||||
node.type == "mqtt-broker"
|
||||
|
||||
Reference in New Issue
Block a user