Yazan Daradkeh

Senior Digital Project/Product Manager

Building the Ultimate Smart Room Node with ESP32 & ESPHome

Building the Ultimate Smart Room Node with ESP32 & ESPHome


G'day, makers and home automation fans! Today I'm sharing a little project I've been working on: a fully loaded multisensor built around the legendary ESP32 and powered by ESPHome. If you want to make your smart home truly "smart," local sensors are the way to go, and this little board packs a massive punch!

For this build, I wanted to create a single node that could monitor the climate, detect motion, track light levels, and even act as a Bluetooth proxy for my home network. Here is the hardware lineup I used:

The Brains: An ESP32 dev board running the ESP-IDF framework. It's powerful, reliable, and handles Wi-Fi/Bluetooth like an absolute champ.

Climate Control (BME280): Hooked up via I2C, this gives me ultra-precise Temperature, Humidity, and Pressure readings.

Motion Detection (HC-SR501): A classic PIR sensor to trigger automations the second someone walks into the room.

Custom Light Sensing (LDR): An analog light-dependent resistor to measure ambient light in volts, complete with a sliding window moving average filter to smooth out the readings.

One of my absolute favorite parts of this configuration is the custom logic for the light sensor. Instead of just relying on raw voltage drops, I created a custom template number component. This lets me adjust the "Light Threshold" dynamically from my dashboard! The board then uses a template binary sensor to calculate if the light is "on" or "off" based on that live threshold, with a 2-second delay to prevent annoying flickering.

Oh, and because the ESP32 has the extra horsepower, I enabled the bluetooth_proxy feature. This means the node is actively extending my Bluetooth range, picking up BLE devices from across the house without breaking a sweat!

Here is the full ESPHome YAML configuration so you can build your own. Check out the clean YAML structure, especially how the Wi-Fi secrets and static IPs are organized:

YAML

esphome:

  name: br-esp32

  friendly_name: BR ESP32

esp32:

  board: esp32dev

  framework:

    type: esp-idf

# Enable logging

logger:

  level: WARN

# Enable Home Assistant API

api:

  encryption:

    key: "mj2jSrdGC25OoEt6VNcMgfTU+Be0eVuG6Kc9i2eLFPU="

ota:

  - platform: esphome

    password: "17236dc7a7dd96ab92822407cb142c4e"

wifi:

  # This 'networks:' key is the fix.

  # It holds the list of networks to connect to.

  networks:

    - ssid: !secret wifi_ssid

      password: !secret wifi_password

      hidden: true

      manual_ip:

        static_ip: 192.168.3.162

        gateway: 192.168.3.1

        subnet: 255.255.255.0

  # 'ap:' is now at the same level as 'networks:',

  # which is valid YAML.

  ap:

    ssid: "BR ESP32"

    password: "2vsPcQNqWFt9"

mqtt:

  broker: !secret mqtt

  username: !secret mqtt_user

  password: !secret mqtt_password

# Enable Bluetooth

esp32_ble_tracker:

  scan_parameters:

    active: true

bluetooth_proxy:

  active: true

captive_portal:

# ---------------- I2C BUS ----------------

i2c:

  sda: GPIO21

  scl: GPIO22

  scan: true

  id: bus_a

sensor:

    # ---------- BME280 ----------

  - platform: bme280_i2c

    i2c_id: bus_a

    address: 0x76

    update_interval: 10s

    temperature:

      name: "BR Temperature H"

      id: bme280_temp

      oversampling: 16x

    pressure:

      name: "BR Pressure H"

      id: bme280_pressure

    humidity:

      name: "BR Humidity H"

      id: bme280_humidity

  # ---------- LDR on ADC ----------

  - platform: adc

    pin: GPIO36

    id: light_level_v

    name: "BR Light Level H"

    unit_of_measurement: "V"

    icon: "mdi:sun-wireless"

    accuracy_decimals: 3

    update_interval: 1s

    filters:

      - sliding_window_moving_average:

          window_size: 6

          send_every: 1

# ---------------- NUMBER (Single Threshold) ----------------

number:

  - platform: template

    id: light_threshold_v

    name: "BR Light Threshold H"

    optimistic: true

    restore_value: true

    initial_value: 0.60

    step: 0.01

    min_value: 0.05

    max_value: 2.50

# ---------------- BINARY SENSORS ----------------

binary_sensor:

  # Motion Sensor (HC-SR501)

  - platform: gpio

    pin:

      number: GPIO19

      mode: INPUT_PULLDOWN  # This line is the fix

    name: "BR Motion H"

    device_class: motion

  # Simple light detection

  - platform: template

    name: "BR Light Detected H"

    device_class: light

    lambda: |-

      // If the current voltage is greater than the threshold, light is detected (return true).

      return id(light_level_v).state < id(light_threshold_v).state;

    filters:

      # These prevent the light from flickering rapidly if the voltage is hovering

      # right at the threshold.

      - delayed_on: 2s

      - delayed_off: 2s

Have you guys tried combining analog LDRs with template thresholds in ESPHome before? It saves hardcoding values and makes tweaking a breeze! Let me know what you'd add to this board in the comments. Cheers! 🍻



"If you've got any questions or need a hand wrangling your own setup, don't hesitate to reach out at [email protected] or connect with me via www.yazan.me. I'm always keen to help out!"