├── LD2410-move-energy-chart.yaml ├── LD2410-still-energy-chart.yaml ├── esp32-notification-light.yaml ├── LD2410-esphome-config.yaml ├── LD2450-ESPHome-Component-map-chart.yaml ├── LD2450-map-chart.yaml └── LD2450-esphome-config.yaml /LD2410-move-energy-chart.yaml: -------------------------------------------------------------------------------- 1 | # The following code for a lovelace card requires installation of the Plotly Graph Card from HACS in Home Assistant. 2 | # To use this card, add a manual lovelace card and paste the follow code and replace the sensor name variables 3 | # with your sensors name without the gate number prefix. 4 | type: custom:plotly-graph 5 | title: Movement Energy 6 | fn: 7 | - $ex vars.moveEnergySensorName = "move_energy_front_door" 8 | - $ex vars.moveThresholdSensorName = "move_threshold_front_door" 9 | refresh_interval: 1 10 | hours_to_show: current_day 11 | layout: 12 | height: 350 13 | margin: 14 | l: 50 15 | r: 50 16 | t: 50 17 | b: 50 18 | showlegend: true 19 | legend: 20 | x: 0.3 21 | "y": -0.3 22 | xaxis: 23 | dtick: 1 24 | type: number 25 | fixedrange: true 26 | range: 27 | - 0 28 | - 8 29 | yaxis: 30 | dtick: 10 31 | fixedrange: true 32 | range: 33 | - 0 34 | - 100 35 | entities: 36 | - entity: "" 37 | name: Threshold 38 | mode: lines 39 | line: 40 | shape: spline 41 | width: 2 42 | color: FB239F 43 | x: 44 | - 0 45 | - 1 46 | - 2 47 | - 3 48 | - 4 49 | - 5 50 | - 6 51 | - 7 52 | - 8 53 | "y": 54 | - $ex hass.states["number.g0_" + vars.moveThresholdSensorName].state 55 | - $ex hass.states["number.g1_" + vars.moveThresholdSensorName].state 56 | - $ex hass.states["number.g2_" + vars.moveThresholdSensorName].state 57 | - $ex hass.states["number.g3_" + vars.moveThresholdSensorName].state 58 | - $ex hass.states["number.g4_" + vars.moveThresholdSensorName].state 59 | - $ex hass.states["number.g5_" + vars.moveThresholdSensorName].state 60 | - $ex hass.states["number.g6_" + vars.moveThresholdSensorName].state 61 | - $ex hass.states["number.g7_" + vars.moveThresholdSensorName].state 62 | - $ex hass.states["number.g8_" + vars.moveThresholdSensorName].state 63 | - entity: "" 64 | name: Energy 65 | mode: lines 66 | line: 67 | shape: spline 68 | width: 2 69 | color: blue 70 | x: 71 | - 0 72 | - 1 73 | - 2 74 | - 3 75 | - 4 76 | - 5 77 | - 6 78 | - 7 79 | - 8 80 | "y": 81 | - $ex hass.states["sensor.g0_" + vars.moveEnergySensorName].state 82 | - $ex hass.states["sensor.g1_" + vars.moveEnergySensorName].state 83 | - $ex hass.states["sensor.g2_" + vars.moveEnergySensorName].state 84 | - $ex hass.states["sensor.g3_" + vars.moveEnergySensorName].state 85 | - $ex hass.states["sensor.g4_" + vars.moveEnergySensorName].state 86 | - $ex hass.states["sensor.g5_" + vars.moveEnergySensorName].state 87 | - $ex hass.states["sensor.g6_" + vars.moveEnergySensorName].state 88 | - $ex hass.states["sensor.g7_" + vars.moveEnergySensorName].state 89 | - $ex hass.states["sensor.g8_" + vars.moveEnergySensorName].state 90 | raw_plotly_config: true 91 | 92 | -------------------------------------------------------------------------------- /LD2410-still-energy-chart.yaml: -------------------------------------------------------------------------------- 1 | # The following code for a lovelace card requires installation of the Plotly Graph Card from HACS in Home Assistant. 2 | # To use this card, add a manual lovelace card and paste the follow code and replace the sensor name variables 3 | # with your sensors name without the gate number prefix. 4 | type: custom:plotly-graph 5 | title: Still Energy 6 | fn: 7 | - $ex vars.stillEnergySensorName = "still_energy_front_door" 8 | - $ex vars.stillThresholdSensorName = "still_threshold_front_door" 9 | refresh_interval: 1 10 | hours_to_show: current_day 11 | layout: 12 | height: 350 13 | margin: 14 | l: 50 15 | r: 50 16 | t: 50 17 | b: 50 18 | showlegend: true 19 | legend: 20 | x: 0.3 21 | "y": -0.3 22 | xaxis: 23 | dtick: 1 24 | type: number 25 | fixedrange: true 26 | range: 27 | - 0 28 | - 8 29 | yaxis: 30 | dtick: 10 31 | fixedrange: true 32 | range: 33 | - 0 34 | - 100 35 | entities: 36 | - entity: "" 37 | name: Threshold 38 | mode: lines 39 | line: 40 | shape: spline 41 | width: 2 42 | color: FB239F 43 | x: 44 | - 0 45 | - 1 46 | - 2 47 | - 3 48 | - 4 49 | - 5 50 | - 6 51 | - 7 52 | - 8 53 | "y": 54 | - $ex hass.states["number.g0_" + vars.stillThresholdSensorName].state 55 | - $ex hass.states["number.g1_" + vars.stillThresholdSensorName].state 56 | - $ex hass.states["number.g2_" + vars.stillThresholdSensorName].state 57 | - $ex hass.states["number.g3_" + vars.stillThresholdSensorName].state 58 | - $ex hass.states["number.g4_" + vars.stillThresholdSensorName].state 59 | - $ex hass.states["number.g5_" + vars.stillThresholdSensorName].state 60 | - $ex hass.states["number.g6_" + vars.stillThresholdSensorName].state 61 | - $ex hass.states["number.g7_" + vars.stillThresholdSensorName].state 62 | - $ex hass.states["number.g8_" + vars.stillThresholdSensorName].state 63 | - entity: "" 64 | name: Energy 65 | mode: lines 66 | line: 67 | shape: spline 68 | width: 2 69 | color: blue 70 | x: 71 | - 0 72 | - 1 73 | - 2 74 | - 3 75 | - 4 76 | - 5 77 | - 6 78 | - 7 79 | - 8 80 | "y": 81 | - $ex hass.states["sensor.g0_" + vars.stillEnergySensorName].state 82 | - $ex hass.states["sensor.g1_" + vars.stillEnergySensorName].state 83 | - $ex hass.states["sensor.g2_" + vars.stillEnergySensorName].state 84 | - $ex hass.states["sensor.g3_" + vars.stillEnergySensorName].state 85 | - $ex hass.states["sensor.g4_" + vars.stillEnergySensorName].state 86 | - $ex hass.states["sensor.g5_" + vars.stillEnergySensorName].state 87 | - $ex hass.states["sensor.g6_" + vars.stillEnergySensorName].state 88 | - $ex hass.states["sensor.g7_" + vars.stillEnergySensorName].state 89 | - $ex hass.states["sensor.g8_" + vars.stillEnergySensorName].state 90 | raw_plotly_config: true 91 | 92 | -------------------------------------------------------------------------------- /esp32-notification-light.yaml: -------------------------------------------------------------------------------- 1 | substitutions: 2 | name: "esp32-c3" 3 | friendly_name: ESP32-C3 4 | espID: esphome_1 5 | 6 | esphome: 7 | name: ${name} 8 | friendly_name: ${friendly_name} 9 | platformio_options: 10 | board_build.flash_mode: dio 11 | 12 | esp32: 13 | board: esp32-c3-devkitm-1 14 | framework: 15 | type: esp-idf 16 | 17 | api: 18 | encryption: 19 | key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 20 | 21 | ota: 22 | - platform: esphome 23 | 24 | wifi: 25 | ssid: !secret wifi_ssid 26 | password: !secret wifi_password 27 | 28 | ap: 29 | ssid: ${friendly_name} 30 | password: "xxxxxxxxxxxxxxx" 31 | 32 | captive_portal: 33 | 34 | debug: 35 | update_interval: 120s 36 | 37 | logger: 38 | level: INFO 39 | baud_rate: 0 40 | 41 | esp32_ble_tracker: 42 | scan_parameters: 43 | active: true 44 | 45 | bluetooth_proxy: 46 | active: true 47 | 48 | light: 49 | - platform: status_led 50 | id: status_light 51 | output: status_output 52 | - platform: esp32_rmt_led_strip 53 | rgb_order: GRB 54 | id: ${espID}_rgb_led 55 | name: Status RGB LED 56 | chipset: ws2812 57 | effects: 58 | - pulse: 59 | transition_length: 60 | on_length: 500ms 61 | off_length: 1s 62 | update_interval: 1.5s 63 | max_brightness: 80% 64 | pin: 8 65 | num_leds: 1 66 | icon: mdi:led-outline 67 | entity_category: config 68 | restore_mode: ALWAYS_OFF 69 | 70 | output: 71 | - platform: template 72 | id: status_output 73 | type: binary 74 | write_action: 75 | - if: 76 | condition: 77 | lambda: return state > 0; 78 | then: 79 | - if: 80 | condition: 81 | switch.is_off: status_led_switch 82 | then: 83 | switch.turn_on: status_led_switch 84 | else: 85 | - if: 86 | condition: 87 | switch.is_on: status_led_switch 88 | then: 89 | switch.turn_off: status_led_switch 90 | 91 | switch: 92 | - platform: template 93 | id: status_led_switch 94 | optimistic: true 95 | on_turn_on: 96 | - light.turn_on: 97 | id: ${espID}_rgb_led 98 | red: 100% 99 | green: 0% 100 | blue: 0% 101 | brightness: 20% 102 | transition_length: 50ms 103 | on_turn_off: 104 | - light.turn_off: 105 | id: ${espID}_rgb_led 106 | transition_length: 50ms 107 | - platform: template 108 | name: "Pulse LED ${friendly_name}" 109 | optimistic: True 110 | turn_on_action: 111 | - light.turn_on: 112 | id: ${espID}_rgb_led 113 | effect: pulse 114 | turn_off_action: 115 | - light.turn_off: 116 | id: ${espID}_rgb_led 117 | 118 | button: 119 | - platform: restart 120 | name: "ESP32 Restart ${friendly_name}" 121 | - platform: safe_mode 122 | name: "ESP32 Safe Mode Boot ${friendly_name}" 123 | entity_category: diagnostic 124 | 125 | text_sensor: 126 | - platform: wifi_info 127 | ip_address: 128 | name: "ESP IP Address ${friendly_name}" 129 | ssid: 130 | name: "ESP Connected SSID ${friendly_name}" 131 | bssid: 132 | name: "ESP Connected BSSID ${friendly_name}" 133 | mac_address: 134 | name: "ESP Mac Wifi Address ${friendly_name}" 135 | scan_results: 136 | name: "ESP Latest Scan Results ${friendly_name}" 137 | 138 | binary_sensor: 139 | - platform: status 140 | name: "ESP Status ${friendly_name}" 141 | 142 | sensor: 143 | - platform: debug 144 | free: 145 | name: "ESP Memory Free ${friendly_name}" 146 | - platform: internal_temperature 147 | name: "ESP Temperature ${friendly_name}" 148 | - platform: wifi_signal # Reports the WiFi signal strength/RSSI in dB 149 | name: "WiFi Signal dB ${friendly_name}" 150 | id: wifi_signal_db${espID} 151 | update_interval: 60s 152 | entity_category: "diagnostic" 153 | - platform: copy # Reports the WiFi signal strength in % 154 | source_id: wifi_signal_db${espID} 155 | name: "WiFi Signal Percent ${friendly_name}" 156 | filters: 157 | - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0); 158 | unit_of_measurement: "%" 159 | entity_category: "diagnostic" 160 | - platform: uptime 161 | name: "ESP Uptime Sensor ${friendly_name}" 162 | -------------------------------------------------------------------------------- /LD2410-esphome-config.yaml: -------------------------------------------------------------------------------- 1 | substitutions: 2 | name: esp32-c3-ld2410 3 | friendly_name: ESP32-C3-LD2410 4 | espID: esp32_c3_ld2410 5 | 6 | esphome: 7 | name: ${name} 8 | friendly_name: ${friendly_name} 9 | on_boot: 10 | - priority: 100 11 | then: 12 | lambda: |- 13 | id(cpu_speed) = ESP.getCpuFreqMHz(); 14 | 15 | esp32: 16 | board: esp32-c3-devkitm-1 17 | framework: 18 | type: arduino 19 | 20 | # Enable logging 21 | logger: 22 | 23 | # Enable Home Assistant API 24 | api: 25 | encryption: 26 | # Replace with your own 27 | key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 28 | 29 | ota: 30 | # Replace with your own 31 | password: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 32 | 33 | wifi: 34 | ssid: !secret wifi_ssid 35 | password: !secret wifi_password 36 | 37 | # Enable fallback hotspot (captive portal) in case wifi connection fails 38 | ap: 39 | ssid: ${friendly_name}_Fallback_Hotspot 40 | password: ${name} 41 | 42 | captive_portal: 43 | 44 | globals: 45 | - id: cpu_speed 46 | type: int 47 | restore_value: no 48 | initial_value: '0' 49 | 50 | esp32_ble_tracker: 51 | scan_parameters: 52 | active: true 53 | 54 | bluetooth_proxy: 55 | active: true 56 | #cache_services: false 57 | 58 | debug: 59 | update_interval: 30s 60 | 61 | uart: 62 | id: ld2410_uart 63 | tx_pin: GPIO7 64 | rx_pin: GPIO6 65 | baud_rate: 256000 66 | parity: NONE 67 | stop_bits: 1 68 | 69 | ld2410: 70 | uart_id: ld2410_uart 71 | throttle: 1500ms 72 | id: ld2410_comp 73 | 74 | number: 75 | - platform: ld2410 76 | timeout: 77 | name: "timeout" 78 | max_move_distance_gate: 79 | name: "max move distance gate" 80 | max_still_distance_gate: 81 | name: "max still distance gate" 82 | g0: 83 | move_threshold: 84 | name: "g0 move threshold" 85 | still_threshold: 86 | name: "g0 still threshold" 87 | g1: 88 | move_threshold: 89 | name: "g1 move threshold" 90 | still_threshold: 91 | name: "g1 still threshold" 92 | g2: 93 | move_threshold: 94 | name: "g2 move threshold" 95 | still_threshold: 96 | name: "g2 still threshold" 97 | g3: 98 | move_threshold: 99 | name: "g3 move threshold" 100 | still_threshold: 101 | name: "g3 still threshold" 102 | g4: 103 | move_threshold: 104 | name: "g4 move threshold" 105 | still_threshold: 106 | name: "g4 still threshold" 107 | g5: 108 | move_threshold: 109 | name: "g5 move threshold" 110 | still_threshold: 111 | name: "g5 still threshold" 112 | g6: 113 | move_threshold: 114 | name: "g6 move threshold" 115 | still_threshold: 116 | name: "g6 still threshold" 117 | g7: 118 | move_threshold: 119 | name: "g7 move threshold" 120 | still_threshold: 121 | name: "g7 still threshold" 122 | g8: 123 | move_threshold: 124 | name: "g8 move threshold" 125 | still_threshold: 126 | name: "g8 still threshold" 127 | light_threshold: 128 | name: "light threshold" 129 | 130 | text_sensor: 131 | - platform: debug 132 | reset_reason: 133 | name: "ESP Reset Reason" 134 | icon: mdi:anchor 135 | disabled_by_default: True 136 | - platform: wifi_info 137 | ip_address: 138 | name: "ESP IP Address" 139 | ssid: 140 | name: "ESP Connected SSID" 141 | bssid: 142 | name: "ESP Connected BSSID" 143 | mac_address: 144 | name: "ESP Mac Wifi Address" 145 | scan_results: 146 | name: "ESP Latest Scan Results" 147 | - platform: ld2410 148 | version: 149 | name: "Presenece Sensor Version" 150 | mac_address: 151 | name: "Presenece Sensor Mac Address" 152 | 153 | sensor: 154 | - platform: template 155 | name: "ESP CPU Speed" 156 | accuracy_decimals: 0 157 | icon: mdi:cpu-32-bit 158 | unit_of_measurement: Mhz 159 | disabled_by_default: True 160 | lambda: |- 161 | return (id(cpu_speed)); 162 | entity_category: "diagnostic" 163 | update_interval: 600s 164 | - platform: template 165 | id: sys_esp_temperature 166 | name: ESP Temperature 167 | lambda: return temperatureRead(); 168 | unit_of_measurement: °C 169 | device_class: TEMPERATURE 170 | update_interval: 45s 171 | entity_category: "diagnostic" 172 | - platform: uptime 173 | name: ESP Uptime 174 | id: sys_uptime 175 | update_interval: 60s 176 | - platform: wifi_signal 177 | name: RSSI 178 | id: wifi_signal_db 179 | update_interval: 60s 180 | entity_category: "diagnostic" 181 | - platform: template 182 | id: esp_memory 183 | icon: mdi:memory 184 | name: ESP Free Memory 185 | lambda: return heap_caps_get_free_size(MALLOC_CAP_INTERNAL) / 1024; 186 | unit_of_measurement: 'kB' 187 | state_class: measurement 188 | entity_category: "diagnostic" 189 | update_interval: 60s 190 | - platform: ld2410 191 | moving_distance: 192 | name: "Moving distance (cm)" 193 | still_distance: 194 | name: "Still Distance (cm)" 195 | moving_energy: 196 | name: "Move Energy (%)" 197 | still_energy: 198 | name: "Still Energy (%)" 199 | detection_distance: 200 | name: "Distance Detection (cm)" 201 | g0: 202 | move_energy: 203 | name: "g0 move energy" 204 | still_energy: 205 | name: "g0 still energy" 206 | g1: 207 | move_energy: 208 | name: "g1 move energy" 209 | still_energy: 210 | name: "g1 still energy" 211 | g2: 212 | move_energy: 213 | name: "g2 move energy" 214 | still_energy: 215 | name: "g2 still energy" 216 | g3: 217 | move_energy: 218 | name: "g3 move energy" 219 | still_energy: 220 | name: "g3 still energy" 221 | g4: 222 | move_energy: 223 | name: "g4 move energy" 224 | still_energy: 225 | name: "g4 still energy" 226 | g5: 227 | move_energy: 228 | name: "g5 move energy" 229 | still_energy: 230 | name: "g5 still energy" 231 | g6: 232 | move_energy: 233 | name: "g6 move energy" 234 | still_energy: 235 | name: "g6 still energy" 236 | g7: 237 | move_energy: 238 | name: "g7 move energy" 239 | still_energy: 240 | name: "g7 still energy" 241 | g8: 242 | move_energy: 243 | name: "g8 move energy" 244 | still_energy: 245 | name: "g8 still energy" 246 | light: 247 | name: "light" 248 | 249 | button: 250 | - platform: restart 251 | icon: mdi:power-cycle 252 | name: "ESP Reboot" 253 | entity_category: diagnostic 254 | - platform: ld2410 255 | factory_reset: 256 | name: "LD2410 Factory Reset" 257 | entity_category: diagnostic 258 | restart: 259 | name: "LD2410 Restart" 260 | entity_category: config 261 | query_params: 262 | name: "LD2410 query params" 263 | 264 | switch: 265 | - platform: ld2410 266 | engineering_mode: 267 | name: "LD2410 Engineering Mode" 268 | bluetooth: 269 | name: "LD2410 Control Bluetooth" 270 | - platform: factory_reset 271 | name: Factory Reset 272 | disabled_by_default: True 273 | icon: mdi:heart-broken 274 | 275 | select: 276 | - platform: ld2410 277 | distance_resolution: 278 | name: "distance resolution" 279 | baud_rate: 280 | name: "baud rate" 281 | light_function: 282 | name: "light function" 283 | out_pin_level: 284 | name: "out pin level" 285 | 286 | binary_sensor: 287 | - platform: status 288 | name: "ESP Status" 289 | - platform: ld2410 290 | has_target: 291 | name: "Presence" 292 | has_moving_target: 293 | name: "Moving Target" 294 | has_still_target: 295 | name: "Still Target" 296 | -------------------------------------------------------------------------------- /LD2450-ESPHome-Component-map-chart.yaml: -------------------------------------------------------------------------------- 1 | # The following code for a lovelace card requires installation of the Plotly Graph Card from HACS in Home Assistant. 2 | # To use this card, add a manual lovelace card and paste the follow code and replace the variable values with 3 | # your sensor names 4 | # 5 | # To configure, adjust the name vars below to match the sensor and number entity names in Home Assistant. 6 | # eg. 7 | # If your sensor name is 'sensor.ld2450-radar_target_1_x' 8 | # Use vars.sensorName = "ld2450-radar" 9 | # 10 | # If your number entity name is 'number.ld2450-radar_zone_1_x1' 11 | # Use vars.numberEntityName = "ld2450-radar" 12 | 13 | type: custom:plotly-graph 14 | fn: 15 | - $ex vars.espName = "ESP32-1" 16 | - $ex vars.sensorName = "ld2450-radar" 17 | - $ex vars.numberEntityName = "ld2450-radar" 18 | - $ex vars.zone1Name = "Zone 1" 19 | - $ex vars.zone2Name = "Zone 2" 20 | - $ex vars.zone3Name = "Zone 3" 21 | title: $ex vars.espName + " Target Positions" 22 | refresh_interval: 1 23 | hours_to_show: current_day 24 | layout: 25 | height: 230 26 | margin: 27 | l: 50 28 | r: 20 29 | t: 20 30 | b: 40 31 | showlegend: true 32 | xaxis: 33 | dtick: 1000 34 | gridcolor: RGBA(200,200,200,0.15) 35 | zerolinecolor: RGBA(200,200,200,0.15) 36 | type: number 37 | fixedrange: true 38 | range: 39 | - 5000 40 | - -5000 41 | yaxis: 42 | dtick: 1000 43 | gridcolor: RGBA(200,200,200,0.15) 44 | zerolinecolor: RGBA(200,200,200,0.15) 45 | scaleanchor: x 46 | scaleratio: 1 47 | fixedrange: true 48 | range: 49 | - 7500 50 | - 0 51 | entities: 52 | - entity: "" 53 | name: Target1 54 | marker: 55 | size: 12 56 | line: 57 | shape: spline 58 | width: 5 59 | x: 60 | - >- 61 | $ex { var x = hass.states["sensor." + vars.sensorName + 62 | "_target_1_x"].state; var y = hass.states["sensor." + vars.sensorName + 63 | "_target_1_y"].state; if (x == 0 && y == 0) { return -9999 }; return x; } 64 | "y": 65 | - >- 66 | $ex { var x = hass.states["sensor." + vars.sensorName + 67 | "_target_1_x"].state; var y = hass.states["sensor." + vars.sensorName + 68 | "_target_1_y"].state; if (x == 0 && y == 0) { return -9999 }; return y; } 69 | - entity: "" 70 | name: Target2 71 | marker: 72 | size: 12 73 | line: 74 | shape: spline 75 | width: 5 76 | x: 77 | - >- 78 | $ex { var x = hass.states["sensor." + vars.sensorName + 79 | "_target_2_x"].state; var y = hass.states["sensor." + vars.sensorName + 80 | "_target_2_y"].state; if (x == 0 && y == 0) { return -9999 }; return x; } 81 | "y": 82 | - >- 83 | $ex { var x = hass.states["sensor." + vars.sensorName + 84 | "_target_2_x"].state; var y = hass.states["sensor." + vars.sensorName + 85 | "_target_2_y"].state; if (x == 0 && y == 0) { return -9999 }; return y; } 86 | - entity: "" 87 | name: Target3 88 | marker: 89 | size: 12 90 | line: 91 | shape: spline 92 | width: 5 93 | x: 94 | - >- 95 | $ex { var x = hass.states["sensor." + vars.sensorName + 96 | "_target_3_x"].state; var y = hass.states["sensor." + vars.sensorName + 97 | "_target_3_y"].state; if (x == 0 && y == 0) { return -9999 }; return x; } 98 | "y": 99 | - >- 100 | $ex { var x = hass.states["sensor." + vars.sensorName + 101 | "_target_3_x"].state; var y = hass.states["sensor." + vars.sensorName + 102 | "_target_3_y"].state; if (x == 0 && y == 0) { return -9999 }; return y; } 103 | - entity: "" 104 | name: $ex vars.zone1Name 105 | mode: lines 106 | fill: toself 107 | fillcolor: RGBA(20,200,0,0.06) 108 | line: 109 | color: RGBA(20,200,0,0.2) 110 | shape: line 111 | width: 2 112 | x: 113 | - >- 114 | $ex hass.states["number." + vars.numberEntityName + 115 | "_zone_1_x1"].state 116 | - >- 117 | $ex hass.states["number." + vars.numberEntityName + 118 | "_zone_1_x1"].state 119 | - $ex hass.states["number." + vars.numberEntityName + "_zone_1_x2"].state 120 | - $ex hass.states["number." + vars.numberEntityName + "_zone_1_x2"].state 121 | - >- 122 | $ex hass.states["number." + vars.numberEntityName + 123 | "_zone_1_x1"].state 124 | "y": 125 | - >- 126 | $ex hass.states["number." + vars.numberEntityName + 127 | "_zone_1_y1"].state 128 | - $ex hass.states["number." + vars.numberEntityName + "_zone_1_y2"].state 129 | - $ex hass.states["number." + vars.numberEntityName + "_zone_1_y2"].state 130 | - >- 131 | $ex hass.states["number." + vars.numberEntityName + 132 | "_zone_1_y1"].state 133 | - >- 134 | $ex hass.states["number." + vars.numberEntityName + 135 | "_zone_1_y1"].state 136 | - entity: "" 137 | name: $ex vars.zone2Name 138 | mode: lines 139 | fill: toself 140 | fillcolor: RGBA(200,0,255,0.06) 141 | line: 142 | color: RGBA(200,0,255,0.2) 143 | shape: line 144 | width: 2 145 | x: 146 | - >- 147 | $ex hass.states["number." + vars.numberEntityName + 148 | "_zone_2_x1"].state 149 | - >- 150 | $ex hass.states["number." + vars.numberEntityName + 151 | "_zone_2_x1"].state 152 | - $ex hass.states["number." + vars.numberEntityName + "_zone_2_x2"].state 153 | - $ex hass.states["number." + vars.numberEntityName + "_zone_2_x2"].state 154 | - >- 155 | $ex hass.states["number." + vars.numberEntityName + 156 | "_zone_2_x1"].state 157 | "y": 158 | - >- 159 | $ex hass.states["number." + vars.numberEntityName + 160 | "_zone_2_y1"].state 161 | - $ex hass.states["number." + vars.numberEntityName + "_zone_2_y2"].state 162 | - $ex hass.states["number." + vars.numberEntityName + "_zone_2_y2"].state 163 | - >- 164 | $ex hass.states["number." + vars.numberEntityName + 165 | "_zone_2_y1"].state 166 | - >- 167 | $ex hass.states["number." + vars.numberEntityName + 168 | "_zone_2_y1"].state 169 | - entity: "" 170 | name: $ex vars.zone3Name 171 | mode: lines 172 | fill: toself 173 | fillcolor: RGBA(200,120,55,0.06) 174 | line: 175 | color: RGBA(200,120,55,0.2) 176 | shape: line 177 | width: 2 178 | x: 179 | - >- 180 | $ex hass.states["number." + vars.numberEntityName + 181 | "_zone_3_x1"].state 182 | - >- 183 | $ex hass.states["number." + vars.numberEntityName + 184 | "_zone_3_x1"].state 185 | - $ex hass.states["number." + vars.numberEntityName + "_zone_3_x2"].state 186 | - $ex hass.states["number." + vars.numberEntityName + "_zone_3_x2"].state 187 | - >- 188 | $ex hass.states["number." + vars.numberEntityName + 189 | "_zone_3_x1"].state 190 | "y": 191 | - >- 192 | $ex hass.states["number." + vars.numberEntityName + 193 | "_zone_3_y1"].state 194 | - $ex hass.states["number." + vars.numberEntityName + "_zone_3_y2"].state 195 | - $ex hass.states["number." + vars.numberEntityName + "_zone_3_y2"].state 196 | - >- 197 | $ex hass.states["number." + vars.numberEntityName + 198 | "_zone_3_y1"].state 199 | - >- 200 | $ex hass.states["number." + vars.numberEntityName + 201 | "_zone_3_y1"].state 202 | - entity: "" 203 | name: Coverage 204 | mode: lines 205 | fill: tonexty 206 | fillcolor: rgba(168, 216, 234, 0.07) 207 | line: 208 | shape: line 209 | width: 1 210 | dash: dot 211 | x: 212 | - 0 213 | - $ex 7500 * Math.sin((2 * Math.PI)/360 * 60) 214 | - 4500 215 | - 4000 216 | - 3000 217 | - 2000 218 | - 1000 219 | - 0 220 | - -1000 221 | - -2000 222 | - -3000 223 | - -4000 224 | - -4500 225 | - $ex -7500 * Math.sin((2 * Math.PI)/360 * 60) 226 | - 0 227 | "y": 228 | - 0 229 | - $ex 7500 * Math.cos((2 * Math.PI)/360 * 60) 230 | - $ex Math.sqrt( 7500**2 - 4500**2 ) 231 | - $ex Math.sqrt( 7500**2 - 4000**2 ) 232 | - $ex Math.sqrt( 7500**2 - 3000**2 ) 233 | - $ex Math.sqrt( 7500**2 - 2000**2 ) 234 | - $ex Math.sqrt( 7500**2 - 1000**2 ) 235 | - 7500 236 | - $ex Math.sqrt( 7500**2 - 1000**2 ) 237 | - $ex Math.sqrt( 7500**2 - 2000**2 ) 238 | - $ex Math.sqrt( 7500**2 - 3000**2 ) 239 | - $ex Math.sqrt( 7500**2 - 4000**2 ) 240 | - $ex Math.sqrt( 7500**2 - 4500**2 ) 241 | - $ex 7500 * Math.cos((2 * Math.PI)/360 * 60) 242 | - 0 243 | raw_plotly_config: true 244 | -------------------------------------------------------------------------------- /LD2450-map-chart.yaml: -------------------------------------------------------------------------------- 1 | # The following code for a lovelace card requires installation of the Plotly Graph Card from HACS in Home Assistant. 2 | # To use this card, add a manual lovelace card and paste the follow code and replace the variable values with 3 | # your sensor names 4 | 5 | type: custom:plotly-graph 6 | fn: 7 | - $ex vars.espName = "ESP32-1" 8 | - $ex vars.sensorName = "ld2450-radar" 9 | - $ex vars.zoneSensorName = "ld2450-zones" 10 | - $ex vars.zone1Name = "Zone 1" 11 | - $ex vars.zone2Name = "Zone 2" 12 | - $ex vars.zone3Name = "Zone 3" 13 | - $ex vars.exlusionZoneName = "Exclusion" 14 | title: $ex vars.espName + " Target Positions" 15 | refresh_interval: 1 16 | hours_to_show: current_day 17 | layout: 18 | height: 230 19 | margin: 20 | l: 50 21 | r: 20 22 | t: 20 23 | b: 40 24 | showlegend: true 25 | xaxis: 26 | dtick: 1000 27 | gridcolor: RGBA(200,200,200,0.15) 28 | zerolinecolor: RGBA(200,200,200,0.15) 29 | type: number 30 | fixedrange: true 31 | range: 32 | - 5000 33 | - -5000 34 | yaxis: 35 | dtick: 1000 36 | gridcolor: RGBA(200,200,200,0.15) 37 | zerolinecolor: RGBA(200,200,200,0.15) 38 | scaleanchor: x 39 | scaleratio: 1 40 | fixedrange: true 41 | range: 42 | - 7500 43 | - 0 44 | entities: 45 | - entity: "" 46 | name: Target1 47 | marker: 48 | size: 12 49 | line: 50 | shape: spline 51 | width: 5 52 | x: 53 | - >- 54 | $ex { var x = hass.states["sensor." + vars.sensorName + 55 | "_target1_x"].state; var y = hass.states["sensor." + vars.sensorName + 56 | "_target1_y"].state; if (x == 0 && y == 0) { return -9999 }; return x; } 57 | "y": 58 | - >- 59 | $ex { var x = hass.states["sensor." + vars.sensorName + 60 | "_target1_x"].state; var y = hass.states["sensor." + vars.sensorName + 61 | "_target1_y"].state; if (x == 0 && y == 0) { return -9999 }; return y; } 62 | - entity: "" 63 | name: Target2 64 | marker: 65 | size: 12 66 | line: 67 | shape: spline 68 | width: 5 69 | x: 70 | - >- 71 | $ex { var x = hass.states["sensor." + vars.sensorName + 72 | "_target2_x"].state; var y = hass.states["sensor." + vars.sensorName + 73 | "_target2_y"].state; if (x == 0 && y == 0) { return -9999 }; return x; } 74 | "y": 75 | - >- 76 | $ex { var x = hass.states["sensor." + vars.sensorName + 77 | "_target2_x"].state; var y = hass.states["sensor." + vars.sensorName + 78 | "_target2_y"].state; if (x == 0 && y == 0) { return -9999 }; return y; } 79 | - entity: "" 80 | name: Target3 81 | marker: 82 | size: 12 83 | line: 84 | shape: spline 85 | width: 5 86 | x: 87 | - >- 88 | $ex { var x = hass.states["sensor." + vars.sensorName + 89 | "_target3_x"].state; var y = hass.states["sensor." + vars.sensorName + 90 | "_target3_y"].state; if (x == 0 && y == 0) { return -9999 }; return x; } 91 | "y": 92 | - >- 93 | $ex { var x = hass.states["sensor." + vars.sensorName + 94 | "_target3_x"].state; var y = hass.states["sensor." + vars.sensorName + 95 | "_target3_y"].state; if (x == 0 && y == 0) { return -9999 }; return y; } 96 | - entity: "" 97 | name: $ex vars.zone1Name 98 | mode: lines 99 | fill: toself 100 | fillcolor: RGBA(20,200,0,0.06) 101 | line: 102 | color: RGBA(20,200,0,0.2) 103 | shape: line 104 | width: 2 105 | x: 106 | - >- 107 | $ex hass.states["number." + vars.zoneSensorName + 108 | "_zone1_x_begin"].state 109 | - >- 110 | $ex hass.states["number." + vars.zoneSensorName + 111 | "_zone1_x_begin"].state 112 | - $ex hass.states["number." + vars.zoneSensorName + "_zone1_x_end"].state 113 | - $ex hass.states["number." + vars.zoneSensorName + "_zone1_x_end"].state 114 | - >- 115 | $ex hass.states["number." + vars.zoneSensorName + 116 | "_zone1_x_begin"].state 117 | "y": 118 | - >- 119 | $ex hass.states["number." + vars.zoneSensorName + 120 | "_zone1_y_begin"].state 121 | - $ex hass.states["number." + vars.zoneSensorName + "_zone1_y_end"].state 122 | - $ex hass.states["number." + vars.zoneSensorName + "_zone1_y_end"].state 123 | - >- 124 | $ex hass.states["number." + vars.zoneSensorName + 125 | "_zone1_y_begin"].state 126 | - >- 127 | $ex hass.states["number." + vars.zoneSensorName + 128 | "_zone1_y_begin"].state 129 | - entity: "" 130 | name: $ex vars.zone2Name 131 | mode: lines 132 | fill: toself 133 | fillcolor: RGBA(200,0,255,0.06) 134 | line: 135 | color: RGBA(200,0,255,0.2) 136 | shape: line 137 | width: 2 138 | x: 139 | - >- 140 | $ex hass.states["number." + vars.zoneSensorName + 141 | "_zone2_x_begin"].state 142 | - >- 143 | $ex hass.states["number." + vars.zoneSensorName + 144 | "_zone2_x_begin"].state 145 | - $ex hass.states["number." + vars.zoneSensorName + "_zone2_x_end"].state 146 | - $ex hass.states["number." + vars.zoneSensorName + "_zone2_x_end"].state 147 | - >- 148 | $ex hass.states["number." + vars.zoneSensorName + 149 | "_zone2_x_begin"].state 150 | "y": 151 | - >- 152 | $ex hass.states["number." + vars.zoneSensorName + 153 | "_zone2_y_begin"].state 154 | - $ex hass.states["number." + vars.zoneSensorName + "_zone2_y_end"].state 155 | - $ex hass.states["number." + vars.zoneSensorName + "_zone2_y_end"].state 156 | - >- 157 | $ex hass.states["number." + vars.zoneSensorName + 158 | "_zone2_y_begin"].state 159 | - >- 160 | $ex hass.states["number." + vars.zoneSensorName + 161 | "_zone2_y_begin"].state 162 | - entity: "" 163 | name: $ex vars.zone3Name 164 | mode: lines 165 | fill: toself 166 | fillcolor: RGBA(200,120,55,0.06) 167 | line: 168 | color: RGBA(200,120,55,0.2) 169 | shape: line 170 | width: 2 171 | x: 172 | - >- 173 | $ex hass.states["number." + vars.zoneSensorName + 174 | "_zone3_x_begin"].state 175 | - >- 176 | $ex hass.states["number." + vars.zoneSensorName + 177 | "_zone3_x_begin"].state 178 | - $ex hass.states["number." + vars.zoneSensorName + "_zone3_x_end"].state 179 | - $ex hass.states["number." + vars.zoneSensorName + "_zone3_x_end"].state 180 | - >- 181 | $ex hass.states["number." + vars.zoneSensorName + 182 | "_zone3_x_begin"].state 183 | "y": 184 | - >- 185 | $ex hass.states["number." + vars.zoneSensorName + 186 | "_zone3_y_begin"].state 187 | - $ex hass.states["number." + vars.zoneSensorName + "_zone3_y_end"].state 188 | - $ex hass.states["number." + vars.zoneSensorName + "_zone3_y_end"].state 189 | - >- 190 | $ex hass.states["number." + vars.zoneSensorName + 191 | "_zone3_y_begin"].state 192 | - >- 193 | $ex hass.states["number." + vars.zoneSensorName + 194 | "_zone3_y_begin"].state 195 | - entity: "" 196 | name: $ex vars.exlusionZoneName 197 | mode: lines 198 | fill: toself 199 | fillcolor: RGBA(255,0,0,0.15) 200 | line: 201 | shape: line 202 | width: 1 203 | color: RGBA(255,0,0,0.2) 204 | x: 205 | - >- 206 | $ex hass.states["number." + vars.zoneSensorName + 207 | "_zout1_x_begin"].state 208 | - >- 209 | $ex hass.states["number." + vars.zoneSensorName + 210 | "_zout1_x_begin"].state 211 | - $ex hass.states["number." + vars.zoneSensorName + "_zout1_x_end"].state 212 | - $ex hass.states["number." + vars.zoneSensorName + "_zout1_x_end"].state 213 | - >- 214 | $ex hass.states["number." + vars.zoneSensorName + 215 | "_zout1_x_begin"].state 216 | "y": 217 | - >- 218 | $ex hass.states["number." + vars.zoneSensorName + 219 | "_zout1_y_begin"].state 220 | - $ex hass.states["number." + vars.zoneSensorName + "_zout1_y_end"].state 221 | - $ex hass.states["number." + vars.zoneSensorName + "_zout1_y_end"].state 222 | - >- 223 | $ex hass.states["number." + vars.zoneSensorName + 224 | "_zout1_y_begin"].state 225 | - >- 226 | $ex hass.states["number." + vars.zoneSensorName + 227 | "_zout1_y_begin"].state 228 | - entity: "" 229 | name: Coverage 230 | mode: lines 231 | fill: tonexty 232 | fillcolor: rgba(168, 216, 234, 0.07) 233 | line: 234 | shape: line 235 | width: 1 236 | dash: dot 237 | x: 238 | - 0 239 | - $ex 7500 * Math.sin((2 * Math.PI)/360 * 60) 240 | - 4500 241 | - 4000 242 | - 3000 243 | - 2000 244 | - 1000 245 | - 0 246 | - -1000 247 | - -2000 248 | - -3000 249 | - -4000 250 | - -4500 251 | - $ex -7500 * Math.sin((2 * Math.PI)/360 * 60) 252 | - 0 253 | "y": 254 | - 0 255 | - $ex 7500 * Math.cos((2 * Math.PI)/360 * 60) 256 | - $ex Math.sqrt( 7500**2 - 4500**2 ) 257 | - $ex Math.sqrt( 7500**2 - 4000**2 ) 258 | - $ex Math.sqrt( 7500**2 - 3000**2 ) 259 | - $ex Math.sqrt( 7500**2 - 2000**2 ) 260 | - $ex Math.sqrt( 7500**2 - 1000**2 ) 261 | - 7500 262 | - $ex Math.sqrt( 7500**2 - 1000**2 ) 263 | - $ex Math.sqrt( 7500**2 - 2000**2 ) 264 | - $ex Math.sqrt( 7500**2 - 3000**2 ) 265 | - $ex Math.sqrt( 7500**2 - 4000**2 ) 266 | - $ex Math.sqrt( 7500**2 - 4500**2 ) 267 | - $ex 7500 * Math.cos((2 * Math.PI)/360 * 60) 268 | - 0 269 | raw_plotly_config: true 270 | -------------------------------------------------------------------------------- /LD2450-esphome-config.yaml: -------------------------------------------------------------------------------- 1 | substitutions: 2 | name: esphome-web-xxxxxx 3 | friendly_name: ESP32-C3-1 4 | espID: esphome_web_xxxxxx 5 | 6 | esphome: 7 | name: ${name} 8 | friendly_name: ${friendly_name} 9 | 10 | on_boot: 11 | - priority: 100 12 | then: 13 | lambda: |- 14 | id(cpu_speed) = ESP.getCpuFreqMHz(); 15 | - priority: -200 16 | then: 17 | lambda: |- 18 | id(zone1_target_exsits).publish_state(false); 19 | id(zone2_target_exsits).publish_state(false); 20 | id(zone3_target_exsits).publish_state(false); 21 | id(zone_ex1_target_exsits).publish_state(false); 22 | 23 | esp32: 24 | board: esp32-c3-devkitm-1 25 | framework: 26 | type: arduino 27 | 28 | debug: 29 | update_interval: 30s 30 | 31 | # Enable logging 32 | logger: 33 | 34 | # Enable Home Assistant API 35 | api: 36 | encryption: 37 | key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 38 | 39 | ota: 40 | 41 | esp32_ble_tracker: 42 | scan_parameters: 43 | active: true 44 | 45 | bluetooth_proxy: 46 | active: true 47 | 48 | wifi: 49 | networks: 50 | - ssid: !secret wifi2_ssid 51 | password: !secret wifi2_password 52 | priority: 2 53 | - ssid: !secret wifi_ssid 54 | password: !secret wifi_password 55 | priority: 1 56 | # Enable fallback hotspot (captive portal) in case wifi connection fails 57 | ap: 58 | ssid: ${name} 59 | password: "xxxxxxxxx" 60 | 61 | captive_portal: 62 | 63 | light: 64 | - platform: status_led 65 | id: status_light 66 | output: status_output 67 | - platform: neopixelbus 68 | id: ${espID}_rgb_led 69 | name: Status RGB LED 70 | type: GRB 71 | variant: WS2812 72 | pin: 8 73 | num_leds: 1 74 | icon: mdi:led-outline 75 | entity_category: config 76 | restore_mode: ALWAYS_OFF 77 | method: 78 | type: esp32_rmt 79 | channel: 0 80 | 81 | output: 82 | - platform: template 83 | id: status_output 84 | type: binary 85 | write_action: 86 | - if: 87 | condition: 88 | lambda: return state > 0; 89 | then: 90 | - if: 91 | condition: 92 | switch.is_off: status_led_switch 93 | then: 94 | switch.turn_on: status_led_switch 95 | else: 96 | - if: 97 | condition: 98 | switch.is_on: status_led_switch 99 | then: 100 | switch.turn_off: status_led_switch 101 | 102 | preferences: 103 | flash_write_interval: 5s 104 | 105 | globals: 106 | - id: cpu_speed 107 | type: int 108 | restore_value: no 109 | initial_value: '0' 110 | - id: last_update_ld2450 111 | type: unsigned long 112 | restore_value: no 113 | initial_value: '0' 114 | - id: init_zone_publish 115 | type: bool 116 | restore_value: no 117 | initial_value: "false" 118 | 119 | text_sensor: 120 | - platform: debug 121 | reset_reason: 122 | name: "ESP Reset Reason" 123 | icon: mdi:anchor 124 | disabled_by_default: True 125 | - platform: wifi_info 126 | ip_address: 127 | name: ESP IP Address 128 | entity_category: "diagnostic" 129 | disabled_by_default: True 130 | icon: mdi:ip-network 131 | mac_address: 132 | name: ESP MAC 133 | entity_category: "diagnostic" 134 | icon: mdi:ip-network 135 | disabled_by_default: True 136 | - platform: template 137 | name: "Zone1 Info" 138 | id: tips_zone1_conf 139 | icon: mdi:information-outline 140 | entity_category: config 141 | lambda: |- 142 | return {"Configure below" }; 143 | update_interval: 1000s 144 | - platform: template 145 | name: "Zone2 Info" 146 | id: tips_zone2_conf 147 | icon: mdi:information-outline 148 | entity_category: config 149 | lambda: |- 150 | return {"Configure below" }; 151 | update_interval: 1000s 152 | - platform: template 153 | name: "Zone3 Info" 154 | id: tips_zone3_conf 155 | icon: mdi:information-outline 156 | entity_category: config 157 | lambda: |- 158 | return {"Configure below" }; 159 | update_interval: 1000s 160 | - platform: template 161 | name: "Zout1 Info" 162 | id: tips_zone_ex1_conf 163 | icon: mdi:information-outline 164 | entity_category: config 165 | lambda: |- 166 | return {"Zone Exclusion 1" }; 167 | update_interval: 1000s 168 | 169 | number: 170 | - platform: template 171 | name: "Any Presence Timeout" 172 | id: any_presence_timeout 173 | min_value: 0 174 | max_value: 600 175 | mode: box 176 | device_class: duration 177 | entity_category: config 178 | unit_of_measurement: s 179 | icon: mdi:timer-off 180 | step: 1 181 | optimistic: True 182 | initial_value: 0 183 | restore_value: True 184 | - platform: template 185 | name: "Zone1 Timeout" 186 | id: zone1_x_timeout 187 | min_value: 0 188 | max_value: 600 189 | mode: box 190 | device_class: duration 191 | entity_category: config 192 | unit_of_measurement: s 193 | icon: mdi:timer-off 194 | step: 1 195 | optimistic: True 196 | initial_value: 0 197 | restore_value: True 198 | - platform: template 199 | name: "Zone2 Timeout" 200 | id: zone2_x_timeout 201 | min_value: 0 202 | max_value: 600 203 | mode: box 204 | device_class: duration 205 | entity_category: config 206 | unit_of_measurement: s 207 | icon: mdi:timer-off 208 | step: 1 209 | optimistic: True 210 | initial_value: 0 211 | restore_value: True 212 | - platform: template 213 | name: "Zone3 Timeout" 214 | id: zone3_x_timeout 215 | min_value: 0 216 | max_value: 600 217 | mode: box 218 | device_class: duration 219 | entity_category: config 220 | unit_of_measurement: s 221 | icon: mdi:timer-off 222 | step: 1 223 | optimistic: True 224 | initial_value: 0 225 | restore_value: True 226 | # Zone 1 227 | - platform: template 228 | name: Zone1 X-Begin 229 | id: zone1_x_begin 230 | min_value: -4000 231 | max_value: 4000 232 | mode: box 233 | device_class: distance 234 | entity_category: config 235 | unit_of_measurement: mm 236 | icon: mdi:arrow-left-bold 237 | step: 10 238 | optimistic: True 239 | initial_value: 0 240 | restore_value: True 241 | on_value: 242 | then: 243 | - script.execute: check_zone1_vaild 244 | - platform: template 245 | name: Zone1 X-End 246 | id: zone1_x_end 247 | mode: box 248 | min_value: -4000 249 | max_value: 4000 250 | device_class: distance 251 | unit_of_measurement: mm 252 | entity_category: config 253 | icon: mdi:arrow-right-bold 254 | step: 10 255 | initial_value: 0 256 | optimistic: True 257 | restore_value: True 258 | on_value: 259 | then: 260 | - script.execute: check_zone1_vaild 261 | - platform: template 262 | name: Zone1 Y-Begin 263 | id: zone1_y_begin 264 | mode: box 265 | min_value: 0 266 | max_value: 6000 267 | device_class: distance 268 | entity_category: config 269 | icon: mdi:arrow-up-bold 270 | unit_of_measurement: mm 271 | step: 10 272 | initial_value: 0 273 | optimistic: True 274 | restore_value: True 275 | on_value: 276 | then: 277 | - script.execute: check_zone1_vaild 278 | - platform: template 279 | name: Zone1 Y-End 280 | id: zone1_y_end 281 | icon: mdi:arrow-down-bold 282 | mode: box 283 | min_value: 0 284 | max_value: 6000 285 | initial_value: 0 286 | entity_category: config 287 | device_class: distance 288 | unit_of_measurement: mm 289 | step: 10 290 | optimistic: True 291 | restore_value: True 292 | on_value: 293 | then: 294 | - script.execute: check_zone1_vaild 295 | 296 | # Zone 2 297 | - platform: template 298 | name: Zone2 X-Begin 299 | id: zone2_x_begin 300 | min_value: -4000 301 | max_value: 4000 302 | mode: box 303 | device_class: distance 304 | entity_category: config 305 | unit_of_measurement: mm 306 | icon: mdi:arrow-left-bold 307 | step: 10 308 | optimistic: True 309 | initial_value: 0 310 | restore_value: True 311 | on_value: 312 | then: 313 | - script.execute: check_zone2_vaild 314 | - platform: template 315 | name: Zone2 X-End 316 | id: zone2_x_end 317 | mode: box 318 | min_value: -4000 319 | max_value: 4000 320 | device_class: distance 321 | unit_of_measurement: mm 322 | entity_category: config 323 | icon: mdi:arrow-right-bold 324 | step: 10 325 | initial_value: 0 326 | optimistic: True 327 | restore_value: True 328 | on_value: 329 | then: 330 | - script.execute: check_zone2_vaild 331 | - platform: template 332 | name: Zone2 Y-Begin 333 | id: zone2_y_begin 334 | mode: box 335 | min_value: 0 336 | max_value: 6000 337 | device_class: distance 338 | entity_category: config 339 | icon: mdi:arrow-up-bold 340 | unit_of_measurement: mm 341 | step: 10 342 | initial_value: 0 343 | optimistic: True 344 | restore_value: True 345 | on_value: 346 | then: 347 | - script.execute: check_zone2_vaild 348 | - platform: template 349 | name: Zone2 Y-End 350 | id: zone2_y_end 351 | icon: mdi:arrow-down-bold 352 | mode: box 353 | min_value: 0 354 | max_value: 6000 355 | initial_value: 0 356 | entity_category: config 357 | device_class: distance 358 | unit_of_measurement: mm 359 | step: 10 360 | optimistic: True 361 | restore_value: True 362 | on_value: 363 | then: 364 | - script.execute: check_zone2_vaild 365 | 366 | # Zone 3 367 | - platform: template 368 | name: Zone3 X-Begin 369 | id: zone3_x_begin 370 | min_value: -4000 371 | max_value: 4000 372 | mode: box 373 | device_class: distance 374 | entity_category: config 375 | unit_of_measurement: mm 376 | icon: mdi:arrow-left-bold 377 | step: 10 378 | optimistic: True 379 | initial_value: 0 380 | restore_value: True 381 | on_value: 382 | then: 383 | - script.execute: check_zone3_vaild 384 | - platform: template 385 | name: Zone3 X-End 386 | id: zone3_x_end 387 | mode: box 388 | min_value: -4000 389 | max_value: 4000 390 | device_class: distance 391 | unit_of_measurement: mm 392 | entity_category: config 393 | icon: mdi:arrow-right-bold 394 | step: 10 395 | initial_value: 0 396 | optimistic: True 397 | restore_value: True 398 | on_value: 399 | then: 400 | - script.execute: check_zone3_vaild 401 | - platform: template 402 | name: Zone3 Y-Begin 403 | id: zone3_y_begin 404 | mode: box 405 | min_value: 0 406 | max_value: 6000 407 | device_class: distance 408 | entity_category: config 409 | icon: mdi:arrow-up-bold 410 | unit_of_measurement: mm 411 | step: 10 412 | initial_value: 0 413 | optimistic: True 414 | restore_value: True 415 | on_value: 416 | then: 417 | - script.execute: check_zone3_vaild 418 | - platform: template 419 | name: Zone3 Y-End 420 | id: zone3_y_end 421 | icon: mdi:arrow-down-bold 422 | mode: box 423 | min_value: 0 424 | max_value: 6000 425 | initial_value: 0 426 | entity_category: config 427 | device_class: distance 428 | unit_of_measurement: mm 429 | step: 10 430 | optimistic: True 431 | restore_value: True 432 | on_value: 433 | then: 434 | - script.execute: check_zone3_vaild 435 | 436 | # Zout1 437 | - platform: template 438 | name: Zout1 X-Begin 439 | id: zone_ex1_x_begin 440 | min_value: -4000 441 | max_value: 4000 442 | mode: box 443 | device_class: distance 444 | entity_category: config 445 | unit_of_measurement: mm 446 | icon: mdi:arrow-left-bold 447 | step: 10 448 | optimistic: True 449 | initial_value: 0 450 | restore_value: True 451 | on_value: 452 | then: 453 | - script.execute: check_zout1_vaild 454 | - platform: template 455 | name: Zout1 X-End 456 | id: zone_ex1_x_end 457 | mode: box 458 | min_value: -4000 459 | max_value: 4000 460 | device_class: distance 461 | unit_of_measurement: mm 462 | entity_category: config 463 | icon: mdi:arrow-right-bold 464 | step: 10 465 | initial_value: 0 466 | optimistic: True 467 | restore_value: True 468 | on_value: 469 | then: 470 | - script.execute: check_zout1_vaild 471 | - platform: template 472 | name: Zout1 Y-Begin 473 | id: zone_ex1_y_begin 474 | mode: box 475 | min_value: 0 476 | max_value: 6000 477 | device_class: distance 478 | entity_category: config 479 | icon: mdi:arrow-up-bold 480 | unit_of_measurement: mm 481 | step: 10 482 | initial_value: 0 483 | optimistic: True 484 | restore_value: True 485 | on_value: 486 | then: 487 | - script.execute: check_zout1_vaild 488 | - platform: template 489 | name: Zout1 Y-End 490 | id: zone_ex1_y_end 491 | icon: mdi:arrow-down-bold 492 | mode: box 493 | min_value: 0 494 | max_value: 6000 495 | initial_value: 0 496 | entity_category: config 497 | device_class: distance 498 | unit_of_measurement: mm 499 | step: 10 500 | optimistic: True 501 | restore_value: True 502 | on_value: 503 | then: 504 | - script.execute: check_zout1_vaild 505 | 506 | binary_sensor: 507 | - platform: status 508 | name: Online 509 | id: ink_ha_connected 510 | - platform: template 511 | name: "Any Presence" 512 | id: any_target_exsits 513 | device_class: occupancy 514 | filters: 515 | - delayed_off: !lambda |- 516 | return id(any_presence_timeout).state * 1000.0; 517 | - platform: template 518 | name: "Zone1 Presence" 519 | id: zone1_target_exsits 520 | device_class: occupancy 521 | filters: 522 | - delayed_off: !lambda |- 523 | return id(zone1_x_timeout).state * 1000.0; 524 | - platform: template 525 | name: "Zone2 Presence" 526 | id: zone2_target_exsits 527 | device_class: occupancy 528 | filters: 529 | - delayed_off: !lambda |- 530 | return id(zone2_x_timeout).state * 1000.0; 531 | - platform: template 532 | name: "Zone3 Presence" 533 | id: zone3_target_exsits 534 | device_class: occupancy 535 | filters: 536 | - delayed_off: !lambda |- 537 | return id(zone3_x_timeout).state * 1000.0; 538 | - platform: template 539 | name: "Zout1 Presence" 540 | id: zone_ex1_target_exsits 541 | icon: mdi:account-multiple-remove 542 | device_class: occupancy 543 | 544 | script: 545 | - id: check_zone1_vaild 546 | then: 547 | - lambda: |- 548 | if (id(zone1_x_begin).state > id(zone1_x_end).state){ 549 | id(tips_zone1_conf).publish_state("Err: X-Begin > X-End"); 550 | return; 551 | } 552 | if (id(zone1_y_begin).state > id(zone1_y_end).state){ 553 | id(tips_zone1_conf).publish_state("Err: Y-Begin > Y-End"); 554 | return; 555 | } 556 | if (id(zone1_x_begin).state == 0, id(zone1_x_end).state == 0, id(zone1_y_begin).state == 0, id(zone1_y_end).state == 0){ 557 | id(tips_zone1_conf).publish_state("Configure below"); 558 | return; 559 | } 560 | 561 | int x_size = id(zone1_x_end).state - id(zone1_x_begin).state; 562 | int y_size = id(zone1_y_end).state - id(zone1_y_begin).state; 563 | 564 | char combined[80]; 565 | sprintf(combined, "Curr Size: %d x %d", x_size, y_size); 566 | id(tips_zone1_conf).publish_state(combined); 567 | - id: check_zone2_vaild 568 | then: 569 | - lambda: |- 570 | if (id(zone2_x_begin).state > id(zone2_x_end).state){ 571 | id(tips_zone2_conf).publish_state("Err: X-Begin > X-End"); 572 | return; 573 | } 574 | if (id(zone2_y_begin).state > id(zone2_y_end).state){ 575 | id(tips_zone2_conf).publish_state("Err: Y-Begin > Y-End"); 576 | return; 577 | } 578 | if (id(zone2_x_begin).state == 0, id(zone2_x_end).state == 0, id(zone2_y_begin).state == 0, id(zone2_y_end).state == 0){ 579 | id(tips_zone2_conf).publish_state("Configure below"); 580 | return; 581 | } 582 | 583 | int x_size = id(zone2_x_end).state - id(zone2_x_begin).state; 584 | int y_size = id(zone2_y_end).state - id(zone2_y_begin).state; 585 | 586 | char combined[80]; 587 | sprintf(combined, "Curr Size: %d x %d", x_size, y_size); 588 | id(tips_zone2_conf).publish_state(combined); 589 | - id: check_zone3_vaild 590 | then: 591 | - lambda: |- 592 | if (id(zone3_x_begin).state > id(zone3_x_end).state){ 593 | id(tips_zone3_conf).publish_state("Err: X-Begin > X-End"); 594 | return; 595 | } 596 | if (id(zone3_y_begin).state > id(zone3_y_end).state){ 597 | id(tips_zone3_conf).publish_state("Err: Y-Begin > Y-End"); 598 | return; 599 | } 600 | if (id(zone3_x_begin).state == 0, id(zone3_x_end).state == 0, id(zone3_y_begin).state == 0, id(zone3_y_end).state == 0){ 601 | id(tips_zone3_conf).publish_state("Configure below"); 602 | return; 603 | } 604 | 605 | int x_size = id(zone3_x_end).state - id(zone3_x_begin).state; 606 | int y_size = id(zone3_y_end).state - id(zone3_y_begin).state; 607 | 608 | char combined[80]; 609 | sprintf(combined, "Curr Size: %d x %d", x_size, y_size); 610 | id(tips_zone3_conf).publish_state(combined); 611 | - id: check_zout1_vaild 612 | then: 613 | - lambda: |- 614 | if (id(zone_ex1_x_begin).state > id(zone_ex1_x_end).state){ 615 | id(tips_zone_ex1_conf).publish_state("Err: X-Begin > X-End"); 616 | return; 617 | } 618 | if (id(zone_ex1_y_begin).state > id(zone_ex1_y_end).state){ 619 | id(tips_zone_ex1_conf).publish_state("Err: Y-Begin > Y-End"); 620 | return; 621 | } 622 | id(tips_zone_ex1_conf).publish_state("Zone Exclusion 1"); 623 | 624 | sensor: 625 | - platform: template 626 | name: "ESP CPU Speed" 627 | accuracy_decimals: 0 628 | icon: mdi:cpu-32-bit 629 | unit_of_measurement: Mhz 630 | disabled_by_default: True 631 | lambda: |- 632 | return (id(cpu_speed)); 633 | entity_category: "diagnostic" 634 | update_interval: 600s 635 | - platform: template 636 | id: sys_esp_temperature 637 | name: ESP Temperature 638 | lambda: return temperatureRead(); 639 | unit_of_measurement: °C 640 | device_class: TEMPERATURE 641 | update_interval: 45s 642 | entity_category: "diagnostic" 643 | - platform: uptime 644 | name: ESP Uptime 645 | id: sys_uptime 646 | update_interval: 60s 647 | - platform: wifi_signal 648 | name: RSSI 649 | id: wifi_signal_db 650 | update_interval: 60s 651 | entity_category: "diagnostic" 652 | - platform: template 653 | id: esp_memory 654 | icon: mdi:memory 655 | name: ESP Free Memory 656 | lambda: return heap_caps_get_free_size(MALLOC_CAP_INTERNAL) / 1024; 657 | unit_of_measurement: 'kB' 658 | state_class: measurement 659 | entity_category: "diagnostic" 660 | update_interval: 60s 661 | #-------------------------------------# 662 | # 高级雷达数据 663 | - platform: template 664 | name: "All Target Counts" 665 | id: all_target_count 666 | accuracy_decimals: 0 667 | icon: "mdi:counter" 668 | unit_of_measurement: "targets" 669 | - platform: template 670 | name: "Zone1 Target Counts" 671 | id: zone1_target_count 672 | accuracy_decimals: 0 673 | icon: "mdi:counter" 674 | unit_of_measurement: "targets" 675 | - platform: template 676 | name: "Zone2 Target Counts" 677 | id: zone2_target_count 678 | accuracy_decimals: 0 679 | icon: "mdi:counter" 680 | unit_of_measurement: "targets" 681 | - platform: template 682 | name: "Zone3 Target Counts" 683 | id: zone3_target_count 684 | accuracy_decimals: 0 685 | icon: "mdi:counter" 686 | unit_of_measurement: "targets" 687 | - platform: template 688 | name: "Zout1 Target Counts" 689 | id: zone_ex1_target_count 690 | accuracy_decimals: 0 691 | icon: mdi:account-multiple-minus-outline 692 | unit_of_measurement: "targets" 693 | 694 | # Target 1 695 | - platform: template 696 | name: "Target1 X" 697 | id: target1_x 698 | accuracy_decimals: 0 699 | unit_of_measurement: 'mm' 700 | state_class: measurement 701 | device_class: distance 702 | - platform: template 703 | name: "Target1 Y" 704 | id: target1_y 705 | accuracy_decimals: 0 706 | unit_of_measurement: 'mm' 707 | state_class: measurement 708 | device_class: distance 709 | - platform: template 710 | name: "Target1 Speed" 711 | id: target1_speed 712 | accuracy_decimals: 2 713 | unit_of_measurement: 'm/s' 714 | state_class: measurement 715 | device_class: speed 716 | - platform: template 717 | name: "Target1 Resolution" 718 | id: target1_resolution 719 | accuracy_decimals: 0 720 | unit_of_measurement: 'mm' 721 | state_class: measurement 722 | device_class: distance 723 | 724 | # Target 2 725 | - platform: template 726 | name: "Target2 X" 727 | id: target2_x 728 | accuracy_decimals: 0 729 | unit_of_measurement: 'mm' 730 | state_class: measurement 731 | device_class: distance 732 | - platform: template 733 | name: "Target2 Y" 734 | id: target2_y 735 | accuracy_decimals: 0 736 | unit_of_measurement: 'mm' 737 | state_class: measurement 738 | device_class: distance 739 | - platform: template 740 | name: "Target2 Speed" 741 | id: target2_speed 742 | accuracy_decimals: 0 743 | unit_of_measurement: 'm/s' 744 | state_class: measurement 745 | device_class: speed 746 | - platform: template 747 | name: "Target2 Resolution" 748 | id: target2_resolution 749 | accuracy_decimals: 0 750 | unit_of_measurement: 'mm' 751 | state_class: measurement 752 | device_class: distance 753 | 754 | # Target 3 755 | - platform: template 756 | name: "Target3 X" 757 | id: target3_x 758 | accuracy_decimals: 0 759 | unit_of_measurement: 'mm' 760 | state_class: measurement 761 | device_class: distance 762 | - platform: template 763 | name: "Target3 Y" 764 | id: target3_y 765 | accuracy_decimals: 0 766 | unit_of_measurement: 'mm' 767 | state_class: measurement 768 | device_class: distance 769 | - platform: template 770 | name: "Target3 Speed" 771 | id: target3_speed 772 | accuracy_decimals: 0 773 | unit_of_measurement: 'm/s' 774 | state_class: measurement 775 | device_class: speed 776 | - platform: template 777 | name: "Target3 Resolution" 778 | id: target3_resolution 779 | accuracy_decimals: 0 780 | unit_of_measurement: 'mm' 781 | state_class: measurement 782 | device_class: distance 783 | 784 | time: 785 | - platform: sntp 786 | id: time_now 787 | 788 | switch: 789 | - platform: factory_reset 790 | name: Factory Reset 791 | disabled_by_default: True 792 | icon: mdi:heart-broken 793 | - platform: template 794 | name: Zout1 Enable 795 | id: zone_ex1_enable 796 | optimistic: True 797 | icon: mdi:account-cancel 798 | entity_category: config 799 | restore_mode: RESTORE_DEFAULT_OFF 800 | - platform: template 801 | id: status_led_switch 802 | # name: "Status LED Switch" 803 | optimistic: true 804 | on_turn_on: 805 | - light.turn_on: 806 | id: ${espID}_rgb_led 807 | red: 100% 808 | green: 0% 809 | blue: 0% 810 | brightness: 20% 811 | transition_length: 50ms 812 | on_turn_off: 813 | - light.turn_off: 814 | id: ${espID}_rgb_led 815 | transition_length: 50ms 816 | 817 | button: 818 | - platform: restart 819 | icon: mdi:power-cycle 820 | name: "ESP Reboot" 821 | entity_category: diagnostic 822 | 823 | uart: 824 | id: uart_bus 825 | tx_pin: 826 | number: GPIO7 827 | mode: 828 | input: true 829 | pullup: true 830 | rx_pin: 831 | number: GPIO6 832 | mode: 833 | input: true 834 | pullup: true 835 | baud_rate: 256000 836 | parity: NONE 837 | stop_bits: 1 838 | data_bits: 8 839 | debug: 840 | direction: BOTH 841 | dummy_receiver: True 842 | after: 843 | delimiter: [0X55, 0XCC] 844 | sequence: 845 | - lambda: |- 846 | if ((millis() - id(last_update_ld2450)) <= 500) { 847 | return; 848 | }; 849 | id(last_update_ld2450) = millis(); 850 | 851 | // p1 852 | int16_t p1_x = (uint16_t((bytes[5] << 8) | bytes[4] )); 853 | if ((bytes[5] & 0x80) >> 7){ 854 | p1_x -= pow(2, 15); 855 | }else{ 856 | p1_x = 0 - p1_x; 857 | } 858 | 859 | int16_t p1_y = (uint16_t((bytes[7] << 8) | bytes[6] )); 860 | if ((bytes[7] & 0x80) >> 7){ 861 | p1_y -= pow(2, 15); 862 | }else{ 863 | p1_y = 0 - p1_y; 864 | } 865 | 866 | int p1_speed = (bytes[9] << 8 | bytes[8] ); 867 | if ((bytes[9] & 0x80) >> 7){ 868 | p1_speed -= pow(2, 15); 869 | }else{ 870 | p1_speed = 0 - p1_speed; 871 | } 872 | int16_t p1_distance_resolution = (uint16_t((bytes[11] << 8) | bytes[10] )); 873 | 874 | // p2 875 | int16_t p2_x = (uint16_t((bytes[13] << 8) | bytes[12] )); 876 | if ((bytes[13] & 0x80) >> 7){ 877 | p2_x -= pow(2, 15); 878 | }else{ 879 | p2_x = 0 - p2_x; 880 | } 881 | 882 | int16_t p2_y = (uint16_t((bytes[15] << 8) | bytes[14] )); 883 | if ((bytes[15] & 0x80) >> 7){ 884 | p2_y -= pow(2, 15); 885 | }else{ 886 | p2_y = 0 - p2_y; 887 | } 888 | 889 | int p2_speed = (bytes[17] << 8 | bytes[16] ); 890 | if ((bytes[17] & 0x80) >> 7){ 891 | p2_speed -= pow(2, 15); 892 | }else{ 893 | p2_speed = 0 - p2_speed; 894 | } 895 | int16_t p2_distance_resolution = (uint16_t((bytes[19] << 8) | bytes[18] )); 896 | 897 | // p3 898 | int16_t p3_x = (uint16_t((bytes[21] << 8) | bytes[20] )); 899 | if ((bytes[21] & 0x80) >> 7){ 900 | p3_x -= pow(2, 15); 901 | }else{ 902 | p3_x = 0 - p3_x; 903 | } 904 | 905 | int16_t p3_y = (uint16_t((bytes[23] << 8) | bytes[22] )); 906 | if ((bytes[23] & 0x80) >> 7){ 907 | p3_y -= pow(2, 15); 908 | }else{ 909 | p3_y = 0 - p3_y; 910 | } 911 | 912 | int p3_speed = (bytes[25] << 8 | bytes[24] ); 913 | if ((bytes[25] & 0x80) >> 7){ 914 | p3_speed -= pow(2, 15); 915 | }else{ 916 | p3_speed = 0 - p3_speed; 917 | } 918 | 919 | int16_t p3_distance_resolution = (uint16_t((bytes[27] << 8) | bytes[26] )); 920 | 921 | bool p1_vaild = (p1_x != 0 || p1_y > 0); 922 | bool p2_vaild = (p2_x != 0 || p2_y > 0); 923 | bool p3_vaild = (p3_x != 0 || p3_y > 0); 924 | 925 | // zone exlude 1 926 | 927 | int16_t target_count_in_zone_ex1 = 0; 928 | 929 | int16_t zone_ex1_x_min = id(zone_ex1_x_begin).state; 930 | int16_t zone_ex1_x_max = id(zone_ex1_x_end).state; 931 | int16_t zone_ex1_y_min = id(zone_ex1_y_begin).state; 932 | int16_t zone_ex1_y_max = id(zone_ex1_y_end).state; 933 | 934 | bool p1_zone_ex_enter = false; 935 | bool p2_zone_ex_enter = false; 936 | bool p3_zone_ex_enter = false; 937 | 938 | if (id(zone_ex1_enable).state){ 939 | if (p1_vaild){ 940 | if (p1_x >= zone_ex1_x_min && p1_x <= zone_ex1_x_max && p1_y >= zone_ex1_y_min && p1_y <= zone_ex1_y_max){ 941 | p1_zone_ex_enter = true; 942 | target_count_in_zone_ex1 ++; 943 | } 944 | } 945 | if (p2_vaild){ 946 | if (p2_x >= zone_ex1_x_min && p2_x <= zone_ex1_x_max && p2_y >= zone_ex1_y_min && p2_y <= zone_ex1_y_max){ 947 | p2_zone_ex_enter = true; 948 | target_count_in_zone_ex1 ++; 949 | } 950 | } 951 | if (p3_vaild){ 952 | if (p3_x >= zone_ex1_x_min && p3_x <= zone_ex1_x_max && p3_y >= zone_ex1_y_min && p3_y <= zone_ex1_y_max){ 953 | p3_zone_ex_enter = true; 954 | target_count_in_zone_ex1 ++; 955 | } 956 | } 957 | } 958 | 959 | bool has_target_in_zone_ex1 = (target_count_in_zone_ex1 > 0); 960 | 961 | int16_t all_target_counts = 0; 962 | if (p1_vaild && !p1_zone_ex_enter){ 963 | all_target_counts ++; 964 | } 965 | if (p2_vaild && !p2_zone_ex_enter){ 966 | all_target_counts ++; 967 | } 968 | if (p3_vaild && !p3_zone_ex_enter){ 969 | all_target_counts ++; 970 | } 971 | 972 | bool has_target_in_zone_all = (all_target_counts > 0); 973 | 974 | // zone 1 check 975 | 976 | int16_t target_count_in_zone1 = 0; 977 | int16_t zone1_x_min = id(zone1_x_begin).state; 978 | int16_t zone1_x_max = id(zone1_x_end).state; 979 | int16_t zone1_y_min = id(zone1_y_begin).state; 980 | int16_t zone1_y_max = id(zone1_y_end).state; 981 | 982 | if (p1_vaild && !p1_zone_ex_enter){ 983 | if (p1_x >= zone1_x_min && p1_x <= zone1_x_max && p1_y >= zone1_y_min && p1_y <= zone1_y_max){ 984 | target_count_in_zone1 ++; 985 | } 986 | } 987 | if (p2_vaild && !p2_zone_ex_enter){ 988 | if (p2_x >= zone1_x_min && p2_x <= zone1_x_max && p2_y >= zone1_y_min && p2_y <= zone1_y_max){ 989 | target_count_in_zone1 ++; 990 | } 991 | } 992 | if (p3_vaild && !p3_zone_ex_enter){ 993 | if (p3_x >= zone1_x_min && p3_x <= zone1_x_max && p3_y >= zone1_y_min && p3_y <= zone1_y_max){ 994 | target_count_in_zone1 ++; 995 | } 996 | } 997 | bool has_target_in_zone1 = (target_count_in_zone1 > 0); 998 | 999 | // zone 2 check 1000 | 1001 | int16_t target_count_in_zone2 = 0; 1002 | int16_t zone2_x_min = id(zone2_x_begin).state; 1003 | int16_t zone2_x_max = id(zone2_x_end).state; 1004 | int16_t zone2_y_min = id(zone2_y_begin).state; 1005 | int16_t zone2_y_max = id(zone2_y_end).state; 1006 | 1007 | if (p1_vaild && !p1_zone_ex_enter){ 1008 | if (p1_x >= zone2_x_min && p1_x <= zone2_x_max && p1_y >= zone2_y_min && p1_y <= zone2_y_max){ 1009 | target_count_in_zone2 ++; 1010 | } 1011 | } 1012 | if (p2_vaild && !p2_zone_ex_enter){ 1013 | if (p2_x >= zone2_x_min && p2_x <= zone2_x_max && p2_y >= zone2_y_min && p2_y <= zone2_y_max){ 1014 | target_count_in_zone2 ++; 1015 | } 1016 | } 1017 | if (p3_vaild && !p3_zone_ex_enter){ 1018 | if (p3_x >= zone2_x_min && p3_x <= zone2_x_max && p3_y >= zone2_y_min && p3_y <= zone2_y_max){ 1019 | target_count_in_zone2 ++; 1020 | } 1021 | } 1022 | 1023 | bool has_target_in_zone2 = (target_count_in_zone2 > 0); 1024 | 1025 | // zone 3 check 1026 | 1027 | int16_t target_count_in_zone3 = 0; 1028 | int16_t zone3_x_min = id(zone3_x_begin).state; 1029 | int16_t zone3_x_max = id(zone3_x_end).state; 1030 | int16_t zone3_y_min = id(zone3_y_begin).state; 1031 | int16_t zone3_y_max = id(zone3_y_end).state; 1032 | 1033 | if (p1_vaild && !p1_zone_ex_enter){ 1034 | if (p1_x >= zone3_x_min && p1_x <= zone3_x_max && p1_y >= zone3_y_min && p1_y <= zone3_y_max){ 1035 | target_count_in_zone3 ++; 1036 | } 1037 | } 1038 | if (p2_vaild && !p2_zone_ex_enter){ 1039 | if (p2_x >= zone3_x_min && p2_x <= zone3_x_max && p2_y >= zone3_y_min && p2_y <= zone3_y_max){ 1040 | target_count_in_zone3 ++; 1041 | } 1042 | } 1043 | if (p3_vaild && !p3_zone_ex_enter){ 1044 | if (p3_x >= zone3_x_min && p3_x <= zone3_x_max && p3_y >= zone3_y_min && p3_y <= zone3_y_max){ 1045 | target_count_in_zone3 ++; 1046 | } 1047 | } 1048 | bool has_target_in_zone3 = (target_count_in_zone3 > 0); 1049 | 1050 | // public all info 1051 | if (id(target1_x).state != p1_x){ 1052 | id(target1_x).publish_state(p1_x); 1053 | } 1054 | if (id(target1_y).state != p1_y){ 1055 | id(target1_y).publish_state(p1_y); 1056 | } 1057 | 1058 | float p1_m_speed = float(p1_speed) / 100.0; 1059 | if (id(target1_speed).state != p1_m_speed){ 1060 | id(target1_speed).publish_state(p1_m_speed); 1061 | } 1062 | if (id(target1_resolution).state != p1_distance_resolution){ 1063 | id(target1_resolution).publish_state(p1_distance_resolution); 1064 | } 1065 | 1066 | if (id(target2_x).state != p2_x){ 1067 | id(target2_x).publish_state(p2_x); 1068 | } 1069 | if (id(target2_y).state != p2_y){ 1070 | id(target2_y).publish_state(p2_y); 1071 | } 1072 | if (id(target2_speed).state != p2_speed){ 1073 | id(target2_speed).publish_state(p2_speed); 1074 | } 1075 | if (id(target2_resolution).state != p2_distance_resolution){ 1076 | id(target2_resolution).publish_state(p2_distance_resolution); 1077 | } 1078 | 1079 | if (id(target3_x).state != p3_x){ 1080 | id(target3_x).publish_state(p3_x); 1081 | } 1082 | if (id(target3_y).state != p3_y){ 1083 | id(target3_y).publish_state(p3_y); 1084 | } 1085 | if (id(target3_speed).state != p3_speed){ 1086 | id(target3_speed).publish_state(p3_speed); 1087 | } 1088 | if (id(target3_resolution).state != p3_distance_resolution){ 1089 | id(target3_resolution).publish_state(p3_distance_resolution); 1090 | } 1091 | 1092 | // publish target info 1093 | 1094 | if (id(all_target_count).state != all_target_counts){ 1095 | id(all_target_count).publish_state(all_target_counts); 1096 | id(any_target_exsits).publish_state(has_target_in_zone_all); 1097 | } 1098 | 1099 | if (id(zone1_target_count).state != target_count_in_zone1){ 1100 | id(zone1_target_count).publish_state(target_count_in_zone1); 1101 | id(zone1_target_exsits).publish_state(has_target_in_zone1); 1102 | } 1103 | 1104 | if (id(zone2_target_count).state != target_count_in_zone2){ 1105 | id(zone2_target_count).publish_state(target_count_in_zone2); 1106 | id(zone2_target_exsits).publish_state(has_target_in_zone2); 1107 | } 1108 | 1109 | if (id(zone3_target_count).state != target_count_in_zone3){ 1110 | id(zone3_target_count).publish_state(target_count_in_zone3); 1111 | id(zone3_target_exsits).publish_state(has_target_in_zone3); 1112 | } 1113 | 1114 | // zout 1115 | if (id(zone_ex1_target_count).state != target_count_in_zone_ex1){ 1116 | id(zone_ex1_target_count).publish_state(target_count_in_zone_ex1); 1117 | id(zone_ex1_target_exsits).publish_state(has_target_in_zone_ex1); 1118 | } 1119 | 1120 | if (!id(init_zone_publish)){ 1121 | id(init_zone_publish) = true; 1122 | } 1123 | --------------------------------------------------------------------------------