Understanding the Node-RED Flow
Relevant source files
The following files were used as context for generating this wiki page:The Node-RED flow, defined in dns.json, serves as the central orchestration layer for the Overlord Network Kill Switch. Its primary purpose is to act as a bridge between the MQTT message broker and the backend FastAPI web server. It listens for command and status messages published via MQTT (typically originating from HomeKit via homebridge-mqttthing), parses these messages to determine the user's intent, and translates them into corresponding HTTP API calls to the backend server which then controls Pi-hole and Ubiquiti services.
This design keeps the Node-RED flow focused on message transport and routing, while the complex business logic for managing network devices and services is handled by the Python-based FastAPI application. The flow is divided into three main logical sections: Pi-hole domain blocking ("Media Control"), global Pi-hole DNS control ("Master Control"), and Ubiquiti firewall/device control ("Router Control").
Sources: README.md, node_red_flows/dns.json
Architecture and Core Components
The flow utilizes a standard set of Node-RED nodes to process messages. The general pattern is to receive an MQTT message, parse it, construct an API request, send the request, and then publish the result back to an MQTT status topic.
Sources: node_red_flows/dns.json
Key Node-RED Nodes
| Node Type | Purpose |
|---|---|
mqtt in | Subscribes to specific MQTT topics to receive commands or status requests. |
rbe | "Report by exception" node. It blocks messages unless the payload value has changed, preventing redundant processing. |
change | Used for common parsing tasks, such as extracting parts of the MQTT topic into message properties like msg.target and msg.verb. |
function | Contains JavaScript code to build the final HTTP request URL, method, and payload based on the incoming MQTT message. |
http request | Executes the HTTP call to the backend FastAPI server. |
mqtt out | Publishes the status returned from the web server back to a corresponding stat/... topic. |
Sources: node_red_flows/dns.json
Configuration
The flow requires a flow-level context variable endpoint to be set to the address of the backend web server. In the provided file, this is hardcoded and must be manually updated.
// node_red_flows/dns.json:302-311
{
"t": "set",
"p": "endpoint",
"pt": "flow",
"to": "http://XXXX:19000",
"tot": "str"
}
The MQTT broker is also configured within the flow, with the example pointing to 192.168.100.104:1883.
Sources: node_red_flows/dns.json:302-311, 461-488
Pi-hole Media Control Flow
This flow manages the enabling and disabling of specific Pi-hole domain block groups, such as "hbomax" or "school_work". It listens for commands on cmnd/dns_controller/media/+/change and translates them into API calls to the /pihole endpoint.
Sources: node_red_flows/dns.json:14-25, 102-132, lib/pihole/pihole_router.py:40-56
The following diagram illustrates the message flow for a media control change request.
Logic Details
- An
mqtt innode subscribes tocmnd/dns_controller/media/+/change. The+is a wildcard for the target domain block (e.g.,hbomax). - A
changenode parses the topic to setmsg.target(e.g.,hbomax) andmsg.verb(change). - The
functionnode constructs the API call.- It sets
msg.methodtoPOST. - It translates the payload (
true/false) into a verb (enable/disable). - It builds the URL:
http://<endpoint>/pihole/{verb}/{target}.
- It sets
- The
http requestnode calls the web server. - The response payload's
statusfield is extracted and published back tostat/dns_controller/media/{target}/status.
Sources: node_red_flows/dns.json:102-132, 161-177
Master DNS Control Flow
This flow handles globally enabling or disabling Pi-hole DNS blocking across all configured instances. It supports both permanent and temporary (timed) disabling.
Sources: node_red_flows/dns.json:179-190, 222-263, lib/pihole/alldns.py
The diagram below shows the process for a master control change.
Logic Details
- The flow is triggered by messages on
cmnd/dns_controller/master/+. The topic suffix determines the action (e.g.,perm_change,short_change). - The
functionnode determines the HTTP method and URL.- If the payload is
true(disable blocking),msg.methodisPOST. - If the payload is
false(enable blocking),msg.methodisDELETE. - The URL is
http://<endpoint>/alldns/. - If the topic includes
short_change, a?timer=300query parameter is added to the URL for temporary disabling.
- If the payload is
- The
http requestnode calls the/alldns/endpoint on the web server. - The response status is published to
stat/dns_controller/master/status.
Sources: node_red_flows/dns.json:222-263, lib/pihole/pihole_router.py:72-84
Ubiquiti Router Control Flow
This flow manages Ubiquiti firewall rules and device blocking. It listens on topics like cmnd/router_controller/change_rule/+ and translates them into calls to the /ubiquiti API endpoints.
Sources: node_red_flows/dns.json:313-324, 372-432, lib/ubiquity/ubiquity.py:449-488
The diagram below outlines the router control logic.
Logic Details
- An
mqtt innode subscribes to topics likecmnd/router_controller/change_rule/+andstat/router_controller/status_rule/+. - A
changenode parses the topic intomsg.verb(e.g.,change_rule) andmsg.target. - The main
functionnode constructs the API call based onmsg.verb.change_rulewith payloadtruemaps to/ubiquiti/enable_rule/{target}.change_rulewith payloadfalsemaps to/ubiquiti/disable_rule/{target}.change_devicewith payloadonlinemaps to/ubiquiti/enable_device/{target}.change_devicewith payloadofflinemaps to/ubiquiti/disable_device/{target}.- Status requests (
status_rule,status_device) are also handled.
- The
http requestnode calls the appropriate/ubiquitiendpoint. - The response is delayed by 1 second before being processed and published back to a status topic like
stat/router_controller/status_rule/{target}.
Sources: node_red_flows/dns.json:372-432, lib/ubiquity/ubiquity.py:449-488.
MQTT Topic Summary
The Node-RED flow relies on a structured set of MQTT topics to function. The cmnd topics are for sending commands, and the stat topics are for reporting the current state.
| Topic Pattern | Direction | Description | Triggered API Endpoint(s) |
|---|---|---|---|
cmnd/dns_controller/media/+/change | Inbound | Enable/disable a specific Pi-hole domain block group. | POST /pihole/enable/{group}, POST /pihole/disable/{group} |
stat/dns_controller/media/+/status | Outbound | Reports the status (true/false) of a domain block group. | GET /pihole/status/{group} |
cmnd/dns_controller/master/+ | Inbound | Globally enable/disable Pi-hole DNS blocking (e.g., perm_change). | POST /alldns/, DELETE /alldns/ |
stat/dns_controller/master/status | Outbound | Reports the global DNS blocking status. | GET /alldns/ |
cmnd/router_controller/change_rule/+ | Inbound | Enable/disable a Ubiquiti firewall rule. | GET /ubiquiti/enable_rule/{rule}, GET /ubiquiti/disable_rule/{rule} |
cmnd/router_controller/change_device/+ | Inbound | Block/unblock a Ubiquiti client device group. | GET /ubiquiti/enable_device/{device}, GET /ubiquiti/disable_device/{device} |
stat/router_controller/status_rule/+ | Outbound | Reports the status of a Ubiquiti firewall rule. | GET /ubiquiti/status_rule/{rule} |
Sources: node_red_flows/dns.json, README.md:60-88, AGENTS.md:41-61
In summary, the Node-RED flow is a critical but lightweight component that translates user actions from an MQTT-based interface into standardized API requests. It effectively decouples the home automation frontend (HomeKit) from the backend service logic, allowing for flexible and maintainable control over network services.
Sources: README.md:29-31, node_red_flows/dns.json