@faxioman/node-red-contrib-matter-dynamic 0.2.4
Dynamic Matter device nodes for Node-RED
Node-RED Matter Dynamic
Dynamic Matter device nodes for Node-RED. Create any Matter device by specifying only the device type in JSON configuration - no need for device-specific nodes!
Installation
npm install @faxioman/node-red-contrib-matter-dynamic
Requirements
- Node.js >= 18.0.0
- Node-RED >= 3.0.0
Features
- Create Matter devices dynamically via JSON configuration
- No need to create separate nodes for each device type
- Automatic event subscription and state management
- Compatible with Apple HomeKit, Google Home, Amazon Alexa (via Matter)
- Support for all Matter.js device types
- Composite devices support (e.g., thermostat with battery)
- Auto-confirm commands for immediate state feedback (OnOff cluster only)
Quick Start
1. Setup Matter Bridge
- Drag a Matter Dynamic Bridge node from the palette
- Double-click to configure:
- Name: Give your bridge a name
- Port: Default 5540 (change if needed)
- Network Interface: Select your network interface or leave default
- Deploy the flow
- Open the bridge node to see the QR code for pairing
2. Add Dynamic Devices
- Drag a Matter Device node
- Configure:
- Name: Device name
- Bridge: Select your bridge
- Config: JSON configuration (see examples below)
- Connect input/output nodes as needed
- Deploy
3. Pair with HomeKit/Google/Alexa
- Open your Matter controller app
- Add new device
- Scan QR code from bridge or enter manual pairing code
Configuration Examples
Simple Light
{
"deviceType": "OnOffLightDevice"
}
Advanced Configuration
Behavior Features
Some devices require specific features to be enabled on their behaviors:
{
"deviceType": "DeviceType",
"behaviorFeatures": {
"BehaviorName": ["Feature1", "Feature2"]
}
}
Additional Behaviors
You can add extra behaviors (clusters) to any device type. This is useful for adding battery status, power monitoring, or other capabilities:
{
"deviceType": "YourDeviceType",
"additionalBehaviors": ["PowerSourceServer", "ElectricalEnergyMeasurementServer"],
"initialState": {
"powerSource": {
"status": 1,
"batPercentRemaining": 100
}
}
}
Common Additional Behaviors:
PowerSourceServer- Battery/power statusElectricalEnergyMeasurementServer- Energy monitoringBooleanStateServer- Binary state indication
Dimmable Light
{
"deviceType": "DimmableLightDevice"
}
Color Temperature Light
{
"deviceType": "ColorTemperatureLightDevice"
}
Temperature Sensor
{
"deviceType": "TemperatureSensorDevice"
}
Generic Switch (Multi-button)
{
"deviceType": "GenericSwitchDevice",
"initialState": {
"switch": {
"numberOfPositions": 2, // Number of buttons (2 = on/off)
"currentPosition": 0, // Initial position (0-based)
"multiPressMax": 2 // Max consecutive presses
}
}
}
For a 3-button switch:
{
"deviceType": "GenericSwitchDevice",
"initialState": {
"switch": {
"numberOfPositions": 3,
"currentPosition": 0
}
}
}
Thermostat
Thermostats require features to be specified:
{
"deviceType": "ThermostatDevice",
"behaviorFeatures": {
"Thermostat": ["Heating", "Cooling"] // Specify features needed
},
"initialState": {
"thermostat": {
"localTemperature": 2000,
"systemMode": 4,
"controlSequenceOfOperation": 4, // 2=HeatingOnly, 4=CoolingAndHeating
"minHeatSetpointLimit": 500,
"maxHeatSetpointLimit": 3500,
"minCoolSetpointLimit": 0,
"maxCoolSetpointLimit": 2100,
"occupiedHeatingSetpoint": 2000,
"occupiedCoolingSetpoint": 2600
}
}
}
Enhanced Devices with Additional Behaviors
Add extra functionality to any device using additional behaviors/clusters.
Thermostat with Battery Status
{
"deviceType": "ThermostatDevice",
"additionalBehaviors": ["PowerSourceServer"],
"behaviorFeatures": {
"Thermostat": ["Heating", "Cooling"],
"PowerSource": ["Battery", "Replaceable"]
},
"initialState": {
"thermostat": {
"localTemperature": 2000,
"systemMode": 4,
"controlSequenceOfOperation": 4,
"occupiedHeatingSetpoint": 2000,
"occupiedCoolingSetpoint": 2600
},
"powerSource": {
"status": 1,
"order": 1,
"description": "Battery",
"batChargeLevel": 0,
"batPercentRemaining": 200,
"batReplacementNeeded": false,
"batReplaceability": 1
}
}
}
Key Points:
controlSequenceOfOperationis mandatory for Thermostat (4 = Cooling and Heating)PowerSourcewith Battery feature requires specifying["Battery", "Replaceable"]in behaviorFeaturesbatPercentRemaining: 200 = 100% (value is percentage × 2)batChargeLevel: 0=Ok, 1=Warning, 2=CriticalbatReplacementNeeded: Mandatory with Battery feature (true/false)batReplaceability: Mandatory with Battery feature (0=Unspecified, 1=NotReplaceable, 2=UserReplaceable, 3=FactoryReplaceable)
Motion Sensor with Battery
{
"deviceType": "MotionSensorDevice",
"additionalBehaviors": ["PowerSourceServer"],
"initialState": {
"occupancySensing": {
"occupancy": { "occupied": false }
},
"powerSource": {
"status": 1,
"order": 1,
"batPercentRemaining": 100,
"batChargeLevel": 1,
"description": "Battery"
}
}
}
Contact Sensor with Battery
{
"deviceType": "ContactSensorDevice",
"additionalBehaviors": ["PowerSourceServer"],
"behaviorFeatures": {
"PowerSource": ["Battery", "Replaceable"]
},
"initialState": {
"booleanState": {
"stateValue": false
},
"powerSource": {
"status": 1,
"order": 1,
"description": "CR2032 Battery",
"batChargeLevel": 0,
"batPercentRemaining": 190,
"batReplaceability": 1,
"batReplacementNeeded": false
}
}
}
Updating Battery Status
To update the battery level or other PowerSource attributes, send a message with the powerSource object:
{
"payload": {
"powerSource": {
"batPercentRemaining": 150, // 75% (value × 2)
"batReplacementNeeded": false
}
}
}
You can update any combination of PowerSource attributes:
{
"payload": {
"powerSource": {
"status": 0, // 0=Active, 1=Standby, 2=Unavailable
"batPercentRemaining": 100, // 50% battery (value × 2)
"batReplacementNeeded": true, // Battery needs replacement
"batChargeLevel": 1 // 0=OK, 1=Warning, 2=Critical
}
}
}
You can also update device state and battery together:
{
"payload": {
"thermostat": {
"localTemperature": 2150 // 21.5°C
},
"powerSource": {
"batPercentRemaining": 120 // 60% battery
}
}
}
The device will emit events when these values change, allowing you to monitor battery status in real-time.
Fan Device
{
"deviceType": "FanDevice",
"initialState": {
"fanControl": {
"fanModeSequence": 2, // 0-5 based on supported modes
"percentCurrent": 0, // 0-100 (actual current speed)
"percentSetting": 0 // 0-100 (target speed)
}
}
}
Note: FanControl has two key attributes:
percentSetting: Target speed set by HomeKit/controllerpercentCurrent: Actual current speed of the fan
The system automatically syncs percentCurrent to match percentSetting when changed from HomeKit.
Basic Video Player
{
"deviceType": "BasicVideoPlayerDevice",
"initialState": {
"mediaPlayback": {
"currentState": 0 // 0=Playing, 1=Paused, 2=NotPlaying, 3=Buffering
}
}
}
Casting Video Player
{
"deviceType": "CastingVideoPlayerDevice",
"initialState": {
"mediaPlayback": {
"currentState": 0 // 0=Playing, 1=Paused, 2=NotPlaying, 3=Buffering
},
"contentLauncher": {
"supportedStreamingProtocols": 0, // Bitmask of supported protocols
"acceptHeader": [] // Array of accepted content types
}
}
}
Video Player Command Messages
Video players emit command messages when controlled via Matter:
Media Playback Commands
// Received when play is pressed
msg.payload = {
command: "play",
cluster: "mediaPlayback"
}
// Other commands: pause, stop, next, previous, startOver
// Commands with data: skipForward, skipBackward, seek, rewind, fastForward
msg.payload = {
command: "skipForward",
cluster: "mediaPlayback",
data: { deltaPositionMilliseconds: 30000 }
}
Keypad Input Commands
// Received when a key is pressed
msg.payload = {
command: "sendKey",
cluster: "keypadInput",
data: { keyCode: 0 } // 0=Select, 1=Up, 2=Down, etc.
}
Input/Output Format
The Matter Device node has 2 outputs:
- Output 1: Commands received from Matter controllers (HomeKit, Alexa, etc.)
- Output 2: State change events from the device
Input Messages
Messages must use Matter cluster format:
Light On/Off
// Turn on
msg.payload = {
onOff: {
onOff: true
}
}
// Turn off
msg.payload = {
onOff: {
onOff: false
}
}
Dimmer Level
msg.payload = {
levelControl: {
currentLevel: 128 // 0-255
}
}
Temperature Sensor
// Set to 21.5°C (value × 100)
msg.payload = {
temperatureMeasurement: {
measuredValue: 2150
}
}
Query State
msg.topic = "state"
// Returns current device state in payload
Output Messages
Output 1 - Events (state changes):
// Light state changed
msg.payload = {
onOff: {
onOff: true
}
}
// Dimmer level changed
msg.payload = {
levelControl: {
currentLevel: 200
}
}
// Thermostat temperature changed
msg.payload = {
thermostat: {
occupiedHeatingSetpoint: 2100
}
}
Output 2 - Commands (from Matter controllers):
// Command received from HomeKit/Alexa
msg.payload = {
command: "on", // or "off", "toggle"
cluster: "OnOff",
data: undefined // Some commands have data
}
// Command with data
msg.payload = {
command: "moveToLevel",
cluster: "LevelControl",
data: { level: 128, transitionTime: 10 }
}
// Video player commands
msg.payload = {
command: "play",
cluster: "MediaPlayback"
}
Command vs State Change Behavior
Some Matter devices may use attribute writes instead of commands:
In Matter, not all device operations use explicit commands. Some devices (like thermostats) primarily use direct attribute writes rather than commands.
When this happens:
- Commands (Output 2): Only appear for explicit device commands
- State Changes (Output 1): Appear when controllers write directly to device attributes
Example - Thermostat:
- Setting temperature via HomeKit → Appears as state change in Output 1
- Using
setpointRaiseLowercommand → Appears as command in Output 2
This behavior varies by device type and depends on how the Matter specification defines each device's interaction model. Always check both outputs to ensure you capture all device interactions.
Complete Flow Example
[
{
"id": "bridge1",
"type": "matter-dynamic-bridge",
"name": "My Matter Bridge"
},
{
"id": "light1",
"type": "matter-device",
"name": "Living Room Light",
"bridge": "bridge1",
"deviceConfig": "{\"deviceType\": \"OnOffLightDevice\"}",
"x": 300,
"y": 100,
"wires": [["debug1"]]
},
{
"id": "inject1",
"type": "inject",
"name": "Turn On",
"payload": "{\"onOff\":{\"onOff\":true}}",
"payloadType": "json",
"x": 100,
"y": 100,
"wires": [["light1"]]
},
{
"id": "debug1",
"type": "debug",
"name": "Light State",
"x": 500,
"y": 100
}
]
Supported Device Types
Lighting
OnOffLightDevice- Simple on/off lightDimmableLightDevice- Dimmable lightColorTemperatureLightDevice- Adjustable color temperatureExtendedColorLightDevice- Full RGB color control
Sensors
ContactSensorDevice- Door/window sensorLightSensorDevice- Ambient light sensorOccupancySensorDevice- Occupancy detectionMotionSensorDevice- Motion detectionTemperatureSensorDevice- Temperature measurementPressureSensorDevice- Pressure measurementFlowSensorDevice- Flow rate measurementHumiditySensorDevice- Humidity measurementWaterLeakDetectorDevice- Water leak detectionRainSensorDevice- Rain detectionSmokeCoAlarmDevice- Smoke/CO detection
Switches & Controls
GenericSwitchDevice- Multi-button switchOnOffSensorDevice- Binary sensorDimmableSwitchDevice- Dimmer switchColorDimmerSwitchDevice- Color control switch
Smart Plugs
OnOffPlugInUnitDevice- Simple smart plugDimmablePlugInUnitDevice- Dimmable plug
HVAC & Comfort
ThermostatDevice- Heating/cooling controlFanDevice- Fan controlHeatingCoolingUnitDevice- HVAC unitAirQualitySensorDevice- Air quality monitoringAirPurifierDevice- Air purifier control
Appliances
DishwasherDevice- Dishwasher controlLaundryWasherDevice- Washing machineLaundryDryerDevice- DryerRefrigeratorDevice- RefrigeratorCookSurfaceDevice- CooktopCooktopDevice- Cooktop controlOvenDevice- Oven controlExtractorHoodDevice- Range hoodMicrowaveOvenDevice- Microwave
Other Devices
WindowCoveringDevice- Blinds/curtainsDoorLockDevice- Smart lockPumpDevice- Pump controlRoboticVacuumCleanerDevice- Robot vacuumRoomAirConditionerDevice- AC unitWaterFreezeDetectorDevice- Freeze detection
Media & Entertainment
BasicVideoPlayerDevice- Basic video controlCastingVideoPlayerDevice- Casting deviceVideoRemoteControlDevice- Remote controlSpeakerDevice- Speaker control
Auto-Confirm Feature
The auto-confirm feature provides immediate state feedback when interactions are received from Matter controllers (HomeKit, Alexa, etc.). This prevents the controller from reverting the device state due to timeout.
Currently supports both:
- Commands: Explicit device commands (e.g.,
on,off,toggle) - Events: Attribute writes that may require additional confirmation (e.g., fan speed synchronization)
The feature automatically handles device-specific behaviors to ensure proper state synchronization with Matter controllers.
Troubleshooting
Device shows "Not Responding" in HomeKit
- Check Node-RED logs for errors
- Ensure Matter bridge is running (green status)
- Try redeploying the flow
- Check network connectivity
Events not triggering
- Verify the device is showing "ready" status
- Check the debug output for errors
- Ensure payload format matches Matter cluster structure
Cannot pair with controller
- Make sure bridge is not already paired (check bridge config)
- Use "Reopen Commissioning" if already paired
- Check firewall settings for port 5540 (or configured port)
- Ensure mDNS is working on your network
Device validation errors
Some devices have complex requirements:
- GenericSwitchDevice: Requires explicit button configuration
- ThermostatDevice: Requires features to be specified via
behaviorFeatures - BasicVideoPlayerDevice: Not supported by Alexa (Matter 1.4 device)
When devices fail validation, check Node-RED logs for specific missing attributes.
Commands not appearing in Output 2
Some devices (like thermostats) may not show commands in Output 2 when controlled from HomeKit/Alexa. This is expected behavior - these devices use direct attribute writes instead of commands.
Solution: Monitor Output 1 for state changes, as this is where attribute modifications will appear.
Common Payload Format Reference
| Device Type | Action | Payload |
|---|---|---|
| Light | On/Off | {onOff: {onOff: true/false}} |
| Dimmer | Set Level | {levelControl: {currentLevel: 0-255}} |
| Color Light | Set Color | {colorControl: {currentHue: 0-254, currentSaturation: 0-254}} |
| Temperature | Set Temp | {temperatureMeasurement: {measuredValue: value*100}} |
| Thermostat | Set Target | {thermostat: {occupiedHeatingSetpoint: value*100}} |
| Lock | Lock/Unlock | {doorLock: {lockState: 1/2}} |
| Contact | Open/Close | {booleanState: {stateValue: true/false}} |
| Fan | Speed | {fanControl: {percentSetting: 0-100}} |
| Video Player | State | {mediaPlayback: {currentState: 0/1/2}} |
Support
- GitHub Issues: Report bugs or request features
- 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.