@airnexus/node-red-contrib-matter-airnexus 0.2.4-airnexus.1
AirNexus Matter bridge + dynamic devices + pairing management for Node-RED
AirNexus Node-RED Matter Dynamic
Dynamic Matter bridge + dynamic devices for Node-RED. Create any Matter device by specifying the device type in JSON configuration — no need for device-specific nodes.
This AirNexus fork adds:
Matter Pairing node (get QR/manual codes, reopen pairing, factory reset commissioning)
Matter Device “hidden until enabled” mode (devices don’t appear in Alexa/HomeKit until you enable them by payload)
Dynamic rename by payload
Thermostat-friendly event handling (captures attribute writes even when controllers don’t send explicit commands)
Installation npm install @airnexus/node-red-contrib-matter-airnexus
Requirements
Node.js >= 18.0.0
Node-RED >= 3.0.0
Nodes Included
- Matter Dynamic Bridge (matter-dynamic-bridge)
Creates a Matter bridge and hosts all devices.
- Matter Device (matter-device)
Creates a dynamic Matter endpoint from JSON config.
AirNexus behavior (Option 2 – hidden until enabled):
Device is created locally, but NOT registered into the bridge/aggregator until enabled
Once enabled, the device becomes visible in Alexa/HomeKit/Google
Disable sets reachable=false and suppresses outputs (device may remain listed in the controller until you remove it there)
- Matter Pairing (matter-pairing)
Provides commissioning info (QR/manual) and supports “reset pairing” flows.
Quick Start
- Create a Bridge
Add Matter Dynamic Bridge
Configure name/port/interface (default port 5540)
Deploy
- Get Pairing Codes (recommended: use Matter Pairing node)
Add Matter Pairing
Select your bridge
Deploy
Inject get to output pairing info (QR code string + manual code)
- Add Devices
Add Matter Device
Select the same bridge
Set your JSON device config (examples below)
Deploy
- Enable a Device (AirNexus Option 2)
Devices will not show up in Alexa until you enable them:
Inject to the device:
topic: enable
payload can include a name
Example:
{ "topic": "enable", "payload": { "name": "Lounge Thermostat" } }
Matter Pairing Node Inputs (commands)
Send an Inject into the Matter Pairing node:
Command How to send What it does get msg.topic="get" Outputs current pairing info (if commissioned → state=commissioned) pair msg.topic="pair" Ensures bridge is online and ready to commission (best effort) reset msg.topic="reset" Factory reset commissioning (wipes bridge commissioning storage, regenerates codes) unpair / delete msg.topic="unpair" Same as reset disable msg.topic="disable" Best-effort stop advertising (takes server offline)
Optional payload:
{ "timeoutMins": 15, "includeSvg": true, "forceReset": true }
Output payload (example) { "bridgeId": "5318704ab571aeeb", "pairingEnabled": true, "pairingUntil": "2026-01-25T02:30:00.000Z", "state": "ready", "commissioned": false, "qrPairingCode": "MT:....", "manualPairingCode": "123-45-678", "qrSvg": "" }
Matter Device Node (AirNexus Option 2: hidden until enabled) Enable / Disable / Rename (by payload)
Enable
msg.topic = "enable"; msg.payload = { name: "Zone 1 Thermostat" }; // optional return msg;
Disable
msg.topic = "disable"; return msg;
Rename
msg.topic = "name"; msg.payload = "New Name Here"; return msg;
Config combined
msg.topic = "config"; msg.payload = { enabled: true, name: "Zone 2 Thermostat" }; return msg;
State query msg.topic = "state"; return msg;
Inputs / Outputs (Matter Device)
The Matter Device node has 3 outputs:
Output 1 – Events / State
$Changed attribute events (when Matter.js emits them)
Thermostat writes often appear as interactionEnd snapshot diffs (even when no explicit commands are used)
Output 2 – Commands
Real Matter cluster commands (e.g. OnOff.on, LevelControl.moveToLevel)
Some controllers do attribute writes instead of commands (especially thermostats)
Output 3 – Debug / Diagnostics
subscription logs, init status, bridgeReset, write retries, sanitization info, etc.
Example Output 2 (command) { "command": "on", "cluster": "OnOff", "data": {} }
Example Output 1 (thermostat diff from Alexa) { "thermostat": { "systemMode": 3, "occupiedCoolingSetpoint": 2000, "occupiedHeatingSetpoint": 2000 } }
Command vs Attribute Writes (Thermostats)
Many Matter thermostats are controlled via attribute writes rather than explicit commands.
Typical behavior:
Changing setpoint in Alexa/HomeKit → Output 1 (state diff)
Using something like setpointRaiseLower (if controller uses it) → Output 2 (command)
Always monitor Output 1 for thermostat changes.
Configuration Examples Simple On/Off Light { "deviceType": "OnOffLightDevice" }
Thermostat (Heating + Cooling + Auto) { "deviceType": "ThermostatDevice", "behaviorFeatures": { "Thermostat": ["Heating", "Cooling", "AutoMode"] }, "initialState": { "thermostat": { "controlSequenceOfOperation": 4, "systemMode": 1, "localTemperature": 2500, "minSetpointDeadBand": 100, "occupiedHeatingSetpoint": 2000, "occupiedCoolingSetpoint": 2600, "minHeatSetpointLimit": 500, "maxHeatSetpointLimit": 3500, "minCoolSetpointLimit": 500, "maxCoolSetpointLimit": 3500 } } }
Troubleshooting Device doesn’t appear in Alexa/HomeKit
If you’re using AirNexus Option 2:
You must enable the Matter Device node:
msg.topic="enable"
optionally set name
Pairing issues / want to re-pair
Use Matter Pairing node:
reset to wipe commissioning + generate new QR/manual
Commands not appearing in Output 2
Expected for devices controlled by attribute writes (thermostats). Use Output 1 diffs.
License
MIT
Acknowledgments
Inspired by and based on patterns from node-red-matter-bridge and Matter.js.
Support
- Node-RED Forum: Get help from the community
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT
Acknowledgments
This project was heavily inspired by and based on the excellent work done in node-red-matter-bridge by Sam Machin. The architecture and implementation patterns from that project served as a fundamental guide for developing this dynamic Matter bridge implementation.
Built on top of the excellent Matter.js library.