########################################################################################## ########################################################################################## # HiLink LD2410 mmWave sensor, with BME280 Temp/Hum/Pres Sensor and PIR on an ESP32 # VERSION # V2.1 2025-08-25 Added some MQTT to send commands to turn on remote lights # V2.0 2025-06-05 YAML Tidyups # # https://github.com/patrick3399/Hi-Link_mmWave_Radar_ESPHome/tree/main # https://github.com/patrick3399/Hi-Link_mmWave_Radar_ESPHome/blob/main/LD1125H/ESP32-LD1125H-Complete.yaml # # https://esphome.io/components/sensor/ld2410.html # https://www.simplysmart.house/blog/presence-detection-ld2410-home-assistant # # The B and C versions of this device can use Bluetooth, but we are not using it here. ########################################################################################## ########################################################################################## ########################################################################################## # SPECIFIC DEVICE VARIABLE SUBSTITUTIONS # If NOT using a secrets file, just replace these with the passwords etc (in quotes) ########################################################################################## substitutions: # Device Naming device_name: "esp-occupancystair" friendly_name: "Stair Occupancy and Underhouse Environment" description_comment: "D1 Mini ESP32 with LD2410 mmWave for internal stairwell and environment sensors for under house" device_area: "Underhouse" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming project_name: "Generic.ESP32" # Project Details project_version: "v2.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version # Passwords & Secrets (unfortunately you can't use substitutions inside secrets names) api_key: !secret esp-api_key ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-occupancystair_ip mqtt_command_main_topic: !secret mqtt_command_main_topic mqtt_status_main_topic: !secret mqtt_status_main_topic # Device Settings #relay_icon: "mdi:lightbulb-group" log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE update_interval: "60s" # update time for for general sensors etc # MQTT REMOTE Controls mqtt_remote_device1_name: "stair-footerlights" mqtt_remote_device1_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device1_name}/set" #mqtt_remote_device1_status_topic: "${mqtt_status_main_topic}/${mqtt_remote_device1_name}/state" mqtt_remote_device_command_ON: "ON" mqtt_remote_device_command_OFF: "OFF" ######################################################################################### # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html ########################################################################################## packages: common_wifi: !include file: common/network_common.yaml vars: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" common_api: !include file: common/api_common.yaml vars: local_api_key: "${api_key}" #common_webportal: !include # file: common/webportal_common.yaml common_mqtt: !include file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" common_sntp: !include file: common/sntp_common.yaml common_general_sensors: !include file: common/sensors_common.yaml vars: local_friendly_name: "${friendly_name}" local_update_interval: "${update_interval}" ########################################################################################## # ESPHome CORE CONFIGURATION # https://esphome.io/components/esphome.html ########################################################################################## esphome: name: "${device_name}" friendly_name: "${friendly_name}" comment: "${description_comment}" # appears on the esphome page in HA min_version: 2024.6.0 area: "${device_area}" #on_boot: # Initial Setting, will remember previous values (if set) #priority: -200 #then: ########################################################################################## # ESP PLATFORM AND FRAMEWORK # https://esphome.io/components/esp8266.html # https://esphome.io/components/esp32.html ########################################################################################## esp32: board: esp32dev framework: type: esp-idf # "esp-idf" OR "arduino". Suggested ESP-IDF Framework, or Plug Out the UART Cable Might Cause ESP32 Hang. version: recommended # recommended, latest or dev ########################################################################################## # GLOBAL VARIABLES # https://esphome.io/components/globals.html ########################################################################################## globals: - id: stair_footer_auto_default_s type: int restore_value: yes initial_value: '20' ########################################################################################## # i2c BUS COMPONENT # https://esphome.io/components/i2c.html ########################################################################################## i2c: sda: GPIO19 scl: GPIO21 scan: True frequency: 100kHz #10, 50, 100, 200, 800 are possible settings, 100kHz was reliable for me ########################################################################################## # LOGGER COMPONENT # https://esphome.io/components/logger.html # Logs all log messages through the serial port and through MQTT topics. ########################################################################################## logger: level: INFO # INFO Level suggested, or DEBUG for testing baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 ########################################################################################## # BLUETOOTH # Proxy https://esphome.io/components/bluetooth_proxy.html # BLE https://esphome.io/components/esp32_ble_tracker.html # Remember that this takes a LOT of processing. On the # ESP32, enable the IDF framework, and disable the # Web server component. Changing to the IDF framework # needs to be via cable not OTA to change the # partition setup. ########################################################################################## #bluetooth_proxy: #esp32_ble_tracker: ########################################################################################## # UART BUS # hardware on EPS32, but software (and can be glitchy) on ESP8266 # https://esphome.io/components/uart.html ########################################################################################## uart: id: ld2410_uart rx_pin: GPIO16 #For ESP32, you can use any pin, Recommend Use UART_2, Don't use UART_0, It might Cause Boot Fail or System Hang tx_pin: GPIO17 #For ESP32, you can use any pin, Recommend Use UART_2, Don't use UART_0, It might Cause Boot Fail or System Hang baud_rate: 256000 # default for LD2410 is 25600, 8, 0, NONE data_bits: 8 stop_bits: 1 parity: NONE ######################################################################################### # STATUS LED # https://esphome.io/components/status_led.html ######################################################################################### # ESP32 D1 Mini Board: Onboard Status LED on GPIO2, active-low ######################################################################################### status_led: pin: number: GPIO2 # ESP32 Onboard LED ignore_strapping_warning: True #https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins inverted: false ########################################################################################## # LD2410 Sensors # https://esphome.io/components/sensor/ld2410.html # https://www.hlktech.net/index.php?id=988 ########################################################################################## ld2410: uart_id: ld2410_uart #uart_id (Optional, ID): Manually specify the ID of the UART Component if you want to use multiple UART buses. #throttle (Optional, int): Time in milliseconds to control the rate of data updates. Defaults to 1000ms. #id (Optional, ID): Manually specify the ID for this LD2410 Sensor component if you need multiple components. # light (Optional, int): When in engineering mode, indicates the light sensitivity, otherwise unknown. Value between 0 and 255 inclusive. Though it seems that the value 85 is the lowest value at complete darkness. All options from Sensor. # moving_distance (Optional, int): Distance in cm of detected moving target. All options from Sensor. # still_distance (Optional, int): Distance in cm of detected still target. All options from Sensor. # moving_energy (Optional, int): Energy for moving target. Value between 0 and 100 inclusive. All options from Sensor. # still_energy (Optional, int): Energy for still target. Value between 0 and 100 inclusive. All options from Sensor. # detection_distance (Optional, int): Distance in cm of target. All options from Sensor. # gX (Optional): Energies for the Xth gate (X => 0 to 8). # move_energy (Optional, int): When in engineering mode, the move energy of the gate, otherwise unknown. Value between 0 and 100 inclusive. All options from Sensor. #still_energy (Optional, int): When in engineering mode, the still energy of the gate, otherwise unknown. Value between 0 and 100 inclusive. All options from Sensor. #ld2410_id (Optional, ID): Manually specify the ID for the LD2410 Sensor component if you are using multiple components. ########################################################################################## # NUMBER COMPONENT # https://esphome.io/components/number/ ########################################################################################## #The ld2410 number values for setting thresholds # timeout: 5s # max_move_distance: 2.25m # max_still_distance: 2.25m # g0_move_threshold: 40 # 0m / 0' # g0_still_threshold: 10 # 0m / 0' # g1_move_threshold: 40 # 0 - 0.75m / 0 - 2.46' # g1_still_threshold: 10 # 0 - 0.75m / 0 - 2.46' # g2_move_threshold: 40 # 0.75 - 1.5m / 2.46' - 4.92' # g2_still_threshold: 10 # 0.75 - 1.5m / 2.46' - 4.92' # g3_move_threshold: 40 # 1.5 - 2.25m / 4.92' - 7.38' # g3_still_threshold: 10 # 1.5 - 2.25m / 4.92' - 7.38' # g4_move_threshold: 40 # 2.25 - 3m' / 7.38' - 9.84' # g4_still_threshold: 40 # 2.25 - 3m' / 7.38' - 9.84' # g5_move_threshold: 40 # 3 - 3.75 / 9.84' - 12.30' # g5_still_threshold: 40 # 3 - 3.75 / 9.84' - 12.30' # g6_move_threshold: 30 # 3.75 - 4.5m / 12.30' - 14.76' # g6_still_threshold: 15 # 3.75 - 4.5m / 12.30' - 14.76' # g7_move_threshold: 30 # 4.5 - 5.25m / 14.76' - 17.22' # g7_still_threshold: 15 # 4.5 - 5.25m / 14.76' - 17.22' # g8_move_threshold: 30 # 5.25 - 6m / 17.22' - 19.68' # g8_still_threshold: 15 # 5.25 - 6m / 17.22' - 19.68' number: - platform: ld2410 timeout: name: "Timeout" light_threshold: name: "Light Threshold" max_move_distance_gate: name: "Max Move Distance Gate" max_still_distance_gate: name: "Max Still Distance Gate" g0: move_threshold: name: "g0 move threshold" still_threshold: name: "g0 still threshold" g1: move_threshold: name: "g1 move threshold" still_threshold: name: "g1 still threshold" g2: move_threshold: name: "g2 move threshold" still_threshold: name: "g2 still threshold" g3: move_threshold: name: "g3 move threshold" still_threshold: name: "g3 still threshold" g4: move_threshold: name: "g4 move threshold" still_threshold: name: "g4 still threshold" g5: move_threshold: name: "g5 move threshold" still_threshold: name: "g5 still threshold" g6: move_threshold: name: "g6 move threshold" still_threshold: name: "g6 still threshold" g7: move_threshold: name: "g7 move threshold" still_threshold: name: "g7 still threshold" g8: move_threshold: name: "g8 move threshold" still_threshold: name: "g8 still threshold" - platform: template id: stair_footer_auto_time_s name: "Stair Footer Lights Auto Time" unit_of_measurement: s min_value: 10 max_value: 300 step: 1 optimistic: true restore_value: true initial_value: 20 ######################################################################################### # SELECT COMPONENT # https://esphome.io/components/select/index.html ######################################################################################### # LD2410 SELECT # distance_resolution (Optional): Control the gates distance resolution. Can be 0.75m or 0.2m. # Defaults to 0.75m. All options from Select. # baud_rate (Optional): Control the serial port baud rate. Defaults to 256000. Once changed, # all sensors will stop working until a fresh install with an updated UART Component # configuration. All options from Select. # light_function (Optional): If set, will affect the OUT pin value, based on light # threshold. Can be off, low or above. Defaults to off. All options from Select. # out_pin_level (Optional): Control OUT pin away value. Can be low or high. Defaults # to low. All options from Select. # ld2410_id (Optional, ID): Manually specify the ID for the LD2410 Sensor component # if you are using multiple components. ######################################################################################### select: - platform: ld2410 distance_resolution: name: "${friendly_name} LD2140 Distance Resolution" baud_rate: name: "${friendly_name} LD2140 Baud Rate" light_function: name: "${friendly_name} LD2140 Light Function" out_pin_level: name: "${friendly_name} LD2140 Out Pin Level" ########################################################################################## # SENSOR COMPONENT # https://esphome.io/components/sensor/ ########################################################################################## sensor: - platform: bme280_i2c temperature: name: "Temperature" accuracy_decimals: 1 oversampling: 2x pressure: name: "Pressure" oversampling: 2x humidity: name: "Humidity" accuracy_decimals: 1 oversampling: 2x address: 0x76 update_interval: "${update_interval}" # The ld2410 sensor values # https://esphome.io/components/sensor/ld2410/#sensor - platform: ld2410 light: name: "Light" moving_distance: name: "Moving Distance" still_distance: name: "Still Distance" moving_energy: name: "Move Energy" still_energy: name: "Still Energy" detection_distance: name: "Detection Distance" g0: move_energy: name: "g0 move energy" still_energy: name: "g0 still energy" g1: move_energy: name: "g1 move energy" still_energy: name: "g1 still energy" g2: move_energy: name: "g2 move energy" still_energy: name: "g2 still energy" g3: move_energy: name: "g3 move energy" still_energy: name: "g3 still energy" g4: move_energy: name: "g4 move energy" still_energy: name: "g4 still energy" g5: move_energy: name: "g5 move energy" still_energy: name: "g5 still energy" g6: move_energy: name: "g6 move energy" still_energy: name: "g6 still energy" g7: move_energy: name: "g7 move energy" still_energy: name: "g7 still energy" g8: move_energy: name: "g8 move energy" still_energy: name: "g8 still energy" ########################################################################################## # SWITCH COMPONENT # https://esphome.io/components/switch/ ########################################################################################## # The ld2410 switch allows you to control your LD2410 Sensor. # Bluetooth switch is only useful of you have a B or C model ########################################################################################## switch: # https://esphome.io/components/sensor/ld2410/#switch - platform: ld2410 engineering_mode: name: "${friendly_name} LD2140 Engineering Mode" #bluetooth: #name: "${friendly_name} LD2140 Control Bluetooth" - platform: template id: stair_footer_auto_enabled name: "Stair Footer Lights Auto" optimistic: true restore_mode: RESTORE_DEFAULT_ON ######################################################################################### # BINARY SENSORS # https://esphome.io/components/binary_sensor/ ######################################################################################### binary_sensor: # The ld2410 binary sensors to get presence notification # https://esphome.io/components/sensor/ld2410/#binary-sensor - platform: ld2410 has_target: name: "mmWave Presence" on_press: - if: condition: switch.is_on: stair_footer_auto_enabled then: - script.execute: stair_footer_auto_script has_moving_target: name: "mmWave Moving Target" on_press: - if: condition: switch.is_on: stair_footer_auto_enabled then: - script.execute: stair_footer_auto_script has_still_target: name: "mmWave Still Target" out_pin_presence_status: name: "LD2140 Out Pin Presence Status" entity_category: diagnostic # Generic PIR Sensor # https://devices.esphome.io/devices/Generic-PIR - platform: gpio pin: number: GPIO13 mode: input: true pullup: true inverted: true name: "PIR Sensor" device_class: motion filters: - delayed_on: 50ms on_press: - if: condition: switch.is_on: stair_footer_auto_enabled then: - script.execute: stair_footer_auto_script ################################################################################################# # BUTTON COMPONENT # https://esphome.io/components/button/index.html ################################################################################################# # The ld2410 button allows resetting ################################################################################################# button: - platform: ld2410 factory_reset: name: "${friendly_name} LD2140 Factory reset" restart: name: "${friendly_name} LD2140 Restart" query_params: name: "Query Parameters" ################################################################################################# # TEXT SENSOR COMPONENT # https://esphome.io/components/text_sensor/ ################################################################################################# text_sensor: # The ld2410 text sensor allows you to get information about your LD2410 Sensor. # Bluetooth sensor is only useful of you have a B or C model # https://esphome.io/components/sensor/ld2410/#text-sensor - platform: ld2410 version: name: "${friendly_name} LD2140 Firmware Version" #mac_address: #name: "${friendly_name} LD2140 BT MAC Address" ########################################################################################## # SCRIPT COMPONENT # https://esphome.io/components/script.html # Scripts can be executed nearly anywhere in your device configuration with a single call. ########################################################################################## script: # Sends commands to turn on and off a remote light - id: stair_footer_auto_script mode: restart then: # Turn lights on (command the Top switch's footer relay) - mqtt.publish: topic: "${mqtt_remote_device1_command_topic}" payload: "${mqtt_remote_device_command_ON}" retain: false # Wait for the HA-adjustable timeout - delay: !lambda 'return (uint32_t)(id(stair_footer_auto_time_s).state) * 1000;' # Turn lights back off - mqtt.publish: topic: "${mqtt_remote_device1_command_topic}" payload: "${mqtt_remote_device_command_OFF}" retain: false