Skip to content

ESP32 Puzhong Board Function Test Case ​

Case Overview ​

Using the Puzhong PZ-ESP32 board (ESP32-WROOM-32 module), build a complete IoT demo with zero code:

  • Data acquisition: DHT11 temperature/humidity + ADC potentiometer (0-4095), sampled and reported to the IoT platform every 10 seconds
  • Local display: TM1637 7-segment display alternates temperature/humidity; the OLED shows a three-line welcome message on boot and can display text pushed from the platform
  • Alarm linkage: the buzzer sounds automatically when temperature exceeds 28°C (passive buzzer, continuous 2700Hz PWM tone) and stops when it recovers
  • Button control: KEY1 relay, KEY2 buzzer, KEY3 RGB pixels, KEY4 the four LEDs
  • IR remote: rules match the raw NEC codes of the bundled Puzhong remote by default, so they work out of the box with no pairing; when switching to another remote, learn its keys through the Web panel and switch the rules to key-name binding — the actions never change
  • Remote control: the platform can control the relay, buzzer, RGB effects, LED group and OLED text

Everything is implemented through Peripheral Configuration + Peripheral Execution rules, without writing any code.

Hardware Information ​

The Puzhong PZ-ESP32 board consists of a core board (ESP32-WROOM-32) plus a base board. The base board integrates LEDs, buttons and a buzzer; the remaining modules are connected with jumper wires.

Pin Mapping ​

PeripheralGPIOWiring
DHT11 temp/humidityGPIO32DATA→GPIO32, VCC→3.3V, GND→GND
ADC potentiometerGPIO34Wiper→GPIO34, the two ends to 3.3V / GND
TM1637 7-segmentGPIO18 / GPIO19CLK→GPIO18, DIO→GPIO19, VCC→3.3V
OLED 0.91" (I2C)GPIO22 / GPIO23SDA→GPIO22, SCL→GPIO23, VCC→3.3V (the two adjacent pins at the far right of the bottom row, next to GND); never use 5V
WS2812B RGB pixels ×5GPIO12DIN→GPIO12, VCC→5V, GND→GND
BuzzerGPIO13Control pin→GPIO13 (passive buzzer, PWM driven), VCC→3.3V, GND→GND (next to the GND pin on the top row)
RelayGPIO33IN→GPIO33 (active high), VCC→5V, GND→GND (must share ground with the ESP32)
KEY1-KEY4GPIO14 / 27 / 26 / 25The other side of each button to GND (internal pull-up, pressed = low); four consecutive pins on the top row for easy wiring
LED D1-D4GPIO4 / 16 / 17 / 5Active low (anode to VCC through a resistor); four consecutive pins on the bottom row
IR receiver (VS1838B)GPIO35OUT→GPIO35, GND→GND, VCC→3.3V (facing the bulged side of the receiver, pins from left to right are OUT / GND / VCC)

Pin Notes ​

  • GPIO34 is input-only (no internal pull-up) and belongs to ADC1, so it still works while WiFi is active (ADC2 is unavailable under WiFi)
  • GPIO35 is also input-only, which suits IR reception; the VS1838B has a push-pull output and needs no external pull-up. IO14 used by the original tutorial is already taken by KEY1, so IR moves to GPIO35 (between 32/34 on the top row, convenient for wiring)
  • KEY1-KEY4 (GPIO14/27/26/25) are four consecutive pins on the top row, all with internal pull-ups, so no external resistors are needed
  • GPIO13 (buzzer): the onboard buzzer of the Puzhong board is a passive buzzer — plain high/low levels (digital output) produce no sound. It must be configured as a PWM output (this setup: 2700Hz, 8-bit resolution) and is driven on/off via duty cycle
  • GPIO12 (MTDI) is a strapping pin and must not drive an active-low load with a pull-up; the WS2812B DIN is a high-impedance input and does not disturb boot, so it is safe here
  • GPIO5 (LED D4) is a strapping pin (affects SDIO timing) but is safe as an LED output; this design avoids GPIO2/15 entirely, so flashing is unaffected by the LED wiring
  • GPIO0/1/3 are reserved by the firmware (BOOT/serial); GPIO2/15/21 are unused and left for expansion
  • The relay deliberately avoids GPIO25 used by KEY4 to prevent a pin conflict

Implementation ​

Step 1: Flash the Firmware ​

Option A — Online flasher (recommended)

  1. Open the online flashing tool
  2. Pick a baud rate → pick the serial port → pick the firmware file fastbee-esp32-f4ro.bin
  3. Click Flash and wait for it to finish

Option B — Flash from source

powershell
powershell -ExecutionPolicy Bypass -File scripts\deploy.ps1 -Env esp32-F4R0

See Flashing and Testing for details.

Step 2: Configure the Network ​

  1. After flashing the device reboots; connect your computer to the WiFi hotspot fastbee-xxxx (password: admin123)
  2. Browse to http://192.168.4.1 or http://fastbee.local and log in with admin / admin123
  3. Go to Network Configuration, choose Station mode (STA), fill in the WiFi SSID and password, then save
  4. Wait for the reboot, reconnect your computer to the normal WiFi, and access the device through fastbee.local

You may also stay in AP mode for the whole configuration process instead of switching to STA.

Step 3: Peripheral Configuration (peripherals.json) ​

Create the peripherals one by one on the Peripheral Configuration page, or simply use the config import at the end of this page. There are 16 peripherals:

Peripheral IDNameTypePinsKey parameters
dht11DHT11 Temp & Humidity Sensor38 Generic sensor32sensorType:0 (DHT11), sampleInterval:10000
adc_potADC Potentiometer26 ADC34attenuation:3, resolution:12
tm16374-Digit Display47 TM163718, 19brightness:4, colon:false
oledOLED Display36 LCD (OLED)22, 23width:128, height:32, interface:2 (I2C), contrast:200
rgb_ledRGB Pixels45 WS2812B12count:5, brightness:128
buzzerBuzzer17 PWM output13pwmFrequency:2700, pwmResolution:8, initialState:0
relayRelay12 Digital output33initialState:0
key1 - key4Button KEY1-KEY413 Digital input (pull-up)14, 27, 26, 25none
led_d1 - led_d4LED D1-D412 Digital output4, 16, 17, 5initialState:1 (active low, off at power-on)
ir_recvIR Receiver53 IR receiver35none

Peripheral types: 38 = generic sensor (DHT11), 26 = ADC, 47 = TM1637 7-segment, 36 = LCD (OLED panels belong to this type, I2C interface), 45 = WS2812B, 12 = GPIO digital output, 17 = GPIO PWM output, 13 = GPIO input (pull-up), 53 = IR receiver. LEDs are active low, so initialState: 1 means off at power-on. Peripheral IDs must match the rules and the thing-model identifiers used later.

Step 4: IR Learning (Pairing Remote Keys, Optional) ​

The IR rules of this case match the raw NEC codes of the bundled Puzhong remote by default (see the table in Step 5), so with the bundled remote they work out of the box — no pairing needed. Only perform this step when switching to another brand of remote or when you prefer key-name binding: first learn remote keys into the device key library and name them, then change the rules' match value to key:<name>. Afterwards, swapping in any brand of remote only requires re-pairing — no rule needs to change.

  1. Turn on Developer Mode at the top-right of the page (pairing/clearing are write operations and require it)
  2. Go to the Peripheral Configuration page and click the IR Management button on the "IR Receiver" row
  3. Set the learn timeout (default 10 seconds, allowed 3-60 seconds) and click Start Learning
  4. Aim the remote at the receiver and press the key to record; the page shows the captured code and protocol
  5. Type a name in the Key Name field (e.g., key1) and click Save Key
  6. Repeat steps 3-5 to record the keys you need

If you switch to key-name binding, the suggested keys and bound actions (names are up to you, but must match the rules):

Remote keySuggested nameCode on the bundled remoteBound action
Key 1key1NEC 0x00FF30CFToggle relay
Key 2key2NEC 0x00FF18E7Toggle buzzer
Key 3key3NEC 0x00FF7A85RGB rainbow
Key 4key4NEC 0x00FF10EFToggle LED D1-D4
Key 0key0NEC 0x00FF6897Turn RGB off

Key names accept letters, digits, underscore and hyphen only (1-32 characters), up to 40 keys. The key library is persisted to /config/ir_keys.json and can be exported/imported together with the rest of the config. No ir_code_received event is dispatched during the learning window, so pairing never fires existing rules. You can skip this step when using the bundled Puzhong remote; for a different remote, re-pair using the same key names to overwrite them, then change the rules' compareValue to key:<name>.

Step 5: Peripheral Execution Rules (periph_exec.json) ​

Create the rules on the Peripheral Execution Management page — 20 in total:

RuleTriggerAction
exec_001 Data collection & reportPolling, every 10sRead temperature + humidity + ADC, report after execution
exec_002 Alternate temp/humidity on displayTimer, every 10sShow temperature → delay 5s → show humidity
exec_003 High-temperature alarmData-source event, temperature > 28Buzzer PWM duty 128 (50%), continuous tone
exec_004 Clear alarm on recoveryData-source event, temperature ≤ 28Buzzer PWM duty set to 0, tone stops
exec_005 / 006KEY1 / KEY2 single clickToggle relay / buzzer
exec_007 / 008KEY3 single / double clickRGB rainbow / off
exec_009KEY4 single clickToggle LED D1-D4
exec_010 OLED default displaySystem ready eventOLED shows a three-line welcome message (first line centered)
exec_011 Platform sends OLED textPlatform trigger (oled)OLED shows the received $value
exec_012 - 014Platform trigger (relay/buzzer/rgb_led)Control relay/buzzer/RGB effect by the received value
exec_015Platform trigger (led_all)Control LED D1-D4 by the received value
exec_016 / 017IR code NEC:0x00FF30CF / NEC:0x00FF18E7Toggle relay / buzzer
exec_018 / 019IR code NEC:0x00FF7A85 / NEC:0x00FF6897RGB rainbow / off
exec_020IR code NEC:0x00FF10EFToggle LED D1-D4

All IR rules use Event Trigger → IR Code Received (ir_code_received). This case uses <protocol>:<code> (e.g., NEC:0x00FF30CF) by default to match the bundled Puzhong remote directly — no pairing required. If you paired keys in Step 4, you can instead pick a learned key from the IR Key dropdown in the form (options show both the key name and the code, and the saved compareValue becomes key:<name>). compareValue supports three formats:

FormatExampleDescription
<protocol>:<code>NEC:0x00FF30CFDefault in this case. Matches the bundled remote directly, works out of the box
key:<name>key:key1Matches a learned key name; switching remotes needs no rule change (requires pairing first)
<code>0x00FF30CF or 00FF30CFAny protocol + code; the 0x prefix is optional and matching is case-insensitive

Leaving it empty (-- Any IR Key --) triggers on any received IR code. Each trigger enforces a 1-second minimum repeat interval, and the driver adds a 150ms debounce plus NEC repeat-code filtering, so holding a key does not fire repeatedly.

Step 6: FastBee Platform Configuration (Optional) ​

1. On the platform

Create a product on the FastBee IoT platform. The thing-model identifiers must match the peripheral IDs on the device:

IdentifierDirectionDescription
temperature / humidityReportDHT11 temperature (°C) / humidity (%RH)
adcReportPotentiometer reading 0-4095
oledCommandString, text shown on the OLED (ASCII only)
relay / buzzerCommand/Report1 on, 0 off, toggle to toggle
rgb_ledCommandEffects: red, green, blue, rainbow, breathing, off, etc.
led_allCommandLED group (D1-D4): 0 all on (active low), 1 all off, toggle

2. On the device

  • Device Configuration → fill in the Product ID under basic information
  • Network Protocol → configure the MQTT parameters:
ParameterValue
Serveriot.fastbee.cn (demo address)
Port1883 (default)
Username/PasswordCredentials from the platform
Client IDFormat: S&deviceNumber&productId&1

Once MQTT connects, you can view the collected data and control the device from the platform Web console or the FastBee App.

How It Works ​

  1. Temperature alarm: after each temperature/humidity sample the firmware pushes the values to the data-driven rule evaluator. Temperature > 28°C triggers exec_003 and the buzzer sounds continuously at 2700Hz PWM with 50% duty; temperature ≤ 28°C triggers exec_004, which sets the duty to 0 and stops it
  2. Data reporting: exec_001 reads temperature, humidity and the ADC potentiometer every 10 seconds and reports them to the platform (reportAfterExec: true)
  3. Alternating display: each cycle of exec_002 shows the temperature for about 5 seconds, then the humidity for about 5 seconds, repeatedly
  4. Button control: single-clicking KEY1-KEY4 toggles the relay, buzzer, RGB (double-click KEY3 to turn it off) and the 4 LEDs
  5. IR remote: the IR receiver decodes a frame and dispatches an ir_code_received event; the rules match the raw NEC codes of the bundled Puzhong remote by default — key 1 relay, key 2 buzzer, key 3 RGB rainbow, key 0 RGB off, key 4 toggles the 4 LEDs, identical to the button behavior. If keys have been learned into the key library, the event also carries a key field and rules may match with key:<name> instead
  6. OLED display: at boot (system_ready event) it shows the three lines #FastBee Arduino / PuZhong ESP32 / IoT Demo Ready, where the leading # centers the first line; text pushed to the oled identifier refreshes the screen immediately. The OLED action (actionType: 27) also supports ${peripheralId.field} placeholders — for example setting actionValue to #Sensor\n T:${dht11.temperature}C\n H:${dht11.humidity}% prints live readings on the screen

Config Import ​

The configuration below can be imported directly: Device Configuration → Advanced → Import Config; reboot to apply. It contains two files (identical to the configuration measured on the actual device): peripherals.json (16 peripherals) and periph_exec.json (20 rules). The IR rules already embed the NEC codes of the bundled Puzhong remote, so the remote works right after import; for a different remote, pair the keys as in Step 4 and switch to key-name matching.

json
{
  "type": "fastbee-config-bundle",
  "version": 1,
  "scope": "selected",
  "exportedAt": "2026-07-28T08:00:00.000Z",
  "files": [
    {
      "name": "peripherals.json",
      "content": "{\"peripherals\":[{\"id\":\"dht11\",\"name\":\"DHT11 Temp & Humidity Sensor\",\"type\":38,\"enabled\":true,\"pins\":[32],\"pinCount\":1,\"params\":{\"sensorType\":0,\"sampleInterval\":10000}},{\"id\":\"adc_pot\",\"name\":\"ADC Potentiometer\",\"type\":26,\"enabled\":true,\"pins\":[34],\"pinCount\":1,\"params\":{\"attenuation\":3,\"resolution\":12,\"sampleRate\":0}},{\"id\":\"tm1637\",\"name\":\"4-Digit Display\",\"type\":47,\"enabled\":true,\"pins\":[18,19],\"pinCount\":2,\"params\":{\"brightness\":4,\"colon\":false}},{\"id\":\"oled\",\"name\":\"OLED Display\",\"type\":36,\"enabled\":true,\"pins\":[22,23],\"pinCount\":2,\"params\":{\"width\":128,\"height\":32,\"interface\":2,\"contrast\":200}},{\"id\":\"rgb_led\",\"name\":\"RGB Pixels\",\"type\":45,\"enabled\":true,\"pins\":[12],\"pinCount\":1,\"params\":{\"count\":5,\"brightness\":128}},{\"id\":\"buzzer\",\"name\":\"Buzzer\",\"type\":17,\"enabled\":true,\"pins\":[13],\"pinCount\":1,\"params\":{\"initialState\":0,\"pwmChannel\":13,\"pwmFrequency\":2700,\"pwmResolution\":8}},{\"id\":\"relay\",\"name\":\"Relay\",\"type\":12,\"enabled\":true,\"pins\":[33],\"pinCount\":1,\"params\":{\"initialState\":0}},{\"id\":\"key1\",\"name\":\"Button KEY1\",\"type\":13,\"enabled\":true,\"pins\":[14],\"pinCount\":1,\"params\":{}},{\"id\":\"key2\",\"name\":\"Button KEY2\",\"type\":13,\"enabled\":true,\"pins\":[27],\"pinCount\":1,\"params\":{}},{\"id\":\"key3\",\"name\":\"Button KEY3\",\"type\":13,\"enabled\":true,\"pins\":[26],\"pinCount\":1,\"params\":{}},{\"id\":\"key4\",\"name\":\"Button KEY4\",\"type\":13,\"enabled\":true,\"pins\":[25],\"pinCount\":1,\"params\":{}},{\"id\":\"led_d1\",\"name\":\"LED D1\",\"type\":12,\"enabled\":true,\"pins\":[4],\"pinCount\":1,\"params\":{\"initialState\":1}},{\"id\":\"led_d2\",\"name\":\"LED D2\",\"type\":12,\"enabled\":true,\"pins\":[16],\"pinCount\":1,\"params\":{\"initialState\":1}},{\"id\":\"led_d3\",\"name\":\"LED D3\",\"type\":12,\"enabled\":true,\"pins\":[17],\"pinCount\":1,\"params\":{\"initialState\":1}},{\"id\":\"led_d4\",\"name\":\"LED D4\",\"type\":12,\"enabled\":true,\"pins\":[5],\"pinCount\":1,\"params\":{\"initialState\":1}},{\"id\":\"ir_recv\",\"name\":\"IR Receiver\",\"type\":53,\"enabled\":true,\"pins\":[35],\"pinCount\":1,\"params\":{}}]}"
    },
    {
      "name": "periph_exec.json",
      "content": "{\"rules\":[{\"id\":\"exec_001\",\"name\":\"Data Collection & Report\",\"enabled\":true,\"execMode\":0,\"triggers\":[{\"triggerType\":5,\"triggerPeriphId\":\"\",\"operatorType\":0,\"compareValue\":\"\",\"timerMode\":0,\"intervalSec\":10,\"timePoint\":\"\",\"eventId\":\"\",\"pollResponseTimeout\":1000,\"pollMaxRetries\":2,\"pollInterPollDelay\":100}],\"actions\":[{\"targetPeriphId\":\"dht11\",\"actionType\":19,\"actionValue\":\"{\\\"periphId\\\":\\\"dht11\\\",\\\"sensorCategory\\\":\\\"dht11\\\",\\\"scaleFactor\\\":1,\\\"offset\\\":0,\\\"decimalPlaces\\\":1,\\\"sensorLabel\\\":\\\"temperature\\\",\\\"unit\\\":\\\"°C\\\",\\\"dataField\\\":\\\"temperature\\\"}\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0},{\"targetPeriphId\":\"dht11\",\"actionType\":19,\"actionValue\":\"{\\\"periphId\\\":\\\"dht11\\\",\\\"sensorCategory\\\":\\\"dht11\\\",\\\"scaleFactor\\\":1,\\\"offset\\\":0,\\\"decimalPlaces\\\":1,\\\"sensorLabel\\\":\\\"humidity\\\",\\\"unit\\\":\\\"%RH\\\",\\\"dataField\\\":\\\"humidity\\\"}\",\"useReceivedValue\":false,\"syncDelayMs\":200,\"execMode\":0},{\"targetPeriphId\":\"adc_pot\",\"actionType\":19,\"actionValue\":\"{\\\"periphId\\\":\\\"adc_pot\\\",\\\"sensorCategory\\\":\\\"analog\\\",\\\"scaleFactor\\\":1,\\\"offset\\\":0,\\\"decimalPlaces\\\":0,\\\"sensorLabel\\\":\\\"adc\\\",\\\"unit\\\":\\\"\\\"}\",\"useReceivedValue\":false,\"syncDelayMs\":200,\"execMode\":0}],\"protocolType\":0,\"reportAfterExec\":true},{\"id\":\"exec_002\",\"name\":\"Alternate Temp/Humidity on Display\",\"enabled\":true,\"execMode\":0,\"triggers\":[{\"triggerType\":1,\"triggerPeriphId\":\"\",\"operatorType\":0,\"compareValue\":\"\",\"timerMode\":0,\"intervalSec\":10,\"timePoint\":\"\",\"eventId\":\"\",\"pollResponseTimeout\":1000,\"pollMaxRetries\":2,\"pollInterPollDelay\":100}],\"actions\":[{\"targetPeriphId\":\"dht11\",\"actionType\":19,\"actionValue\":\"{\\\"periphId\\\":\\\"dht11\\\",\\\"sensorCategory\\\":\\\"dht11\\\",\\\"scaleFactor\\\":1,\\\"offset\\\":0,\\\"decimalPlaces\\\":1,\\\"sensorLabel\\\":\\\"temperature\\\",\\\"unit\\\":\\\"°C\\\",\\\"dataField\\\":\\\"temperature\\\"}\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0},{\"targetPeriphId\":\"tm1637\",\"actionType\":24,\"actionValue\":\"${dht11.temperature}\",\"useReceivedValue\":false,\"syncDelayMs\":200,\"execMode\":0},{\"targetPeriphId\":\"dht11\",\"actionType\":19,\"actionValue\":\"{\\\"periphId\\\":\\\"dht11\\\",\\\"sensorCategory\\\":\\\"dht11\\\",\\\"scaleFactor\\\":1,\\\"offset\\\":0,\\\"decimalPlaces\\\":1,\\\"sensorLabel\\\":\\\"humidity\\\",\\\"unit\\\":\\\"%RH\\\",\\\"dataField\\\":\\\"humidity\\\"}\",\"useReceivedValue\":false,\"syncDelayMs\":5000,\"execMode\":0},{\"targetPeriphId\":\"tm1637\",\"actionType\":24,\"actionValue\":\"${dht11.humidity}\",\"useReceivedValue\":false,\"syncDelayMs\":200,\"execMode\":0}],\"protocolType\":0,\"reportAfterExec\":false},{\"id\":\"exec_003\",\"name\":\"High Temperature Alarm\",\"enabled\":true,\"execMode\":0,\"triggers\":[{\"triggerType\":4,\"triggerPeriphId\":\"\",\"operatorType\":2,\"compareValue\":\"28\",\"timerMode\":0,\"intervalSec\":0,\"timePoint\":\"\",\"eventId\":\"ds:dht11_temperature\",\"pollResponseTimeout\":1000,\"pollMaxRetries\":2,\"pollInterPollDelay\":100}],\"actions\":[{\"targetPeriphId\":\"buzzer\",\"actionType\":4,\"actionValue\":\"128\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0}],\"protocolType\":0,\"reportAfterExec\":false},{\"id\":\"exec_004\",\"name\":\"Clear Alarm on Temperature Recovery\",\"enabled\":true,\"execMode\":0,\"triggers\":[{\"triggerType\":4,\"triggerPeriphId\":\"\",\"operatorType\":5,\"compareValue\":\"28\",\"timerMode\":0,\"intervalSec\":0,\"timePoint\":\"\",\"eventId\":\"ds:dht11_temperature\",\"pollResponseTimeout\":1000,\"pollMaxRetries\":2,\"pollInterPollDelay\":100}],\"actions\":[{\"targetPeriphId\":\"buzzer\",\"actionType\":4,\"actionValue\":\"0\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0}],\"protocolType\":0,\"reportAfterExec\":false},{\"id\":\"exec_005\",\"name\":\"KEY1 Controls Relay\",\"enabled\":true,\"execMode\":0,\"triggers\":[{\"triggerType\":4,\"triggerPeriphId\":\"key1\",\"operatorType\":0,\"compareValue\":\"\",\"timerMode\":0,\"intervalSec\":0,\"timePoint\":\"\",\"eventId\":\"button_click\",\"pollResponseTimeout\":1000,\"pollMaxRetries\":2,\"pollInterPollDelay\":100}],\"actions\":[{\"targetPeriphId\":\"relay\",\"actionType\":10,\"actionValue\":\"toggle\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0}],\"protocolType\":0,\"reportAfterExec\":true},{\"id\":\"exec_006\",\"name\":\"KEY2 Controls Buzzer\",\"enabled\":true,\"execMode\":0,\"triggers\":[{\"triggerType\":4,\"triggerPeriphId\":\"key2\",\"operatorType\":0,\"compareValue\":\"\",\"timerMode\":0,\"intervalSec\":0,\"timePoint\":\"\",\"eventId\":\"button_click\",\"pollResponseTimeout\":1000,\"pollMaxRetries\":2,\"pollInterPollDelay\":100}],\"actions\":[{\"targetPeriphId\":\"buzzer\",\"actionType\":10,\"actionValue\":\"toggle\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0}],\"protocolType\":0,\"reportAfterExec\":true},{\"id\":\"exec_007\",\"name\":\"KEY3 Starts RGB Rainbow\",\"enabled\":true,\"execMode\":0,\"triggers\":[{\"triggerType\":4,\"triggerPeriphId\":\"key3\",\"operatorType\":0,\"compareValue\":\"\",\"timerMode\":0,\"intervalSec\":0,\"timePoint\":\"\",\"eventId\":\"button_click\",\"pollResponseTimeout\":1000,\"pollMaxRetries\":2,\"pollInterPollDelay\":100}],\"actions\":[{\"targetPeriphId\":\"rgb_led\",\"actionType\":11,\"actionValue\":\"rainbow\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0}],\"protocolType\":0,\"reportAfterExec\":false},{\"id\":\"exec_008\",\"name\":\"KEY3 Double-Click Turns Off RGB\",\"enabled\":true,\"execMode\":0,\"triggers\":[{\"triggerType\":4,\"triggerPeriphId\":\"key3\",\"operatorType\":0,\"compareValue\":\"\",\"timerMode\":0,\"intervalSec\":0,\"timePoint\":\"\",\"eventId\":\"button_double_click\",\"pollResponseTimeout\":1000,\"pollMaxRetries\":2,\"pollInterPollDelay\":100}],\"actions\":[{\"targetPeriphId\":\"rgb_led\",\"actionType\":11,\"actionValue\":\"off\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0}],\"protocolType\":0,\"reportAfterExec\":false},{\"id\":\"exec_009\",\"name\":\"KEY4 Controls LED D1-D4\",\"enabled\":true,\"execMode\":0,\"triggers\":[{\"triggerType\":4,\"triggerPeriphId\":\"key4\",\"operatorType\":0,\"compareValue\":\"\",\"timerMode\":0,\"intervalSec\":0,\"timePoint\":\"\",\"eventId\":\"button_click\",\"pollResponseTimeout\":1000,\"pollMaxRetries\":2,\"pollInterPollDelay\":100}],\"actions\":[{\"targetPeriphId\":\"led_d1\",\"actionType\":10,\"actionValue\":\"toggle\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0},{\"targetPeriphId\":\"led_d2\",\"actionType\":10,\"actionValue\":\"toggle\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0},{\"targetPeriphId\":\"led_d3\",\"actionType\":10,\"actionValue\":\"toggle\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0},{\"targetPeriphId\":\"led_d4\",\"actionType\":10,\"actionValue\":\"toggle\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0}],\"protocolType\":0,\"reportAfterExec\":false},{\"id\":\"exec_010\",\"name\":\"OLED Default Display\",\"enabled\":true,\"execMode\":0,\"triggers\":[{\"triggerType\":4,\"triggerPeriphId\":\"\",\"operatorType\":0,\"compareValue\":\"\",\"timerMode\":0,\"intervalSec\":0,\"timePoint\":\"\",\"eventId\":\"system_ready\",\"pollResponseTimeout\":1000,\"pollMaxRetries\":2,\"pollInterPollDelay\":100}],\"actions\":[{\"targetPeriphId\":\"oled\",\"actionType\":27,\"actionValue\":\"#FastBee Arduino\\nPuZhong ESP32\\nIoT Demo Ready\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0}],\"protocolType\":0,\"reportAfterExec\":false},{\"id\":\"exec_011\",\"name\":\"Platform Sends OLED Text\",\"enabled\":true,\"execMode\":0,\"triggers\":[{\"triggerType\":0,\"triggerPeriphId\":\"oled\",\"operatorType\":1,\"compareValue\":\"\",\"timerMode\":0,\"intervalSec\":0,\"timePoint\":\"\",\"eventId\":\"\",\"pollResponseTimeout\":1000,\"pollMaxRetries\":2,\"pollInterPollDelay\":100}],\"actions\":[{\"targetPeriphId\":\"oled\",\"actionType\":27,\"actionValue\":\"$value\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0}],\"protocolType\":0,\"reportAfterExec\":true},{\"id\":\"exec_012\",\"name\":\"Platform Controls Relay\",\"enabled\":true,\"execMode\":0,\"triggers\":[{\"triggerType\":0,\"triggerPeriphId\":\"relay\",\"operatorType\":1,\"compareValue\":\"\",\"timerMode\":0,\"intervalSec\":0,\"timePoint\":\"\",\"eventId\":\"\",\"pollResponseTimeout\":1000,\"pollMaxRetries\":2,\"pollInterPollDelay\":100}],\"actions\":[{\"targetPeriphId\":\"relay\",\"actionType\":10,\"actionValue\":\"$value\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0}],\"protocolType\":0,\"reportAfterExec\":true},{\"id\":\"exec_013\",\"name\":\"Platform Controls Buzzer\",\"enabled\":true,\"execMode\":0,\"triggers\":[{\"triggerType\":0,\"triggerPeriphId\":\"buzzer\",\"operatorType\":1,\"compareValue\":\"\",\"timerMode\":0,\"intervalSec\":0,\"timePoint\":\"\",\"eventId\":\"\",\"pollResponseTimeout\":1000,\"pollMaxRetries\":2,\"pollInterPollDelay\":100}],\"actions\":[{\"targetPeriphId\":\"buzzer\",\"actionType\":10,\"actionValue\":\"$value\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0}],\"protocolType\":0,\"reportAfterExec\":true},{\"id\":\"exec_014\",\"name\":\"Platform Controls RGB Effect\",\"enabled\":true,\"execMode\":0,\"triggers\":[{\"triggerType\":0,\"triggerPeriphId\":\"rgb_led\",\"operatorType\":1,\"compareValue\":\"\",\"timerMode\":0,\"intervalSec\":0,\"timePoint\":\"\",\"eventId\":\"\",\"pollResponseTimeout\":1000,\"pollMaxRetries\":2,\"pollInterPollDelay\":100}],\"actions\":[{\"targetPeriphId\":\"rgb_led\",\"actionType\":11,\"actionValue\":\"$value\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0}],\"protocolType\":0,\"reportAfterExec\":true},{\"id\":\"exec_015\",\"name\":\"Platform Controls LED D1-D4\",\"enabled\":true,\"execMode\":0,\"triggers\":[{\"triggerType\":0,\"triggerPeriphId\":\"led_all\",\"operatorType\":1,\"compareValue\":\"\",\"timerMode\":0,\"intervalSec\":0,\"timePoint\":\"\",\"eventId\":\"\",\"pollResponseTimeout\":1000,\"pollMaxRetries\":2,\"pollInterPollDelay\":100}],\"actions\":[{\"targetPeriphId\":\"led_d1\",\"actionType\":10,\"actionValue\":\"$value\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0},{\"targetPeriphId\":\"led_d2\",\"actionType\":10,\"actionValue\":\"$value\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0},{\"targetPeriphId\":\"led_d3\",\"actionType\":10,\"actionValue\":\"$value\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0},{\"targetPeriphId\":\"led_d4\",\"actionType\":10,\"actionValue\":\"$value\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0}],\"protocolType\":0,\"reportAfterExec\":true},{\"id\":\"exec_016\",\"name\":\"IR Key 1 Controls Relay\",\"enabled\":true,\"execMode\":0,\"triggers\":[{\"triggerType\":4,\"triggerPeriphId\":\"ir_recv\",\"operatorType\":0,\"compareValue\":\"NEC:0x00FF30CF\",\"timerMode\":0,\"intervalSec\":0,\"timePoint\":\"\",\"eventId\":\"ir_code_received\",\"pollResponseTimeout\":1000,\"pollMaxRetries\":2,\"pollInterPollDelay\":100}],\"actions\":[{\"targetPeriphId\":\"relay\",\"actionType\":10,\"actionValue\":\"toggle\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0}],\"protocolType\":0,\"reportAfterExec\":true},{\"id\":\"exec_017\",\"name\":\"IR Key 2 Controls Buzzer\",\"enabled\":true,\"execMode\":0,\"triggers\":[{\"triggerType\":4,\"triggerPeriphId\":\"ir_recv\",\"operatorType\":0,\"compareValue\":\"NEC:0x00FF18E7\",\"timerMode\":0,\"intervalSec\":0,\"timePoint\":\"\",\"eventId\":\"ir_code_received\",\"pollResponseTimeout\":1000,\"pollMaxRetries\":2,\"pollInterPollDelay\":100}],\"actions\":[{\"targetPeriphId\":\"buzzer\",\"actionType\":10,\"actionValue\":\"toggle\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0}],\"protocolType\":0,\"reportAfterExec\":true},{\"id\":\"exec_018\",\"name\":\"IR Key 3 Starts RGB Rainbow\",\"enabled\":true,\"execMode\":0,\"triggers\":[{\"triggerType\":4,\"triggerPeriphId\":\"ir_recv\",\"operatorType\":0,\"compareValue\":\"NEC:0x00FF7A85\",\"timerMode\":0,\"intervalSec\":0,\"timePoint\":\"\",\"eventId\":\"ir_code_received\",\"pollResponseTimeout\":1000,\"pollMaxRetries\":2,\"pollInterPollDelay\":100}],\"actions\":[{\"targetPeriphId\":\"rgb_led\",\"actionType\":11,\"actionValue\":\"rainbow\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0}],\"protocolType\":0,\"reportAfterExec\":false},{\"id\":\"exec_019\",\"name\":\"IR Key 0 Turns Off RGB\",\"enabled\":true,\"execMode\":0,\"triggers\":[{\"triggerType\":4,\"triggerPeriphId\":\"ir_recv\",\"operatorType\":0,\"compareValue\":\"NEC:0x00FF6897\",\"timerMode\":0,\"intervalSec\":0,\"timePoint\":\"\",\"eventId\":\"ir_code_received\",\"pollResponseTimeout\":1000,\"pollMaxRetries\":2,\"pollInterPollDelay\":100}],\"actions\":[{\"targetPeriphId\":\"rgb_led\",\"actionType\":11,\"actionValue\":\"off\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0}],\"protocolType\":0,\"reportAfterExec\":false},{\"id\":\"exec_020\",\"name\":\"IR Key 4 Controls LED D1-D4\",\"enabled\":true,\"execMode\":0,\"triggers\":[{\"triggerType\":4,\"triggerPeriphId\":\"ir_recv\",\"operatorType\":0,\"compareValue\":\"NEC:0x00FF10EF\",\"timerMode\":0,\"intervalSec\":0,\"timePoint\":\"\",\"eventId\":\"ir_code_received\",\"pollResponseTimeout\":1000,\"pollMaxRetries\":2,\"pollInterPollDelay\":100}],\"actions\":[{\"targetPeriphId\":\"led_d1\",\"actionType\":10,\"actionValue\":\"toggle\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0},{\"targetPeriphId\":\"led_d2\",\"actionType\":10,\"actionValue\":\"toggle\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0},{\"targetPeriphId\":\"led_d3\",\"actionType\":10,\"actionValue\":\"toggle\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0},{\"targetPeriphId\":\"led_d4\",\"actionType\":10,\"actionValue\":\"toggle\",\"useReceivedValue\":false,\"syncDelayMs\":0,\"execMode\":0}],\"protocolType\":0,\"reportAfterExec\":false}]}"
    }
  ]
}

Notes ​

  1. The OLED only renders ASCII characters — Chinese text pushed from the platform will not show. Separate multiple lines with \n; a line starting with # is centered
  2. Power the OLED from 3.3V, never 5V: this setup was validated with a 0.91-inch 128×32 I2C panel (configured as width:128, height:32, interface:2). The SSD1306 has an internal boost charge pump rated for 3.3V; feeding it 5V can make the module run hot and destroy the panel or charge pump (symptom: a top-bright/bottom-dim gradient, then a fully black screen, and in bad cases only the controller still answers while the panel stays dark). Cut power immediately if it gets hot, then check with a multimeter that VCC/GND are not reversed or plugged into the wrong holes
  3. Top-bright / bottom-dim panel: if the gradient appears even on 3.3V, the charge pump is usually under-powered — lower the contrast field in the peripheral form (config contrast) from 255 to 180-200. If nothing improves and a new panel works on the same wiring, the original module's charge pump/panel is damaged
  4. Changing GPIOs does not fix brightness: SDA/SCL carry signal only, not power. If the I2C write error count stays at 0 in the serial log, the signal path is fine and the problem is the supply or the module itself
  5. Buzzer rule interaction: the buzzer is a PWM peripheral, and toggle switches between duty 0 and full duty. While temperature ≤ 28°C, exec_004 forces the duty to 0 after every sample, so a buzzer switched on manually with KEY2 survives at most one sampling cycle. Disable exec_004 on the page if you want purely manual control
  6. The buzzer must be driven by PWM: the onboard buzzer of the Puzhong board is passive — configured as a digital output (type 12) it only clicks or stays silent. Configure it as a PWM output (type 17); 2700Hz is recommended
  7. LEDs are active low: the platform value 0 = on, 1 = off; the toggle used by buttons is unaffected
  8. Number of RGB pixels: the config uses count: 5 per the experiment; change it to count: 4 when using the 4-pixel RGB module on the Puzhong board
  9. The minimum interval for timer/polling rules is 5 seconds; the high-temperature alarm uses a ds: data-source event and is not subject to that limit — it is evaluated after each sample. DHT11 readings are cached for 2 seconds inside the firmware, so repeated reads are not a concern
  10. led_all is a virtual thing-model identifier, it maps to no real peripheral and only exists so the platform can control the 4 LEDs at once
  11. No LED or peripheral occupies the GPIO0/2/15 strapping pins, so nothing has to be unplugged when flashing firmware
  12. Unwired button pins may trigger by accident: button pins have internal pull-ups, but a floating pin can still pick up noise and generate spurious events. If you leave a button unwired, temporarily disable the matching rule or the button peripheral on the page
  13. IR remote requires firmware support: FASTBEE_ENABLE_IR_REMOTE=1 must be compiled and irRemote must be active (the esp32-F4R0 release environment compiles the driver)
  14. Switching remotes: the default rules match the NEC codes of the bundled Puzhong remote. For another remote model, re-pair in the IR Management panel (key names key0-key4) and change the rules' compareValue to key:<name> (or update them to the new codes one by one). Pairing, deleting a key and clearing the library are write operations that require Developer Mode. The library holds at most 40 keys; delete one before adding another once full
  15. When no code is captured: check that the receiver OUT goes to GPIO35 and VCC to 3.3V (reversing them yields no output); press briefly within 20cm facing the receiver; click Start Learning again after a timeout. You can also inspect System Logs for the raw decode result (e.g., [IR] Received: NEC value=0x00FF30CF bits=32) to confirm the hardware path
ResourceAddress
FastBee platform sourcegitee.com/beecue/fastbee
FastBee mobile sourcegitee.com/beecue/fastbee-app
Button control exampleButton Input Detection
TM1637 temperature exampleDisplay Temperature on 7-Segment
OLED temperature exampleDisplay Temperature on OLED

FastBee | fastbee.cn