433MHz RF Module
Function Description
The 433MHz RF module provides synchronous OOK transmission and receive learning. The receive driver decodes EV1527-style pulse ratios, and codes can be captured via the web UI, named, and stored in the key library. Specific remotes and compatible encodings must be verified by measurement — do not claim compatibility with all EV1527/PT2262 devices based on product names alone. A valid decode in normal receiving raises a rule event; the one captured while in learning state is not dispatched.
Firmware requirement: receive learning needs
FASTBEE_ENABLE_RF_LEARN=1. In the current standard matrix, onlyesp32s3-F8R8explicitly disables it; other standard environments includingesp32s3-F8R0andesp32s3-F16R8compile it in; for custom environments, check the actual switch. TX does not depend on the RF-learn switch. Being compiled in does not mean wiring, reception, or wireless loads have passed acceptance.TX-candidate parameters, source ownership, failure handling, and timing limits are in RF TX Source and Guarded Output Boundaries. TX local tests cannot be extended into RX learning, key storage, or physical acceptance.
Supported Peripheral Types
| Type | type value | Description |
|---|---|---|
| RF_MODULE | 48 | 433MHz RF module (transmit / receive learning) |
Event Numbers
| Event | Number | Description |
|---|---|---|
| EVENT_RF_CODE_RECEIVED | 130 | A valid RF code received in normal mode that was not filtered as a duplicate; the learning capture does not dispatch this event |
Hardware Wiring
Transmit module (e.g. SYN115/F115)
| Module pin | ESP32 GPIO | Notes |
|---|---|---|
| VCC | 3.3V or 5V | Power per the module's rating |
| GND | GND | Common ground required |
| DIN / DATA | GPIO4 (example) | Data input; do not use an input-only GPIO |
| ANT | Antenna | A 17cm wire or the matching spring antenna is recommended |
Receive module (e.g. SYN470R/SYN480R)
| Module pin | ESP32 GPIO | Notes |
|---|---|---|
| VCC | 3.3V or 5V | Power per the module's rating |
| GND | GND | Common ground required |
| OUT / DATA | GPIO16 (example) | Data output; needs an input-capable GPIO |
| ANT | Antenna | A 17cm wire is recommended |
The example GPIOs are for the classic ESP32 only; verify per board the input capability, output capability, and Flash/PSRAM usage. Power per the module datasheet — if the receiver is powered at 5V, still verify whether its OUT level is ESP32-compatible and do level shifting if necessary; do not treat the VCC rating as the GPIO tolerance.
Configuration
Method 1: Web UI (recommended)
Step 1: Open the Peripheral Management Page
- Open a browser and visit the ESP32 IP address
- After logging in, click Peripheral Configuration in the left menu
Step 2: Add the RF Peripheral
Click the Add Peripheral button
Fill in the configuration:
Transmit mode:
Field Value Notes Peripheral ID rf_tx_01Unique identifier Name 433M TXDisplay name Peripheral type 433MHz RF module (type: 48) RF_MODULE Pin config 4DATA pin Mode Transmit TX mode Code bits 24Persistent field bitLength; the action bits can override a single transmission Pulse width 350In us, typical EV1527 value Receive-learning mode:
Field Value Notes Peripheral ID rf_rx_01Unique identifier Name 433M RXDisplay name Peripheral type 433MHz RF module (type: 48) RF_MODULE Pin config 16OUT data pin Mode Receive (learning) RX mode, enabling pairing learning Click Save, then Enable the peripheral
Step 3: Pairing Learning (Receive Mode)
- Click the Edit button of the RF receive peripheral in the peripheral list
- Find the RF Remote Management panel at the bottom of the dialog
- Set the learning timeout (default 10 seconds)
- Click Start Learning
- Press the remote button within the timeout
- After a successful capture, enter a key name (e.g.
gate_btn) and click Save Key - The key library shows and allows deleting learned keys
Learning distance, orientation, antenna, and environmental interference must be verified per the specific receive module and remote; success is not guaranteed at a uniform distance. After the capture ends, normal receiving resumes, and subsequent key presses may trigger enabled rules.
Method 2: JSON Configuration File Import
Transmit peripheral:
{
"id": "rf_tx_01",
"name": "433M TX",
"type": 48,
"enabled": false,
"pins": [4],
"params": {
"mode": 0,
"pulseWidth": 350,
"bitLength": 24,
"repeat": 8
}
}Receive-learning peripheral:
{
"id": "rf_rx_01",
"name": "433M RX",
"type": 48,
"enabled": false,
"pins": [16],
"params": {
"mode": 1,
"activeHigh": true
}
}Parameter Description
| Parameter | Description |
|---|---|
| mode | 0=transmit (TX), 1=receive learning (RX) |
| pulseWidth | Transmit pulse width (us), EV1527 typical 350, range 100-2000 |
| bitLength | Default code bits (persistent field); the send action uses the bits field |
| repeat | Transmit repeat count (default 8); does not prove the remote received or executed |
| activeHigh | Receive level polarity (default true) |
pins[0] = RF module DATA pin
Pairing-learning API
In receive mode, the learning flow can be controlled via the HTTP API:
| Endpoint | Method | Description |
|---|---|---|
/api/rf/status | GET | Query the RF-learn driver status |
/api/rf/learn/start | POST | Start learning (parameter timeoutMs) |
/api/rf/learn/status | GET | Query learning progress |
/api/rf/learn/stop | POST | Cancel learning |
/api/rf/keys | GET | Get the key-library list |
/api/rf/keys | POST | Save a key (name/code/bits/pulse) |
/api/rf/keys/delete | POST | Delete a key (name) |
/api/rf/keys/clear | POST | Clear all keys |
Learning-state response example
{
"success": true,
"data": {
"initialized": true,
"learnState": "captured",
"code": "0xA1B2C3",
"bits": 24,
"pulse": 350,
"remainingMs": 0
}
}learnState values: idle, learning, captured, timeout.
Key-library storage
Keys are persisted to LittleFS at /config/rf_keys.json:
[
{ "name": "gate_btn", "code": "0xA1B2C3", "bits": 24, "pulse": 350 },
{ "name": "alarm_off", "code": "0xD4E5F6", "bits": 24, "pulse": 350 }
]Data Reporting Format
The driver does not auto-generate a "receiver ID + code" MQTT report. It dispatches the following internal global event, and the actual action or report depends on the matching rules; the payload has no receiver ID and cannot distinguish multiple receivers.
| Field | Description |
|---|---|
| code | Decoded code (hex) |
| bits | Code bits (usually 24) |
| pulse | Pulse width (us) |
Event Trigger Mechanism
A successful decode raises the EVENT_RF_CODE_RECEIVED (130) event with this data format:
{
"code": "0xA1B2C3",
"bits": 24,
"pulse": 350,
"key": "gate_btn"
}- The
keyfield appears only when the key library matches; it is omitted otherwise.
Working with PeriphExec
Web UI Configuration Steps
Create an RF-remote-controls-LED rule:
- Click PeriphExec in the left menu
- Click the Add Rule button
- Configure the event trigger:
- Trigger type: Event Trigger
- Trigger event: RF Code Received (rf_code_received)
- RF key: select a learned key (e.g.
gate_btn), or leave empty for any code
- Add an action:
- Action type: Toggle
- Target peripheral: led1
- Click Save
💡 Tip: the RF-key dropdown auto-loads keys learned in the key library; you can also fill in a raw code (e.g.
0xA1B2C3) or thekey:nameformat manually.
JSON Configuration Examples
RF remote turns on the LED
{
"name": "RF remote light on",
"enabled": false,
"triggers": [
{
"triggerType": 4,
"eventId": "rf_code_received",
"compareValue": "key:gate_btn"
}
],
"actions": [
{ "actionType": 30, "targetPeriphId": "led1" }
]
}Match by raw code
{
"name": "RF code trigger",
"enabled": false,
"triggers": [
{
"triggerType": 4,
"eventId": "rf_code_received",
"compareValue": "0xA1B2C3"
}
],
"actions": [
{ "actionType": 30, "targetPeriphId": "relay1" }
]
}Trigger on any RF code (any key)
{
"name": "Any RF trigger",
"enabled": false,
"triggers": [
{
"triggerType": 4,
"eventId": "rf_code_received",
"compareValue": ""
}
],
"actions": [
{ "actionType": 30, "targetPeriphId": "buzzer1" }
]
}Transmitting Codes (PeriphExec Invocation)
Send an RF code via the PeriphExec rule action Call Other Peripheral:
{
"periphId": "rf_tx_01",
"action": "send",
"code": "0xA1B2C3",
"bits": 24,
"pulseWidth": 350,
"repeat": 8
}code supports decimal, 0x hex, and 0b binary formats.
Debug Endpoint
POST /api/peripherals/write
Content-Type: application/x-www-form-urlencoded
id=rf_tx_01&code=0xA1B2C3&bits=24&pulseWidth=350&repeat=8Decoding Principle
Receive-learning mode uses GPIO interrupts to capture pulse timing:
- Frame-gap detection: adjacent-edge intervals greater than the sync threshold mark the previous frame complete or reset the buffer, combined with the amount of data collected; this judgment does not involve level polarity
- Data collection: record the following high/low pulse-width sequence (up to 128 pulses)
- Bit decoding: find the smallest pulse as the 1T base and judge one bit per 2 pulses
- High-level share >=2 → bit 1
- Low-level share >=2 → bit 0
- Code output: combined into a 24-bit (or 12-32 bit) hex code
Decoding follows the OOK pulse-ratio scheme above; specific remote encodings and repeated-frame behavior are subject to actual measurement.
Notes
- Firmware environment: confirm the receive-learning switch per the actual build; in the current standard matrix
esp32s3-F8R8disables it — do not generalize that all S3 environments disable it - Antenna: both transmit and receive modules are recommended to use a 17cm wire antenna, otherwise the range is extremely short
- Power: RF modules are sensitive to power supply; use a dedicated 3.3V/5V supply rather than powering from GPIO
- Interference: same-frequency interference may exist in the environment; reception stability and false triggers must be measured
- Transmit limits: do not send continuously at high frequency; trigger via rules by event or at a low timer rate
- Learning distance: confirm the effective distance per the specific module, remote, antenna, and environment; no uniform best distance is adopted
- Code boundaries: the current key library records fixed codes/bit lengths and does not guarantee rolling codes, encrypted codes, or all remote behaviors; a local code also does not identify a unique remote device
- Pulse-width matching: if the learned pulse width differs from the transmit default, use the learned pulse width when transmitting
- Example enablement: imported examples stay disabled; enable rules or peripherals only after confirming the target board's pins, config preservation, wiring, and load
- Acceptance boundary: RX learning/config transactions and TX transmission are accepted separately. Page prompts, GPIO SDK success, or TX host tests cannot prove receiver learning, restart recovery, or wireless-load action succeeded
RX-candidate Concurrency, Storage, and Error Boundaries
The candidate receiver uses a consistent state snapshot; rule events are dispatched outside the receive lock, and a stop that encounters an in-flight dispatch returns failure and keeps the receiver, retrying the stop after the dispatch ends. Re-binding or starting learning is rejected at that time; do not treat one stop request as having canceled everything that entered the queue. Takeover is also rejected when the singleton is already bound to another active pin. The ISR isolates stale callbacks with a cross-core critical section and a generation token; real interrupt timing still needs target-board verification.
RF keys are stored in a separate /config/rf_keys.json array, up to 40 entries. A modification first reads the source, checks the private candidate, writes a temp file and reads it back, then compares the source and atomically replaces; only a successful commit updates the cache. Open, short-write, observed source conflicts, and rename failures all return failure; the main file or an externally written source is not actively deleted to fix a failed repair. This lock only serializes the RF module's own operations — do not treat it as a global CAS shared by every file-manager/factory-recovery entry; the race between the final source comparison and rename from external writes is still not closed.
Learning timeoutMs must be a complete integer from 1000 to 60000; key-library bits must be 12-32, pulse must be 80-2000 microseconds, and code must be complete hex not exceeding the bit length. The RX key library's 80-microsecond lower bound differs from the TX transmit 100-microsecond lower bound; capturing or storing a code does not mean TX can legally replay it. Invalid parameters return 400, unable-to-start-learning returns 409, a genuinely missing delete name returns 404, and storage/source changes/busy or unconfirmed snapshot return 503; clearing does not ignore flush failures and report success.
The key library can be managed without an initialized receiver. When the first file read fails, the key list retries and returns 503 if still unconfirmed; raw-code reception does not pretend an empty key library already exists. With PERIPH_EXEC off but RF_LEARN kept, receiving, learning, and saving RF's own file still work — only rule dispatch stops. This candidate's local gate results must follow the corresponding records; the TX 34-item pass does not cover RX; real reception/wiring/power-loss recovery/load actions and long-term stability remain to be accepted separately.

