SmartHome P4
A local smart-home controller on a 1024×600 touch panel. Up to 15 rooms and 64 devices, relays and discrete inputs over RS-485/Modbus, scenes, schedules and automation rules, MQTT / Home Assistant / IR transports — everything is configured on-screen, stored in NVS and runs without the cloud.
A local hub for the home
The firmware is independent from the weather station and GreenHouse P4. On boot app_main turns the backlight off (so no blue MIPI-DSI frame flashes after a reboot or OTA), then brings up storage, time, networking and the automation core in sequence, and only then draws the interface.
All logic runs locally
Relays, inputs, scenes, schedules and rules run on the controller itself. Wi-Fi and MQTT are optional — the home keeps working without the internet.
Configuration in NVS
Rooms, devices, scenes and rules are stored as a single blob (magic 0x53485034, version 4). Wi-Fi and MQTT settings live in their own NVS namespaces.
Safe state
Output state is deliberately never written to flash: after a reboot the configured “safe” position is always restored, never an accidentally latched output.
Manual timeout
A device switched on by hand can turn itself off after a set interval — handy for lights, ventilation and gates.
Compute, memory and display
A JC1060P470C / JC-ESP32P4-M3 class board: ESP32-P4 as the main SoC and ESP32-C6 as the Wi-Fi 6 radio, connected over ESP-Hosted (SDIO 40 MHz, the single-port Wi-Fi Remote path).
| Unit | Value | Note |
|---|---|---|
| SoC | ESP32-P4 rev 1.3 | 2×RISC-V @ 360 MHz, 256 KB L2 cache |
| Radio | ESP32-C6 | Wi-Fi 6 / BLE, ESP-Hosted SDIO 40 MHz |
| PSRAM | 32 MB | HEX mode, 200 MHz |
| Flash | 16 MB (Boya) | DIO, 40 MHz |
| Display | 1024×600 | MIPI-DSI, JD9165 panel |
| Touch | Capacitive | on the I²C bus (GPIO7/8) |
| Console | USB Serial/JTAG | log and flashing, port COM10 |
Interfaces and buses
Peripherals are split across three buses: a shared I²C (touch + climate sensors), an isolated RS-485 for the power side, and the board’s service interfaces (audio, microSD).
I²C GPIO7 / GPIO8
- Touchscreen of the display
- SHT45 — temperature, humidity
- SCD41 — CO₂
- BH1750 — illuminance
- 100 kHz, internal pull-ups
RS-485 UART3 · GPIO26/27
- Isolated connector
- Modbus-RTU, 9600 8N1
- 2×8-channel relays (addresses 1/2)
- Reads discrete inputs
Audio I²S ES8311 / ES7210
- MCLK 13, SCLK 12
- WS 10, DOUT 9, DIN 48
- Power-amp EN GPIO11
microSD SDIO 4-bit
- CLK 43, CMD 44
- D0–D3 39–42
- FatFS
Full GPIO map
Every pin used by the firmware and the board BSP.
| Unit | Signal | GPIO | Type | Note |
|---|---|---|---|---|
| Display | MIPI-DSI data/clock | DSI | MIPI-DSI | JD9165 panel, 1024×600 |
| Display | Backlight (BL) | 23 | LEDC/GPIO | Turned off first in app_main |
| Display | Reset (RST) | 0 | GPIO | Panel reset |
| I²C | SDA | 7 | I²C0 | Touch + sensors, 100 kHz |
| I²C | SCL | 8 | I²C0 | SHT45 / SCD41 / BH1750 |
| RS-485 | UART3 TX | 26 | RS-485 | Isolated, 9600 8N1 |
| RS-485 | UART3 RX | 27 | RS-485 | Modbus-RTU relays and inputs |
| Audio | I²S MCLK / SCLK | 13/12 | I²S | ES8311 / ES7210 codec |
| Audio | WS / DOUT / DIN | 10/9/48 | I²S | — |
| Audio | Power-amp EN | 11 | GPIO | Amplifier enable |
| microSD | CLK / CMD | 43/44 | SDIO | FatFS |
| microSD | D0–D3 | 39-42 | SDIO | 4-bit mode |
| Service | GPS UART1 (reserved) | 37/38 | UART | Reserved, unused in SmartHome |
Power peripherals over Modbus-RTU
On the isolated UART3 bus (9600 8N1) the firmware drives up to two 8-channel Waveshare relay modules at addresses 1 and 2 — 16 relays total — and reads their discrete inputs.
Relay control · function 0x05
Single-coil write: channels 0–7 → module 1, 8–15 → module 2, coil number = channel % 8. The command is confirmed by the module’s echo reply. Bus access is serialised with a mutex.
Input read · function 0x02
Every second the 8 discrete inputs of each module are polled. Devices with the “RS485 Input” transport mirror the input state — float switch, leak, reed contact.
| Transport | Purpose | Addressing |
|---|---|---|
| RS485 Relay | Relay output | channel 0–15 |
| RS485 Input | Discrete input | channel 0–15 |
| Modbus | Generic Modbus device | address |
| I²C / 1-Wire | Local sensors | address / channel |
| MQTT | Publishes ON/OFF to a command topic | topic |
| Home Assistant | MQTT + subscribes to a state topic | topic |
| IR | IR remote | channel |
Built-in I²C bus
A dedicated task polls three sensors on the shared GPIO7/8 bus every 5 seconds with CRC checking. Each sensor’s presence is detected automatically.
SHT45 0x44
- Temperature −45…+130 °C
- Humidity relative
- High-precision command 0xFD
SCD41 0x62
- CO₂, ppm
- Periodic measurement
- Read on data-ready
BH1750 0x23
- Illuminance, lux
- Continuous high-resolution mode
- Divide by 1.2
Data model and execution rules
Each device is described by a type, transport and address; it also carries a safe state, manual timeout, automation flag, schedule and MQTT topics. Twelve device types: relay, switch, light, thermostat, curtain, ventilation, garage door, intercom, IR remote, sensor, external.
start–end window (in minutes, wrapping past midnight). Inert until time is synced over SNTP.manual_timeout_ms.16 rules.16 scenes.ON/OFF/OPEN/CLOSED/1/0 on a device’s state topic.pool.ntp.org and time.cloudflare.com, refreshed hourly.Interface — 6 pages
Dark theme, #71C9FF accent, instant RU/EN switching (via the button in the top-right corner; since 0.22 the language choice is saved to NVS and restored after a reboot), an SNTP clock and an on-screen keyboard for renaming. The panel below reproduces the real layout and colours of the firmware — tap the tabs at the bottom.
Flash, OTA and flashing
The 16 MB flash is laid out for OTA A/B: two ~6.1 MB app slots, a SPIFFS storage area and a coredump partition for diagnostics.
| Partition | Type | Offset | Size |
|---|---|---|---|
| nvs | data / nvs | 0x00C000 | 24 KB |
| otadata | data / ota | 0x012000 | 8 KB |
| phy_init | data / phy | 0x014000 | 4 KB |
| ota_0 | app | 0x020000 | 6.1 MB |
| ota_1 | app | 0x640000 | 6.1 MB |
| storage | data / spiffs | 0xC60000 | 3 MB |
| coredump | data / coredump | 0xF60000 | 640 KB |
python -m esptool --chip esp32p4 -b 460800 --before default_reset --after hard_reset write_flash 0x0 SmartHome_P4_MERGED_v0.22_20260731.bin
