Bonjour, je ne comprends pas j’ai fait un copié collé du code et j’ai une erreur quand je veux l’installer.
et le message d’erreur :
Je ne suis pas super calé en YAML.
Regarder en line 3 et 71 surement un soucis d’indentation à la 71 je pense
Salut,
problème d’indexion.
code original:
substitutions:
devicename: hpsz-room
ton code:
substitutions:
devicename: hpsz-room #un espace en moins au début de la ligne.
Ligne 71 , ca doit être pareil, mais je connais pas la ligne.
Merci pour votre aide, ça marche, reste plus qu’a tester.
je teste le code depuis hier soir, a première vue je ne constate aucune latence supplémentaire mais a voir a l’usage.
cependant je sèche sur un point, mon capteur se trouve dans ma cuisine ( 5.5x5.5m) mais dans un angle, sur ma capture le capteur est a cette endroit la mais balaye en diagonal le problème est que je suis limité a 4000 sur l’axe des X
Comment puis-je faire
As-tu vérifié que ta position cible (target) était bien détecté à 5,5m ? Si c’est le cas je modifierait le max X pour les zones. J’ai déjà commencé à modifier les max Y (chez moi) pour allez jusqu’à 8m. (Je vais faire une MAJ du code dans quelques jours).
Mais si tu peux orienter ton capteur à 45° vers le coin opposé de la pièce le problème sera résolu
oui la position cible fonctionne et le capteur donne a 45°. en réalité c’est juste pour que la vue plotly corresponde à la pièce. Sinon rien qu’en se positionnant là où on veux avec les coordonnées on le fait sans problème mais dans ce cas la vue plotly ne ressemblera pas à la pièce
faut aussi modifier le Y il est limité a 6000
Voila, 'j’ai modifier toutes les valeurs et cela fonctionne
Tu cherches le texte ci-dessous et tu remplaces 6000 par 8000 et tu recommence pour chaque zone.
- platform: template
name: Zone1 Y-End
id: zone1_y_end
icon: mdi:arrow-down-bold
mode: box
min_value: 0
max_value: 6000
Je suis surpris que tu sois détecté à 5,5m. Excuse mon scepticisme mais la doc dis que tu n’es pas sensé être détecté dans la zone rouge (Voir le graphique 7 à la page 10 du datasheet)
Je suis pas contre une capture d’écran
c’est modifier, tu va mieux comprendre, n’oublie pas que mon capteur est a 45°.
Sur ton dessin c’est comme si mon capteur était dans le coin supérieur gauche mais de face
ps: merci pour ton code
Ok je comprends !
Du coup, pour la prochaine MAJ je mets quelle maximum pour X ?
j’aurais tendance dire que pour satisfaire le plus grand nombre de personnes et de configuration met -8000 et 8000
bon rectification, cela ne va pas comme j’ai fait. ma piece correspond bien a la réalité mais pour lui le capteur est droit et non a 45°, du coup a gauche sur l’axe X0 je suis hors zone.
Alors comment on fait
Pour le moment laisse le capteur à 45°, on va le faire en deux temps :
- tu modifies temporairement (c’est juste une précaution) le graph en +/- 8000 en X et Y
xaxis:
dtick: 1000
gridcolor: RGBA(200,200,200,0.15)
zerolinecolor: RGBA(200,200,200,0.15)
type: number
fixedrange: true
range:
- -8000
- 8000
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
- 8000
- Tu te positionnes aux quatre coins de la pièce et tu relèves les coordonnées de la cible (pas du graph)
- Fond gauche :
- X =
- Y =
- Fond droit:
- X =
- Y =
- Devant gauche :
- X =
- Y =
- Devant droit:
- X =
- Y =
Tu postes le résultat et on analyse
alors on dit que le fond gauche et a l’endroit ou la capteur se trouve. Les valeurs sont approximatives car elle fluctuent a la prise de mesure.
- Fond gauche :
- X =0
- Y =580
- Fond droit:
- X =2800
- Y =2700
- Devant gauche :
- X =-2600
- Y =2200
- Devant droit:
- X =590
- Y =5300
C’est très intéressant !
Concernant l’augmentation des maxi pour l’axe X, je constate que c’est inutile et que la doc avait raison.
Par contre, dès que le capteur n’est pas parallèle au mur, si l’on veut fonctionner par zone, il va falloir appliquer un angle à celles-ci.
Je ne suis pas sûr que je vais y arriver, mais je vais tenter quelque chose. Je t’enverrai le code en message privé et tu me diras si ça fonctionne, si ça te va bien sûr.
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
Qui serait intéressé par cette modification
- Oui, ça m’intéresse
- Non merci
c’est a sacré boulot cette modif, forcement je suis intéressé
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 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.
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
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.
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;
}