HLK-LD2450 Initial experiments to connect to HomeAssistant

Thanks for the idea. I’ve given that a go and the following coverage angle seems to fit my target detection area when I walk around the room.

  - entity: ''
    name: Coverage
    mode: lines
    line:
      shape: line
      width: 1
      dash: dot
    x:
      - 4000
      - 0
      - -4000
    'y':
      - 2000
      - 0
      - 2000

I think the ymax is x/tan(60). It should be arround ymax=2312. May be we can calculate parametric based on range values and tan(60)=x/y.

I’ve added the calculation for the coverage angle and also for the 6m range of the sensor:

Here is the full YAML for the Plotly Graph card that I have put together:

type: custom:plotly-graph
title: Target Positions
refresh_interval: 1
hours_to_show: current_day
layout:
  showlegend: true
  margin:
    l: 50
    r: 20
    t: 20
    b: 40
  autosize: false
  height: 300
  xaxis:
    type: number
    fixedrange: true
    range:
      - 4000
      - -4000
  yaxis:
    fixedrange: true
    range:
      - 6000
      - 0
entities:
  - entity: ''
    name: Target1
    marker:
      size: 15
    line:
      shape: spline
      width: 5
    x:
      - $ex hass.states["sensor.screek_human_sensor_2a_734e6c_target1_x"].state
    'y':
      - $ex hass.states["sensor.screek_human_sensor_2a_734e6c_target1_y"].state
  - entity: ''
    name: Target2
    marker:
      size: 15
    line:
      shape: spline
      width: 5
    x:
      - $ex hass.states["sensor.screek_human_sensor_2a_734e6c_target2_x"].state
    'y':
      - $ex hass.states["sensor.screek_human_sensor_2a_734e6c_target2_y"].state
  - entity: ''
    name: Target3
    marker:
      size: 15
    line:
      shape: spline
      width: 5
    x:
      - $ex hass.states["sensor.screek_human_sensor_2a_734e6c_target3_x"].state
    'y':
      - $ex hass.states["sensor.screek_human_sensor_2a_734e6c_target3_y"].state
  - entity: ''
    name: Zone1
    mode: lines
    line:
      shape: line
      width: 2
    x:
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone1_x_begin"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone1_x_begin"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone1_x_end"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone1_x_end"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone1_x_begin"].state
    'y':
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone1_y_begin"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone1_y_end"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone1_y_end"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone1_y_begin"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone1_y_begin"].state
  - entity: ''
    name: Zone2
    mode: lines
    line:
      shape: line
      width: 2
    x:
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone2_x_begin"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone2_x_begin"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone2_x_end"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone2_x_end"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone2_x_begin"].state
    'y':
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone2_y_begin"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone2_y_end"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone2_y_end"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone2_y_begin"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone2_y_begin"].state
  - entity: ''
    name: Zone3
    mode: lines
    line:
      shape: line
      width: 2
    x:
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone3_x_begin"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone3_x_begin"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone3_x_end"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone3_x_end"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone3_x_begin"].state
    'y':
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone3_y_begin"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone3_y_end"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone3_y_end"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone3_y_begin"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zone3_y_begin"].state
  - entity: ''
    name: ExZone
    mode: lines
    line:
      shape: line
      width: 2
    x:
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zout1_x_begin"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zout1_x_begin"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zout1_x_end"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zout1_x_end"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zout1_x_begin"].state
    'y':
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zout1_y_begin"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zout1_y_end"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zout1_y_end"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zout1_y_begin"].state
      - $ex hass.states["number.screek_human_sensor_2a_734e6c_zout1_y_begin"].state
  - entity: ''
    name: Coverage
    mode: lines
    fill: tonexty
    fillcolor: rgba(168, 216, 234, 0.15)
    line:
      shape: line
      width: 1
      dash: dot
    x:
      - 0
      - $ex 6000 * Math.sin((2 * Math.PI)/360 * 60)
      - 4000
      - 3000
      - 2000
      - 1000
      - 0
      - -1000
      - -2000
      - -3000
      - -4000
      - $ex -6000 * Math.sin((2 * Math.PI)/360 * 60)
      - 0
    'y':
      - 0
      - $ex 6000 * Math.cos((2 * Math.PI)/360 * 60)
      - $ex Math.sqrt( 6000**2 - 4000**2 )
      - $ex Math.sqrt( 6000**2 - 3000**2 )
      - $ex Math.sqrt( 6000**2 - 2000**2 )
      - $ex Math.sqrt( 6000**2 - 1000**2 )
      - 6000
      - $ex Math.sqrt( 6000**2 - 1000**2 )
      - $ex Math.sqrt( 6000**2 - 2000**2 )
      - $ex Math.sqrt( 6000**2 - 3000**2 )
      - $ex Math.sqrt( 6000**2 - 4000**2 )
      - $ex 6000 * Math.cos((2 * Math.PI)/360 * 60)
      - 0
raw_plotly_config: true

5 Likes

Things are getting interesting, great job, athua.
The only problem it seems to have now is that it looks like they’re a little too sketchy in some places, maybe the lines of that zone could be made dashed as well to make them very light, or differentiate their backgrounds with a subtle color.
The solid lines, which look a bit puzzling, take up the entire field of view.

Can you include a screenshot so I can see what it looks like for you?
As you can see from the screenshot in my post above, it all appears ok for me.

I’ve changed the Zones to be shaded and made the lines thinner so it should be clearer and less cluttered now. Also with the Plotly graph, you can click on the Legend items to hide them if you only want to look at a specific items. It is also very customisable and is easy to change the colours and line thickness to meet individual needs.

LD2450-Target-Positions4

type: custom:plotly-graph
title: Target Positions
refresh_interval: 1
hours_to_show: current_day
layout:
  height: 230
  margin:
    l: 50
    r: 20
    t: 20
    b: 40
  showlegend: true
  xaxis:
    dtick: 1000
    gridcolor: RGBA(200,200,200,0.15)
    zerolinecolor: RGBA(200,200,200,0.15)
    type: number
    fixedrange: true
    range:
      - 4000
      - -4000
  yaxis:
    dtick: 1000
    gridcolor: RGBA(200,200,200,0.15)
    zerolinecolor: RGBA(200,200,200,0.15)
    scaleanchor: x
    scaleratio: 1
    fixedrange: true
    range:
      - 6000
      - 0
entities:
  - entity: ''
    name: Target1
    marker:
      size: 12
    line:
      shape: spline
      width: 5
    x:
      - $ex hass.states["sensor.screek_human_sensor_2a_734e6c_target1_x"].state
    'y':
      - $ex hass.states["sensor.screek_human_sensor_2a_734e6c_target1_y"].state
  - entity: ''
    name: Target2
    marker:
      size: 12
    line:
      shape: spline
      width: 5
    x:
      - $ex hass.states["sensor.screek_human_sensor_2a_734e6c_target2_x"].state
    'y':
      - $ex hass.states["sensor.screek_human_sensor_2a_734e6c_target2_y"].state
  - entity: ''
    name: Target3
    marker:
      size: 12
    line:
      shape: spline
      width: 5
    x:
      - $ex hass.states["sensor.screek_human_sensor_2a_734e6c_target3_x"].state
    'y':
      - $ex hass.states["sensor.screek_human_sensor_2a_734e6c_target3_y"].state
  - entity: ''
    name: Zone1
    mode: lines
    fill: toself
    fillcolor: RGBA(20,200,0,0.06)
    line:
      color: RGBA(20,200,0,0.2)
      shape: line
      width: 2
    x:
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone1_x_begin"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone1_x_begin"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone1_x_end"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone1_x_end"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone1_x_begin"].state
    'y':
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone1_y_begin"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone1_y_end"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone1_y_end"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone1_y_begin"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone1_y_begin"].state
  - entity: ''
    name: Zone2
    mode: lines
    fill: toself
    fillcolor: RGBA(200,0,255,0.06)
    line:
      color: RGBA(200,0,255,0.2)
      shape: line
      width: 2
    x:
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone2_x_begin"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone2_x_begin"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone2_x_end"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone2_x_end"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone2_x_begin"].state
    'y':
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone2_y_begin"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone2_y_end"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone2_y_end"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone2_y_begin"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone2_y_begin"].state
  - entity: ''
    name: Zone3
    mode: lines
    fill: toself
    fillcolor: RGBA(200,120,55,0.06)
    line:
      color: RGBA(200,120,55,0.2)
      shape: line
      width: 2
    x:
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone3_x_begin"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone3_x_begin"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone3_x_end"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone3_x_end"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone3_x_begin"].state
    'y':
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone3_y_begin"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone3_y_end"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone3_y_end"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone3_y_begin"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zone3_y_begin"].state
  - entity: ''
    name: ExZone
    mode: lines
    fill: toself
    fillcolor: RGBA(255,0,0,0.15)
    line:
      shape: line
      width: 1
      color: RGBA(255,0,0,0.2)
    x:
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zout1_x_begin"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zout1_x_begin"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zout1_x_end"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zout1_x_end"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zout1_x_begin"].state
    'y':
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zout1_y_begin"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zout1_y_end"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zout1_y_end"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zout1_y_begin"].state
      - >-
        $ex
        hass.states["number.screek_human_sensor_2a_734e6c_zout1_y_begin"].state
  - entity: ''
    name: Coverage
    mode: lines
    fill: tonexty
    fillcolor: rgba(168, 216, 234, 0.15)
    line:
      shape: line
      width: 1
      dash: dot
    x:
      - 0
      - $ex 6000 * Math.sin((2 * Math.PI)/360 * 60)
      - 4500
      - 4000
      - 3000
      - 2000
      - 1000
      - 0
      - -1000
      - -2000
      - -3000
      - -4000
      - -4500
      - $ex -6000 * Math.sin((2 * Math.PI)/360 * 60)
      - 0
    'y':
      - 0
      - $ex 6000 * Math.cos((2 * Math.PI)/360 * 60)
      - $ex Math.sqrt( 6000**2 - 4500**2 )
      - $ex Math.sqrt( 6000**2 - 4000**2 )
      - $ex Math.sqrt( 6000**2 - 3000**2 )
      - $ex Math.sqrt( 6000**2 - 2000**2 )
      - $ex Math.sqrt( 6000**2 - 1000**2 )
      - 6000
      - $ex Math.sqrt( 6000**2 - 1000**2 )
      - $ex Math.sqrt( 6000**2 - 2000**2 )
      - $ex Math.sqrt( 6000**2 - 3000**2 )
      - $ex Math.sqrt( 6000**2 - 4000**2 )
      - $ex Math.sqrt( 6000**2 - 4500**2 )
      - $ex 6000 * Math.cos((2 * Math.PI)/360 * 60)
      - 0
raw_plotly_config: true

If you use the above config without the layout height set on a Dashboard Panel (1 card), you get to see the whole coverage area map:

9 Likes

This looks so cool, athua!
Nice work!
This is an awesome map system!

1 Like

What are your UART settings for this combination (ESP32-C3 “Super Mini” and LD2410C). I just can’t get it to work. :confused:

Here’s the full config:

substitutions:
  # Set the device name
  name: devicename
  # Set the friendly name
  friendly_name: friendly
  # Provide the wifi SSID
  wifi: !secret wifi_ssid
  #Provide the wifi password
  wifi_pass: !secret wifi_password

### No modifications needed below here ###
####################################################################################

esphome:
  name: $name
  friendly_name: $friendly_name
  platformio_options:
    board_build.flash_mode: dio
    board_build.f_cpu: 80000000L
  name_add_mac_suffix: false

wifi:
  ssid: $wifi
  password: $wifi_pass
  power_save_mode: LIGHT
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
  output_power: 15db

captive_portal:

web_server:
  port: 80

esp32:
  board: lolin_c3_mini
  framework:
    type: esp-idf
  
api:

ota:

logger:
  level: DEBUG

uart:
  tx_pin: GPIO4
  rx_pin: GPIO3
  baud_rate: 256000
  parity: NONE
  stop_bits: 1

ld2410:

binary_sensor:
  - platform: ld2410
    has_target:
      name: Presence
    has_moving_target:
      name: Moving Target
    has_still_target:
      name: Still Target
    out_pin_presence_status:
      name: Out Pin Presence Status

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
  - platform: internal_temperature
    name: ESP Temperature
    unit_of_measurement: °C
    device_class: TEMPERATURE
    update_interval: 30s
    entity_category: "diagnostic"
  - platform: uptime
    name: Uptime
    id: sys_uptime
    update_interval: 10s
  - platform: wifi_signal 
    name: WiFi RSSI
    id: wifi_signal_db
    update_interval: 30s
    entity_category: "diagnostic"

switch:
  - platform: ld2410
    engineering_mode:
      name: "LD2410 Engineering Mode"
    bluetooth:
      name: "LD2410 bluetooth"

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

button:
  - platform: ld2410
    factory_reset:
      name: "LD2410 Factory Reset"
    restart:
      name: "LD2410 Reboot"
    query_params:
      name: "LD2410 Query Params"
  - platform: restart
    icon: mdi:power-cycle
    name: "ESP Reboot"

text_sensor:
  - platform: ld2410
    version:
      name: "LD2410 Firmware Version"
    mac_address:
      name: "LD2410 MAC Address"

select:
  - platform: ld2410
    distance_resolution:
      name: "Distance Resolution"
    baud_rate:
      name: "Baud Rate"
    light_function:
      name: Light Function
    out_pin_level:
      name: Out Pin Level

light:
  - platform: status_led
    name: sys_status
    pin: 
      number: GPIO8
      inverted: True
    internal: True
    restore_mode: ALWAYS_OFF

Alternatively, you can just use this bit, which imports the rest of the config from Github.

Just replace the items under substitutions.

This “packages” is pulling in the rest of the configs from here:

1 Like

great, thank you very much
i removed layout: height but it still doesn’t display fully

1 Like

I totally missed that I posted this in the wrong thread. Whoopsies.

1 Like

Are you using a Dashboard with a View Type of Panel (1 card) and tried in landscape mode? The screenshot above that shows the full area is from a PC and not a phone.
If you want to view on the phone, you will need to adjust the height value.
Experiment with the value and see what you get.

Alternatively, leave the height value there but change the X-axis range from 4000 to -4000 to 6000 to -6000 which should widen the chart.

There is no one size fits all due to the many different layouts and devices that can be used.

2 Likes

Hi, just updated to latest esphome addon and I’m getting a bunch of errors with the default yaml (component not found)
Any way to fix this?

@athua The Plotly graph is amazing! Thank you so much.

Just one thing - if your HA instance is set up for Imperial units like we are in the USA the positions all get converted to inches, so to make the graphs work right you have to multiply the target position x/y data by 25.4.

Confusingly, of course, all of the settings remain in mm.

Not sure if there is any good way to automate the adjustments or if this is something us backwards folks in the USA will just have to fix manually and live with.

In any case - THANK YOU for taking the time to put this together and publish it.

Thanks. It took lots of experimenting with different graphing tools before settling on Plotly which supported what I wanted by allowing a custom X-axis that was not time based.
As the data from the sensors are returning metric, maybe you could try creating template sensors to convert each of the metric sensors and then use those for the graph.

Maybe something like this:

template:
  - sensor:
      - name: "Target1_x_inches"
        state: |
          {{(states('sensor.target1_x_presence_radar')|float / 25.4) | round(2)}}
        unit_of_measurement: "in"
        state_class: "measurement"

Or do I have it around the wrong way around and the sensors are returning the values in imperial units but the graph is in metric? If its the graph, you could try chaging the axis limits from 6000 to 236.22 (6000/25.4) which should hopefully graph the points in inches rather than mm.

Can you post the actual errors that you received when compiling the upgrade?
I just upgraded my LD2450 unit with a Wemos D1 Mini ESP32 compatible board to ESPHome 2023.9.1 with no issues. It upgraded and compiled with no errors.
I do have ‘improv_serial:’ commented out in my YAML.

I’ve removed the ‘improv_serial:’ line but I’m still getting the same error on several lines.
Do you mind taking a look at my config?

image

image

I have only upgraded my LD2450 built with a Wemos D1 Mini ESP32 board, I have only used parts of the config from the Screek 2A YAML. For my Screek 2A, it is currently using the Screek firmware and not the ESPHome YAML config.

In particular, I have not used the following and when I try including it, I get errors with the logger component. Maybe you can try excluding it and see if it compiles.

external_components:
  - source:
      type: git
      url: https://github.com/screekworkshop/custom_components_support_for_screek_2a
      ref: main
    components: [esp32, uart]

If that doesn’t work then we will have to wait for someone from Screek Workshop to take a look at it.

1 Like

This is just odd, no difference even with the external_components line removed
I think I need to roll back to the previous esphome addon.
Anyway to do that?

Here is my YAML config. Maybe you could try taking parts from it.
I have included some extra bits as I am experimenting with trying to control the on-board LED on my ESP32 board.

substitutions:
  name: esp32-presence-radar
  friendly_name: "Presence Radar"
  espID: "esp32_presence_radar"

esphome:
  name: ${name}
  on_boot:
    - priority: 2000
      then:
        lambda: |-
          id(zone1_target_exsits).publish_state(false);
          id(zone2_target_exsits).publish_state(false);
          id(zone3_target_exsits).publish_state(false);
          id(zone_ex1_target_exsits).publish_state(false);

#debug:
#  update_interval: 30s

api:
ota:
#improv_serial:

globals:
  - id: last_update_ld2450
    type: unsigned long
    restore_value: no
    initial_value: '0'
  - id: init_zone_publish
    type: bool
    restore_value: no
    initial_value: "false"

logger:
  level: INFO
#  level: DEBUG
#  level: VERBOSE
  baud_rate: 0

esp32:
  board: wemos_d1_mini32
  #board: esp32dev
  framework:
    type: arduino

wifi:
  networks:
  - ssid: !secret wifi_ssid
    password: !secret wifi_password
    priority: 2
  - ssid: !secret wifi2_ssid
    password: !secret wifi2_password
    priority: 1
  output_power: 10dB

output:
  - platform: ledc
    id: onboard_led
    pin:
      number: GPIO2
      inverted: false

light:
  - platform: monochromatic
    name: "ESP LED ${friendly_name}"
    output: onboard_led
    id: led
    effects:
     - pulse:
  - platform: binary
    name: "ESP Binary LED ${friendly_name}"
    output: onboard_led
    id: led_binary

script:
  - id: check_zone1_vaild
    then:
      - lambda: |-
          if (id(zone1_x_begin).state > id(zone1_x_end).state){
            id(tips_zone1_conf).publish_state("Err: X-Begin > X-End");
            return;
          }
          if (id(zone1_y_begin).state > id(zone1_y_end).state){
            id(tips_zone1_conf).publish_state("Err: Y-Begin > Y-End");
            return;
          }
          if (id(zone1_x_begin).state == 0, id(zone1_x_end).state == 0, id(zone1_y_begin).state == 0, id(zone1_y_end).state == 0){
            id(tips_zone1_conf).publish_state("Configure below");
            return;
          }

          int x_size = id(zone1_x_end).state - id(zone1_x_begin).state;
          int y_size = id(zone1_y_end).state - id(zone1_y_begin).state;

          char combined[80]; 
          sprintf(combined, "Curr Size: %d x %d", x_size, y_size);
          id(tips_zone1_conf).publish_state(combined);
  - id: check_zone2_vaild
    then:
      - lambda: |-
          if (id(zone2_x_begin).state > id(zone2_x_end).state){
            id(tips_zone2_conf).publish_state("Err: X-Begin > X-End");
            return;
          }
          if (id(zone2_y_begin).state > id(zone2_y_end).state){
            id(tips_zone2_conf).publish_state("Err: Y-Begin > Y-End");
            return;
          }
          if (id(zone2_x_begin).state == 0, id(zone2_x_end).state == 0, id(zone2_y_begin).state == 0, id(zone2_y_end).state == 0){
            id(tips_zone2_conf).publish_state("Configure below");
            return;
          }

          int x_size = id(zone2_x_end).state - id(zone2_x_begin).state;
          int y_size = id(zone2_y_end).state - id(zone2_y_begin).state;

          char combined[80]; 
          sprintf(combined, "Curr Size: %d x %d", x_size, y_size);
          id(tips_zone2_conf).publish_state(combined);
  - id: check_zone3_vaild
    then:
      - lambda: |-
          if (id(zone3_x_begin).state > id(zone3_x_end).state){
            id(tips_zone3_conf).publish_state("Err: X-Begin > X-End");
            return;
          }
          if (id(zone3_y_begin).state > id(zone3_y_end).state){
            id(tips_zone3_conf).publish_state("Err: Y-Begin > Y-End");
            return;
          }
          if (id(zone3_x_begin).state == 0, id(zone3_x_end).state == 0, id(zone3_y_begin).state == 0, id(zone3_y_end).state == 0){
            id(tips_zone3_conf).publish_state("Configure below");
            return;
          }

          int x_size = id(zone3_x_end).state - id(zone3_x_begin).state;
          int y_size = id(zone3_y_end).state - id(zone3_y_begin).state;

          char combined[80]; 
          sprintf(combined, "Curr Size: %d x %d", x_size, y_size);
          id(tips_zone3_conf).publish_state(combined);
  - id: check_zout1_vaild
    then:
      - lambda: |-
          if (id(zone_ex1_x_begin).state > id(zone_ex1_x_end).state){
            id(tips_zone_ex1_conf).publish_state("Err: X-Begin > X-End");
            return;
          }
          if (id(zone_ex1_y_begin).state > id(zone_ex1_y_end).state){
            id(tips_zone_ex1_conf).publish_state("Err: Y-Begin > Y-End");
            return;
          }
          id(tips_zone_ex1_conf).publish_state("Zone Exclusion 1");

button:
  - platform: restart
    name: "ESP32 Restart ${friendly_name}"
  - platform: safe_mode
    name: "ESP32 Safe Mode Boot ${friendly_name}"
    entity_category: diagnostic

switch:
  - platform: template
    name: "Pulse LED ${friendly_name}"
    optimistic: True
    turn_on_action:
    - light.turn_on:
        id: led
        effect: pulse
    turn_off_action:
    - light.turn_off:
        id: led
  - platform: template
    name: "Presence LED ${friendly_name}"
    id: presenceLED
    optimistic: True
  - platform: template
    name: "Zout1 Enable ${friendly_name}"
    id: zone_ex1_enable
    optimistic: True
    icon: mdi:account-cancel
    entity_category: config
    restore_mode: RESTORE_DEFAULT_OFF

text_sensor:
  - platform: wifi_info
    ip_address:
      name: "ESP IP Address ${friendly_name}"
    ssid:
      name: "ESP Connected SSID ${friendly_name}"
    bssid:
      name: "ESP Connected BSSID ${friendly_name}"
    mac_address:
      name: "ESP Mac Wifi Address ${friendly_name}"
    scan_results:
      name: "ESP Latest Scan Results ${friendly_name}"
  - platform: template
    name: "Zone1 Info ${friendly_name}"
    id: tips_zone1_conf
    icon: mdi:information-outline
    entity_category: config
    lambda: |-
      return {"Configure below" };
    update_interval: 1000s
  - platform: template
    name: "Zone2 Info ${friendly_name}"
    id: tips_zone2_conf
    icon: mdi:information-outline
    entity_category: config
    lambda: |-
      return {"Configure below" };
    update_interval: 1000s
  - platform: template
    name: "Zone3 Info ${friendly_name}"
    id: tips_zone3_conf
    icon: mdi:information-outline
    entity_category: config
    lambda: |-
      return {"Configure below" };
    update_interval: 1000s
  - platform: template
    name: "Zout1 Info ${friendly_name}"
    id: tips_zone_ex1_conf
    icon: mdi:information-outline
    entity_category: config
    lambda: |-
      return {"Zone Exclusion 1" };
    update_interval: 1000s

binary_sensor:
  - platform: status
    name: "ESP Status ${friendly_name}"
  - platform: template
    name: "Any Presence ${friendly_name}"
    id: any_target_exsits
    device_class: occupancy
    filters:
      - delayed_off: !lambda |-
          if (!id(init_zone_publish)) {
            return 0;
          };
          return id(any_presence_timeout).state * 1000.0;
    on_press:
      then:
        - if:
            condition:
              switch.is_on: presenceLED
            then:
              - light.turn_on: led
    on_release:
      then:
        - if:
            condition:
              switch.is_on: presenceLED
            then:
              - light.turn_off: led
  - platform: template
    name: "Zone1 Presence ${friendly_name}"
    id: zone1_target_exsits
    device_class: occupancy
    filters:
      - delayed_off: !lambda |-
          if (!id(init_zone_publish)) {
            return 0;
          };
          return id(zone1_x_timeout).state * 1000.0;
  - platform: template
    name: "Zone2 Presence ${friendly_name}"
    id: zone2_target_exsits
    device_class: occupancy
    filters:
      - delayed_off: !lambda |-
          if (!id(init_zone_publish)) {
            return 0;
          };
          return id(zone2_x_timeout).state * 1000.0;
  - platform: template
    name: "Zone3 Presence ${friendly_name}"
    id: zone3_target_exsits
    device_class: occupancy
    filters:
      - delayed_off: !lambda |-
          if (!id(init_zone_publish)) {
            return 0;
          };
          return id(zone3_x_timeout).state * 1000.0;
  - platform: template
    name: "Zout1 Presence ${friendly_name}"
    id: zone_ex1_target_exsits
    icon: mdi:account-multiple-remove
    device_class: occupancy

sensor:
  - platform: internal_temperature
    name: "ESP Temperature ${friendly_name}"
  - platform: wifi_signal # Reports the WiFi signal strength/RSSI in dB
    name: "WiFi Signal dB ${friendly_name}"
    id: wifi_signal_db
    update_interval: 60s
    entity_category: "diagnostic"
  - platform: copy # Reports the WiFi signal strength in %
    source_id: wifi_signal_db
    name: "WiFi Signal Percent ${friendly_name}"
    filters:
      - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
    unit_of_measurement: "%"
    entity_category: "diagnostic"
  - platform: uptime
    name: "ESP Uptime ${friendly_name}"
  - platform: template
    name: "All Target Counts ${friendly_name}"
    id: all_target_count
    accuracy_decimals: 0
    icon: "mdi:counter"
    unit_of_measurement: "targets"
  - platform: template
    name: "Zone1 Target Counts ${friendly_name}"
    id: zone1_target_count
    accuracy_decimals: 0
    icon: "mdi:counter"
    unit_of_measurement: "targets"
  - platform: template
    name: "Zone2 Target Counts ${friendly_name}"
    id: zone2_target_count
    accuracy_decimals: 0
    icon: "mdi:counter"
    unit_of_measurement: "targets"
  - platform: template
    name: "Zone3 Target Counts ${friendly_name}"
    id: zone3_target_count
    accuracy_decimals: 0
    icon: "mdi:counter"
    unit_of_measurement: "targets"
  - platform: template
    name: "Zout1 Target Counts ${friendly_name}"
    id: zone_ex1_target_count
    accuracy_decimals: 0
    icon: mdi:account-multiple-minus-outline
    unit_of_measurement: "targets"
  - platform: template
    name: "Target1 X ${friendly_name}"
    id: target1_x
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    device_class: distance
  - platform: template
    name: "Target1 Y ${friendly_name}"
    id: target1_y
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    device_class: distance
  - platform: template
    name: "Target1 Speed ${friendly_name}"
    id: target1_speed
    accuracy_decimals: 2
    unit_of_measurement: 'm/s'
    state_class: measurement
    device_class: speed
  - platform: template
    name: "Target1 Resolution ${friendly_name}"
    id: target1_resolution
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    device_class: distance
  - platform: template
    name: "Target2 X ${friendly_name}"
    id: target2_x
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    device_class: distance
    # update_interval: 1s
  - platform: template
    name: "Target2 Y ${friendly_name}"
    id: target2_y
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    device_class: distance
  - platform: template
    name: "Target2 Speed ${friendly_name}"
    id: target2_speed
    accuracy_decimals: 0
    unit_of_measurement: 'm/s'
    state_class: measurement
    device_class: speed
  - platform: template
    name: "Target2 Resolution ${friendly_name}"
    id: target2_resolution
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    device_class: distance
  - platform: template
    name: "Target3 X ${friendly_name}"
    id: target3_x
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    device_class: distance
  - platform: template
    name: "Target3 Y ${friendly_name}"
    id: target3_y
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    device_class: distance
  - platform: template
    name: "Target3 Speed ${friendly_name}"
    id: target3_speed
    accuracy_decimals: 0
    unit_of_measurement: 'm/s'
    state_class: measurement
    device_class: speed
    # update_interval: 1s
  - platform: template
    name: "Target3 Resolution ${friendly_name}"
    id: target3_resolution
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    device_class: distance

number:
  - platform: template
    name: "Any Presence Timeout ${friendly_name}"
    id: any_presence_timeout
    min_value: 0
    max_value: 600
    mode: box
    device_class: duration
    entity_category: config
    unit_of_measurement: s
    icon: mdi:timer-off
    step: 1
    optimistic: True
    initial_value: 0
    restore_value: True
  - platform: template
    name: "Zone1 Timeout ${friendly_name}"
    id: zone1_x_timeout
    min_value: 0
    max_value: 600
    mode: box
    device_class: duration
    entity_category: config
    unit_of_measurement: s
    icon: mdi:timer-off
    step: 1
    optimistic: True
    initial_value: 0
    restore_value: True
  - platform: template
    name: "Zone1 X-Begin ${friendly_name}"
    id: zone1_x_begin
    min_value: -4000
    max_value: 4000
    mode: box
    device_class: distance
    entity_category: config
    unit_of_measurement: mm
    icon: mdi:arrow-left-bold
    step: 10
    optimistic: True
    initial_value: 0
    restore_value: True
  - platform: template
    name: "Zone1 X-End ${friendly_name}"
    id: zone1_x_end
    mode: box
    min_value: -4000
    max_value: 4000
    device_class: distance
    unit_of_measurement: mm
    entity_category: config
    icon: mdi:arrow-right-bold
    step: 10
    initial_value: 0
    optimistic: True
    restore_value: True
  - platform: template
    name: "Zone1 Y-Begin ${friendly_name}"
    id: zone1_y_begin
    mode: box
    min_value: 0
    max_value: 6000
    device_class: distance
    entity_category: config
    icon: mdi:arrow-up-bold
    unit_of_measurement: mm
    step: 10
    initial_value: 0
    optimistic: True
    restore_value: True
  - platform: template
    name: "Zone1 Y-End ${friendly_name}"
    id: zone1_y_end
    icon: mdi:arrow-down-bold
    mode: box
    min_value: 0
    max_value: 6000
    initial_value: 0
    entity_category: config
    device_class: distance
    unit_of_measurement: mm
    step: 10
    optimistic: True
    restore_value: True
  - platform: template
    name: "Zone2 Timeout ${friendly_name}"
    id: zone2_x_timeout
    min_value: 0
    max_value: 600
    mode: box
    device_class: duration
    entity_category: config
    unit_of_measurement: s
    icon: mdi:timer-off
    step: 1
    optimistic: True
    initial_value: 0
    restore_value: True
  - platform: template
    name: "Zone2 X-Begin ${friendly_name}"
    id: zone2_x_begin
    min_value: -4000
    max_value: 4000
    mode: box
    device_class: distance
    entity_category: config
    unit_of_measurement: mm
    icon: mdi:arrow-left-bold
    step: 10
    optimistic: True
    initial_value: 0
    restore_value: True
  - platform: template
    name: "Zone2 X-End ${friendly_name}"
    id: zone2_x_end
    mode: box
    min_value: -4000
    max_value: 4000
    device_class: distance
    unit_of_measurement: mm
    entity_category: config
    icon: mdi:arrow-right-bold
    step: 10
    initial_value: 0
    optimistic: True
    restore_value: True
  - platform: template
    name: "Zone2 Y-Begin ${friendly_name}"
    id: zone2_y_begin
    mode: box
    min_value: 0
    max_value: 6000
    device_class: distance
    entity_category: config
    icon: mdi:arrow-up-bold
    unit_of_measurement: mm
    step: 10
    initial_value: 0
    optimistic: True
    restore_value: True
  - platform: template
    name: "Zone2 Y-End ${friendly_name}"
    id: zone2_y_end
    icon: mdi:arrow-down-bold
    mode: box
    min_value: 0
    max_value: 6000
    initial_value: 0
    entity_category: config
    device_class: distance
    unit_of_measurement: mm
    step: 10
    optimistic: True
    restore_value: True
  - platform: template
    name: "Zone3 Timeout ${friendly_name}"
    id: zone3_x_timeout
    min_value: 0
    max_value: 600
    mode: box
    device_class: duration
    entity_category: config
    unit_of_measurement: s
    icon: mdi:timer-off
    step: 1
    optimistic: True
    initial_value: 0
    restore_value: True
  - platform: template
    name: "Zone3 X-Begin ${friendly_name}"
    id: zone3_x_begin
    min_value: -4000
    max_value: 4000
    mode: box
    device_class: distance
    entity_category: config
    unit_of_measurement: mm
    icon: mdi:arrow-left-bold
    step: 10
    optimistic: True
    initial_value: 0
    restore_value: True
  - platform: template
    name: "Zone3 X-End ${friendly_name}"
    id: zone3_x_end
    mode: box
    min_value: -4000
    max_value: 4000
    device_class: distance
    unit_of_measurement: mm
    entity_category: config
    icon: mdi:arrow-right-bold
    step: 10
    initial_value: 0
    optimistic: True
    restore_value: True
  - platform: template
    name: "Zone3 Y-Begin ${friendly_name}"
    id: zone3_y_begin
    mode: box
    min_value: 0
    max_value: 6000
    device_class: distance
    entity_category: config
    icon: mdi:arrow-up-bold
    unit_of_measurement: mm
    step: 10
    initial_value: 0
    optimistic: True
    restore_value: True
  - platform: template
    name: "Zone3 Y-End ${friendly_name}"
    id: zone3_y_end
    icon: mdi:arrow-down-bold
    mode: box
    min_value: 0
    max_value: 6000
    initial_value: 0
    entity_category: config
    device_class: distance
    unit_of_measurement: mm
    step: 10
    optimistic: True
    restore_value: True
  - platform: template
    name: "Zout1 X-Begin ${friendly_name}"
    id: zone_ex1_x_begin
    min_value: -4000
    max_value: 4000
    mode: box
    device_class: distance
    entity_category: config
    unit_of_measurement: mm
    icon: mdi:arrow-left-bold
    step: 10
    optimistic: True
    initial_value: 0
    restore_value: True
  - platform: template
    name: "Zout1 X-End ${friendly_name}"
    id: zone_ex1_x_end
    mode: box
    min_value: -4000
    max_value: 4000
    device_class: distance
    unit_of_measurement: mm
    entity_category: config
    icon: mdi:arrow-right-bold
    step: 10
    initial_value: 0
    optimistic: True
    restore_value: True
  - platform: template
    name: "Zout1 Y-Begin ${friendly_name}"
    id: zone_ex1_y_begin
    mode: box
    min_value: 0
    max_value: 6000
    device_class: distance
    entity_category: config
    icon: mdi:arrow-up-bold
    unit_of_measurement: mm
    step: 10
    initial_value: 0
    optimistic: True
    restore_value: True
  - platform: template
    name: "Zout1 Y-End ${friendly_name}"
    id: zone_ex1_y_end
    icon: mdi:arrow-down-bold
    mode: box
    min_value: 0
    max_value: 6000
    initial_value: 0
    entity_category: config
    device_class: distance
    unit_of_measurement: mm
    step: 10
    optimistic: True
    restore_value: True

uart:
  id: uart_ld2450
  tx_pin: 
    number: GPIO17
    mode:
      pullup: true
  rx_pin: 
    number: GPIO16
    mode:
      pullup: true
  baud_rate: 256000
  parity: NONE
  stop_bits: 1
  debug:
    direction: BOTH
    dummy_receiver: True
    after:
     delimiter: [0X55, 0XCC]
    sequence:
      - lambda: |-
          if ((millis() - id(last_update_ld2450)) <= 500) { 
            return;
          };
          id(last_update_ld2450) = millis();

          // p1
          int16_t p1_x = (uint16_t((bytes[5] << 8) | bytes[4] ));
          if ((bytes[5] & 0x80) >> 7){
            p1_x -= pow(2, 15); 
          }else{
            p1_x = 0 - p1_x;
          }

          int16_t p1_y = (uint16_t((bytes[7] << 8) | bytes[6] ));
          if ((bytes[7] & 0x80) >> 7){
            p1_y -= pow(2, 15);
          }else{
            p1_y = 0 - p1_y;
          }

          int p1_speed = (bytes[9] << 8 | bytes[8] );
          if ((bytes[9] & 0x80) >> 7){
            p1_speed -= pow(2, 15);
          }else{
            p1_speed = 0 - p1_speed;
          }
          int16_t p1_distance_resolution = (uint16_t((bytes[11] << 8) | bytes[10] )); 

          // p2
          int16_t p2_x = (uint16_t((bytes[13] << 8) | bytes[12] ));
          if ((bytes[13] & 0x80) >> 7){
            p2_x -=  pow(2, 15); 
          }else{
            p2_x = 0 - p2_x;
          }

          int16_t p2_y = (uint16_t((bytes[15] << 8) | bytes[14] ));
          if ((bytes[15] & 0x80) >> 7){
            p2_y -= pow(2, 15);
          }else{
            p2_y = 0 - p2_y;
          }

          int p2_speed = (bytes[17] << 8 | bytes[16] );
          if ((bytes[17] & 0x80) >> 7){
            p2_speed -= pow(2, 15);
          }else{
            p2_speed = 0 - p2_speed;
          }
          int16_t p2_distance_resolution = (uint16_t((bytes[19] << 8) | bytes[18] )); 

          // p3
          int16_t p3_x = (uint16_t((bytes[21] << 8) | bytes[20] ));
          if ((bytes[21] & 0x80) >> 7){
            p3_x -=  pow(2, 15); 
          }else{
            p3_x = 0 - p3_x;
          }

          int16_t p3_y = (uint16_t((bytes[23] << 8) | bytes[22] ));
          if ((bytes[23] & 0x80) >> 7){
            p3_y -= pow(2, 15);
          }else{
            p3_y = 0 - p3_y;
          }

          int p3_speed = (bytes[25] << 8 | bytes[24] );
          if ((bytes[25] & 0x80) >> 7){
            p3_speed -= pow(2, 15);
          }else{
            p3_speed = 0 - p3_speed;
          }
          
          int16_t p3_distance_resolution = (uint16_t((bytes[27] << 8) | bytes[26] )); 

          bool p1_vaild = (p1_x != 0 || p1_y > 0);
          bool p2_vaild = (p2_x != 0 || p2_y > 0);
          bool p3_vaild = (p3_x != 0 || p3_y > 0);

          // zone exlude 1

          int16_t target_count_in_zone_ex1 = 0;

          int16_t zone_ex1_x_min = id(zone_ex1_x_begin).state;
          int16_t zone_ex1_x_max = id(zone_ex1_x_end).state;
          int16_t zone_ex1_y_min = id(zone_ex1_y_begin).state;
          int16_t zone_ex1_y_max = id(zone_ex1_y_end).state;

          bool p1_zone_ex_enter = false;
          bool p2_zone_ex_enter = false;
          bool p3_zone_ex_enter = false;

          if (id(zone_ex1_enable).state){
            if (p1_vaild){
              if (p1_x >= zone_ex1_x_min && p1_x <= zone_ex1_x_max && p1_y >= zone_ex1_y_min && p1_y <= zone_ex1_y_max){
                  p1_zone_ex_enter = true;
                  target_count_in_zone_ex1 ++;
              }
            }
            if (p2_vaild){
              if (p2_x >= zone_ex1_x_min && p2_x <= zone_ex1_x_max && p2_y >= zone_ex1_y_min && p2_y <= zone_ex1_y_max){
                  p2_zone_ex_enter = true;
                  target_count_in_zone_ex1 ++;
              }
            }
            if (p3_vaild){
              if (p3_x >= zone_ex1_x_min && p3_x <= zone_ex1_x_max && p3_y >= zone_ex1_y_min && p3_y <= zone_ex1_y_max){
                  p3_zone_ex_enter = true;
                  target_count_in_zone_ex1 ++;
              }
            }
          }

          bool has_target_in_zone_ex1 = (target_count_in_zone_ex1 > 0);
          
          int16_t all_target_counts = 0;
          if (p1_vaild && !p1_zone_ex_enter){
            all_target_counts ++;
          }
          if (p2_vaild && !p2_zone_ex_enter){
            all_target_counts ++;
          }
          if (p3_vaild && !p3_zone_ex_enter){
            all_target_counts ++;
          }

          bool has_target_in_zone_all = (all_target_counts > 0);

          // zone 1 check

          int16_t target_count_in_zone1 = 0;
          int16_t zone1_x_min = id(zone1_x_begin).state;
          int16_t zone1_x_max = id(zone1_x_end).state;
          int16_t zone1_y_min = id(zone1_y_begin).state;
          int16_t zone1_y_max = id(zone1_y_end).state;

          if (p1_vaild && !p1_zone_ex_enter){
            if (p1_x >= zone1_x_min && p1_x <= zone1_x_max && p1_y >= zone1_y_min && p1_y <= zone1_y_max){
                target_count_in_zone1 ++;
            }
          }
          if (p2_vaild && !p2_zone_ex_enter){
            if (p2_x >= zone1_x_min && p2_x <= zone1_x_max && p2_y >= zone1_y_min && p2_y <= zone1_y_max){
                target_count_in_zone1 ++;
            }
          }
          if (p3_vaild && !p3_zone_ex_enter){
            if (p3_x >= zone1_x_min && p3_x <= zone1_x_max && p3_y >= zone1_y_min && p3_y <= zone1_y_max){
                target_count_in_zone1 ++;
            }
          }
          bool has_target_in_zone1 = (target_count_in_zone1 > 0);

          // zone 2 check

          int16_t target_count_in_zone2 = 0;
          int16_t zone2_x_min = id(zone2_x_begin).state;
          int16_t zone2_x_max = id(zone2_x_end).state;
          int16_t zone2_y_min = id(zone2_y_begin).state;
          int16_t zone2_y_max = id(zone2_y_end).state;

          if (p1_vaild && !p1_zone_ex_enter){
            if (p1_x >= zone2_x_min && p1_x <= zone2_x_max && p1_y >= zone2_y_min && p1_y <= zone2_y_max){
                target_count_in_zone2 ++;
            }
          }
          if (p2_vaild && !p2_zone_ex_enter){
            if (p2_x >= zone2_x_min && p2_x <= zone2_x_max && p2_y >= zone2_y_min && p2_y <= zone2_y_max){
                target_count_in_zone2 ++;
            }
          }
          if (p3_vaild && !p3_zone_ex_enter){
            if (p3_x >= zone2_x_min && p3_x <= zone2_x_max && p3_y >= zone2_y_min && p3_y <= zone2_y_max){
                target_count_in_zone2 ++;
            }
          }

          bool has_target_in_zone2 = (target_count_in_zone2 > 0);

          // zone 3 check

          int16_t target_count_in_zone3 = 0;
          int16_t zone3_x_min = id(zone3_x_begin).state;
          int16_t zone3_x_max = id(zone3_x_end).state;
          int16_t zone3_y_min = id(zone3_y_begin).state;
          int16_t zone3_y_max = id(zone3_y_end).state;

          if (p1_vaild && !p1_zone_ex_enter){
            if (p1_x >= zone3_x_min && p1_x <= zone3_x_max && p1_y >= zone3_y_min && p1_y <= zone3_y_max){
                target_count_in_zone3 ++;
            }
          }
          if (p2_vaild && !p2_zone_ex_enter){
            if (p2_x >= zone3_x_min && p2_x <= zone3_x_max && p2_y >= zone3_y_min && p2_y <= zone3_y_max){
                target_count_in_zone3 ++;
            }
          }
          if (p3_vaild && !p3_zone_ex_enter){
            if (p3_x >= zone3_x_min && p3_x <= zone3_x_max && p3_y >= zone3_y_min && p3_y <= zone3_y_max){
                target_count_in_zone3 ++;
            }
          }
          bool has_target_in_zone3 = (target_count_in_zone3 > 0);

          // public all info
          if (id(target1_x).state != p1_x){
            id(target1_x).publish_state(p1_x);
          }
          if (id(target1_y).state != p1_y){
            id(target1_y).publish_state(p1_y);
          }

          float p1_m_speed = float(p1_speed) / 100.0;
          if (id(target1_speed).state != p1_m_speed){
            id(target1_speed).publish_state(p1_m_speed);
          }
          if (id(target1_resolution).state != p1_distance_resolution){
            id(target1_resolution).publish_state(p1_distance_resolution);
          }

          if (id(target2_x).state != p2_x){
            id(target2_x).publish_state(p2_x);
          }
          if (id(target2_y).state != p2_y){
            id(target2_y).publish_state(p2_y);
          }
          if (id(target2_speed).state != p2_speed){
            id(target2_speed).publish_state(p2_speed);
          }
          if (id(target2_resolution).state != p2_distance_resolution){
            id(target2_resolution).publish_state(p2_distance_resolution);
          }

          if (id(target3_x).state != p3_x){
            id(target3_x).publish_state(p3_x);
          }
          if (id(target3_y).state != p3_y){
            id(target3_y).publish_state(p3_y);
          }
          if (id(target3_speed).state != p3_speed){
            id(target3_speed).publish_state(p3_speed);
          }
          if (id(target3_resolution).state != p3_distance_resolution){
            id(target3_resolution).publish_state(p3_distance_resolution);
          }

          // publish target info
          
          if (id(all_target_count).state != all_target_counts){
            id(all_target_count).publish_state(all_target_counts);
            id(any_target_exsits).publish_state(has_target_in_zone_all);
          }else if (id(any_target_exsits).state != has_target_in_zone_all){
            id(any_target_exsits).publish_state(has_target_in_zone_all);
          }

          if (id(zone1_target_count).state != target_count_in_zone1){
            id(zone1_target_count).publish_state(target_count_in_zone1);
            id(zone1_target_exsits).publish_state(has_target_in_zone1);
          }else if (id(zone1_target_exsits).state != has_target_in_zone1){
            id(zone1_target_exsits).publish_state(has_target_in_zone1);
          }

          if (id(zone2_target_count).state != target_count_in_zone2){
            id(zone2_target_count).publish_state(target_count_in_zone2);
            id(zone2_target_exsits).publish_state(has_target_in_zone2);
          }else if (id(zone2_target_exsits).state != has_target_in_zone2){
            id(zone2_target_exsits).publish_state(has_target_in_zone2);
          }

          if (id(zone3_target_count).state != target_count_in_zone3){
            id(zone3_target_count).publish_state(target_count_in_zone3);
            id(zone3_target_exsits).publish_state(has_target_in_zone3);
          }else if (id(zone3_target_exsits).state != has_target_in_zone3){
            id(zone3_target_exsits).publish_state(has_target_in_zone3);
          }
          
          // zout
          if (id(zone_ex1_target_count).state != target_count_in_zone_ex1){
            id(zone_ex1_target_count).publish_state(target_count_in_zone_ex1);
          }

          if (id(zone_ex1_target_exsits).state != has_target_in_zone_ex1){
            id(zone_ex1_target_exsits).publish_state(has_target_in_zone_ex1);
          }

          if (!id(init_zone_publish)){
            id(init_zone_publish) = true;
          }
5 Likes