Upload files to "/"

This commit is contained in:
rafal 2026-01-18 23:49:09 +00:00
commit fcd5bc52d3
5 changed files with 393 additions and 0 deletions

100
binary_sensors.yaml Normal file
View File

@ -0,0 +1,100 @@
# =======================
# BINARY SENSORS
# =======================
binary_sensor:
- platform: status
name: Online
id: ink_ha_connected
- platform: ld2410
has_target:
name: Presence
id: ld2410_has_target
has_moving_target:
name: Moving Target
id: has_moving_target
has_still_target:
name: Still Target
id: has_still_target
- platform: gpio
name: "OUT Pin"
id: ld2410_out_pin
pin:
number: GPIO16
mode:
input: true
inverted: false
device_class: motion
# ===== STREFA 1 (GŁÓWNA WC / ŁAZIENKA) =====
- platform: template
id: presence_zone_1
name: "Presence Zone 1"
device_class: occupancy
filters:
- delayed_off: 1s # BYŁO: 5s → TERAZ SZYBKO
lambda: |-
// brak targetu = brak obecności
if (!id(ld2410_has_target).state) return false;
// ======================
// FAST PATH RUCH
// ======================
if (id(has_moving_target).state &&
id(moving_distance).has_state() &&
id(moving_distance).state > 0) {
float dm = id(moving_distance).state;
if (dm >= id(zone1_min_distance).state &&
dm <= id(zone1_max_distance).state) {
return true; // NATYCHMIASTOWA REAKCJA
}
}
// ======================
// STABLE PATH STILL
// ======================
if (id(has_still_target).state &&
id(still_distance).has_state() &&
id(still_distance).state > 0) {
float ds = id(still_distance).state;
// ignorowanie odbić (lustra / drzwi / kot)
if (id(ignore_static_reflections).state &&
id(still_energy).has_state() &&
id(still_energy).state < 30) {
return false;
}
return ds >= id(zone1_min_distance).state &&
ds <= id(zone1_max_distance).state;
}
// fallback: target jest → obecność
return true;
# ===== STREFA 2 (DALEJ / ZA DRZWIAMI) =====
- platform: template
id: presence_zone_2
name: "Presence Zone 2"
device_class: occupancy
filters:
- delayed_off: 1s # BYŁO: 5s → TERAZ SZYBKO
lambda: |-
if (!id(ld2410_has_target).state) return false;
if (id(has_moving_target).state &&
id(moving_distance).has_state() &&
id(moving_distance).state > 0) {
float dm = id(moving_distance).state;
return dm >= id(zone2_min_distance).state &&
dm <= id(zone2_max_distance).state;
}
return false;

36
buttons.yaml Normal file
View File

@ -0,0 +1,36 @@
# =======================
# BUTTONS
# =======================
button:
- platform: template
name: "Enable LD2410 BLE"
icon: mdi:bluetooth
entity_category: config
on_press:
lambda: |-
id(ld2410_radar)->ble_control(true);
- platform: template
name: "Disable LD2410 BLE"
icon: mdi:bluetooth-off
entity_category: config
on_press:
lambda: |-
id(ld2410_radar)->ble_control(false);
- platform: template
name: "LD2410 Reboot"
icon: mdi:radar
entity_category: config
on_press:
lambda: |-
id(ld2410_radar)->reboot();
- platform: restart
name: "ESP Reboot"
icon: mdi:power-cycle
- platform: factory_reset
name: Factory Reset
id: factory_reset_all
disabled_by_default: true

185
ld2450_uart.h Normal file
View File

@ -0,0 +1,185 @@
#include "esphome.h"
#define CHECK_BIT(var, pos) (((var) >> (pos)) & 1)
#define STATE_SIZE 8
#define TARGETS 3
static const char *TAG = "ld2450";
class LD2450 : public PollingComponent, public UARTDevice
{
public:
LD2450(UARTComponent *parent) : UARTDevice(parent) {}
// BinarySensor *lastCommandSuccess = new BinarySensor();
Sensor *lastCommandSuccess = new Sensor();
Sensor *target1Resolution = new Sensor();
Sensor *target1Speed = new Sensor();
Sensor *target1X = new Sensor();
Sensor *target1Y = new Sensor();
Sensor *target2Resolution = new Sensor();
Sensor *target2Speed = new Sensor();
Sensor *target2X = new Sensor();
Sensor *target2Y = new Sensor();
Sensor *target3Resolution = new Sensor();
Sensor *target3Speed = new Sensor();
Sensor *target3X = new Sensor();
Sensor *target3Y = new Sensor();
Sensor *targets = new Sensor();
uint32_t lastPeriodicMillis = millis();
uint16_t twoByteToUint(char firstByte, char secondByte) {
return (uint16_t)(secondByte << 8) + firstByte;
}
void reportTargetInfo(int target, char *raw) {
int16_t newX, newY, newSpeed, sum;
uint16_t newResolution;
ESP_LOGV(TAG, "Will reporting taget %d", target);
switch (target) {
case 0:
newX = twoByteToUint(raw[0], raw[1] & 0x7F);
if (raw[1] >> 7 != 0x1)
newX = 0 - newX / 10;
else
newX = newX / 10;
if (target1X->get_state() != newX)
target1X->publish_state(newX);
newY = twoByteToUint(raw[2], raw[3] & 0x7F);
if (raw[3] >> 7 != 0x1)
newY = 0 - newY / 10;
else
newY = newY / 10;
if (target1Y->get_state() != newY)
target1Y->publish_state(newY);
newSpeed = twoByteToUint(raw[4], raw[5] & 0x7F);
if (raw[5] >> 7 != 0x1)
newSpeed = 0 - newSpeed;
if (target1Speed->get_state() != newSpeed)
target1Speed->publish_state(newSpeed);
newResolution = twoByteToUint(raw[6], raw[7]);
if (target1Resolution->get_state() != newResolution)
target1Resolution->publish_state(newResolution);
break;
case 1:
newX = twoByteToUint(raw[0], raw[1] & 0x7F);
if (raw[1] >> 7 != 0x1)
newX = 0 - newX / 10;
else
newX = newX / 10;
if (target2X->get_state() != newX)
target2X->publish_state(newX);
newY = twoByteToUint(raw[2], raw[3] & 0x7F);
if (raw[3] >> 7 != 0x1)
newY = 0 - newY / 10;
else
newY = newY / 10;
if (target2Y->get_state() != newY)
target2Y->publish_state(newY);
newSpeed = twoByteToUint(raw[4], raw[5] & 0x7F);
if (raw[5] >> 7 != 0x1)
newSpeed = 0 - newSpeed;
if (target2Speed->get_state() != newSpeed)
target2Speed->publish_state(newSpeed);
newResolution = twoByteToUint(raw[6], raw[7]);
if (target2Resolution->get_state() != newResolution)
target2Resolution->publish_state(newResolution);
break;
case 2:
newX = twoByteToUint(raw[0], raw[1] & 0x7F);
if (raw[1] >> 7 != 0x1)
newX = 0 - newX / 10;
else
newX = newX / 10;
if (target3X->get_state() != newX)
target3X->publish_state(newX);
newY = twoByteToUint(raw[2], raw[3] & 0x7F);
if (raw[3] >> 7 != 0x1)
newY = 0 - newY / 10;
else
newY = newY / 10;
if (target3Y->get_state() != newY)
target3Y->publish_state(newY);
newSpeed = twoByteToUint(raw[4], raw[5] & 0x7F);
if (raw[5] >> 7 != 0x1)
newSpeed = 0 - newSpeed;
if (target3Speed->get_state() != newSpeed)
target3Speed->publish_state(newSpeed);
newResolution = twoByteToUint(raw[6], raw[7]);
if (target3Resolution->get_state() != newResolution)
target3Resolution->publish_state(newResolution);
break;
}
sum = 0;
if (target1Resolution->get_state() > 0){
sum+=1;
}
if (target2Resolution->get_state() > 0){
sum+=1;
}
if (target3Resolution->get_state() > 0){
sum+=1;
}
if (targets->get_state() != sum){
targets->publish_state(sum);
}
}
void handlePeriodicData(char *buffer, int len) {
if (len < 29)
return; // 4 frame start bytes + 2 length bytes + 1 data end byte + 1 crc byte + 4 frame end bytes
if (buffer[0] != 0xAA || buffer[1] != 0xFF || buffer[2] != 0x03 || buffer[3] != 0x00)
return; // check 4 frame start bytes
if (buffer[len - 2] != 0x55 || buffer[len - 1] != 0xCC)
return; // data end=0x55, 0xcc
char stateBytes[STATE_SIZE];
/*
Reduce data update rate to prevent home assistant database size glow fast
*/
uint32_t currentMillis = millis();
if (currentMillis - lastPeriodicMillis < 1000)
return;
lastPeriodicMillis = currentMillis;
for (int i = 0; i < TARGETS; i++) {
memcpy(stateBytes, &buffer[4 + i * STATE_SIZE], STATE_SIZE);
reportTargetInfo(i, stateBytes);
}
}
void readline(int readch, char *buffer, int len) {
static int pos = 0;
if (readch >= 0) {
if (pos < len - 1) {
buffer[pos++] = readch;
buffer[pos] = 0;
} else {
pos = 0;
}
if (pos >= 4) {
if (buffer[pos - 2] == 0x55 && buffer[pos - 1] == 0xCC) {
handlePeriodicData(buffer, pos);
pos = 0; // Reset position index ready for next time
}
}
}
return;
}
void setup() override {
set_update_interval(15000);
}
void loop() override {
const int max_line_length = 160;
static char buffer[max_line_length];
while (available()) {
readline(read(), buffer, max_line_length);
}
}
void update(){
}
};

25
led_time_uart.yaml Normal file
View File

@ -0,0 +1,25 @@
# =======================
# LED / TIME / UART
# =======================
light:
- platform: status_led
name: sys_status
pin: GPIO15
internal: true
restore_mode: ALWAYS_OFF
time:
- platform: sntp
id: time_sntp
uart:
id: uart_ld2410
tx_pin: GPIO18
rx_pin: GPIO33
baud_rate: 256000
parity: NONE
stop_bits: 1
ld2410:
timeout: 150s
id: ld2410_radar

47
numbers.yaml Normal file
View File

@ -0,0 +1,47 @@
# =======================
# NUMBERS (SUWAKI)
# =======================
number:
- platform: template
name: "Zone 1 MIN distance (cm)"
id: zone1_min_distance
min_value: 0
max_value: 200
step: 10
initial_value: 0
restore_value: true
optimistic: true
entity_category: config
- platform: template
name: "Zone 1 MAX distance (cm)"
id: zone1_max_distance
min_value: 50
max_value: 400
step: 10
initial_value: 220
restore_value: true
optimistic: true
entity_category: config
- platform: template
name: "Zone 2 MIN distance (cm)"
id: zone2_min_distance
min_value: 200
max_value: 600
step: 10
initial_value: 230
restore_value: true
optimistic: true
entity_category: config
- platform: template
name: "Zone 2 MAX distance (cm)"
id: zone2_max_distance
min_value: 300
max_value: 800
step: 10
initial_value: 450
restore_value: true
optimistic: true
entity_category: config