Tutoriel détecteur LD2450 esphome

C’est quel modèle ? Car j’ai pris 5 exemplaire il y a quelques temps ils fonctionnent tous.

Il y a juste le BT qui soit il est coupé soit ne marche pas mais sinon la détection de présence marche mais sur 1 seule personne pas deux

Salut, Ah moi aussi j’en ai que le BT ne fonctionne pas. Du coup on pourra les flasher comment?
Apres un flashage, peut etre que le BT refonctionnera :slight_smile:
Merci Bonne journée

J’ai pris ce LD2450, il y en a un ou il manque un composant sur la carte, et l’autre la détection fonctionne très mal.

Et les ESP32 j’en ai testé qu’un sur les 2 pour l’instant, et il perd très souvent la connexion avec HA.

Bonjour a vous
Qu’est ce que vous laissez d’actif comme entitées sur les 2450? car mon journal n’arrete pas de s’affoler quand je suis dans la mire du ld :slight_smile:
Merci
Bonne journée a vous

j’ai la même chose. c’est pourquoi j’utilise plutôt les zones. Je me mets aux 4 coins de la zone que je veux détecter et je conserve les valeurs max. Ma zone ainsi étalonné, je désactive l’envoie des infos de la cible.

2 « J'aime »

donc tu desactives tout sauf les zone presence 1 - 2 -3 ?

Le multi personne fonctionne ? En multi zone !

c’est ça : je désactive « Target Enable » et j’active « Zone Enable »
(il faut bien sûr avoir réglé au préalable les différentes zones mais j’ai vu que c’était bien fait chez toi)

1 « J'aime »

Tout à fait!

Le capteur en lui-même ne renvoie aucune information concernant des zones. Le capteur est seulement capable d’indiquer les positions jusqu’à trois personnes. C’est le code qui est rajouté dans l’ESP qui vient définir des zones. Si l’on le voulait on pourrait avoir six zones ou beaucoup plus. Par contre, au vu de la surface que le capteur est capable de surveiller, je ne suis pas sûr que ce serait pertinent de mettre plus de six zones.

Mais la réponse courte c’est « oui »

Bonjour Maxime,

Merci pour ton retour. Je n’avais pas pensé à l’histoire du mouvement d’air chaud. Pour moi c’est un capteur de type radar (effet doppler).
Je vais essayer de faire des essais, avec un ventilateur et un chauffage soufflant, pour voir si j’arrive a retrouver cette effet.

Je vous fais un retour des que possible.

1 « J'aime »

Ok sur le multi zone
Et oui je comprends qu’il ne faille pas en déclarer 50 et peu ou pas d’intérêt à mon sens.

Par contre je n’arrive pas à avoir plusieurs personnes :thinking:

Si tu veux, je veux bien regarder le code que tu utilises et ton paramétrage. On essaiera de comprendre ensemble le problème

Bonjour à tous alors grace à un coup de pouce de la part de @selecus j’ai pu ajuster le paramétrage car j’avais laissé les titmeout de zone à 0 en pressant à tord que cela détecterait plus vite. Et ce n’est pas un timein :slight_smile:

Bref en passant mes timeout à 1s sur les 3 zones je retrouve la détection de mes 2 personnes !
image

la 3ème ne veut pas apparaitre c’est chelou quand même !!

Sinon je mets le code de la carte aussi je sais que cela va faire plaisir à certain en particulier à @selecus

Code la carte de présence LD2450
type: custom:plotly-graph
title: Présence Couloir
refresh_interval: 1
hours_to_show: current_day
ha_theme: true
layout:
  height: 300
  legend:
    'y': 6000
    orientation: h
  autosize: true
  margin:
    autoexpand: true
    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:
      - -6000
      - 6000
  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
      - -100
entities:
  - entity: ''
    name: Person1
    show_value: true
    unit_of_measurement: mm
    marker:
      size: 12
    line:
      shape: spline
      width: 5
    x:
      - $ex hass.states["sensor.pre_couloir_target1_x"].state
    'y':
      - $ex hass.states["sensor.pre_couloir_target1_y"].state
  - entity: ''
    name: Person2
    show_value: true
    unit_of_measurement: mm
    marker:
      size: 12
    line:
      shape: spline
      width: 5
    x:
      - $ex hass.states["sensor.pre_couloir_target2_x"].state
    'y':
      - $ex hass.states["sensor.pre_couloir_target2_y"].state
  - entity: ''
    name: Person3
    show_value: true
    unit_of_measurement: mm
    marker:
      size: 12
    line:
      shape: spline
      width: 5
    x:
      - $ex hass.states["sensor.pre_couloir_target3_x"].state
    'y':
      - $ex hass.states["sensor.pre_couloir_target3_y"].state
  - entity: ''
    name: Zone1
    mode: lines
    fill: toself
    fillcolor: RGBA(20,200,0,0.1)
    line:
      color: RGBA(20,200,0,0.2)
      shape: line
      width: 2
    x:
      - $ex hass.states["number.pre_couloir_zone1_x_begin"].state
      - $ex hass.states["number.pre_couloir_zone1_x_begin"].state
      - $ex hass.states["number.pre_couloir_zone1_x_end"].state
      - $ex hass.states["number.pre_couloir_zone1_x_end"].state
      - $ex hass.states["number.pre_couloir_zone1_x_begin"].state
    'y':
      - $ex hass.states["number.pre_couloir_zone1_y_begin"].state
      - $ex hass.states["number.pre_couloir_zone1_y_end"].state
      - $ex hass.states["number.pre_couloir_zone1_y_end"].state
      - $ex hass.states["number.pre_couloir_zone1_y_begin"].state
      - $ex hass.states["number.pre_couloir_zone1_y_begin"].state
  - entity: ''
    name: Zone2
    mode: lines
    fill: toself
    fillcolor: RGBA(200,0,255,0.1)
    line:
      color: RGBA(200,0,255,0.2)
      shape: line
      width: 2
    x:
      - $ex hass.states["number.pre_couloir_zone2_x_begin"].state
      - $ex hass.states["number.pre_couloir_zone2_x_begin"].state
      - $ex hass.states["number.pre_couloir_zone2_x_end"].state
      - $ex hass.states["number.pre_couloir_zone2_x_end"].state
      - $ex hass.states["number.pre_couloir_zone2_x_begin"].state
    'y':
      - $ex hass.states["number.pre_couloir_zone2_y_begin"].state
      - $ex hass.states["number.pre_couloir_zone2_y_end"].state
      - $ex hass.states["number.pre_couloir_zone2_y_end"].state
      - $ex hass.states["number.pre_couloir_zone2_y_begin"].state
      - $ex hass.states["number.pre_couloir_zone2_y_begin"].state
  - entity: ''
    name: Zone3
    mode: lines
    fill: toself
    fillcolor: RGBA(200,120,55,0.1)
    line:
      color: RGBA(200,120,55,0.2)
      shape: line
      width: 2
    x:
      - $ex hass.states["number.pre_couloir_zone3_x_begin"].state
      - $ex hass.states["number.pre_couloir_zone3_x_begin"].state
      - $ex hass.states["number.pre_couloir_zone3_x_end"].state
      - $ex hass.states["number.pre_couloir_zone3_x_end"].state
      - $ex hass.states["number.pre_couloir_zone3_x_begin"].state
    'y':
      - $ex hass.states["number.pre_couloir_zone3_y_begin"].state
      - $ex hass.states["number.pre_couloir_zone3_y_end"].state
      - $ex hass.states["number.pre_couloir_zone3_y_end"].state
      - $ex hass.states["number.pre_couloir_zone3_y_begin"].state
      - $ex hass.states["number.pre_couloir_zone3_y_begin"].state
  - entity: ''
    name: ExZone
    mode: lines
    fill: toself
    fillcolor: RGBA(255,0,0,0.1)
    line:
      shape: line
      width: 1
      color: RGBA(255,0,0,0.1)
    x:
      - $ex hass.states["number.pre_couloir_zout1_x_begin"].state
      - $ex hass.states["number.pre_couloir_zout1_x_begin"].state
      - $ex hass.states["number.pre_couloir_zout1_x_end"].state
      - $ex hass.states["number.pre_couloir_zout1_x_end"].state
      - $ex hass.states["number.pre_couloir_zout1_x_begin"].state
    'y':
      - $ex hass.states["number.pre_couloir_zout1_y_begin"].state
      - $ex hass.states["number.pre_couloir_zout1_y_end"].state
      - $ex hass.states["number.pre_couloir_zout1_y_end"].state
      - $ex hass.states["number.pre_couloir_zout1_y_begin"].state
      - $ex hass.states["number.pre_couloir_zout1_y_begin"].state
  - entity: ''
    name: Coverage
    mode: lines
    fill: tonexty
    fillcolor: rgba(168, 216, 234, 0.08)
    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

Bon il reste quand même à trouver, faire une boite pour installation dans un angle, avec un pied de capteur de mouvement aqara etc…

2 « J'aime »

merci @jerome6994 pour le plotly-graph :star_struck:

2 « J'aime »

Merci pour la carte ploty-graph

De rien c’est avec plaisir
Partage du visuel et de son code me semble juste et normal quand on voit l’aide que chacun donne ici ou ailleurs

Bonjour,
C’est mon papa qui me fait mes modules et voila le code qu’il a utilisé, j’ai lu plus haut qu’il était possible d’ajouter plus de 3 zones. Qu’est ce que je doit ajouter au code pour avoir une 4eme zone ?.

Avez aussi trouver si il était possible tous comme le LD2410 de jouer sur la sensibilité static target, impossible de trouver ce réglage même avec l’application bluethoot et il arrive que lorsqu’on reste immobile le capteur ne nous détecte plus. Avec le 2410 et le réglage de sensibilité rien qu’en respirant le graphique de sensibilité detecte notre respiration ( mouvement)

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:
  encryption:
    key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx="

ota:
  password: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
#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
  baud_rate: 0

esp32:
  board: esp32dev
  framework:
    type: arduino

wifi:
  networks:
  - ssid: !secret wifi_ssid
    password: !secret wifi_password
    priority: 2
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "presenceseba Fallback Hotspot"
    password: "connection"
  output_power: 10dB

captive_portal:

web_server:
  port: 80


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: "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: debug
    reset_reason:
      name: "ESP Reset Reason"
      icon: mdi:anchor
      disabled_by_default: True
  - 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;
  - 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
    
  - platform: gpio
    pin: 
      number: 18
    name: "PIR Sensor"
    device_class: motion

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: 7500
    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: 7500
    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: 7500
    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: 7500
    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: 7500
    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: 7500
    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: 7500
    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: 7500
    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;
          }
    

Avez aussi trouver si il était possible tous comme le LD2410 de jouer sur la sensibilité static target,

La doc du LD2450 ne parle d’aucun réglage que se soit. Et donc pas de la sensibilité.

Pour les zones, il faut se mettre dans le code. Je me suis remis à travaillé sur le LD 2450 depuis hier. Je pense que d’ici le WE prochain, je pourrais fournir un nouveau code avec 6 zones de détections et 3 d’exclusions

5 « J'aime »

Comme promis voilà la mise à jour du code. Il y a maintenant six zones de détections et trois d’exclusions.

J’ai aussi mis à jour la carte qui permet de visualiser ce que voit le capteur. Il fonctionne avec la carte « Plotly-graph » que l’on peut installer dans HACS avec le dépôt du même nom.
Les zones d’exclusion n’apparaissent sur la carte que si ils sont activés dans l’ESP32.

Le GitHub est à jour

Plotly-graph

Dans l’exemple ci-dessus, Zout1 est un frigo et son déclenchement pourrait provoquer un faux positif. Zout2 et 3 sont des fenêtres équipées de rideaux. J’ai ajouté dans Home assistant une automatisation qui active uniquement ces deux zones d’exclusion lorsque les fenêtres sont ouvertes, évitant ainsi que les rideaux soient détectés en faux positif à cause du vent.

La Zone3, à cheval sur la Zone1 et 2, quant à elle est situé sur une porte. Elle permet d’allumer la lumière de la pièce dans laquelle on arrive avant même d’être rentré dedans, évitant ainsi un décalage d’une seconde à l’allumage.

La zone en pointillé gris clair représente la zone de détection approximative du capteur. Son motif en forme de poire provient de la documentation de HLK. Elle permet de comprendre que la zone optimale de détections est de 6 mètres mais que l’on peut aller un peu plus loin en pratique.

ESP32

#https://github.com/Emile86/HLK-2450/blob/main/2450.yaml
#https://community.home-assistant.io/t/hlk-ld2450-initial-experiments-to-connect-to-homeassistant/578878/185?page=10
substitutions:
  devicename: hpsz-room
  
#ESP32/LD2450 : Human Presence Sensor by Zone
esphome:
  name: $devicename
  comment: Human Presence Sensor by Zone (ESP32/LD2450)
  #name_add_mac_suffix: True
  platformio_options:
    board_build.flash_mode: dio
    # board_build.f_cpu: 80000000L
  project: 
    name: 53l3cu5.Human_Presence_Sensor_by_Zone
    version: 2.O
  on_boot:
    - priority: -200
      then:
        lambda: |-
          id(zone1_target_exsits).publish_state(false);
          id(zone2_target_exsits).publish_state(false);
          id(zone3_target_exsits).publish_state(false);
          id(zone4_target_exsits).publish_state(false);
          id(zone5_target_exsits).publish_state(false);
          id(zone6_target_exsits).publish_state(false);
          id(zone_ex1_target_exsits).publish_state(false);
          id(zone_ex2_target_exsits).publish_state(false);
          id(zone_ex3_target_exsits).publish_state(false);

preferences:
    flash_write_interval: 5s
  

esp32:
  board: esp32dev

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"
  - id: last_illuminance
    type: float
    restore_value: no
    initial_value: "-1"
  - id: last_illuminance_timestamp
    type: int
    restore_value: no
    initial_value: "-1"

improv_serial:
  
logger:

debug:
  update_interval: 30s

api:
  encryption:
    key: "Xd8KczJ8qKVYtAjyh3zVPar7zF8pkmZeOpnHSfjOqwA="
ota:
  # use your own ota password plz. this is a words by Socrates.
  password: !secret ota_password
  safe_mode: False

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  power_save_mode: LIGHT
  reboot_timeout: 10min
  ap:
    ssid: "${devicename} Hotspot"
    password: !secret hotspot_password

captive_portal:

web_server:
  port: 80
  
text_sensor:
  - platform: debug
    reset_reason:
      name: "ESP Reset Reason"
      icon: mdi:anchor
      disabled_by_default: True
  - platform: wifi_info
    ip_address:
      name: ESP IP Address
      entity_category: "diagnostic"
      disabled_by_default: True
      icon: mdi:ip-network
    mac_address:
      name: ESP MAC
      entity_category: "diagnostic"
      icon: mdi:ip-network
      disabled_by_default: True
  - platform: template
    name: "Zone1 Info"
    id: tips_zone1_conf
    icon: mdi:information-outline
    entity_category: config
    lambda: |-
      return {"Configure below" };
    update_interval: 1000s
  - platform: template
    name: "Zone2 Info"
    id: tips_zone2_conf
    icon: mdi:information-outline
    entity_category: config
    lambda: |-
      return {"Configure below" };
    update_interval: 1000s
  - platform: template
    name: "Zone3 Info"
    id: tips_zone3_conf
    icon: mdi:information-outline
    entity_category: config
  - platform: template
    name: "Zone4 Info"
    id: tips_zone4_conf
    icon: mdi:information-outline
    entity_category: config
    lambda: |-
      return {"Configure below" };
    update_interval: 1000s
  - platform: template
    name: "Zone5 Info"
    id: tips_zone5_conf
    icon: mdi:information-outline
    entity_category: config
    lambda: |-
      return {"Configure below" };
    update_interval: 1000s
  - platform: template
    name: "Zone6 Info"
    id: tips_zone6_conf
    icon: mdi:information-outline
    entity_category: config
    lambda: |-
      return {"Configure below" };
    update_interval: 1000s
  - platform: template
    name: "Zout1 Info"
    id: tips_zone_ex1_conf
    icon: mdi:information-outline
    entity_category: config
    lambda: |-
      return {"Zone Exclusion 1" };
    update_interval: 1000s
  - platform: template
    name: "Zout2 Info"
    id: tips_zone_ex2_conf
    icon: mdi:information-outline
    entity_category: config
    lambda: |-
      return {"Zone Exclusion 2" };
    update_interval: 1000s
  - platform: template
    name: "Zout3 Info"
    id: tips_zone_ex3_conf
    icon: mdi:information-outline
    entity_category: config
    lambda: |-
      return {"Zone Exclusion 3" };
    update_interval: 1000s
  - platform: template
    name: "Any-Presence Info"
    id: tips_any_presence_conf
    icon: mdi:information-outline
    entity_category: config
    lambda: |-
      return {"Any Presence Config" };
    update_interval: 1000s
  - platform: template
    name: "Target1 Direction"
    id: target1_direction
    icon: mdi:directions
  - platform: template
    name: "Target2 Direction"
    id: target2_direction
    icon: mdi:directions
  - platform: template
    name: "Target3 Direction"
    id: target3_direction
    icon: mdi:directions
  - platform: template
    name: "Target1 Position"
    id: target1_position
    icon: mdi:directions
  - platform: template
    name: "Target2 Position"
    id: target2_position
    icon: mdi:directions
  - platform: template
    name: "Target3 Position"
    id: target3_position
    icon: mdi:directions

number:
  - platform: template
    name: "Any Presence Timeout"
    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"
    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: "Zone2 Timeout"
    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: "Zone3 Timeout"
    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: "Zone4 Timeout"
    id: zone4_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: "Zone5 Timeout"
    id: zone5_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: "Zone6 Timeout"
    id: zone6_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
    
  # Zone 1
  - platform: template
    name: Zone1 X-Begin
    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
    on_value: 
      then:
        - script.execute: check_zone1_vaild
  - platform: template
    name: Zone1 X-End
    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
    on_value: 
      then:
        - script.execute: check_zone1_vaild
  - platform: template
    name: Zone1 Y-Begin
    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
    on_value: 
      then:
        - script.execute: check_zone1_vaild
  - platform: template
    name: Zone1 Y-End
    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
    on_value: 
      then:
        - script.execute: check_zone1_vaild
    
  # Zone 2
  - platform: template
    name: Zone2 X-Begin
    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
    on_value: 
      then:
        - script.execute: check_zone2_vaild
  - platform: template
    name: Zone2 X-End
    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
    on_value: 
      then:
        - script.execute: check_zone2_vaild
  - platform: template
    name: Zone2 Y-Begin
    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
    on_value: 
      then:
        - script.execute: check_zone2_vaild
  - platform: template
    name: Zone2 Y-End
    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
    on_value: 
      then:
        - script.execute: check_zone2_vaild
    
  # Zone 3
  - platform: template
    name: Zone3 X-Begin
    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
    on_value: 
      then:
        - script.execute: check_zone3_vaild
  - platform: template
    name: Zone3 X-End
    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
    on_value: 
      then:
        - script.execute: check_zone3_vaild
  - platform: template
    name: Zone3 Y-Begin
    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
    on_value: 
      then:
        - script.execute: check_zone3_vaild
  - platform: template
    name: Zone3 Y-End
    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
    on_value: 
      then:
        - script.execute: check_zone3_vaild
    
  # Zone 4
  - platform: template
    name: Zone4 X-Begin
    id: zone4_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
    on_value: 
      then:
        - script.execute: check_zone4_vaild
  - platform: template
    name: Zone4 X-End
    id: zone4_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
    on_value: 
      then:
        - script.execute: check_zone4_vaild
  - platform: template
    name: Zone4 Y-Begin
    id: zone4_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
    on_value: 
      then:
        - script.execute: check_zone4_vaild
  - platform: template
    name: Zone4 Y-End
    id: zone4_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
    on_value: 
      then:
        - script.execute: check_zone4_vaild
    
  # Zone 5
  - platform: template
    name: Zone5 X-Begin
    id: zone5_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
    on_value: 
      then:
        - script.execute: check_zone5_vaild
  - platform: template
    name: Zone5 X-End
    id: zone5_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
    on_value: 
      then:
        - script.execute: check_zone5_vaild
  - platform: template
    name: Zone5 Y-Begin
    id: zone5_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
    on_value: 
      then:
        - script.execute: check_zone5_vaild
  - platform: template
    name: Zone5 Y-End
    id: zone5_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
    on_value: 
      then:
        - script.execute: check_zone5_vaild
    
  # Zone 6
  - platform: template
    name: Zone6 X-Begin
    id: zone6_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
    on_value: 
      then:
        - script.execute: check_zone6_vaild
  - platform: template
    name: Zone6 X-End
    id: zone6_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
    on_value: 
      then:
        - script.execute: check_zone6_vaild
  - platform: template
    name: Zone6 Y-Begin
    id: zone6_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
    on_value: 
      then:
        - script.execute: check_zone6_vaild
  - platform: template
    name: Zone6 Y-End
    id: zone6_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
    on_value: 
      then:
        - script.execute: check_zone6_vaild
    
  # Zout1
  - platform: template
    name: Zout1 X-Begin
    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
    on_value: 
      then:
        - script.execute: check_zout1_vaild
  - platform: template
    name: Zout1 X-End
    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
    on_value: 
      then:
        - script.execute: check_zout1_vaild
  - platform: template
    name: Zout1 Y-Begin
    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
    on_value: 
      then:
        - script.execute: check_zout1_vaild
  - platform: template
    name: Zout1 Y-End
    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
    on_value: 
      then:
        - script.execute: check_zout1_vaild
    
  # Zout2
  - platform: template
    name: Zout2 X-Begin
    id: zone_ex2_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
    on_value: 
      then:
        - script.execute: check_zout2_vaild
  - platform: template
    name: Zout2 X-End
    id: zone_ex2_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
    on_value: 
      then:
        - script.execute: check_zout2_vaild
  - platform: template
    name: Zout2 Y-Begin
    id: zone_ex2_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
    on_value: 
      then:
        - script.execute: check_zout2_vaild
  - platform: template
    name: Zout2 Y-End
    id: zone_ex2_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
    on_value: 
      then:
        - script.execute: check_zout2_vaild
    
  # Zout3
  - platform: template
    name: Zout3 X-Begin
    id: zone_ex3_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
    on_value: 
      then:
        - script.execute: check_zout3_vaild
  - platform: template
    name: Zout3 X-End
    id: zone_ex3_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
    on_value: 
      then:
        - script.execute: check_zout3_vaild
  - platform: template
    name: Zout3 Y-Begin
    id: zone_ex3_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
    on_value: 
      then:
        - script.execute: check_zout3_vaild
  - platform: template
    name: Zout3 Y-End
    id: zone_ex3_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
    on_value: 
      then:
        - script.execute: check_zout3_vaild

binary_sensor:
  - platform: status
    name: Online
    id: ink_ha_connected
  - platform: template
    name: "Any Presence"
    id: any_target_exsits
    device_class: occupancy
    filters:
      - delayed_off: !lambda |-
          if (!id(init_zone_publish) || !id(zone_fn_enable).state) {
            return 0;
          };
          return id(any_presence_timeout).state * 1000.0;
  - platform: template
    name: "Zone1 Presence"
    id: zone1_target_exsits
    device_class: occupancy
    filters:
      - delayed_off: !lambda |-
          if (!id(init_zone_publish) || !id(zone_fn_enable).state) {
            return 0;
          }
          return id(zone1_x_timeout).state * 1000.0;
  - platform: template
    name: "Zone2 Presence"
    id: zone2_target_exsits
    device_class: occupancy
    filters:
      - delayed_off: !lambda |-
          if (!id(init_zone_publish) || !id(zone_fn_enable).state) {
            return 0;
          }
          return id(zone2_x_timeout).state * 1000.0;
  - platform: template
    name: "Zone3 Presence"
    id: zone3_target_exsits
    device_class: occupancy
    filters:
      - delayed_off: !lambda |-
          if (!id(init_zone_publish) || !id(zone_fn_enable).state) {
            return 0;
          }
          return id(zone3_x_timeout).state * 1000.0;
  - platform: template
    name: "Zone4 Presence"
    id: zone4_target_exsits
    device_class: occupancy
    filters:
      - delayed_off: !lambda |-
          if (!id(init_zone_publish) || !id(zone_fn_enable).state) {
            return 0;
          }
          return id(zone4_x_timeout).state * 1000.0;
  - platform: template
    name: "Zone5 Presence"
    id: zone5_target_exsits
    device_class: occupancy
    filters:
      - delayed_off: !lambda |-
          if (!id(init_zone_publish) || !id(zone_fn_enable).state) {
            return 0;
          }
          return id(zone5_x_timeout).state * 1000.0;
  - platform: template
    name: "Zone6 Presence"
    id: zone6_target_exsits
    device_class: occupancy
    filters:
      - delayed_off: !lambda |-
          if (!id(init_zone_publish) || !id(zone_fn_enable).state) {
            return 0;
          }
          return id(zone6_x_timeout).state * 1000.0;
  - platform: template
    name: "Zout1 Presence"
    id: zone_ex1_target_exsits
    icon: mdi:account-multiple-remove
    device_class: occupancy
  - platform: template
    name: "Zout2 Presence"
    id: zone_ex2_target_exsits
    icon: mdi:account-multiple-remove
    device_class: occupancy
  - platform: template
    name: "Zout3 Presence"
    id: zone_ex3_target_exsits
    icon: mdi:account-multiple-remove
    device_class: occupancy

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_zone4_vaild
    then:
      - lambda: |-
          if (id(zone4_x_begin).state > id(zone4_x_end).state){
            id(tips_zone4_conf).publish_state("Err: X-Begin > X-End");
            return;
          }
          if (id(zone4_y_begin).state > id(zone4_y_end).state){
            id(tips_zone4_conf).publish_state("Err: Y-Begin > Y-End");
            return;
          }
          if (id(zone4_x_begin).state == 0 && id(zone4_x_end).state == 0 && id(zone4_y_begin).state == 0 && id(zone4_y_end).state == 0){
            id(tips_zone4_conf).publish_state("Configure below");
            return;
          }

          int x_size = id(zone4_x_end).state - id(zone4_x_begin).state;
          int y_size = id(zone4_y_end).state - id(zone4_y_begin).state;

          char combined[80]; 
          sprintf(combined, "Curr Size: %d x %d", x_size, y_size);
          id(tips_zone4_conf).publish_state(combined);
  - id: check_zone5_vaild
    then:
      - lambda: |-
          if (id(zone5_x_begin).state > id(zone5_x_end).state){
            id(tips_zone5_conf).publish_state("Err: X-Begin > X-End");
            return;
          }
          if (id(zone5_y_begin).state > id(zone5_y_end).state){
            id(tips_zone5_conf).publish_state("Err: Y-Begin > Y-End");
            return;
          }
          if (id(zone5_x_begin).state == 0 && id(zone5_x_end).state == 0 && id(zone5_y_begin).state == 0 && id(zone5_y_end).state == 0){
            id(tips_zone5_conf).publish_state("Configure below");
            return;
          }

          int x_size = id(zone5_x_end).state - id(zone5_x_begin).state;
          int y_size = id(zone5_y_end).state - id(zone5_y_begin).state;

          char combined[80]; 
          sprintf(combined, "Curr Size: %d x %d", x_size, y_size);
          id(tips_zone5_conf).publish_state(combined);
  - id: check_zone6_vaild
    then:
      - lambda: |-
          if (id(zone6_x_begin).state > id(zone6_x_end).state){
            id(tips_zone6_conf).publish_state("Err: X-Begin > X-End");
            return;
          }
          if (id(zone6_y_begin).state > id(zone6_y_end).state){
            id(tips_zone6_conf).publish_state("Err: Y-Begin > Y-End");
            return;
          }
          if (id(zone6_x_begin).state == 0 && id(zone6_x_end).state == 0 && id(zone6_y_begin).state == 0 && id(zone6_y_end).state == 0){
            id(tips_zone6_conf).publish_state("Configure below");
            return;
          }

          int x_size = id(zone6_x_end).state - id(zone6_x_begin).state;
          int y_size = id(zone6_y_end).state - id(zone6_y_begin).state;

          char combined[80]; 
          sprintf(combined, "Curr Size: %d x %d", x_size, y_size);
          id(tips_zone6_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");

  - id: check_zout2_vaild
    then:
      - lambda: |-
          if (id(zone_ex2_x_begin).state > id(zone_ex2_x_end).state){
            id(tips_zone_ex2_conf).publish_state("Err: X-Begin > X-End");
            return;
          }
          if (id(zone_ex2_y_begin).state > id(zone_ex2_y_end).state){
            id(tips_zone_ex2_conf).publish_state("Err: Y-Begin > Y-End");
            return;
          }
          id(tips_zone_ex2_conf).publish_state("Zone Exclusion 2");

  - id: check_zout3_vaild
    then:
      - lambda: |-
          if (id(zone_ex3_x_begin).state > id(zone_ex3_x_end).state){
            id(tips_zone_ex3_conf).publish_state("Err: X-Begin > X-End");
            return;
          }
          if (id(zone_ex3_y_begin).state > id(zone_ex3_y_end).state){
            id(tips_zone_ex3_conf).publish_state("Err: Y-Begin > Y-End");
            return;
          }
          id(tips_zone_ex3_conf).publish_state("Zone Exclusion 3");

sensor:
  - platform: uptime
    name: ESP Uptime
    id: sys_uptime
    update_interval: 60s
    disabled_by_default: True
  - platform: wifi_signal 
    name: RSSI
    id: wifi_signal_db
    update_interval: 60s
    entity_category: "diagnostic"
    
#-------------------------------------#
  # Advanced radar data
  - platform: template
    name: "All Target Counts"
    id: all_target_count
    accuracy_decimals: 0
    icon: "mdi:counter"
    unit_of_measurement: "targets"
  - platform: template
    name: "Zone1 Target Counts"
    id: zone1_target_count
    accuracy_decimals: 0
    icon: "mdi:counter"
    unit_of_measurement: "targets"
  - platform: template
    name: "Zone2 Target Counts"
    id: zone2_target_count
    accuracy_decimals: 0
    icon: "mdi:counter"
    unit_of_measurement: "targets"
  - platform: template
    name: "Zone3 Target Counts"
    id: zone3_target_count
    accuracy_decimals: 0
    icon: "mdi:counter"
    unit_of_measurement: "targets"
  - platform: template
    name: "Zone4 Target Counts"
    id: zone4_target_count
    accuracy_decimals: 0
    icon: "mdi:counter"
    unit_of_measurement: "targets"
  - platform: template
    name: "Zone5 Target Counts"
    id: zone5_target_count
    accuracy_decimals: 0
    icon: "mdi:counter"
    unit_of_measurement: "targets"
  - platform: template
    name: "Zone6 Target Counts"
    id: zone6_target_count
    accuracy_decimals: 0
    icon: "mdi:counter"
    unit_of_measurement: "targets"
  - platform: template
    name: "Zout1 Target Counts"
    id: zone_ex1_target_count
    accuracy_decimals: 0
    icon: mdi:account-multiple-minus-outline
    unit_of_measurement: "targets"
  - platform: template
    name: "Zout2 Target Counts"
    id: zone_ex2_target_count
    accuracy_decimals: 0
    icon: mdi:account-multiple-minus-outline
    unit_of_measurement: "targets"
  - platform: template
    name: "Zout3 Target Counts"
    id: zone_ex3_target_count
    accuracy_decimals: 0
    icon: mdi:account-multiple-minus-outline
    unit_of_measurement: "targets"

  # Target 1
  - platform: template
    name: "Target1 X"
    id: target1_x
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    icon: mdi:focus-field-horizontal
    device_class: distance
  - platform: template
    name: "Target1 Y"
    id: target1_y
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    device_class: distance
    icon: mdi:focus-field-vertical
  - platform: template
    name: "Target1 Speed"
    id: target1_speed
    accuracy_decimals: 2
    unit_of_measurement: 'm/s'
    state_class: measurement
    device_class: speed
  - platform: template
    name: "Target1 Resolution"
    id: target1_resolution
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    device_class: distance
  
  # Target 2
  - platform: template
    name: "Target2 X"
    id: target2_x
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    device_class: distance
    icon: mdi:focus-field-horizontal
  - platform: template
    name: "Target2 Y"
    id: target2_y
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    device_class: distance
    icon: mdi:focus-field-vertical
  - platform: template
    name: "Target2 Speed"
    id: target2_speed
    accuracy_decimals: 0
    unit_of_measurement: 'm/s'
    state_class: measurement
    device_class: speed
  - platform: template
    name: "Target2 Resolution"
    id: target2_resolution
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    device_class: distance

  # Target 3
  - platform: template
    name: "Target3 X"
    id: target3_x
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    device_class: distance
    icon: mdi:focus-field-horizontal
  - platform: template
    name: "Target3 Y"
    id: target3_y
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    device_class: distance
    icon: mdi:focus-field-vertical
  - platform: template
    name: "Target3 Speed"
    id: target3_speed
    accuracy_decimals: 0
    unit_of_measurement: 'm/s'
    state_class: measurement
    device_class: speed
  - platform: template
    name: "Target3 Resolution"
    id: target3_resolution
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    device_class: distance
  - platform: template
    name: "Target1 Angle"
    id: target1_angle
    unit_of_measurement: 'º'
    accuracy_decimals: 1
    icon: mdi:angle-acute
  - platform: template
    name: "Target2 Angle"
    id: target2_angle
    accuracy_decimals: 1
    unit_of_measurement: 'º'
    icon: mdi:angle-acute
  - platform: template
    name: "Target3 Angle"
    id: target3_angle
    accuracy_decimals: 1
    unit_of_measurement: 'º'
    icon: mdi:angle-acute

light:
  - platform: status_led
    name: sys_status
    pin: GPIO13
    internal: True
    restore_mode: ALWAYS_OFF
  - platform: binary
    name: "Red Info Light"
    output: board_info_ed
    entity_category: diagnostic
    restore_mode: ALWAYS_OFF
    disabled_by_default: True
time:
  - platform: sntp
    id: time_now

output:
  - platform: gpio
    id: board_info_ed
    pin: GPIO12

switch:
#  - platform: factory_reset
#    name: Factory Reset
#    disabled_by_default: True
#    icon: mdi:heart-broken
#    entity_category: diagnostic
  - platform: template
    name: Zout1 Enable
    id: zone_ex1_enable
    optimistic: True
    icon: mdi:account-cancel
    entity_category: config
    restore_mode: RESTORE_DEFAULT_OFF
  - platform: template
    name: Zout2 Enable
    id: zone_ex2_enable
    optimistic: True
    icon: mdi:account-cancel
    entity_category: config
    restore_mode: RESTORE_DEFAULT_OFF
  - platform: template
    name: Zout3 Enable
    id: zone_ex3_enable
    optimistic: True
    icon: mdi:account-cancel
    entity_category: config
    restore_mode: RESTORE_DEFAULT_OFF
  - platform: template
    name: Target Enable
    id: target_fn_enable
    optimistic: True
    icon: mdi:target-variant
    entity_category: config
    restore_mode: RESTORE_DEFAULT_ON
  - platform: template
    name: Zone Enable
    id: zone_fn_enable
    optimistic: True
    icon: mdi:target-variant
    entity_category: config
    restore_mode: RESTORE_DEFAULT_ON
  - platform: template
    name: Illuminance Fast-Update
    id: bh1750_fast_update
    optimistic: True
    entity_category: diagnostic
    restore_mode: RESTORE_DEFAULT_OFF
    icon: mdi:run-fast
    disabled_by_default: True

button:
  - platform: restart
    icon: mdi:power-cycle
    name: "ESP Reboot"
    entity_category: diagnostic

uart:
  id: uart_bus
  tx_pin: 
    number: GPIO17
    mode:
      input: true
      pullup: true
  rx_pin: 
    number: GPIO16
    mode:
      input: true
      pullup: true
  baud_rate: 256000
  parity: NONE
  stop_bits: 1
  data_bits: 8
  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;
          }
          p1_x = p1_x * -1;

          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;
          }
          p2_x = p2_x * -1;

          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;
          }
          p3_x = p3_x * -1;

          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);

          // Zones exludes

          bool p1_zone_ex_enter = false;
          bool p2_zone_ex_enter = false;
          bool p3_zone_ex_enter = false;
          
          // 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;

          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);
          
          // zone exlude 2

          int16_t target_count_in_zone_ex2 = 0;

          int16_t zone_ex2_x_min = id(zone_ex2_x_begin).state;
          int16_t zone_ex2_x_max = id(zone_ex2_x_end).state;
          int16_t zone_ex2_y_min = id(zone_ex2_y_begin).state;
          int16_t zone_ex2_y_max = id(zone_ex2_y_end).state;

          if (id(zone_ex2_enable).state){
            if (p1_vaild){
              if (p1_x >= zone_ex2_x_min && p1_x <= zone_ex2_x_max && p1_y >= zone_ex2_y_min && p1_y <= zone_ex2_y_max){
                  p1_zone_ex_enter = true;
                  target_count_in_zone_ex2 ++;
              }
            }
            if (p2_vaild){
              if (p2_x >= zone_ex2_x_min && p2_x <= zone_ex2_x_max && p2_y >= zone_ex2_y_min && p2_y <= zone_ex2_y_max){
                  p2_zone_ex_enter = true;
                  target_count_in_zone_ex2 ++;
              }
            }
            if (p3_vaild){
              if (p3_x >= zone_ex2_x_min && p3_x <= zone_ex2_x_max && p3_y >= zone_ex2_y_min && p3_y <= zone_ex2_y_max){
                  p3_zone_ex_enter = true;
                  target_count_in_zone_ex2 ++;
              }
            }
          }

          bool has_target_in_zone_ex2 = (target_count_in_zone_ex2 > 0);
          
          // zone exlude 3

          int16_t target_count_in_zone_ex3 = 0;

          int16_t zone_ex3_x_min = id(zone_ex3_x_begin).state;
          int16_t zone_ex3_x_max = id(zone_ex3_x_end).state;
          int16_t zone_ex3_y_min = id(zone_ex3_y_begin).state;
          int16_t zone_ex3_y_max = id(zone_ex3_y_end).state;

          if (id(zone_ex3_enable).state){
            if (p1_vaild){
              if (p1_x >= zone_ex3_x_min && p1_x <= zone_ex3_x_max && p1_y >= zone_ex3_y_min && p1_y <= zone_ex3_y_max){
                  p1_zone_ex_enter = true;
                  target_count_in_zone_ex3 ++;
              }
            }
            if (p2_vaild){
              if (p2_x >= zone_ex3_x_min && p2_x <= zone_ex3_x_max && p2_y >= zone_ex3_y_min && p2_y <= zone_ex3_y_max){
                  p2_zone_ex_enter = true;
                  target_count_in_zone_ex3 ++;
              }
            }
            if (p3_vaild){
              if (p3_x >= zone_ex3_x_min && p3_x <= zone_ex3_x_max && p3_y >= zone_ex3_y_min && p3_y <= zone_ex3_y_max){
                  p3_zone_ex_enter = true;
                  target_count_in_zone_ex3 ++;
              }
            }
          }

          bool has_target_in_zone_ex3 = (target_count_in_zone_ex3 > 0);

          // all targets

          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);

          // zones check

          int16_t target_count_in_zone1 = 0;
          bool has_target_in_zone1 = false;

          int16_t target_count_in_zone2 = 0;
          bool has_target_in_zone2 = false;

          int16_t target_count_in_zone3 = 0;
          bool has_target_in_zone3 = false;

          int16_t target_count_in_zone4 = 0;
          bool has_target_in_zone4 = false;

          int16_t target_count_in_zone5 = 0;
          bool has_target_in_zone5 = false;

          int16_t target_count_in_zone6 = 0;
          bool has_target_in_zone6 = false;

          if (id(zone_fn_enable).state){

            // zone 1 check

            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 ++;
              }
            }
            has_target_in_zone1 = (target_count_in_zone1 > 0);

            // zone 2 check

            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 ++;
              }
            }

            has_target_in_zone2 = (target_count_in_zone2 > 0);

            // zone 3 check

            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 ++;
              }
            }
            has_target_in_zone3 = (target_count_in_zone3 > 0);

            // zone 4 check

            int16_t zone4_x_min = id(zone4_x_begin).state;
            int16_t zone4_x_max = id(zone4_x_end).state;
            int16_t zone4_y_min = id(zone4_y_begin).state;
            int16_t zone4_y_max = id(zone4_y_end).state;

            if (p1_vaild && !p1_zone_ex_enter){
              if (p1_x >= zone4_x_min && p1_x <= zone4_x_max && p1_y >= zone4_y_min && p1_y <= zone4_y_max){
                  target_count_in_zone4 ++;
              }
            }
            if (p2_vaild && !p2_zone_ex_enter){
              if (p2_x >= zone4_x_min && p2_x <= zone4_x_max && p2_y >= zone4_y_min && p2_y <= zone4_y_max){
                  target_count_in_zone4 ++;
              }
            }
            if (p3_vaild && !p3_zone_ex_enter){
              if (p3_x >= zone4_x_min && p3_x <= zone4_x_max && p3_y >= zone4_y_min && p3_y <= zone4_y_max){
                  target_count_in_zone4 ++;
              }
            }
            has_target_in_zone4 = (target_count_in_zone4 > 0);

            // zone 5 check

            int16_t zone5_x_min = id(zone5_x_begin).state;
            int16_t zone5_x_max = id(zone5_x_end).state;
            int16_t zone5_y_min = id(zone5_y_begin).state;
            int16_t zone5_y_max = id(zone5_y_end).state;

            if (p1_vaild && !p1_zone_ex_enter){
              if (p1_x >= zone5_x_min && p1_x <= zone5_x_max && p1_y >= zone5_y_min && p1_y <= zone5_y_max){
                  target_count_in_zone5 ++;
              }
            }
            if (p2_vaild && !p2_zone_ex_enter){
              if (p2_x >= zone5_x_min && p2_x <= zone5_x_max && p2_y >= zone5_y_min && p2_y <= zone5_y_max){
                  target_count_in_zone5 ++;
              }
            }
            if (p3_vaild && !p3_zone_ex_enter){
              if (p3_x >= zone5_x_min && p3_x <= zone5_x_max && p3_y >= zone5_y_min && p3_y <= zone5_y_max){
                  target_count_in_zone5 ++;
              }
            }

            has_target_in_zone5 = (target_count_in_zone5 > 0);

            // zone 6 check

            int16_t zone6_x_min = id(zone6_x_begin).state;
            int16_t zone6_x_max = id(zone6_x_end).state;
            int16_t zone6_y_min = id(zone6_y_begin).state;
            int16_t zone6_y_max = id(zone6_y_end).state;

            if (p1_vaild && !p1_zone_ex_enter){
              if (p1_x >= zone6_x_min && p1_x <= zone6_x_max && p1_y >= zone6_y_min && p1_y <= zone6_y_max){
                  target_count_in_zone6 ++;
              }
            }
            if (p2_vaild && !p2_zone_ex_enter){
              if (p2_x >= zone6_x_min && p2_x <= zone6_x_max && p2_y >= zone6_y_min && p2_y <= zone6_y_max){
                  target_count_in_zone6 ++;
              }
            }
            if (p3_vaild && !p3_zone_ex_enter){
              if (p3_x >= zone6_x_min && p3_x <= zone6_x_max && p3_y >= zone6_y_min && p3_y <= zone6_y_max){
                  target_count_in_zone6 ++;
              }
            }
            has_target_in_zone6 = (target_count_in_zone6 > 0);

          }

          // Angle, Position and Direction, idea from walberjunior.

          float p1_angle = 0;
          if (p1_vaild){
            p1_angle = ((float)p1_x / (float)p1_y) * 180 / M_PI;;
          }

          std::basic_string<char> p1_position = "Static";
          if (p1_speed > 0) {
            p1_position = "Moving away";
          } else if (p1_speed < 0) {
            p1_position = "Approaching";
          } 

          std::basic_string<char> p1_direction = "None";
          if (p1_x > 0) {
            p1_direction = "Right";
          } else if (p1_x < 0) {
            p1_direction = "Left";
          } else if (p1_y > 0){
            p1_direction = "Middle";
          }

          float p2_angle = 0;
          if (p2_vaild){
            p2_angle = ((float)p2_x / (float)p2_y) * 180 / M_PI;;
          }

          std::basic_string<char> p2_position = "Static";;
          if (p2_speed > 0) {
            p2_position = "Moving away";
          } else if (p2_speed < 0) {
            p2_position = "Approaching";
          } 
          
          std::basic_string<char> p2_direction = "None";
          if (p2_x > 0) {
            p2_direction = "Right";
          } else if (p2_x < 0) {
            p2_direction = "Left";
          } else if (p2_y > 0){
            p2_direction = "Middle";
          }

          float p3_angle = 0;
          if (p3_vaild){
            p3_angle = ((float)p3_x / (float)p3_y) * 180 / M_PI;;
          }
          
          std::basic_string<char> p3_position = "Static";;
          if (p3_speed > 0) {
            p3_position = "Moving away";
          } else if (p3_speed < 0) {
            p3_position = "Approaching";
          } 

          std::basic_string<char> p3_direction = "None";
          if (p3_x > 0) {
            p3_direction = "Right";
          } else if (p3_x < 0) {
            p3_direction = "Left";
          } else if (p3_y > 0){
            p3_direction = "Middle";
          }

          if (id(target1_angle).state != p1_angle && id(target_fn_enable).state){
            id(target1_angle).publish_state(p1_angle);
          }
          if (id(target2_angle).state != p2_angle && id(target_fn_enable).state){
            id(target2_angle).publish_state(p2_angle);
          }
          if (id(target3_angle).state != p3_angle && id(target_fn_enable).state){
            id(target3_angle).publish_state(p3_angle);
          }

          if (p1_position != id(target1_position).state && id(target_fn_enable).state){
            id(target1_position).publish_state(p1_position);
          }
          if (p2_position != id(target2_position).state && id(target_fn_enable).state){
            id(target2_position).publish_state(p2_position);
          }
          if (p3_position != id(target3_position).state && id(target_fn_enable).state){
            id(target3_position).publish_state(p3_position);
          }

          if (p1_direction != id(target1_direction).state && id(target_fn_enable).state){
            id(target1_direction).publish_state(p1_direction);
          }
          if (p2_direction != id(target2_direction).state && id(target_fn_enable).state){
            id(target2_direction).publish_state(p2_direction);
          }
          if (p3_direction != id(target3_direction).state && id(target_fn_enable).state){
            id(target3_direction).publish_state(p3_direction);
          }

          // public all info

          if (id(target1_x).state != p1_x && id(target_fn_enable).state){
            id(target1_x).publish_state(p1_x);
          }
          if (id(target1_y).state != p1_y && id(target_fn_enable).state){
            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(target_fn_enable).state){
            id(target1_speed).publish_state(p1_m_speed);
          }
          if (id(target1_resolution).state != p1_distance_resolution && id(target_fn_enable).state){
            id(target1_resolution).publish_state(p1_distance_resolution);
          }

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

          if (id(target3_x).state != p3_x && id(target_fn_enable).state){
            id(target3_x).publish_state(p3_x);
          }
          if (id(target3_y).state != p3_y && id(target_fn_enable).state){
            id(target3_y).publish_state(p3_y);
          }
          if (id(target3_speed).state != p3_speed && id(target_fn_enable).state){
            id(target3_speed).publish_state(p3_speed);
          }
          if (id(target3_resolution).state != p3_distance_resolution && id(target_fn_enable).state){
            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);
          }

          if (id(zone4_target_count).state != target_count_in_zone4){
            id(zone4_target_count).publish_state(target_count_in_zone4);
            id(zone4_target_exsits).publish_state(has_target_in_zone4);
          }else if (id(zone4_target_exsits).state != has_target_in_zone4){
            id(zone4_target_exsits).publish_state(has_target_in_zone4);
          }

          if (id(zone5_target_count).state != target_count_in_zone5){
            id(zone5_target_count).publish_state(target_count_in_zone5);
            id(zone5_target_exsits).publish_state(has_target_in_zone5);
          }else if (id(zone5_target_exsits).state != has_target_in_zone5){
            id(zone5_target_exsits).publish_state(has_target_in_zone5);
          }

          if (id(zone6_target_count).state != target_count_in_zone6){
            id(zone6_target_count).publish_state(target_count_in_zone6);
            id(zone6_target_exsits).publish_state(has_target_in_zone6);
          }else if (id(zone6_target_exsits).state != has_target_in_zone6){
            id(zone6_target_exsits).publish_state(has_target_in_zone6);
          }
          
          // 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(zone_ex2_target_count).state != target_count_in_zone_ex2){
            id(zone_ex2_target_count).publish_state(target_count_in_zone_ex2);
          }
          if (id(zone_ex2_target_exsits).state != has_target_in_zone_ex2){
            id(zone_ex2_target_exsits).publish_state(has_target_in_zone_ex2);
          }
          
          if (id(zone_ex3_target_count).state != target_count_in_zone_ex3){
            id(zone_ex3_target_count).publish_state(target_count_in_zone_ex3);
          }
          if (id(zone_ex3_target_exsits).state != has_target_in_zone_ex3){
            id(zone_ex3_target_exsits).publish_state(has_target_in_zone_ex3);
          }

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

Carte Plotly-graph

type: custom:plotly-graph
title: LD2450
refresh_interval: 2
hours_to_show: current_day
ha_theme: true
layout:
  legend:
    'y': 8000
    orientation: h
  autosize: true
  margin:
    autoexpand: true
    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:
      - 8000
      - 0
entities:
  - entity: ''
    name: Person1
    show_value: true
    unit_of_measurement: mm
    marker:
      size: 12
    line:
      shape: spline
      width: 5
    x:
      - $ex hass.states["sensor.target1_x"].state
    'y':
      - $ex hass.states["sensor.target1_y"].state
  - entity: ''
    name: Person2
    show_value: true
    unit_of_measurement: mm
    marker:
      size: 12
    line:
      shape: spline
      width: 5
    x:
      - $ex hass.states["sensor.target2_x"].state
    'y':
      - $ex hass.states["sensor.target2_y"].state
  - entity: ''
    name: Person3
    show_value: true
    unit_of_measurement: mm
    marker:
      size: 12
    line:
      shape: spline
      width: 5
    x:
      - $ex hass.states["sensor.target3_x"].state
    'y':
      - $ex hass.states["sensor.target3_y"].state
  - entity: ''
    name: Zone1
    mode: lines
    fill: toself
    fillcolor: RGBA(20,200,0,0.1)
    line:
      color: RGBA(20,200,0,0.4)
      shape: line
      width: 2
    x:
      - $ex hass.states["number.zone1_x_begin"].state
      - $ex hass.states["number.zone1_x_begin"].state
      - $ex hass.states["number.zone1_x_end"].state
      - $ex hass.states["number.zone1_x_end"].state
      - $ex hass.states["number.zone1_x_begin"].state
    'y':
      - $ex hass.states["number.zone1_y_begin"].state
      - $ex hass.states["number.zone1_y_end"].state
      - $ex hass.states["number.zone1_y_end"].state
      - $ex hass.states["number.zone1_y_begin"].state
      - $ex hass.states["number.zone1_y_begin"].state
  - entity: ''
    name: Zone2
    mode: lines
    fill: toself
    fillcolor: RGBA(255,233,107,0.1)
    line:
      color: RGBA(255,233,107,0.4)
      shape: line
      width: 2
    x:
      - $ex hass.states["number.zone2_x_begin"].state
      - $ex hass.states["number.zone2_x_begin"].state
      - $ex hass.states["number.zone2_x_end"].state
      - $ex hass.states["number.zone2_x_end"].state
      - $ex hass.states["number.zone2_x_begin"].state
    'y':
      - $ex hass.states["number.zone2_y_begin"].state
      - $ex hass.states["number.zone2_y_end"].state
      - $ex hass.states["number.zone2_y_end"].state
      - $ex hass.states["number.zone2_y_begin"].state
      - $ex hass.states["number.zone2_y_begin"].state
  - entity: ''
    name: Zone3
    mode: lines
    fill: toself
    fillcolor: RGBA(0,137,207,0.1)
    line:
      color: RGBA(0,137,207,0.4)
      shape: line
      width: 2
    x:
      - $ex hass.states["number.zone3_x_begin"].state
      - $ex hass.states["number.zone3_x_begin"].state
      - $ex hass.states["number.zone3_x_end"].state
      - $ex hass.states["number.zone3_x_end"].state
      - $ex hass.states["number.zone3_x_begin"].state
    'y':
      - $ex hass.states["number.zone3_y_begin"].state
      - $ex hass.states["number.zone3_y_end"].state
      - $ex hass.states["number.zone3_y_end"].state
      - $ex hass.states["number.zone3_y_begin"].state
      - $ex hass.states["number.zone3_y_begin"].state
  - entity: ''
    name: Zone4
    mode: lines
    fill: toself
    fillcolor: RGBA(0,169,164,0.1)
    line:
      color: RGBA(0,169,164,0.4)
      shape: line
      width: 2
    x:
      - $ex hass.states["number.zone4_x_begin"].state
      - $ex hass.states["number.zone4_x_begin"].state
      - $ex hass.states["number.zone4_x_end"].state
      - $ex hass.states["number.zone4_x_end"].state
      - $ex hass.states["number.zone4_x_begin"].state
    'y':
      - $ex hass.states["number.zone4_y_begin"].state
      - $ex hass.states["number.zone4_y_end"].state
      - $ex hass.states["number.zone4_y_end"].state
      - $ex hass.states["number.zone4_y_begin"].state
      - $ex hass.states["number.zone4_y_begin"].state
  - entity: ''
    name: Zone5
    mode: lines
    fill: toself
    fillcolor: RGBA(244,143,159,0.1)
    line:
      color: RGBA(244,143,159,0.4)
      shape: line
      width: 2
    x:
      - $ex hass.states["number.zone5_x_begin"].state
      - $ex hass.states["number.zone5_x_begin"].state
      - $ex hass.states["number.zone5_x_end"].state
      - $ex hass.states["number.zone5_x_end"].state
      - $ex hass.states["number.zone5_x_begin"].state
    'y':
      - $ex hass.states["number.zone5_y_begin"].state
      - $ex hass.states["number.zone5_y_end"].state
      - $ex hass.states["number.zone5_y_end"].state
      - $ex hass.states["number.zone5_y_begin"].state
      - $ex hass.states["number.zone5_y_begin"].state
  - entity: ''
    name: Zone6
    mode: lines
    fill: toself
    fillcolor: RGBA(255,194,34,0.1)
    line:
      color: RGBA(255,194,34,0.4)
      shape: line
      width: 2
    x:
      - $ex hass.states["number.zone6_x_begin"].state
      - $ex hass.states["number.zone6_x_begin"].state
      - $ex hass.states["number.zone6_x_end"].state
      - $ex hass.states["number.zone6_x_end"].state
      - $ex hass.states["number.zone6_x_begin"].state
    'y':
      - $ex hass.states["number.zone6_y_begin"].state
      - $ex hass.states["number.zone6_y_end"].state
      - $ex hass.states["number.zone6_y_end"].state
      - $ex hass.states["number.zone6_y_begin"].state
      - $ex hass.states["number.zone6_y_begin"].state
  - entity: ''
    name: Zout1
    mode: lines
    fill: toself
    fillcolor: >-
      $ex hass.states["switch.zout1_enable"].state == "on" ?
      "RGBA(238,48,78,0.2)" : "RGBA(0,0,0,0)"
    line:
      color: >-
        $ex hass.states["switch.zout1_enable"].state == "on" ?
        "RGBA(0,137,207,0.4)" : "RGBA(0,0,0,0)" 
      width: 3
      dash: dash
    x:
      - $ex hass.states["number.zout1_x_begin"].state
      - $ex hass.states["number.zout1_x_begin"].state
      - $ex hass.states["number.zout1_x_end"].state
      - $ex hass.states["number.zout1_x_end"].state
      - $ex hass.states["number.zout1_x_begin"].state
    'y':
      - $ex hass.states["number.zout1_y_begin"].state
      - $ex hass.states["number.zout1_y_end"].state
      - $ex hass.states["number.zout1_y_end"].state
      - $ex hass.states["number.zout1_y_begin"].state
      - $ex hass.states["number.zout1_y_begin"].state
  - entity: ''
    name: Zout2
    mode: lines
    fill: toself
    fillcolor: >-
      $ex hass.states["switch.zout2_enable"].state == "on" ?
      "RGBA(215,11,140,0.2)" : "RGBA(0,0,0,0)" 
    line:
      color: >-
        $ex hass.states["switch.zout2_enable"].state == "on" ?
        "RGBA(215,11,140, 0.4)" : "RGBA(0,0,0,0)" 
      width: 3
      dash: dash
    x:
      - $ex hass.states["number.zout2_x_begin"].state
      - $ex hass.states["number.zout2_x_begin"].state
      - $ex hass.states["number.zout2_x_end"].state
      - $ex hass.states["number.zout2_x_end"].state
      - $ex hass.states["number.zout2_x_begin"].state
    'y':
      - $ex hass.states["number.zout2_y_begin"].state
      - $ex hass.states["number.zout2_y_end"].state
      - $ex hass.states["number.zout2_y_end"].state
      - $ex hass.states["number.zout2_y_begin"].state
      - $ex hass.states["number.zout2_y_begin"].state
  - entity: ''
    name: Zout3
    mode: lines
    fill: toself
    fillcolor: >-
      $ex hass.states["switch.zout2_enable"].state == "on" ?
      "RGBA(255,48,140,0.2)" : "RGBA(0,0,0,0)" 
    line:
      color: >-
        $ex hass.states["switch.zout2_enable"].state == "on" ?
        "RGBA(246,140,30,0.4)" : "RGBA(0,0,0,0)" 
      width: 3
      dash: dash
    x:
      - $ex hass.states["number.zout3_x_begin"].state
      - $ex hass.states["number.zout3_x_begin"].state
      - $ex hass.states["number.zout3_x_end"].state
      - $ex hass.states["number.zout3_x_end"].state
      - $ex hass.states["number.zout3_x_begin"].state
    'y':
      - $ex hass.states["number.zout3_y_begin"].state
      - $ex hass.states["number.zout3_y_end"].state
      - $ex hass.states["number.zout3_y_end"].state
      - $ex hass.states["number.zout3_y_begin"].state
      - $ex hass.states["number.zout3_y_begin"].state
  - entity: ''
    name: Coverage
    mode: lines
    line:
      width: 1
      color: rgba(100, 100, 100, .6)
      dash: dot
    x:
      - 0
      - 1000
      - 3700
      - 3500
      - 2000
      - 0
      - -2000
      - -3500
      - -3700
      - -1000
      - 0
    'y':
      - 0
      - 500
      - 3700
      - 6000
      - 7400
      - 8000
      - 7400
      - 6000
      - 3700
      - 500
      - 0
raw_plotly_config: true

4 « J'aime »

Super :+1:
Avec autant de zone cela ne dégrade pas trop la performance du capteur ?

1 « J'aime »