homebridge-rf433-gpiod
v2.0.6
Published
RF433 Chacon/DIO plugin for Homebridge using libgpiod
Downloads
752
Maintainers
Readme
homebridge-rf433-gpiod
✨ Description
Homebridge plugin to control 433 MHz RF devices X10 (Chacon / Dio)
using a Raspberry Pi (including Zero 2 W) with libgpiod.
🎯 Goals
- Reliable RF transmission
- Low power consumption
- No root / sudo required
- Clean architecture (C++ + Node.js)
🚀 Features
- ✅ Native RF transmission (C++ for precise timing)
- ✅ Raspberry Pi OS 64-bit compatible
- ✅ No
sudorequired - ✅ RF queue (collision prevention)
- ✅ Multi-device support
- ✅ Learn mode (on-demand RF capture)
- ✅ Dynamic device storage
- ✅ Zero idle CPU usage (no background sniffing)
The main reason I created this plugin is to free myself from Home Assistant.
My Raspberry Pi Zero 2W can't run Home Assistant, MQTT, Docker, and other services simultaneously.
This plugin allows me to do all of that directly from Homebridge.
📦 Installation
1. Install system dependencies
sudo apt update sudo apt install libgpiod-dev gpiod
2. Install plugin
cd /var/lib/homebridge npm install homebridge-rf433-gpiod
3. Configure plugin in config.json
See Basic Configuration section below
Note: Starting from version 2.0.3, the chacon_gpiod binary is pre-compiled and bundled. No manual compilation or setcap configuration is required.
⚙️ Basic Configuration
Add to your config.json:
{
"platform": "RF433",
"devices": {
"living_room_lamp": {
"gpioPin": 17,
"emitterID": 325263,
"switchNumber": 1,
"type": "switch"
},
"kitchen_lamp": {
"gpioPin": 17,
"emitterID": 325263,
"switchNumber": 2,
"type": "switch"
},
"bedroom_shutter": {
"gpioPin": 17,
"emitterID": 325268,
"switchNumber": 1,
"type": "cover",
"fullTravelTime": 15000,
"inverted": false
}
}
}Understanding emitterID and switchNumber
emitterID: Virtual remote control identifier (26-bit value)
- Represents the "remote control" in the RF433 protocol
- All devices with the same emitterID act as if controlled by the same remote
- You can reuse the same emitterID for multiple devices
switchNumber: Button number on the virtual remote (1-4)
- Chacon/Dio protocol supports 4 buttons per remote
- Use different switchNumbers for different devices on the same emitterID
- Example: emitterID=1001, devices use switchNumber 1, 2, 3, 4
Configuration Examples
Option A: One virtual remote per device
"device_1": { "emitterID": 1001, "switchNumber": 1 }
"device_2": { "emitterID": 1002, "switchNumber": 1 }
"device_3": { "emitterID": 1003, "switchNumber": 1 }Option B: One virtual remote for multiple devices
"device_1": { "emitterID": 1001, "switchNumber": 1 }
"device_2": { "emitterID": 1001, "switchNumber": 2 }
"device_3": { "emitterID": 1001, "switchNumber": 3 }Choose the setup that matches your device configuration best.
🎮 Usage
Devices appear as HomeKit switches ON/OFF triggers RF transmission Works with Siri and Apple Home
🧠 Learn Mode
Automatic Device Discovery
A virtual "RF Learn Mode" accessory appears in HomeKit: (beta version)
- Enable: Turn ON the "RF Learn Mode" switch in HomeKit
- Wait: Plugin listens for 10 seconds (active sniffing)
- Send: Press a button on your RF remote control
- Capture: Signal is automatically decoded
- Save: Device is added to
runtime-devices.json - Disable: Switch turns OFF automatically after capture
Important Notes
- ✅ No background listening — Only active when you enable the switch
- ✅ Automatic learning — No manual emitterID/switchNumber needed
- ✅ Dynamic device creation — Learned devices appear immediately
- ✅ Persistent storage — Learned devices survive restarts
Advanced: Manual Signal Capture
For advanced users, you can manually decode RF signals:
# Compile the receiver (optional)
g++ chacon_receiver.cpp -o rf_receiver -lgpiod
# Run and press remote button
./rf_receiver 17 # Use GPIO pin 17
# Output example:
# Signal #1 detected!
# emitterID: 12325263
# switchNumber: 1
# Pin: 17📁 Device Storage
Static Configuration
- File:
config.json - Location: Homebridge config directory
- Usage: Define devices on startup
Learned Devices
- File:
runtime-devices.json - Location: Plugin directory
- Usage: Devices captured via Learn Mode
- Auto-updated: When new devices are learned
Cover Position State
- Files:
rfcover_*.json(per cover) - Location: Homebridge storage directory
- Usage: Persist cover position across restarts
- Auto-updated: On every movement completion
⚙️ Advanced Configuration
{
"platform": "RF433",
"options": {
"delay": 150,
"minInterval": 120,
"retries": 2,
"timeout": 2000
},
"devices": {
"living_room_lamp": {
"name": "Living Room Lamp",
"gpioPin": 17,
"emitterID": 325263,
"switchNumber": 1,
"type": "switch"
},
"bedroom_shutter": {
"name": "Bedroom Shutter",
"gpioPin": 17,
"emitterID": 12325268,
"switchNumber": 1,
"type": "cover",
"fullTravelTime": 15000,
"inverted": false
}
}
}Queue Options
| Option | Type | Default | Description | |--------|------|---------|-------------| | delay | ms | 150 | Delay between retry attempts | | minInterval | ms | 120 | Minimum interval between RF commands (rate limiting) | | retries | count | 2 | Number of transmission retries (1 for covers, 2 for switches) | | timeout | ms | 2000 | Command execution timeout |
Device Options
| Option | Type | Default | Description | |--------|------|---------|-------------| | type | string | "switch" | Device type: "switch" or "cover" | | fullTravelTime | ms | 15000 | Time to fully open/close (covers only) | | inverted | bool | false | Invert open/close direction (covers only) |
Cover-specific Options
- fullTravelTime: Adjust based on your physical shutter speed
- inverted: Set to
trueif your shutter motor is installed in reverse orientation
🧱 Architecture
HomeKit ↓ Homebridge ↓ RF433 Plugin ↓ RFQueue (anti-collision) ↓ C++ chacon_gpiod ↓ libgpiod ↓ GPIO ↓ 433 MHz RF module
🔋 Power Consumption
Optimized for Raspberry Pi Zero 2 W: ❌ No polling ❌ No background daemon ✅ On-demand RF sniffing only ✅ Near-zero CPU usage when idle
🧪 Troubleshooting
Enable Debug Logs
Set the DEBUG environment variable before starting Homebridge:
DEBUG=homebridge-rf433-gpiod homebridge -U ~/.homebridgeExample Debug Output
[RF433] Platform ready
[RF433] Registry loaded
[RF433] living_room_lamp → ON
[RF433] queue send
[RF433] _execute: 12325263_1 -> ON
[RF433] okCommon Issues
1. GPIO Permission Denied
- Ensure user running Homebridge is in the
gpiogroup - Run:
sudo usermod -aG gpio homebridge
2. Cannot open gpiochip0
- Verify libgpiod is installed:
dpkg -l | grep libgpiod - Check GPIO device exists:
ls /dev/gpiochip*
3. RF signals not received in Learn Mode
- Verify RF receiver is wired correctly
- Check GPIO pin configuration
- Move remote control closer to the receiver
4. Devices not responding
- Test RF command manually:
chacon_gpiod 17 325263 1 on - Verify emitterID and switchNumber match your remote
- Check GPIO pin assignment
🔐 Security & Limitations
Security
- ✅ No
sudorequired for operation - ✅ Uses
libgpiodcapability model for GPIO access - ✅ Plugin runs with standard Homebridge user permissions
- ✅ Binary path validation prevents command injection
Limitations
- ⚠️ RF Unreliability: 433 MHz is license-free and subject to interference
- ⚠️ Stateless: No feedback from devices (position is simulated)
- ⚠️ Protocol Specificity: Designed for Chacon/Dio RF433 devices
- ⚠️ Single GPIO Pin: All RF transmissions share one GPIO pin (queue managed)
🤝 Contributing
Pull requests welcome! Areas for contribution:
- Protocol support expansion
- Performance optimizations
- Documentation improvements
- Issue reporting and testing
