Home Assistant and ESPHome devices

Five ESP32-C3 devices for Home Assistant, the Arduino code they run in Mokxi, and the ESPHome YAML you would flash at home.

Mokxi has five templates for the devices people build first for a smart home: a room multisensor, a radar hallway sensor, a garage door opener, an LED strip controller and a plant sensor. Each one runs on a simulated ESP32-C3, and the Home Assistant devices course walks through all five.

What is simulated, and what is not

Mokxi runs Arduino sketches, not ESPHome. ESPHome turns a YAML file into firmware and talks to Home Assistant over its native API. Mokxi cannot compile YAML, so each template does by hand, in an Arduino sketch, what the ESPHome components would do. The YAML below is reference for when you move to real hardware, and reading it next to the sketch is a good way to learn what each component does underneath.

The network is simulated, and there is no MQTT broker. The board joins a simulated access point and serves pages to the Web tab (Simulated WiFi). Nothing reaches your real network or a real Home Assistant. Each sketch prints the topic and payload it would publish, one line per message, such as publish home/multisensor/temperature 21.5, and serves its state as JSON at /state, which is the shape Home Assistant's RESTful sensor could poll on a real network.

The multisensor

A DHT22 for temperature and humidity on GPIO 3, a BH1750 light sensor on I2C (GPIO 4 and 5) and a PIR on GPIO 18. The sensors that talk to the board's pins run from 3.3 V; the PIR needs 5 V to run and outputs 3.3 V. Motion is published the moment it changes, the climate every ten seconds.

i2c:
  sda: GPIO4
  scl: GPIO5
sensor:
  - platform: dht
    pin: GPIO3
    model: DHT22
    temperature:
      name: "Temperature"
    humidity:
      name: "Humidity"
    update_interval: 10s
  - platform: bh1750
    name: "Illuminance"
binary_sensor:
  - platform: gpio
    pin: GPIO18
    name: "Motion"
    device_class: motion

The radar hallway sensor

An RCWL-0516 on GPIO 18, an LDR light module on GPIO 0 and a lamp LED on GPIO 19. The RCWL-0516 is not an mmWave presence sensor. It is a microwave Doppler board that sees movement, through plastic and thin walls too. The 24 GHz mmWave boards sold for true presence, such as the LD2410, also sense someone sitting still and talk over UART; Mokxi does not model them. The sketch holds the hallway occupied for ten seconds after the last movement, and switches the light on only when it is dark, on the device itself.

binary_sensor:
  - platform: gpio
    pin: GPIO18
    name: "Hallway occupancy"
    device_class: occupancy
    filters:
      - delayed_off: 10s

The garage door opener

A relay on GPIO 18 wired across the opener's wall button, two reed switches on GPIO 3 (closed) and GPIO 2 (open), and a local button on GPIO 9. The relay closes for half a second, as a finger on the button would, and the reed switches report where the door really is.

Safety. Connect only to the opener's low-voltage wall-button terminals, never to mains or to the motor. The relay must boot off and never stay on. Never bypass the photo-eyes or the obstruction reversal, test the reversal after installing, and only trigger the door remotely when the opener's own safety features are working.

switch:
  - platform: gpio
    pin: GPIO18
    id: door_relay
    restore_mode: ALWAYS_OFF
    on_turn_on:
      - delay: 500ms
      - switch.turn_off: door_relay
binary_sensor:
  - platform: gpio
    pin: { number: GPIO3, inverted: true, mode: INPUT_PULLUP }
    id: door_closed
  - platform: gpio
    pin: { number: GPIO2, inverted: true, mode: INPUT_PULLUP }
    id: door_open
cover:
  - platform: template
    name: "Garage door"
    device_class: garage
    lambda: |-
      if (id(door_closed).state) return COVER_CLOSED;
      if (id(door_open).state) return COVER_OPEN;
      return {};
    open_action:
      - switch.turn_on: door_relay
    close_action:
      - switch.turn_on: door_relay

The LED strip controller

Sixteen WS2812B pixels on GPIO 18, a power button on GPIO 9, an effect button on GPIO 10 and a brightness knob on GPIO 0. Every change fades over about half a second, and /set in the Web tab takes the state, brightness, color and effect. For a real strip, use its own 5 V supply sized for it, inject power along long runs, share the ground with the board, put a level shifter on the data line and a fuse near the supply.

light:
  - platform: esp32_rmt_led_strip
    pin: GPIO18
    num_leds: 16
    chipset: WS2812
    rgb_order: GRB
    name: "Strip"
    default_transition_length: 600ms
    effects:
      - addressable_rainbow:

The plant sensor

A capacitive soil sensor on GPIO 3, an LDR light module on GPIO 4 and a red LED on GPIO 19 that lights while the plant is thirsty. Wetter soil reads lower, and two calibration readings, the stake in dry air and in water, map everything between them to 0 to 100 percent. It is a sensor only, with no pump.

sensor:
  - platform: adc
    pin: GPIO3
    name: "Soil moisture"
    unit_of_measurement: "%"
    attenuation: 12db
    filters:
      - median:
          window_size: 5
      - calibrate_linear:
          - 2.55 -> 0.0
          - 1.27 -> 100.0

Where to go next

Open the templates from /templates, take the course from /learn, or read the guide at /learn/home-assistant-esphome-devices.