Tutoriel détecteur LD2450 esphome

Bon j’ai retourné le problème dans à peu près tous les sens et je suis arrivé à la conclusion que pour prendre en compte l’angle du capteur par rapport au mur, je ne peux plus continuer à prendre les coordonnées X et Y de fin de zone. Je dois prendre les coordonnées X et Y du début puis la longueur et la largeur de la zone. Avec ces quatre informations et celle de l’angle entre le mur et le capteur, je peux déterminer la zone.
Il me faudrait donc rajouter un nouveau champ Side wall angle pour l’angle et renommer tous Zone ? X-End en Zone ? Width et les Zone ? Y-End en Zone ? Height
Sans titre-1

newplot

Qui serait intéressé par cette modification

  • Oui, ça m’intéresse
  • Non merci
0 votant
1 « J'aime »

c’est a sacré boulot cette modif, forcement je suis intéressé :wink: :wink:

Je ne dis pas que je vais réussir. Les maths sont du niveaux du niveau collège mais le manque de pratique et aussi d’assiduité à l’époque :roll_eyes: se font sentir.
J’ai galéré avec les sinus et cosinus pour dessiner la forme, et c’était la partie facile. Je dois maintenant faire des calcules de vérification d’inclusions (le point est-il dans la zone) et là j’ai le sentiment d’avoir raté le cour…
La théorie est passionnante, mais j’ai un peu peur pour la pratique.

1 « J'aime »

Salut Selecus
Merci ton code que j’utilise depuis une semaine avec succès, comment fait tu pour avoir le graph ploty associé a un second LD2450?
Regard
Victor

Salut Victor,
Comme tu as pu le comprendre je ne suis pas à l’origine de ce code mais je l’ai modifié.
J’ai remarqué comme toi qu’il n’était pas franchement très pratique quand tu as plus d’un capteur à utiliser. Je travaille sur une nouvelle version qui facilitera le déploiement de plusieurs capteurs dans différentes pièces.

Je vais partir du principe que tu as déjà deux capteurs avec deux ESP32 (ou équivalent) en ta possession.
Lorsque tu es intègres à ESP Home le fichier YAML, home assistant ajoute un nouvel appareil. Ce dernier est constitué de plusieurs entités.
Chaque entité prend pour ID le titre de son champ. Par exemple Target1 X devient target1_x. Mais lorsque tu rajoutes un deuxième appareil, bien que les titres vont rester identiques l’ID, lui, ne peut pas être identique. Alors plutôt que de te poser la question comment tu veux le renommer, Home assistant ajoute un numéro à la fin de l’ID. Et donc, pour ton deuxième appareil Target1 X devient target1_x_2.

C’est ça que tu dois chercher dans le graphe et remplacer une fois que tu as trouvé l’ancien nom tu le remplaces par le nouveau
Donc

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

va devenir

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_2"].state
    'y':
      - $ex hass.states["sensor.target1_y_2].state

C’est en faisant ces remplacements que tu pourras utiliser plus d’un graphe

1 « J'aime »

Voici la nouvelle mise à jour !
Merci à @thebadboy et @jerome6994 de m’avoir aidé à tester le code avant de le diffuser

Plusieurs changements ont été faits :

  • On peu définir un angle si on n’a pas posé le capteur à plat contre un mur
  • La longueur maximum de détection est passé de 6 à 8 mètres et peut maintenant commencer à - 0,5 mètres
  • Le positionnement des zones ne fonctionnent plus avec le même système. Avant il y avait une zone X et Y minimum et une zone X et Y maximum. Maintenant il y a juste une position X et Y avec une longueur et une largeur
  • Chaque entité du capteur possède maintenant le nom de la pièce dans laquelle on l’intègre. Il faut choisir le nom de cette pièce manuellement. (entity_name: « Room »)
  • Le graphique est devenu plus interactif. Que la cible soit affichée soit ou non, quand quelqu’un est dans une zone, elle devient plus colorée.
  • Pour supporter tous ces changements, le code a été à écrire en profondeur avec des ajouts, des suppressions et des modifications. Il est maintenant nécessaire d’avoir un fichier supplémentaire à côté de notre fichier principal YAML. C’est une librairie de code.

Screenshot_20240420-162508_Zoom
Screenshot_20240420-155111_Zoom

Le graph

type: custom:plotly-graph
title: "Room:\_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.room_target1_x"].state
    'y':
      - $ex hass.states["sensor.room_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.room_target2_x"].state
    'y':
      - $ex hass.states["sensor.room_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.room_target3_x"].state
    'y':
      - $ex hass.states["sensor.room_target3_y"].state
  - entity: ''
    name: Zone1
    mode: lines
    fill: toself
    fillcolor: >-
      $ex hass.states["binary_sensor.room_zone1_presence"].state == "on" ?
      "RGBA(0,250,0,0.4)" : "RGBA(0,250,0,0.1)"
    line:
      color: RGBA(0,250,0,0.9)
      shape: line
      width: 2
    x:
      - $ex hass.states["number.room_zone1_x"].state*1
      - >-
        $ex hass.states["number.room_zone1_x"].state*1 -
        hass.states["number.room_zone1_width"].state *
        Math.cos((hass.states["number.room_angle"].state)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone1_x"].state*1 -
        hass.states["number.room_zone1_width"].state *
        Math.cos((hass.states["number.room_angle"].state)*3.1415/180) +
        hass.states["number.room_zone1_height"].state *
        Math.cos((hass.states["number.room_angle"].state*1-90)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone1_x"].state*1 +
        hass.states["number.room_zone1_height"].state *
        Math.cos((hass.states["number.room_angle"].state*1-90)*3.1415/180)
      - $ex hass.states["number.room_zone1_x"].state*1
    'y':
      - $ex hass.states["number.room_zone1_y"].state*1
      - >-
        $ex hass.states["number.room_zone1_y"].state*1 +
        hass.states["number.room_zone1_width"].state *
        Math.sin((hass.states["number.room_angle"].state)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone1_y"].state*1 +
        hass.states["number.room_zone1_width"].state *
        Math.sin((hass.states["number.room_angle"].state)*3.1415/180) +
        hass.states["number.room_zone1_height"].state *
        Math.sin((hass.states["number.room_angle"].state*1+90)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone1_y"].state*1 +
        hass.states["number.room_zone1_height"].state *
        Math.sin((hass.states["number.room_angle"].state*1+90)*3.1415/180)
      - $ex hass.states["number.room_zone1_y"].state*1
  - entity: ''
    name: Zone2
    mode: lines
    fill: toself
    fillcolor: >-
      $ex hass.states["binary_sensor.room_zone2_presence"].state == "on" ?
      "RGBA(250,110,0,0.4)" : "RGBA(250,110,0,0.1)"
    line:
      color: RGBA(250,110,0,0.9)
      shape: line
      width: 2
    x:
      - $ex hass.states["number.room_zone2_x"].state*1
      - >-
        $ex hass.states["number.room_zone2_x"].state*1 -
        hass.states["number.room_zone2_width"].state *
        Math.cos((hass.states["number.room_angle"].state)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone2_x"].state*1 -
        hass.states["number.room_zone2_width"].state *
        Math.cos((hass.states["number.room_angle"].state)*3.1415/180) +
        hass.states["number.room_zone2_height"].state *
        Math.cos((hass.states["number.room_angle"].state*1-90)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone2_x"].state*1 +
        hass.states["number.room_zone2_height"].state *
        Math.cos((hass.states["number.room_angle"].state*1-90)*3.1415/180)
      - $ex hass.states["number.room_zone2_x"].state*1
    'y':
      - $ex hass.states["number.room_zone2_y"].state*1
      - >-
        $ex hass.states["number.room_zone2_y"].state*1 +
        hass.states["number.room_zone2_width"].state *
        Math.sin((hass.states["number.room_angle"].state)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone2_y"].state*1 +
        hass.states["number.room_zone2_width"].state *
        Math.sin((hass.states["number.room_angle"].state)*3.1415/180) +
        hass.states["number.room_zone2_height"].state *
        Math.sin((hass.states["number.room_angle"].state*1+90)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone2_y"].state*1 +
        hass.states["number.room_zone2_height"].state *
        Math.sin((hass.states["number.room_angle"].state*1+90)*3.1415/180)
      - $ex hass.states["number.room_zone2_y"].state*1
  - entity: ''
    name: Zone3
    mode: lines
    fill: toself
    fillcolor: >-
      $ex hass.states["binary_sensor.room_zone3_presence"].state == "on" ?
      "RGBA(0,0,250,0.4)" : "RGBA(0,0,250,0.1)"
    line:
      color: RGBA(0,0,250,0.9)
      shape: line
      width: 2
    x:
      - $ex hass.states["number.room_zone3_x"].state*1
      - >-
        $ex hass.states["number.room_zone3_x"].state*1 -
        hass.states["number.room_zone3_width"].state *
        Math.cos((hass.states["number.room_angle"].state)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone3_x"].state*1 -
        hass.states["number.room_zone3_width"].state *
        Math.cos((hass.states["number.room_angle"].state)*3.1415/180) +
        hass.states["number.room_zone3_height"].state *
        Math.cos((hass.states["number.room_angle"].state*1-90)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone3_x"].state*1 +
        hass.states["number.room_zone3_height"].state *
        Math.cos((hass.states["number.room_angle"].state*1-90)*3.1415/180)
      - $ex hass.states["number.room_zone3_x"].state*1
    'y':
      - $ex hass.states["number.room_zone3_y"].state*1
      - >-
        $ex hass.states["number.room_zone3_y"].state*1 +
        hass.states["number.room_zone3_width"].state *
        Math.sin((hass.states["number.room_angle"].state)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone3_y"].state*1 +
        hass.states["number.room_zone3_width"].state *
        Math.sin((hass.states["number.room_angle"].state)*3.1415/180) +
        hass.states["number.room_zone3_height"].state *
        Math.sin((hass.states["number.room_angle"].state*1+90)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone3_y"].state*1 +
        hass.states["number.room_zone3_height"].state *
        Math.sin((hass.states["number.room_angle"].state*1+90)*3.1415/180)
      - $ex hass.states["number.room_zone3_y"].state*1
  - entity: ''
    name: Zone4
    mode: lines
    fill: toself
    fillcolor: >-
      $ex hass.states["binary_sensor.room_zone4_presence"].state == "on" ?
      "RGBA(250,210,0,0.4)" : "RGBA(250,210,0,0.1)"
    line:
      color: RGBA(250,210,0,0.9)
      shape: line
      width: 2
    x:
      - $ex hass.states["number.room_zone4_x"].state*1
      - >-
        $ex hass.states["number.room_zone4_x"].state*1 -
        hass.states["number.room_zone4_width"].state *
        Math.cos((hass.states["number.room_angle"].state)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone4_x"].state*1 -
        hass.states["number.room_zone4_width"].state *
        Math.cos((hass.states["number.room_angle"].state)*3.1415/180) +
        hass.states["number.room_zone4_height"].state *
        Math.cos((hass.states["number.room_angle"].state*1-90)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone4_x"].state*1 +
        hass.states["number.room_zone4_height"].state *
        Math.cos((hass.states["number.room_angle"].state*1-90)*3.1415/180)
      - $ex hass.states["number.room_zone4_x"].state*1
    'y':
      - $ex hass.states["number.room_zone4_y"].state*1
      - >-
        $ex hass.states["number.room_zone4_y"].state*1 +
        hass.states["number.room_zone4_width"].state *
        Math.sin((hass.states["number.room_angle"].state)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone4_y"].state*1 +
        hass.states["number.room_zone4_width"].state *
        Math.sin((hass.states["number.room_angle"].state)*3.1415/180) +
        hass.states["number.room_zone4_height"].state *
        Math.sin((hass.states["number.room_angle"].state*1+90)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone4_y"].state*1 +
        hass.states["number.room_zone4_height"].state *
        Math.sin((hass.states["number.room_angle"].state*1+90)*3.1415/180)
      - $ex hass.states["number.room_zone4_y"].state*1
  - entity: ''
    name: Zone5
    mode: lines
    fill: toself
    fillcolor: >-
      $ex hass.states["binary_sensor.room_zone5_presence"].state == "on" ?
      "RGBA(0,150,0,0.4)" : "RGBA(0,150,0,0.1)"
    line:
      color: RGBA(0,150,0,0.9)
      shape: line
      width: 2
    x:
      - $ex hass.states["number.room_zone5_x"].state*1
      - >-
        $ex hass.states["number.room_zone5_x"].state*1 -
        hass.states["number.room_zone5_width"].state *
        Math.cos((hass.states["number.room_angle"].state)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone5_x"].state*1 -
        hass.states["number.room_zone5_width"].state *
        Math.cos((hass.states["number.room_angle"].state)*3.1415/180) +
        hass.states["number.room_zone5_height"].state *
        Math.cos((hass.states["number.room_angle"].state*1-90)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone5_x"].state*1 +
        hass.states["number.room_zone5_height"].state *
        Math.cos((hass.states["number.room_angle"].state*1-90)*3.1415/180)
      - $ex hass.states["number.room_zone5_x"].state*1
    'y':
      - $ex hass.states["number.room_zone5_y"].state*1
      - >-
        $ex hass.states["number.room_zone5_y"].state*1 +
        hass.states["number.room_zone5_width"].state *
        Math.sin((hass.states["number.room_angle"].state)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone5_y"].state*1 +
        hass.states["number.room_zone5_width"].state *
        Math.sin((hass.states["number.room_angle"].state)*3.1415/180) +
        hass.states["number.room_zone5_height"].state *
        Math.sin((hass.states["number.room_angle"].state*1+90)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone5_y"].state*1 +
        hass.states["number.room_zone5_height"].state *
        Math.sin((hass.states["number.room_angle"].state*1+90)*3.1415/180)
      - $ex hass.states["number.room_zone5_y"].state*1
  - entity: ''
    name: Zone6
    mode: lines
    fill: toself
    fillcolor: >-
      $ex hass.states["binary_sensor.room_zone6_presence"].state == "on" ?
      "RGBA(250,50,130,0.4)" : "RGBA(250,50,130,0.1)"
    line:
      color: RGBA(250,50,130,0.9)
      shape: line
      width: 2
    x:
      - $ex hass.states["number.room_zone6_x"].state*1
      - >-
        $ex hass.states["number.room_zone6_x"].state*1 -
        hass.states["number.room_zone6_width"].state *
        Math.cos((hass.states["number.room_angle"].state)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone6_x"].state*1 -
        hass.states["number.room_zone6_width"].state *
        Math.cos((hass.states["number.room_angle"].state)*3.1415/180) +
        hass.states["number.room_zone6_height"].state *
        Math.cos((hass.states["number.room_angle"].state*1-90)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone6_x"].state*1 +
        hass.states["number.room_zone6_height"].state *
        Math.cos((hass.states["number.room_angle"].state*1-90)*3.1415/180)
      - $ex hass.states["number.room_zone6_x"].state*1
    'y':
      - $ex hass.states["number.room_zone6_y"].state*1
      - >-
        $ex hass.states["number.room_zone6_y"].state*1 +
        hass.states["number.room_zone6_width"].state *
        Math.sin((hass.states["number.room_angle"].state)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone6_y"].state*1 +
        hass.states["number.room_zone6_width"].state *
        Math.sin((hass.states["number.room_angle"].state)*3.1415/180) +
        hass.states["number.room_zone6_height"].state *
        Math.sin((hass.states["number.room_angle"].state*1+90)*3.1415/180)
      - >-
        $ex hass.states["number.room_zone6_y"].state*1 +
        hass.states["number.room_zone6_height"].state *
        Math.sin((hass.states["number.room_angle"].state*1+90)*3.1415/180)
      - $ex hass.states["number.room_zone6_y"].state*1
  - entity: ''
    name: Zout1
    mode: lines
    fill: toself
    fillcolor: >-
      $ex hass.states["switch.room_zout1_enable"].state == "on" ?
      hass.states["binary_sensor.room_zout1_presence"].state == "on" ?
      "RGBA(250,0,0,0.4)" : "RGBA(250,0,0,0.2)" : "RGBA(0,0,0,0)"
    line:
      color: >-
        $ex hass.states["switch.room_zout1_enable"].state == "on" ?
        "RGBA(0,150,0,0.9)" : "RGBA(0,0,0,0)" 
      width: 3
      dash: dash
    x:
      - $ex hass.states["number.room_zout1_x"].state*1
      - >-
        $ex hass.states["number.room_zout1_x"].state*1 -
        hass.states["number.room_zout1_width"].state *
        Math.cos((hass.states["number.room_angle"].state)*3.1415/180)
      - >-
        $ex hass.states["number.room_zout1_x"].state*1 -
        hass.states["number.room_zout1_width"].state *
        Math.cos((hass.states["number.room_angle"].state)*3.1415/180) +
        hass.states["number.room_zout1_height"].state *
        Math.cos((hass.states["number.room_angle"].state*1-90)*3.1415/180)
      - >-
        $ex hass.states["number.room_zout1_x"].state*1 +
        hass.states["number.room_zout1_height"].state *
        Math.cos((hass.states["number.room_angle"].state*1-90)*3.1415/180)
      - $ex hass.states["number.room_zout1_x"].state*1
    'y':
      - $ex hass.states["number.room_zout1_y"].state*1
      - >-
        $ex hass.states["number.room_zout1_y"].state*1 +
        hass.states["number.room_zout1_width"].state *
        Math.sin((hass.states["number.room_angle"].state)*3.1415/180)
      - >-
        $ex hass.states["number.room_zout1_y"].state*1 +
        hass.states["number.room_zout1_width"].state *
        Math.sin((hass.states["number.room_angle"].state)*3.1415/180) +
        hass.states["number.room_zout1_height"].state *
        Math.sin((hass.states["number.room_angle"].state*1+90)*3.1415/180)
      - >-
        $ex hass.states["number.room_zout1_y"].state*1 +
        hass.states["number.room_zout1_height"].state *
        Math.sin((hass.states["number.room_angle"].state*1+90)*3.1415/180)
      - $ex hass.states["number.room_zout1_y"].state*1
  - entity: ''
    name: Zout2
    mode: lines
    fill: toself
    fillcolor: >-
      $ex hass.states["switch.room_zout2_enable"].state == "on" ?
      hass.states["binary_sensor.room_zout2_presence"].state == "on" ?
      "RGBA(250,0,0,0.4)" : "RGBA(250,0,0,0.2)" : "RGBA(0,0,0,0)"
    line:
      color: >-
        $ex hass.states["switch.room_zout2_enable"].state == "on" ?
        "RGBA(250,110,0,0.9)" : "RGBA(0,0,0,0)" 
      width: 3
      dash: dash
    x:
      - $ex hass.states["number.room_zout2_x"].state*1
      - >-
        $ex hass.states["number.room_zout2_x"].state*1 -
        hass.states["number.room_zout2_width"].state *
        Math.cos((hass.states["number.room_angle"].state)*3.1415/180)
      - >-
        $ex hass.states["number.room_zout2_x"].state*1 -
        hass.states["number.room_zout2_width"].state *
        Math.cos((hass.states["number.room_angle"].state)*3.1415/180) +
        hass.states["number.room_zout2_height"].state *
        Math.cos((hass.states["number.room_angle"].state*1-90)*3.1415/180)
      - >-
        $ex hass.states["number.room_zout2_x"].state*1 +
        hass.states["number.room_zout2_height"].state *
        Math.cos((hass.states["number.room_angle"].state*1-90)*3.1415/180)
      - $ex hass.states["number.room_zout2_x"].state*1
    'y':
      - $ex hass.states["number.room_zout2_y"].state*1
      - >-
        $ex hass.states["number.room_zout2_y"].state*1 +
        hass.states["number.room_zout2_width"].state *
        Math.sin((hass.states["number.room_angle"].state)*3.1415/180)
      - >-
        $ex hass.states["number.room_zout2_y"].state*1 +
        hass.states["number.room_zout2_width"].state *
        Math.sin((hass.states["number.room_angle"].state)*3.1415/180) +
        hass.states["number.room_zout2_height"].state *
        Math.sin((hass.states["number.room_angle"].state*1+90)*3.1415/180)
      - >-
        $ex hass.states["number.room_zout2_y"].state*1 +
        hass.states["number.room_zout2_height"].state *
        Math.sin((hass.states["number.room_angle"].state*1+90)*3.1415/180)
      - $ex hass.states["number.room_zout2_y"].state*1
  - entity: ''
    name: Zout3
    mode: lines
    fill: toself
    fillcolor: >-
      $ex hass.states["switch.room_zout3_enable"].state == "on" ?
      hass.states["binary_sensor.room_zout3_presence"].state == "on" ?
      "RGBA(250,0,0,0.4)" : "RGBA(250,0,0,0.2)" : "RGBA(0,0,0,0)"
    line:
      color: >-
        $ex hass.states["switch.room_zout3_enable"].state == "on" ?
        "RGBA(0,0,250,0.9)" : "RGBA(0,0,0,0)" 
      width: 3
      dash: dash
    x:
      - $ex hass.states["number.room_zout3_x"].state*1
      - >-
        $ex hass.states["number.room_zout3_x"].state*1 -
        hass.states["number.room_zout3_width"].state *
        Math.cos((hass.states["number.room_angle"].state)*3.1415/180)
      - >-
        $ex hass.states["number.room_zout3_x"].state*1 -
        hass.states["number.room_zout3_width"].state *
        Math.cos((hass.states["number.room_angle"].state)*3.1415/180) +
        hass.states["number.room_zout3_height"].state *
        Math.cos((hass.states["number.room_angle"].state*1-90)*3.1415/180)
      - >-
        $ex hass.states["number.room_zout3_x"].state*1 +
        hass.states["number.room_zout3_height"].state *
        Math.cos((hass.states["number.room_angle"].state*1-90)*3.1415/180)
      - $ex hass.states["number.room_zout3_x"].state*1
    'y':
      - $ex hass.states["number.room_zout3_y"].state*1
      - >-
        $ex hass.states["number.room_zout3_y"].state*1 +
        hass.states["number.room_zout3_width"].state *
        Math.sin((hass.states["number.room_angle"].state)*3.1415/180)
      - >-
        $ex hass.states["number.room_zout3_y"].state*1 +
        hass.states["number.room_zout3_width"].state *
        Math.sin((hass.states["number.room_angle"].state)*3.1415/180) +
        hass.states["number.room_zout3_height"].state *
        Math.sin((hass.states["number.room_angle"].state*1+90)*3.1415/180)
      - >-
        $ex hass.states["number.room_zout3_y"].state*1 +
        hass.states["number.room_zout3_height"].state *
        Math.sin((hass.states["number.room_angle"].state*1+90)*3.1415/180)
      - $ex hass.states["number.room_zout3_y"].state*1
  - 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

Le YAML

#https://github.com/53l3cu5/ESP32_LD2450
#https://docs.screek.io/2a
substitutions:
  devicename: hpsz-room
  entity_name: "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_exist).publish_state(false);
          id(zone2_target_exist).publish_state(false);
          id(zone3_target_exist).publish_state(false);
          id(zone4_target_exist).publish_state(false);
          id(zone5_target_exist).publish_state(false);
          id(zone6_target_exist).publish_state(false);
          id(zone_ex1_target_exist).publish_state(false);
          id(zone_ex2_target_exist).publish_state(false);
          id(zone_ex3_target_exist).publish_state(false);
  includes:
    - zone.h
    
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"

improv_serial:
  
logger:

debug:
  update_interval: 30s

api:
  encryption:
    # use your own encryption key plz.
    # https://esphome.io/components/api.html?#configuration-variables
    key: "Xd8KczJ8qKVYtAjyh3zVPar7zF8pkmZeOpnHSfjOqwA="
    
ota:
  # use your own ota password plz.
  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: "${entity_name} ESP Reset Reason"
      icon: mdi:anchor
      disabled_by_default: True
  - platform: wifi_info
    ip_address:
      name: ${entity_name} ESP IP Address
      entity_category: "diagnostic"
      disabled_by_default: True
      icon: mdi:ip-network
    mac_address:
      name: ${entity_name} ESP MAC
      entity_category: "diagnostic"
      icon: mdi:ip-network
      disabled_by_default: True
  - platform: template
    name: "${entity_name} Zone1 Info"
    id: tips_zone1_conf
    icon: mdi:information-outline
    entity_category: config
    lambda: |-
      return {"Configure below" };
    update_interval: 1000s
  - platform: template
    name: "${entity_name} Zone2 Info"
    id: tips_zone2_conf
    icon: mdi:information-outline
    entity_category: config
    lambda: |-
      return {"Configure below" };
    update_interval: 1000s
  - platform: template
    name: "${entity_name} Zone3 Info"
    id: tips_zone3_conf
    icon: mdi:information-outline
    entity_category: config
  - platform: template
    name: "${entity_name} Zone4 Info"
    id: tips_zone4_conf
    icon: mdi:information-outline
    entity_category: config
    lambda: |-
      return {"Configure below" };
    update_interval: 1000s
  - platform: template
    name: "${entity_name} Zone5 Info"
    id: tips_zone5_conf
    icon: mdi:information-outline
    entity_category: config
    lambda: |-
      return {"Configure below" };
    update_interval: 1000s
  - platform: template
    name: "${entity_name} Zone6 Info"
    id: tips_zone6_conf
    icon: mdi:information-outline
    entity_category: config
    lambda: |-
      return {"Configure below" };
    update_interval: 1000s
  - platform: template
    name: "${entity_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: "${entity_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: "${entity_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: "${entity_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: "${entity_name} Target1 Direction"
    id: target1_direction
    icon: mdi:directions
  - platform: template
    name: "${entity_name} Target2 Direction"
    id: target2_direction
    icon: mdi:directions
  - platform: template
    name: "${entity_name} Target3 Direction"
    id: target3_direction
    icon: mdi:directions
  - platform: template
    name: "${entity_name} Target1 Position"
    id: target1_position
    icon: mdi:directions
  - platform: template
    name: "${entity_name} Target2 Position"
    id: target2_position
    icon: mdi:directions
  - platform: template
    name: "${entity_name} Target3 Position"
    id: target3_position
    icon: mdi:directions

number:
  - platform: template
    name: "${entity_name} Angle"
    id: wall_angle
    min_value: 0
    max_value: 90
    mode: box
    device_class: duration
    entity_category: config
    unit_of_measurement: °
    icon: mdi:angle-acute
    step: 1
    optimistic: True
    initial_value: 0
    restore_value: True
  - platform: template
    name: "${entity_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: "${entity_name} Zone1 Timeout"
    id: zone1_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: "${entity_name} Zone2 Timeout"
    id: zone2_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: "${entity_name} Zone3 Timeout"
    id: zone3_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: "${entity_name} Zone4 Timeout"
    id: zone4_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: "${entity_name} Zone5 Timeout"
    id: zone5_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: "${entity_name} Zone6 Timeout"
    id: zone6_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: ${entity_name} Zone1 X
    id: zone1_x
    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_valide
  - platform: template
    name: ${entity_name} Zone1 Y
    id: zone1_y
    mode: box
    min_value: -500
    max_value: 8000
    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_valide
  - platform: template
    name: ${entity_name} Zone1 Height
    id: zone1_height
    icon: mdi:arrow-down-bold
    mode: box
    min_value: 0
    max_value: 8000
    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_valide
  - platform: template
    name: ${entity_name} Zone1 Width
    id: zone1_width
    mode: box
    min_value: 0
    max_value: 8000
    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_valide
    
  # Zone 2
  - platform: template
    name: ${entity_name} Zone2 X
    id: zone2_x
    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_valide
  - platform: template
    name: ${entity_name} Zone2 Y
    id: zone2_y
    mode: box
    min_value: -500
    max_value: 8000
    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_valide
  - platform: template
    name: ${entity_name} Zone2 Height
    id: zone2_height
    icon: mdi:arrow-down-bold
    mode: box
    min_value: 0
    max_value: 8000
    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_valide
  - platform: template
    name: ${entity_name} Zone2 Width
    id: zone2_width
    mode: box
    min_value: 0
    max_value: 8000
    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_valide
    
  # Zone 3
  - platform: template
    name: ${entity_name} Zone3 X
    id: zone3_x
    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_valide
  - platform: template
    name: ${entity_name} Zone3 Y
    id: zone3_y
    mode: box
    min_value: -500
    max_value: 8000
    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_valide
  - platform: template
    name: ${entity_name} Zone3 Height
    id: zone3_height
    icon: mdi:arrow-down-bold
    mode: box
    min_value: 0
    max_value: 8000
    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_valide
  - platform: template
    name: ${entity_name} Zone3 Width
    id: zone3_width
    mode: box
    min_value: 0
    max_value: 8000
    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_valide
    
  # Zone 4
  - platform: template
    name: ${entity_name} Zone4 X
    id: zone4_x
    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_valide
  - platform: template
    name: ${entity_name} Zone4 Y
    id: zone4_y
    mode: box
    min_value: -500
    max_value: 8000
    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_valide
  - platform: template
    name: ${entity_name} Zone4 Height
    id: zone4_height
    icon: mdi:arrow-down-bold
    mode: box
    min_value: 0
    max_value: 8000
    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_valide
  - platform: template
    name: ${entity_name} Zone4 Width
    id: zone4_width
    mode: box
    min_value: 0
    max_value: 8000
    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_valide
    
  # Zone 5
  - platform: template
    name: ${entity_name} Zone5 X
    id: zone5_x
    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_valide
  - platform: template
    name: ${entity_name} Zone5 Y
    id: zone5_y
    mode: box
    min_value: -500
    max_value: 8000
    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_valide
  - platform: template
    name: ${entity_name} Zone5 Height
    id: zone5_height
    icon: mdi:arrow-down-bold
    mode: box
    min_value: 0
    max_value: 8000
    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_valide
  - platform: template
    name: ${entity_name} Zone5 Width
    id: zone5_width
    mode: box
    min_value: 0
    max_value: 8000
    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_valide
    
  # Zone 6
  - platform: template
    name: ${entity_name} Zone6 X
    id: zone6_x
    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_valide
  - platform: template
    name: ${entity_name} Zone6 Y
    id: zone6_y
    mode: box
    min_value: -500
    max_value: 8000
    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_valide
  - platform: template
    name: ${entity_name} Zone6 Height
    id: zone6_height
    icon: mdi:arrow-down-bold
    mode: box
    min_value: 0
    max_value: 8000
    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_valide
  - platform: template
    name: ${entity_name} Zone6 Width
    id: zone6_width
    mode: box
    min_value: 0
    max_value: 8000
    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_valide
    
  # Zout1
  - platform: template
    name: ${entity_name} Zout1 X
    id: zone_ex1_x
    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_valide
  - platform: template
    name: ${entity_name} Zout1 Y
    id: zone_ex1_y
    mode: box
    min_value: -500
    max_value: 8000
    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_valide
  - platform: template
    name: ${entity_name} Zout1 Height
    id: zone_ex1_height
    icon: mdi:arrow-down-bold
    mode: box
    min_value: 0
    max_value: 8000
    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_valide
  - platform: template
    name: ${entity_name} Zout1 Width
    id: zone_ex1_width
    mode: box
    min_value: 0
    max_value: 8000
    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_valide
    
  # Zout2
  - platform: template
    name: ${entity_name} Zout2 X
    id: zone_ex2_x
    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_valide
  - platform: template
    name: ${entity_name} Zout2 Y
    id: zone_ex2_y
    mode: box
    min_value: -500
    max_value: 8000
    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_valide
  - platform: template
    name: ${entity_name} Zout2 Height
    id: zone_ex2_height
    icon: mdi:arrow-down-bold
    mode: box
    min_value: 0
    max_value: 8000
    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_valide
  - platform: template
    name: ${entity_name} Zout2 Width
    id: zone_ex2_width
    mode: box
    min_value: 0
    max_value: 8000
    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_valide
    
  # Zout3
  - platform: template
    name: ${entity_name} Zout3 X
    id: zone_ex3_x
    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_valide
  - platform: template
    name: ${entity_name} Zout3 Y
    id: zone_ex3_y
    mode: box
    min_value: -500
    max_value: 8000
    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_valide
  - platform: template
    name: ${entity_name} Zout3 Height
    id: zone_ex3_height
    icon: mdi:arrow-down-bold
    mode: box
    min_value: 0
    max_value: 8000
    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_valide
  - platform: template
    name: ${entity_name} Zout3 Width
    id: zone_ex3_width
    mode: box
    min_value: 0
    max_value: 8000
    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_valide

binary_sensor:
  - platform: status
    name: ${entity_name} Online
    id: ink_ha_connected
  - platform: template
    name: "${entity_name} Any Presence"
    id: any_target_exist
    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: "${entity_name} Zone1 Presence"
    id: zone1_target_exist
    device_class: occupancy
    filters:
      - delayed_off: !lambda |-
          if (!id(init_zone_publish) || !id(zone_fn_enable).state) {
            return 0;
          }
          return id(zone1_timeout).state * 1000.0;
  - platform: template
    name: "${entity_name} Zone2 Presence"
    id: zone2_target_exist
    device_class: occupancy
    filters:
      - delayed_off: !lambda |-
          if (!id(init_zone_publish) || !id(zone_fn_enable).state) {
            return 0;
          }
          return id(zone2_timeout).state * 1000.0;
  - platform: template
    name: "${entity_name} Zone3 Presence"
    id: zone3_target_exist
    device_class: occupancy
    filters:
      - delayed_off: !lambda |-
          if (!id(init_zone_publish) || !id(zone_fn_enable).state) {
            return 0;
          }
          return id(zone3_timeout).state * 1000.0;
  - platform: template
    name: "${entity_name} Zone4 Presence"
    id: zone4_target_exist
    device_class: occupancy
    filters:
      - delayed_off: !lambda |-
          if (!id(init_zone_publish) || !id(zone_fn_enable).state) {
            return 0;
          }
          return id(zone4_timeout).state * 1000.0;
  - platform: template
    name: "${entity_name} Zone5 Presence"
    id: zone5_target_exist
    device_class: occupancy
    filters:
      - delayed_off: !lambda |-
          if (!id(init_zone_publish) || !id(zone_fn_enable).state) {
            return 0;
          }
          return id(zone5_timeout).state * 1000.0;
  - platform: template
    name: "${entity_name} Zone6 Presence"
    id: zone6_target_exist
    device_class: occupancy
    filters:
      - delayed_off: !lambda |-
          if (!id(init_zone_publish) || !id(zone_fn_enable).state) {
            return 0;
          }
          return id(zone6_timeout).state * 1000.0;
  - platform: template
    name: "${entity_name} Zout1 Presence"
    id: zone_ex1_target_exist
    icon: mdi:account-multiple-remove
    device_class: occupancy
  - platform: template
    name: "${entity_name} Zout2 Presence"
    id: zone_ex2_target_exist
    icon: mdi:account-multiple-remove
    device_class: occupancy
  - platform: template
    name: "${entity_name} Zout3 Presence"
    id: zone_ex3_target_exist
    icon: mdi:account-multiple-remove
    device_class: occupancy

script:
  - id: check_zone1_valide
    then:
      - lambda: |-
          if (id(zone1_x).state == 0 && id(zone1_width).state == 0 && id(zone1_y).state == 0 && id(zone1_height).state == 0){
            id(tips_zone1_conf).publish_state("Configure below");
            return;
          }

          int x_size = id(zone1_width).state;
          int y_size = id(zone1_height).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_valide
    then:
      - lambda: |-
          if (id(zone2_x).state == 0 && id(zone2_width).state == 0 && id(zone2_y).state == 0 && id(zone2_height).state == 0){
            id(tips_zone2_conf).publish_state("Configure below");
            return;
          }

          int x_size = id(zone2_width).state;
          int y_size = id(zone2_height).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_valide
    then:
      - lambda: |-
          if (id(zone3_x).state == 0 && id(zone3_width).state == 0 && id(zone3_y).state == 0 && id(zone3_height).state == 0){
            id(tips_zone3_conf).publish_state("Configure below");
            return;
          }

          int x_size = id(zone3_width).state;
          int y_size = id(zone3_height).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_valide
    then:
      - lambda: |-
          if (id(zone4_x).state == 0 && id(zone4_width).state == 0 && id(zone4_y).state == 0 && id(zone4_height).state == 0){
            id(tips_zone4_conf).publish_state("Configure below");
            return;
          }

          int x_size = id(zone4_width).state;
          int y_size = id(zone4_height).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_valide
    then:
      - lambda: |-
          if (id(zone5_x).state == 0 && id(zone5_width).state == 0 && id(zone5_y).state == 0 && id(zone5_height).state == 0){
            id(tips_zone5_conf).publish_state("Configure below");
            return;
          }

          int x_size = id(zone5_width).state;
          int y_size = id(zone5_height).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_valide
    then:
      - lambda: |-
          if (id(zone6_x).state == 0 && id(zone6_width).state == 0 && id(zone6_y).state == 0 && id(zone6_height).state == 0){
            id(tips_zone6_conf).publish_state("Configure below");
            return;
          }

          int x_size = id(zone6_width).state;
          int y_size = id(zone6_height).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_valide
    then:
      - lambda: |-
          id(tips_zone_ex1_conf).publish_state("Zone Exclusion 1");

  - id: check_zout2_valide
    then:
      - lambda: |-
          id(tips_zone_ex2_conf).publish_state("Zone Exclusion 2");

  - id: check_zout3_valide
    then:
      - lambda: |-
          id(tips_zone_ex3_conf).publish_state("Zone Exclusion 3");

sensor:
  - platform: uptime
    name: ${entity_name} ESP Uptime
    id: sys_uptime
    update_interval: 60s
    disabled_by_default: True
  - platform: wifi_signal 
    name: ${entity_name} RSSI
    id: wifi_signal_db
    update_interval: 60s
    entity_category: "diagnostic"
    
#-------------------------------------#
  # Advanced radar data
  - platform: template
    name: "${entity_name} All Target Counts"
    id: all_target_count
    accuracy_decimals: 0
    icon: "mdi:counter"
    unit_of_measurement: "targets"
  - platform: template
    name: "${entity_name} Zone1 Target Counts"
    id: zone1_target_count
    accuracy_decimals: 0
    icon: "mdi:counter"
    unit_of_measurement: "targets"
  - platform: template
    name: "${entity_name} Zone2 Target Counts"
    id: zone2_target_count
    accuracy_decimals: 0
    icon: "mdi:counter"
    unit_of_measurement: "targets"
  - platform: template
    name: "${entity_name} Zone3 Target Counts"
    id: zone3_target_count
    accuracy_decimals: 0
    icon: "mdi:counter"
    unit_of_measurement: "targets"
  - platform: template
    name: "${entity_name} Zone4 Target Counts"
    id: zone4_target_count
    accuracy_decimals: 0
    icon: "mdi:counter"
    unit_of_measurement: "targets"
  - platform: template
    name: "${entity_name} Zone5 Target Counts"
    id: zone5_target_count
    accuracy_decimals: 0
    icon: "mdi:counter"
    unit_of_measurement: "targets"
  - platform: template
    name: "${entity_name} Zone6 Target Counts"
    id: zone6_target_count
    accuracy_decimals: 0
    icon: "mdi:counter"
    unit_of_measurement: "targets"
  - platform: template
    name: "${entity_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: "${entity_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: "${entity_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: "${entity_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: "${entity_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: "${entity_name} Target1 Speed"
    id: target1_speed
    accuracy_decimals: 2
    unit_of_measurement: 'm/s'
    state_class: measurement
    device_class: speed
  - platform: template
    name: "${entity_name} Target1 Resolution"
    id: target1_resolution
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    device_class: distance
  
  # Target 2
  - platform: template
    name: "${entity_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: "${entity_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: "${entity_name} Target2 Speed"
    id: target2_speed
    accuracy_decimals: 0
    unit_of_measurement: 'm/s'
    state_class: measurement
    device_class: speed
  - platform: template
    name: "${entity_name} Target2 Resolution"
    id: target2_resolution
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    device_class: distance

  # Target 3
  - platform: template
    name: "${entity_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: "${entity_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: "${entity_name} Target3 Speed"
    id: target3_speed
    accuracy_decimals: 0
    unit_of_measurement: 'm/s'
    state_class: measurement
    device_class: speed
  - platform: template
    name: "${entity_name} Target3 Resolution"
    id: target3_resolution
    accuracy_decimals: 0
    unit_of_measurement: 'mm'
    state_class: measurement
    device_class: distance
  - platform: template
    name: "${entity_name} Target1 Angle"
    id: target1_angle
    unit_of_measurement: 'º'
    accuracy_decimals: 1
    icon: mdi:angle-acute
  - platform: template
    name: "${entity_name} Target2 Angle"
    id: target2_angle
    accuracy_decimals: 1
    unit_of_measurement: 'º'
    icon: mdi:angle-acute
  - platform: template
    name: "${entity_name} Target3 Angle"
    id: target3_angle
    accuracy_decimals: 1
    unit_of_measurement: 'º'
    icon: mdi:angle-acute

light:
  - platform: status_led
    name: ${entity_name} sys_status
    pin: GPIO13
    internal: True
    restore_mode: ALWAYS_OFF
  - platform: binary
    name: "${entity_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: ${entity_name} Factory Reset
#    disabled_by_default: True
#    icon: mdi:heart-broken
#    entity_category: diagnostic
  - platform: template
    name: ${entity_name} Zout1 Enable
    id: zone_ex1_enable
    optimistic: True
    icon: mdi:account-cancel
    entity_category: config
    restore_mode: RESTORE_DEFAULT_OFF
  - platform: template
    name: ${entity_name} Zout2 Enable
    id: zone_ex2_enable
    optimistic: True
    icon: mdi:account-cancel
    entity_category: config
    restore_mode: RESTORE_DEFAULT_OFF
  - platform: template
    name: ${entity_name} Zout3 Enable
    id: zone_ex3_enable
    optimistic: True
    icon: mdi:account-cancel
    entity_category: config
    restore_mode: RESTORE_DEFAULT_OFF
  - platform: template
    name: ${entity_name} Target Enable
    id: target_fn_enable
    optimistic: True
    icon: mdi:target-variant
    entity_category: config
    restore_mode: RESTORE_DEFAULT_ON
  - platform: template
    name: ${entity_name} Zone Enable
    id: zone_fn_enable
    optimistic: True
    icon: mdi:target-variant
    entity_category: config
    restore_mode: RESTORE_DEFAULT_ON
  - platform: template
    name: ${entity_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: "${entity_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: |-
      
          // Tableaux pour stocker les noms des champs
          static template_::TemplateNumber* zone_x[] = {id(zone1_x), id(zone2_x), id(zone3_x), id(zone4_x), id(zone5_x), id(zone6_x)};
          static template_::TemplateNumber* zone_y[] = {id(zone1_y), id(zone2_y), id(zone3_y), id(zone4_y), id(zone5_y), id(zone6_y)};
          static template_::TemplateNumber* zone_height[] = {id(zone1_height), id(zone2_height), id(zone3_height), id(zone4_height), id(zone5_height), id(zone6_height)};
          static template_::TemplateNumber* zone_width[] = {id(zone1_width), id(zone2_width), id(zone3_width), id(zone4_width), id(zone5_width), id(zone6_width)};
          static template_::TemplateSensor* zone_target_count[] = {id(zone1_target_count), id(zone2_target_count), id(zone3_target_count), id(zone4_target_count), id(zone5_target_count), id(zone6_target_count)};
          static template_::TemplateBinarySensor* zone_target_exist[] = {id(zone1_target_exist), id(zone2_target_exist), id(zone3_target_exist), id(zone4_target_exist), id(zone5_target_exist), id(zone6_target_exist)};
          // static template_::TemplateTextSensor* tips_zone_conf[] = {id(tips_zone1_conf), id(tips_zone2_conf), id(tips_zone3_conf), id(tips_zone4_conf), id(tips_zone5_conf), id(tips_zone6_conf)};
          const int NUM_ZONES = 6;
          static template_::TemplateSwitch* zone_ex_enable[] = {id(zone_ex1_enable), id(zone_ex2_enable), id(zone_ex3_enable)};
          static template_::TemplateNumber* zone_ex_x[] = {id(zone_ex1_x), id(zone_ex2_x), id(zone_ex3_x)};
          static template_::TemplateNumber* zone_ex_y[] = {id(zone_ex1_y), id(zone_ex2_y), id(zone_ex3_y)};
          static template_::TemplateNumber* zone_ex_height[] = {id(zone_ex1_height), id(zone_ex2_height), id(zone_ex3_height)};
          static template_::TemplateNumber* zone_ex_width[] = {id(zone_ex1_width), id(zone_ex2_width), id(zone_ex3_width)};
          static template_::TemplateSensor* zone_ex_target_count[] = {id(zone_ex1_target_count), id(zone_ex2_target_count), id(zone_ex3_target_count)};
          static template_::TemplateBinarySensor* zone_ex_target_exist[] = {id(zone_ex1_target_exist), id(zone_ex2_target_exist), id(zone_ex3_target_exist)};
          // static template_::TemplateTextSensor* tips_zone_ex_conf[] = {id(tips_zone_ex1_conf), id(tips_zone_ex2_conf), id(tips_zone_ex3_conf)};
          const int NUM_ZONES_EX = 3;
          static template_::TemplateSensor* target_angle[] = {id(target1_angle), id(target2_angle), id(target3_angle)};
          static template_::TemplateTextSensor* target_position[] = {id(target1_position), id(target2_position), id(target3_position)};
          static template_::TemplateTextSensor* target_direction[] = {id(target1_direction), id(target2_direction), id(target3_direction)};
          static template_::TemplateSensor* target_x[] = {id(target1_x), id(target2_x), id(target3_x)};
          static template_::TemplateSensor* target_y[] = {id(target1_y), id(target2_y), id(target3_y)};
          static template_::TemplateSensor* target_speed[] = {id(target1_speed), id(target2_speed), id(target3_speed)};
          static template_::TemplateSensor* target_resolution[] = {id(target1_resolution), id(target2_resolution), id(target3_resolution)};
          const int NUM_TARGETS = 3;
          float angle = id(wall_angle).state*1;
          
          struct Position  p[NUM_TARGETS];
          struct Zone zone_ex[NUM_ZONES_EX], zone[NUM_ZONES];
          
          if ((millis() - id(last_update_ld2450)) <= 500) { 
            return;
          };
          id(last_update_ld2450) = millis();

          //Targets' data
          int b = 0;
          for (int i = 0; i < NUM_TARGETS; i++) {
            p[i].x = (uint16_t((bytes[b+5] << 8) | bytes[b+4] ));
            if ((bytes[b+5] & 0x80) >> 7){
              p[i].x -= pow(2, 15); 
            }else{
              p[i].x = 0 - p[i].x;
            }
            p[i].x = p[i].x * -1;

            p[i].y = (uint16_t((bytes[b+7] << 8) | bytes[b+6] ));
            if ((bytes[b+7] & 0x80) >> 7){
              p[i].y -= pow(2, 15);
            }else{
              p[i].y = 0 - p[i].y;
            }

            p[i].speed = (bytes[b+9] << 8 | bytes[b+8] );
            if ((bytes[b+9] & 0x80) >> 7){
              p[i].speed -= pow(2, 15);
            }else{
              p[i].speed = 0 - p[i].speed;
            }
            p[i].distance_resolution = (uint16_t((bytes[b+11] << 8) | bytes[b+10] )); 
            p[i].valide = (p[i].x != 0 || p[i].y > 0);
            b += 8;
          }
          
          // Excluded zones 
          for (int i = 0; i < NUM_ZONES_EX; i++) {
            zone_ex[i].x = zone_ex_x[i]->state;
            zone_ex[i].y = zone_ex_y[i]->state;
            zone_ex[i].width = zone_ex_width[i]->state;
            zone_ex[i].height = zone_ex_height[i]->state;
            //zone_ex[i].tips_conf = tips_zone_ex_conf[i];
            //zone_ex[i].name += "_ex" + std::to_string(i+1);

            if (zone_ex_enable[i]->state){
              for (int j = 0; j < NUM_TARGETS; j++) {
                if (p[j].valide){
                  if (check_targets_in_zone(zone_ex[i], p[j], angle)){
                    zone_ex[i].target_count++;
                    p[j].zone_ex_enter = true;
                  }
                }
              }
            }
            zone_ex[i].has_target = (zone_ex[i].target_count > 0);
          }
          
          // all targets
          int16_t all_target_counts = 0;
          for (int i = 0; i < NUM_TARGETS; i++) {
            if (p[i].valide && !p[i].zone_ex_enter){
              all_target_counts ++;
            }
          }

          bool has_target_in_zone_all = (all_target_counts > 0);

          // zones check
          if (id(zone_fn_enable).state){
            for (int i = 0; i < NUM_ZONES; i++) {
              zone[i].x = zone_x[i]->state;
              zone[i].y = zone_y[i]->state;
              zone[i].width = zone_width[i]->state;
              zone[i].height = zone_height[i]->state;
              //zone[i].tips_conf = tips_zone_conf[i];
              //zone[i].name += std::to_string(i+1);
              
              for (int j = 0; j < NUM_TARGETS; j++) {
                if (p[j].valide && !p[j].zone_ex_enter){
                  if(check_targets_in_zone(zone[i], p[j], angle)) {
                    zone[i].target_count++;
                  }
                }
              }
              zone[i].has_target = (zone[i].target_count > 0);
            }
          }

          // Angle, Position and Direction, idea from walberjunior.
          for (int i = 0; i < NUM_TARGETS; i++) {
            if (p[i].valide){
              p[i].angle = ((float)p[i].x / (float)p[i].y) * 180 / M_PI;;
            }
            if (target_angle[i]->state != p[i].angle && id(target_fn_enable).state){
              target_angle[i]->publish_state(p[i].angle);
            }

            if (p[i].speed > 0) {
              p[i].position = "Moving away";
            } else if (p[i].speed < 0) {
              p[i].position = "Approaching";
            } 
            if (p[i].position != target_position[i]->state && id(target_fn_enable).state){
              target_position[i]->publish_state(p[i].position);
            }

            if (p[i].x > 0) {
              p[i].direction = "Right";
            } else if (p[i].x < 0) {
              p[i].direction = "Left";
            } else if (p[i].y > 0){
              p[i].direction = "Middle";
            }
            if (p[i].direction != target_direction[i]->state && id(target_fn_enable).state){
              target_direction[i]->publish_state(p[i].direction);
            }
          }

          // public all info
          for (int i = 0; i < NUM_TARGETS; i++) {
            if (target_x[i]->state != p[i].x && id(target_fn_enable).state){
              target_x[i]->publish_state(p[i].x);
            }
            if (target_y[i]->state != p[i].y && id(target_fn_enable).state){
              target_y[i]->publish_state(p[i].y);
            }

            p[i].speed = float(p[i].speed) / 100.0;
            if (target_speed[i]->state != p[i].speed && id(target_fn_enable).state){
              target_speed[i]->publish_state(p[i].speed);
            }
            if (target_resolution[i]->state != p[i].distance_resolution && id(target_fn_enable).state){
              target_resolution[i]->publish_state(p[i].distance_resolution);
            }
          }

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

          for (int i = 0; i < NUM_ZONES; i++) {
            if (zone_target_count[i]->state != zone[i].target_count){
              zone_target_count[i]->publish_state(zone[i].target_count);
              zone_target_exist[i]->publish_state(zone[i].has_target);
            }else if (zone_target_exist[i]->state != zone[i].has_target){
              zone_target_exist[i]->publish_state(zone[i].has_target);
            }
          }
          for (int i = 0; i < NUM_ZONES_EX; i++) {
            if (zone_ex_target_count[i]->state != zone_ex[i].target_count){
              zone_ex_target_count[i]->publish_state(zone_ex[i].target_count);
            }
            if (zone_ex_target_exist[i]->state != zone_ex[i].has_target){
              zone_ex_target_exist[i]->publish_state(zone_ex[i].has_target);
            }
          }

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

La librairie

Le fichier dois se nommer zone.h et être enregistré dans le même répertoire que le YAML

#include <cmath>
#include <iostream>

struct Position {
  int16_t x; 
  int16_t y;
  int speed;
  int16_t distance_resolution;
  bool valide;
  bool zone_ex_enter = false;
  float angle = 0;
  std::basic_string<char> position = "Static";
  std::basic_string<char> direction = "None";
};
struct Zone {
  int16_t x;
  int16_t y;
  int16_t height;
  int16_t width;
  int16_t target_count = 0;
  bool has_target = false;
  
  // template_::TemplateTextSensor* tips_conf;
  // std::string name = "Zone";
};

struct Pxy {
  int16_t x; 
  int16_t y;
};

// Définition de la fonction pour vérifier les cibles dans une zone donnée
bool check_targets_in_zone(struct Zone &z, struct Position &t, float angle) {
  struct Pxy p1, p2, p3, p4;
  float d12, d14, d15, d23, d25, d34, d35, d45; 
  float a152, a154, a253, a354, a_sum;
  float TAU = 6.283185; // 2*PI
  bool isInside = false;
  
  p1.x = z.x;
  p1.y = z.y;
  p2.x = z.x - z.width * cos(angle*PI/180);
  p2.y = z.y + z.width * sin(angle*PI/180);
  p3.x = z.x - z.width * cos(angle*PI/180) + z.height * cos((angle-90)*PI/180);
  p3.y = z.y + z.width * sin(angle*PI/180) + z.height * sin((angle+90)*PI/180);
  p4.x = z.x + z.height * cos((angle-90)*PI/180);
  p4.y = z.y + z.height * sin((angle+90)*PI/180);
  
  d15 = sqrt(pow(p1.x-t.x,2)+pow(p1.y-t.y,2));
  d25 = sqrt(pow(p2.x-t.x,2)+pow(p2.y-t.y,2));
  d35 = sqrt(pow(p3.x-t.x,2)+pow(p3.y-t.y,2));
  d45 = sqrt(pow(p4.x-t.x,2)+pow(p4.y-t.y,2));
  d12 = sqrt(pow(p1.x-p2.x,2)+pow(p1.y-p2.y,2));
  d14 = sqrt(pow(p1.x-p4.x,2)+pow(p1.y-p4.y,2));
  d23 = sqrt(pow(p2.x-p3.x,2)+pow(p2.y-p3.y,2));
  d34 = sqrt(pow(p3.x-p4.x,2)+pow(p3.y-p4.y,2));
  
  a152 = acos((pow(d15,2)+pow(d25,2)-pow(d12,2))/(2*d15*d25));
  a154 = acos((pow(d15,2)+pow(d45,2)-pow(d14,2))/(2*d15*d45));
  a253 = acos((pow(d25,2)+pow(d35,2)-pow(d23,2))/(2*d25*d35));
  a354 = acos((pow(d35,2)+pow(d45,2)-pow(d34,2))/(2*d35*d45));
  a_sum = a152+a154+a253+a354;
  
  if (a_sum>=TAU) {
    isInside = true;
  }
  return isInside;
}
4 « J'aime »

Il y a vraiment pas grand chose à dire !
Enfin si au contraire :stuck_out_tongue_winking_eye: gros travail de ta part pour obtenir ce délice.

Bravo :tada::champagne::balloon::confetti_ball:

J’attends ma version 1 de mes PCB et mise en Prod de 2 capteurs un à plat sur le mur et un en angle pour commencer.

1 « J'aime »

Merci Jérôme, ça fait plaisir :hugs:

J’attends les retours de la communauté française une ou deux semaines pour voir s’il y a pas un petit détail que j’aurais raté ; et ensuite j’irai en faire profiter la communauté anglophone. C’est vrai que j’ai passé du temps dessus, alors autant en faire profiter un maximum de monde.

2 « J'aime »

En parlant de détails je me rends compte que j’ai oublié de mentionner quelque chose : il y a un petit ralentissement de 0.05s dans les logs comparativement à l’ancienne version.
c’est dû au fait que les calculs nécessitent plus de puissance et l’affichage régulier de la position des cibles n’aide pas.
Je pense que 0,05 secondes une fois de temps en temps ce n’est pas grand-chose ; mais si on veut être vraiment puriste il suffit de désactiver l’affichage des cibles et le problème est résolu ! Il n’y a plus de ralentissement

Bonsoir,
voulant me faire un détecteur de présence j’ai suivi le tutoriel.
j’ai bien réussi à retrouver mon esp32 dans mes appareils, mais j’ai le contrôle uniquement sur la LED.
Les informations du capteur sont toutes définies à « Inconnu ».
J’avais exactement le même problème en ayant suivi la technique mmWave de fixtSE sur yt.
Avez-vous une petite idée de l’erreur que ça pourrait être ??




Je suppose que ça peut être le modèle de ton esp32. Tu dois avoir une version différente de celles qu’on utilise. Peux-tu nous dire quel modèle tu as commandé ?

J’ai le : esp-wroom-32

D’accord tu as le même que le mien.
Dans ce cas il faut que tu vérifies que tu as bien connecté tes entrées et tes sorties sur les bonnes broches
Vérifie également que tu as bien connecté le RX de l’ESP sur le TX du ld2450 et vice et versa

Les entrées et les sorties sont sur les bonnes broches.
Au début je penser au LD2450 défaillant mais avec la technique mmWave la configuration des zones ce fait directement sur une app sur le tel renvoie aussi les infos de le position et toutes les valeurs étaient correctes.

as-tu essayé d’inverser le RX et le TX ?

Malheureusement les résultats restent les mêmes…

Je me dit que c’est ma config espHome qui n’est peut-être pas bonne…

avant de t’attaquer au ld2450 est-ce que tu as essayé de faire fonctionner ESP home avec des diodes ou quelque chose comme ça

je crois que c’est tout ce que tu vas pouvoir faire ce soir. mais avant qu’on se quitte peux-tu me réexpliquer pourquoi tu penses que le ld2450 n’est pas en cause ? je n’ai pas bien compris ton explication tout à l’heure

@selecus
Bon j’ai refait un de mes ESP/LD2540 avec la dernière version.

Tout fonctionne, je vais remettre quelques éléments de diagnostic en route le temps de faire les tests, migrations des autres capteurs pour ne pas me mélanger :slight_smile:

Bien entendu il faut que je définisse à nouveau les valeurs des zones, angle, timeout au besoin.

J’ai l’info Fimware qui est en inconnu.

Mais ce qui me chagrine le plus c’est le nommage :

binary_sensor.pre_couloir_c49018_couloir_any_presence

Je l’ai obtenu en mettant room = couloir
et mon device en pre couloir

le c49018 vient du flash de l’esp et ça je n’arrive jamais à l’enlever ! Il faut le faire à la main :frowning:
et là 110 entités à faire multiplié par x capteurs ouch !!!

Bon après je n’aurais surement pas un besoin de toutes les zones mais bon c’est clair que le renommage en masse serait bienvenue :slight_smile: