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