substitutions:
  # Change device name to match your desired name
  device_name: "ld2411s"
  # Change sensor name below to the one you want to be exposed in Home Assistant
  device_name_pretty: LD2411S Test
  # UART TX Pin
  uart_tx_pin: GPIO21
  # UART RX Pin
  uart_rx_pin: GPIO22

esp32:
  board: firebeetle32
  framework:
    type: arduino

esphome:
  name: $device_name
  includes:
    - LD2411s.h
  platformio_options:
    board_upload.flash_size: 4MB
  on_boot:
    priority: 250
    then:
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xFF, 0x00, 0x01, 0x00, 0x04, 0x03, 0x02, 0x01]
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x02, 0x00, 0x73, 0x00, 0x04, 0x03, 0x02, 0x01]
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xFE, 0x00, 0x01, 0x00, 0x04, 0x03, 0x02, 0x01]

# Enable logging
logger:
  logs:
    sensor: INFO # reduced logging to minimize web_server target overload..

web_server:
  port: 80
  version: 2
  include_internal: true

http_request:
  useragent: esphome/$device_name
  timeout: 2s
  
uart:
  id: uart_bus
  tx_pin: ${uart_tx_pin}
  rx_pin: ${uart_rx_pin}
  baud_rate: 256000
  parity: NONE
  stop_bits: 1

sensor:
  - platform: custom
    lambda: |-
      auto my_sensor = new UARTSensor(id(uart_bus)); 
      App.register_component(my_sensor);
      return {my_sensor->distance_sensor, my_sensor->presence_sensor, my_sensor->motion_sensor, my_sensor->max_motion_sensor, my_sensor->min_motion_sensor, my_sensor->max_presence_sensor, my_sensor->min_presence_sensor, my_sensor->unocc_time_sensor};
    sensors:
      - name: "${device_name} Distance"
        state_class: measurement
        id: distance_sensor
        unit_of_measurement: cm
      - id: presence_sensor
        name: "internal_presense_sensor_to_binary_template"
        internal: true
        on_value:
          - binary_sensor.template.publish:
              id: presence_template
              state: !lambda return x > 0;
      - id: motion_sensor
        name: "internal_motion_sensor_to_binary_template"
        internal: true
        on_value:
          - binary_sensor.template.publish:
              id: motion_template
              state: !lambda return x > 0;
      - name: "internal_max_motion"
        id: max_motion_sensor
        internal: true
        on_value:
          - number.set:
              id: maxmotion
              value: !lambda return x;
      - name: "internal_min_motion"
        id: min_motion_sensor
        internal: true
        on_value:
          - number.set:
              id: minmotion
              value: !lambda return x;
      - name: "internal_max_presence"
        id: max_presence_sensor
        internal: true
        on_value:
          - number.set:
              id: maxpresence
              value: !lambda return x;
      - name: "internal_min_presence"
        id: min_presence_sensor
        internal: true
        on_value:
          - number.set:
              id: minpresence
              value: !lambda return x;
      - name: "internal_unocc"
        id: unocc_time_sensor
        internal: true
        on_value:
          - number.set:
              id: unocc_time
              value: !lambda return x;

number:
  - platform: template
    name: "${device_name} Min Motion Distance"
    id: minmotion
    optimistic: true
    unit_of_measurement: cm
    min_value: 30
    max_value: 717
    step: 1
  - platform: template
    name: "${device_name} Max Motion Distance"
    id: maxmotion
    optimistic: true
    unit_of_measurement: cm
    min_value: 30
    max_value: 717
    step: 1
  - platform: template
    name: "${device_name} Min Presence Distance"
    id: minpresence
    optimistic: true
    unit_of_measurement: cm
    min_value: 30
    max_value: 425
    step: 1
  - platform: template
    name: "${device_name} Max Presence Distance"
    id: maxpresence
    optimistic: true
    unit_of_measurement: cm
    min_value: 30
    max_value: 425
    step: 1
  - platform: template
    name: "${device_name} Unoccupied Time"
    id: unocc_time
    optimistic: true
    unit_of_measurement: sec
    min_value: 0
    max_value: 6553
    step: 1

binary_sensor:
  - platform: template
    id: presence_template
    name: "${device_name} Presence"
    device_class: occupancy
    filters:
      - delayed_off: 5s
  - platform: template
    id: motion_template
    name: "${device_name} Motion"
    device_class: motion
    filters:
      - delayed_off: 5s

switch:
  - platform: template
    name: "${device_name} Bluetooth"
    id: human_switch
    optimistic: true
    restore_mode: "RESTORE_DEFAULT_ON"
    turn_on_action:
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xFF, 0x00, 0x01, 0x00, 0x04, 0x03, 0x02, 0x01]
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xA4, 0x00, 0x01, 0x00, 0x04, 0x03, 0x02, 0x01]
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x02, 0x00, 0xA3, 0x00, 0x04, 0x03, 0x02, 0x01]
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xFE, 0x00, 0x01, 0x00, 0x04, 0x03, 0x02, 0x01]
    turn_off_action:
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xFF, 0x00, 0x01, 0x00, 0x04, 0x03, 0x02, 0x01]
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xA4, 0x00, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01]
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x02, 0x00, 0xA3, 0x00, 0x04, 0x03, 0x02, 0x01]
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xFE, 0x00, 0x01, 0x00, 0x04, 0x03, 0x02, 0x01]

button:
  - platform: restart
    name: "Restart MCU: ${device_name}"
    entity_category: diagnostic
    on_press:
      - uart.write:
          id: uart_bus
          data: "resetSystem 0"
  - platform: template
    name: "${device_name} Reboot Module"
    id: reboot_module
    entity_category: diagnostic
    on_press:
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xFF, 0x00, 0x01, 0x00, 0x04, 0x03, 0x02, 0x01]
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x02, 0x00, 0xA3, 0x00, 0x04, 0x03, 0x02, 0x01]
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xFE, 0x00, 0x01, 0x00, 0x04, 0x03, 0x02, 0x01]
  - platform: template
    name: "${device_name} Factory Reset"
    id: reset_module
    entity_category: diagnostic
    on_press:
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xFF, 0x00, 0x01, 0x00, 0x04, 0x03, 0x02, 0x01]
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x02, 0x00, 0xA2, 0x00, 0x04, 0x03, 0x02, 0x01]
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xFE, 0x00, 0x01, 0x00, 0x04, 0x03, 0x02, 0x01]
  - platform: template
    name: "${device_name} Set Parameter"
    id: param_set
    entity_category: diagnostic
    on_press:
      - script.execute: statepublish

script:
  - id: statepublish
    then:
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xFF, 0x00, 0x01, 0x00, 0x04, 0x03, 0x02, 0x01]
      - uart.write:
          id: uart_bus 
          data: !lambda
                  int minmot = id(minmotion).state;
                  int maxmot = id(maxmotion).state;
                  int minpr = id(minpresence).state;
                  int maxpr = id(maxpresence).state;
                  int unocctm = id(unocc_time).state;
                  uint16_t minmvalue = static_cast<uint16_t>(minmot);
                  uint8_t minmhighByte = static_cast<uint8_t>(minmvalue >> 8);
                  uint8_t minmlowByte = static_cast<uint8_t>(minmvalue & 0xFF);
                  uint16_t maxmvalue = static_cast<uint16_t>(maxmot);
                  uint8_t maxmhighByte = static_cast<uint8_t>(maxmvalue >> 8);
                  uint8_t maxmlowByte = static_cast<uint8_t>(maxmvalue & 0xFF);
                  uint16_t minpvalue = static_cast<uint16_t>(minpr);
                  uint8_t minphighByte = static_cast<uint8_t>(minpvalue >> 8);
                  uint8_t minplowByte = static_cast<uint8_t>(minpvalue & 0xFF);
                  uint16_t maxpvalue = static_cast<uint16_t>(maxpr);
                  uint8_t maxphighByte = static_cast<uint8_t>(maxpvalue >> 8);
                  uint8_t maxplowByte = static_cast<uint8_t>(maxpvalue & 0xFF);
                  uint16_t unoccvalue = static_cast<uint16_t>(unocctm * 10);
                  uint8_t unocchighByte = static_cast<uint8_t>(unoccvalue >> 8);
                  uint8_t unocclowByte = static_cast<uint8_t>(unoccvalue & 0xFF);
                  std::vector<uint8_t> data = {0xFD, 0xFC, 0xFB, 0xFA, 0x20, 0x00, 0x67, 0x00, 0x00, 0x00, maxmlowByte, maxmhighByte, 0x00, 0x00, 0x01, 0x00, minmlowByte, minmhighByte, 0x00, 0x00, 0x02, 0x00, maxplowByte, maxphighByte, 0x00, 0x00, 0x03, 0x00, minplowByte, minphighByte, 0x00, 0x00, 0x04, 0x00, unocclowByte, unocchighByte, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01};
                  return data;
      - uart.write: [0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xFE, 0x00, 0x01, 0x00, 0x04, 0x03, 0x02, 0x01]

# Enable Home Assistant API
api:
  encryption:
    key: !secret encryption_key

ota:
  password: !secret ota_update

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "LD2411S Fallback Hotspot"
    password: !secret fallback_pass

captive_portal:
    
