esphome 2025.2.2__py3-none-any.whl → 2025.3.0b2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- esphome/__main__.py +9 -1
- esphome/components/api/api_connection.cpp +426 -70
- esphome/components/api/api_connection.h +117 -25
- esphome/components/api/api_pb2.cpp +33 -0
- esphome/components/api/api_pb2.h +4 -0
- esphome/components/api/api_server.cpp +2 -2
- esphome/components/api/list_entities.cpp +76 -22
- esphome/components/api/list_entities.h +1 -0
- esphome/components/api/subscribe_state.h +2 -0
- esphome/components/audio/__init__.py +1 -1
- esphome/components/audio/audio_decoder.cpp +43 -11
- esphome/components/audio/audio_reader.cpp +2 -2
- esphome/components/audio/audio_resampler.cpp +4 -2
- esphome/components/audio/audio_transfer_buffer.cpp +19 -9
- esphome/components/audio/audio_transfer_buffer.h +7 -2
- esphome/components/bluetooth_proxy/bluetooth_proxy.h +8 -0
- esphome/components/bmp085/bmp085.cpp +1 -1
- esphome/components/chsc6x/__init__.py +2 -0
- esphome/components/chsc6x/chsc6x_touchscreen.cpp +47 -0
- esphome/components/chsc6x/chsc6x_touchscreen.h +34 -0
- esphome/components/chsc6x/touchscreen.py +33 -0
- esphome/components/climate/__init__.py +0 -1
- esphome/components/cst816/binary_sensor/__init__.py +2 -25
- esphome/components/cst816/touchscreen/cst816_touchscreen.cpp +3 -14
- esphome/components/cst816/touchscreen/cst816_touchscreen.h +0 -4
- esphome/components/esp32_ble_beacon/__init__.py +3 -1
- esphome/components/esp8266/gpio.py +1 -2
- esphome/components/font/__init__.py +185 -185
- esphome/components/font/font.cpp +4 -4
- esphome/components/font/font.h +1 -0
- esphome/components/haier/climate.py +11 -10
- esphome/components/hbridge/switch/hbridge_switch.cpp +2 -2
- esphome/components/heatpumpir/climate.py +2 -1
- esphome/components/heatpumpir/heatpumpir.cpp +1 -0
- esphome/components/heatpumpir/heatpumpir.h +1 -0
- esphome/components/i2c/__init__.py +6 -6
- esphome/components/i2c/i2c_bus_esp_idf.cpp +6 -2
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +1 -1
- esphome/components/ili9xxx/display.py +1 -0
- esphome/components/ili9xxx/ili9xxx_display.h +5 -0
- esphome/components/ili9xxx/ili9xxx_init.h +59 -0
- esphome/components/ld2450/__init__.py +51 -0
- esphome/components/ld2450/binary_sensor.py +47 -0
- esphome/components/ld2450/button/__init__.py +45 -0
- esphome/components/ld2450/button/reset_button.cpp +9 -0
- esphome/components/ld2450/button/reset_button.h +18 -0
- esphome/components/ld2450/button/restart_button.cpp +9 -0
- esphome/components/ld2450/button/restart_button.h +18 -0
- esphome/components/ld2450/ld2450.cpp +876 -0
- esphome/components/ld2450/ld2450.h +234 -0
- esphome/components/ld2450/number/__init__.py +121 -0
- esphome/components/ld2450/number/presence_timeout_number.cpp +12 -0
- esphome/components/ld2450/number/presence_timeout_number.h +18 -0
- esphome/components/ld2450/number/zone_coordinate_number.cpp +14 -0
- esphome/components/ld2450/number/zone_coordinate_number.h +19 -0
- esphome/components/ld2450/select/__init__.py +56 -0
- esphome/components/ld2450/select/baud_rate_select.cpp +12 -0
- esphome/components/ld2450/select/baud_rate_select.h +18 -0
- esphome/components/ld2450/select/zone_type_select.cpp +12 -0
- esphome/components/ld2450/select/zone_type_select.h +18 -0
- esphome/components/ld2450/sensor.py +156 -0
- esphome/components/ld2450/switch/__init__.py +45 -0
- esphome/components/ld2450/switch/bluetooth_switch.cpp +12 -0
- esphome/components/ld2450/switch/bluetooth_switch.h +18 -0
- esphome/components/ld2450/switch/multi_target_switch.cpp +12 -0
- esphome/components/ld2450/switch/multi_target_switch.h +18 -0
- esphome/components/ld2450/text_sensor.py +62 -0
- esphome/components/lvgl/defines.py +0 -2
- esphome/components/lvgl/font.cpp +1 -1
- esphome/components/lvgl/lvgl_esphome.cpp +27 -19
- esphome/components/lvgl/widgets/img.py +1 -3
- esphome/components/mcp2515/mcp2515.cpp +1 -0
- esphome/components/mdns/__init__.py +1 -1
- esphome/components/mixer/speaker/mixer_speaker.cpp +6 -1
- esphome/components/mixer/speaker/mixer_speaker.h +2 -0
- esphome/components/mlx90393/sensor.py +53 -33
- esphome/components/mlx90393/sensor_mlx90393.cpp +4 -0
- esphome/components/mlx90393/sensor_mlx90393.h +8 -3
- esphome/components/mqtt/__init__.py +2 -2
- esphome/components/msa3xx/__init__.py +189 -0
- esphome/components/msa3xx/binary_sensor.py +40 -0
- esphome/components/msa3xx/msa3xx.cpp +417 -0
- esphome/components/msa3xx/msa3xx.h +311 -0
- esphome/components/msa3xx/sensor.py +42 -0
- esphome/components/msa3xx/text_sensor.py +38 -0
- esphome/components/nfc/binary_sensor/__init__.py +4 -4
- esphome/components/opentherm/binary_sensor/__init__.py +4 -4
- esphome/components/opentherm/generate.py +6 -6
- esphome/components/opentherm/sensor/__init__.py +5 -6
- esphome/components/packages/__init__.py +35 -11
- esphome/components/pn532/binary_sensor.py +4 -4
- esphome/components/rc522/binary_sensor.py +4 -4
- esphome/components/resampler/speaker/resampler_speaker.h +2 -0
- esphome/components/socket/bsd_sockets_impl.cpp +1 -0
- esphome/components/socket/lwip_sockets_impl.cpp +1 -0
- esphome/components/socket/socket.h +3 -1
- esphome/components/speaker/speaker.h +2 -2
- esphome/components/ssd1306_base/__init__.py +7 -7
- esphome/components/thermostat/climate.py +1 -1
- esphome/components/tmp1075/tmp1075.cpp +7 -11
- esphome/components/tmp1075/tmp1075.h +1 -2
- esphome/components/tormatic/__init__.py +1 -0
- esphome/components/tormatic/cover.py +47 -0
- esphome/components/tormatic/tormatic_cover.cpp +355 -0
- esphome/components/tormatic/tormatic_cover.h +60 -0
- esphome/components/tormatic/tormatic_protocol.h +211 -0
- esphome/components/touchscreen/binary_sensor/__init__.py +3 -0
- esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.cpp +7 -1
- esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.h +3 -1
- esphome/components/touchscreen/touchscreen.cpp +3 -4
- esphome/components/udp/udp_component.h +4 -1
- esphome/components/web_server/list_entities.cpp +70 -66
- esphome/components/web_server/list_entities.h +43 -22
- esphome/components/web_server/web_server.cpp +345 -68
- esphome/components/web_server/web_server.h +138 -6
- esphome/components/web_server_base/__init__.py +1 -1
- esphome/components/web_server_idf/__init__.py +2 -0
- esphome/components/web_server_idf/web_server_idf.cpp +177 -30
- esphome/components/web_server_idf/web_server_idf.h +53 -4
- esphome/config_validation.py +23 -125
- esphome/const.py +5 -1
- esphome/core/config.py +12 -4
- esphome/core/defines.h +1 -1
- esphome/core/helpers.h +24 -3
- esphome/core/time.cpp +1 -0
- esphome/cpp_generator.py +3 -3
- esphome/dashboard/core.py +30 -21
- esphome/dashboard/dns.py +7 -1
- esphome/dashboard/entries.py +83 -16
- esphome/dashboard/settings.py +0 -4
- esphome/dashboard/status/mdns.py +43 -14
- esphome/dashboard/status/mqtt.py +22 -9
- esphome/dashboard/status/ping.py +54 -10
- esphome/dashboard/web_server.py +56 -24
- esphome/storage_json.py +4 -0
- esphome/wizard.py +13 -17
- esphome/writer.py +1 -3
- esphome/yaml_util.py +36 -33
- esphome/zeroconf.py +9 -21
- {esphome-2025.2.2.dist-info → esphome-2025.3.0b2.dist-info}/METADATA +7 -7
- {esphome-2025.2.2.dist-info → esphome-2025.3.0b2.dist-info}/RECORD +145 -105
- esphome/components/cst816/binary_sensor/cst816_button.h +0 -27
- {esphome-2025.2.2.dist-info → esphome-2025.3.0b2.dist-info}/LICENSE +0 -0
- {esphome-2025.2.2.dist-info → esphome-2025.3.0b2.dist-info}/WHEEL +0 -0
- {esphome-2025.2.2.dist-info → esphome-2025.3.0b2.dist-info}/entry_points.txt +0 -0
- {esphome-2025.2.2.dist-info → esphome-2025.3.0b2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,876 @@
|
|
1
|
+
#include "ld2450.h"
|
2
|
+
#include <utility>
|
3
|
+
#ifdef USE_NUMBER
|
4
|
+
#include "esphome/components/number/number.h"
|
5
|
+
#endif
|
6
|
+
#ifdef USE_SENSOR
|
7
|
+
#include "esphome/components/sensor/sensor.h"
|
8
|
+
#endif
|
9
|
+
#include "esphome/core/component.h"
|
10
|
+
|
11
|
+
#define highbyte(val) (uint8_t)((val) >> 8)
|
12
|
+
#define lowbyte(val) (uint8_t)((val) &0xff)
|
13
|
+
|
14
|
+
namespace esphome {
|
15
|
+
namespace ld2450 {
|
16
|
+
|
17
|
+
static const char *const TAG = "ld2450";
|
18
|
+
static const char *const UNKNOWN_MAC("unknown");
|
19
|
+
|
20
|
+
// LD2450 UART Serial Commands
|
21
|
+
static const uint8_t CMD_ENABLE_CONF = 0x00FF;
|
22
|
+
static const uint8_t CMD_DISABLE_CONF = 0x00FE;
|
23
|
+
static const uint8_t CMD_VERSION = 0x00A0;
|
24
|
+
static const uint8_t CMD_MAC = 0x00A5;
|
25
|
+
static const uint8_t CMD_RESET = 0x00A2;
|
26
|
+
static const uint8_t CMD_RESTART = 0x00A3;
|
27
|
+
static const uint8_t CMD_BLUETOOTH = 0x00A4;
|
28
|
+
static const uint8_t CMD_SINGLE_TARGET_MODE = 0x0080;
|
29
|
+
static const uint8_t CMD_MULTI_TARGET_MODE = 0x0090;
|
30
|
+
static const uint8_t CMD_QUERY_TARGET_MODE = 0x0091;
|
31
|
+
static const uint8_t CMD_SET_BAUD_RATE = 0x00A1;
|
32
|
+
static const uint8_t CMD_QUERY_ZONE = 0x00C1;
|
33
|
+
static const uint8_t CMD_SET_ZONE = 0x00C2;
|
34
|
+
|
35
|
+
static inline uint16_t convert_seconds_to_ms(uint16_t value) { return value * 1000; };
|
36
|
+
|
37
|
+
static inline std::string convert_signed_int_to_hex(int value) {
|
38
|
+
auto value_as_str = str_snprintf("%04x", 4, value & 0xFFFF);
|
39
|
+
return value_as_str;
|
40
|
+
}
|
41
|
+
|
42
|
+
static inline void convert_int_values_to_hex(const int *values, uint8_t *bytes) {
|
43
|
+
for (int i = 0; i < 4; i++) {
|
44
|
+
std::string temp_hex = convert_signed_int_to_hex(values[i]);
|
45
|
+
bytes[i * 2] = std::stoi(temp_hex.substr(2, 2), nullptr, 16); // Store high byte
|
46
|
+
bytes[i * 2 + 1] = std::stoi(temp_hex.substr(0, 2), nullptr, 16); // Store low byte
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
static inline int16_t decode_coordinate(uint8_t low_byte, uint8_t high_byte) {
|
51
|
+
int16_t coordinate = (high_byte & 0x7F) << 8 | low_byte;
|
52
|
+
if ((high_byte & 0x80) == 0) {
|
53
|
+
coordinate = -coordinate;
|
54
|
+
}
|
55
|
+
return coordinate; // mm
|
56
|
+
}
|
57
|
+
|
58
|
+
static inline int16_t decode_speed(uint8_t low_byte, uint8_t high_byte) {
|
59
|
+
int16_t speed = (high_byte & 0x7F) << 8 | low_byte;
|
60
|
+
if ((high_byte & 0x80) == 0) {
|
61
|
+
speed = -speed;
|
62
|
+
}
|
63
|
+
return speed * 10; // mm/s
|
64
|
+
}
|
65
|
+
|
66
|
+
static inline int16_t hex_to_signed_int(const uint8_t *buffer, uint8_t offset) {
|
67
|
+
uint16_t hex_val = (buffer[offset + 1] << 8) | buffer[offset];
|
68
|
+
int16_t dec_val = static_cast<int16_t>(hex_val);
|
69
|
+
if (dec_val & 0x8000) {
|
70
|
+
dec_val -= 65536;
|
71
|
+
}
|
72
|
+
return dec_val;
|
73
|
+
}
|
74
|
+
|
75
|
+
static inline float calculate_angle(float base, float hypotenuse) {
|
76
|
+
if (base < 0.0 || hypotenuse <= 0.0) {
|
77
|
+
return 0.0;
|
78
|
+
}
|
79
|
+
float angle_radians = std::acos(base / hypotenuse);
|
80
|
+
float angle_degrees = angle_radians * (180.0 / M_PI);
|
81
|
+
return angle_degrees;
|
82
|
+
}
|
83
|
+
|
84
|
+
static inline std::string get_direction(int16_t speed) {
|
85
|
+
static const char *const APPROACHING = "Approaching";
|
86
|
+
static const char *const MOVING_AWAY = "Moving away";
|
87
|
+
static const char *const STATIONARY = "Stationary";
|
88
|
+
|
89
|
+
if (speed > 0) {
|
90
|
+
return MOVING_AWAY;
|
91
|
+
}
|
92
|
+
if (speed < 0) {
|
93
|
+
return APPROACHING;
|
94
|
+
}
|
95
|
+
return STATIONARY;
|
96
|
+
}
|
97
|
+
|
98
|
+
static inline std::string format_mac(uint8_t *buffer) {
|
99
|
+
return str_snprintf("%02X:%02X:%02X:%02X:%02X:%02X", 17, buffer[10], buffer[11], buffer[12], buffer[13], buffer[14],
|
100
|
+
buffer[15]);
|
101
|
+
}
|
102
|
+
|
103
|
+
static inline std::string format_version(uint8_t *buffer) {
|
104
|
+
return str_sprintf("%u.%02X.%02X%02X%02X%02X", buffer[13], buffer[12], buffer[17], buffer[16], buffer[15],
|
105
|
+
buffer[14]);
|
106
|
+
}
|
107
|
+
|
108
|
+
LD2450Component::LD2450Component() {}
|
109
|
+
|
110
|
+
void LD2450Component::setup() {
|
111
|
+
ESP_LOGCONFIG(TAG, "Setting up HLK-LD2450...");
|
112
|
+
#ifdef USE_NUMBER
|
113
|
+
if (this->presence_timeout_number_ != nullptr) {
|
114
|
+
this->pref_ = global_preferences->make_preference<float>(this->presence_timeout_number_->get_object_id_hash());
|
115
|
+
this->set_presence_timeout();
|
116
|
+
}
|
117
|
+
#endif
|
118
|
+
this->restart_and_read_all_info();
|
119
|
+
}
|
120
|
+
|
121
|
+
void LD2450Component::dump_config() {
|
122
|
+
ESP_LOGCONFIG(TAG, "HLK-LD2450 Human motion tracking radar module:");
|
123
|
+
#ifdef USE_BINARY_SENSOR
|
124
|
+
LOG_BINARY_SENSOR(" ", "TargetBinarySensor", this->target_binary_sensor_);
|
125
|
+
LOG_BINARY_SENSOR(" ", "MovingTargetBinarySensor", this->moving_target_binary_sensor_);
|
126
|
+
LOG_BINARY_SENSOR(" ", "StillTargetBinarySensor", this->still_target_binary_sensor_);
|
127
|
+
#endif
|
128
|
+
#ifdef USE_SWITCH
|
129
|
+
LOG_SWITCH(" ", "BluetoothSwitch", this->bluetooth_switch_);
|
130
|
+
LOG_SWITCH(" ", "MultiTargetSwitch", this->multi_target_switch_);
|
131
|
+
#endif
|
132
|
+
#ifdef USE_BUTTON
|
133
|
+
LOG_BUTTON(" ", "ResetButton", this->reset_button_);
|
134
|
+
LOG_BUTTON(" ", "RestartButton", this->restart_button_);
|
135
|
+
#endif
|
136
|
+
#ifdef USE_SENSOR
|
137
|
+
LOG_SENSOR(" ", "TargetCountSensor", this->target_count_sensor_);
|
138
|
+
LOG_SENSOR(" ", "StillTargetCountSensor", this->still_target_count_sensor_);
|
139
|
+
LOG_SENSOR(" ", "MovingTargetCountSensor", this->moving_target_count_sensor_);
|
140
|
+
for (sensor::Sensor *s : this->move_x_sensors_) {
|
141
|
+
LOG_SENSOR(" ", "NthTargetXSensor", s);
|
142
|
+
}
|
143
|
+
for (sensor::Sensor *s : this->move_y_sensors_) {
|
144
|
+
LOG_SENSOR(" ", "NthTargetYSensor", s);
|
145
|
+
}
|
146
|
+
for (sensor::Sensor *s : this->move_speed_sensors_) {
|
147
|
+
LOG_SENSOR(" ", "NthTargetSpeedSensor", s);
|
148
|
+
}
|
149
|
+
for (sensor::Sensor *s : this->move_angle_sensors_) {
|
150
|
+
LOG_SENSOR(" ", "NthTargetAngleSensor", s);
|
151
|
+
}
|
152
|
+
for (sensor::Sensor *s : this->move_distance_sensors_) {
|
153
|
+
LOG_SENSOR(" ", "NthTargetDistanceSensor", s);
|
154
|
+
}
|
155
|
+
for (sensor::Sensor *s : this->move_resolution_sensors_) {
|
156
|
+
LOG_SENSOR(" ", "NthTargetResolutionSensor", s);
|
157
|
+
}
|
158
|
+
for (sensor::Sensor *s : this->zone_target_count_sensors_) {
|
159
|
+
LOG_SENSOR(" ", "NthZoneTargetCountSensor", s);
|
160
|
+
}
|
161
|
+
for (sensor::Sensor *s : this->zone_still_target_count_sensors_) {
|
162
|
+
LOG_SENSOR(" ", "NthZoneStillTargetCountSensor", s);
|
163
|
+
}
|
164
|
+
for (sensor::Sensor *s : this->zone_moving_target_count_sensors_) {
|
165
|
+
LOG_SENSOR(" ", "NthZoneMovingTargetCountSensor", s);
|
166
|
+
}
|
167
|
+
#endif
|
168
|
+
#ifdef USE_TEXT_SENSOR
|
169
|
+
LOG_TEXT_SENSOR(" ", "VersionTextSensor", this->version_text_sensor_);
|
170
|
+
LOG_TEXT_SENSOR(" ", "MacTextSensor", this->mac_text_sensor_);
|
171
|
+
for (text_sensor::TextSensor *s : this->direction_text_sensors_) {
|
172
|
+
LOG_TEXT_SENSOR(" ", "NthDirectionTextSensor", s);
|
173
|
+
}
|
174
|
+
#endif
|
175
|
+
#ifdef USE_NUMBER
|
176
|
+
for (auto n : this->zone_numbers_) {
|
177
|
+
LOG_NUMBER(" ", "ZoneX1Number", n.x1);
|
178
|
+
LOG_NUMBER(" ", "ZoneY1Number", n.y1);
|
179
|
+
LOG_NUMBER(" ", "ZoneX2Number", n.x2);
|
180
|
+
LOG_NUMBER(" ", "ZoneY2Number", n.y2);
|
181
|
+
}
|
182
|
+
#endif
|
183
|
+
#ifdef USE_SELECT
|
184
|
+
LOG_SELECT(" ", "BaudRateSelect", this->baud_rate_select_);
|
185
|
+
LOG_SELECT(" ", "ZoneTypeSelect", this->zone_type_select_);
|
186
|
+
#endif
|
187
|
+
#ifdef USE_NUMBER
|
188
|
+
LOG_NUMBER(" ", "PresenceTimeoutNumber", this->presence_timeout_number_);
|
189
|
+
#endif
|
190
|
+
ESP_LOGCONFIG(TAG, " Throttle : %ums", this->throttle_);
|
191
|
+
ESP_LOGCONFIG(TAG, " MAC Address : %s", const_cast<char *>(this->mac_.c_str()));
|
192
|
+
ESP_LOGCONFIG(TAG, " Firmware version : %s", const_cast<char *>(this->version_.c_str()));
|
193
|
+
}
|
194
|
+
|
195
|
+
void LD2450Component::loop() {
|
196
|
+
while (this->available()) {
|
197
|
+
this->readline_(read(), this->buffer_data_, MAX_LINE_LENGTH);
|
198
|
+
}
|
199
|
+
}
|
200
|
+
|
201
|
+
// Count targets in zone
|
202
|
+
uint8_t LD2450Component::count_targets_in_zone_(const Zone &zone, bool is_moving) {
|
203
|
+
uint8_t count = 0;
|
204
|
+
for (auto &index : this->target_info_) {
|
205
|
+
if (index.x > zone.x1 && index.x < zone.x2 && index.y > zone.y1 && index.y < zone.y2 &&
|
206
|
+
index.is_moving == is_moving) {
|
207
|
+
count++;
|
208
|
+
}
|
209
|
+
}
|
210
|
+
return count;
|
211
|
+
}
|
212
|
+
|
213
|
+
// Service reset_radar_zone
|
214
|
+
void LD2450Component::reset_radar_zone() {
|
215
|
+
this->zone_type_ = 0;
|
216
|
+
for (auto &i : this->zone_config_) {
|
217
|
+
i.x1 = 0;
|
218
|
+
i.y1 = 0;
|
219
|
+
i.x2 = 0;
|
220
|
+
i.y2 = 0;
|
221
|
+
}
|
222
|
+
this->send_set_zone_command_();
|
223
|
+
}
|
224
|
+
|
225
|
+
void LD2450Component::set_radar_zone(int32_t zone_type, int32_t zone1_x1, int32_t zone1_y1, int32_t zone1_x2,
|
226
|
+
int32_t zone1_y2, int32_t zone2_x1, int32_t zone2_y1, int32_t zone2_x2,
|
227
|
+
int32_t zone2_y2, int32_t zone3_x1, int32_t zone3_y1, int32_t zone3_x2,
|
228
|
+
int32_t zone3_y2) {
|
229
|
+
this->zone_type_ = zone_type;
|
230
|
+
int zone_parameters[12] = {zone1_x1, zone1_y1, zone1_x2, zone1_y2, zone2_x1, zone2_y1,
|
231
|
+
zone2_x2, zone2_y2, zone3_x1, zone3_y1, zone3_x2, zone3_y2};
|
232
|
+
for (int i = 0; i < MAX_ZONES; i++) {
|
233
|
+
this->zone_config_[i].x1 = zone_parameters[i * 4];
|
234
|
+
this->zone_config_[i].y1 = zone_parameters[i * 4 + 1];
|
235
|
+
this->zone_config_[i].x2 = zone_parameters[i * 4 + 2];
|
236
|
+
this->zone_config_[i].y2 = zone_parameters[i * 4 + 3];
|
237
|
+
}
|
238
|
+
this->send_set_zone_command_();
|
239
|
+
}
|
240
|
+
|
241
|
+
// Set Zone on LD2450 Sensor
|
242
|
+
void LD2450Component::send_set_zone_command_() {
|
243
|
+
uint8_t cmd_value[26] = {};
|
244
|
+
uint8_t zone_type_bytes[2] = {static_cast<uint8_t>(this->zone_type_), 0x00};
|
245
|
+
uint8_t area_config[24] = {};
|
246
|
+
for (int i = 0; i < MAX_ZONES; i++) {
|
247
|
+
int values[4] = {this->zone_config_[i].x1, this->zone_config_[i].y1, this->zone_config_[i].x2,
|
248
|
+
this->zone_config_[i].y2};
|
249
|
+
ld2450::convert_int_values_to_hex(values, area_config + (i * 8));
|
250
|
+
}
|
251
|
+
std::memcpy(cmd_value, zone_type_bytes, 2);
|
252
|
+
std::memcpy(cmd_value + 2, area_config, 24);
|
253
|
+
this->set_config_mode_(true);
|
254
|
+
this->send_command_(CMD_SET_ZONE, cmd_value, 26);
|
255
|
+
this->set_config_mode_(false);
|
256
|
+
}
|
257
|
+
|
258
|
+
// Check presense timeout to reset presence status
|
259
|
+
bool LD2450Component::get_timeout_status_(uint32_t check_millis) {
|
260
|
+
if (check_millis == 0) {
|
261
|
+
return true;
|
262
|
+
}
|
263
|
+
if (this->timeout_ == 0) {
|
264
|
+
this->timeout_ = ld2450::convert_seconds_to_ms(DEFAULT_PRESENCE_TIMEOUT);
|
265
|
+
}
|
266
|
+
auto current_millis = millis();
|
267
|
+
return current_millis - check_millis >= this->timeout_;
|
268
|
+
}
|
269
|
+
|
270
|
+
// Extract, store and publish zone details LD2450 buffer
|
271
|
+
void LD2450Component::process_zone_(uint8_t *buffer) {
|
272
|
+
uint8_t index, start;
|
273
|
+
for (index = 0; index < MAX_ZONES; index++) {
|
274
|
+
start = 12 + index * 8;
|
275
|
+
this->zone_config_[index].x1 = ld2450::hex_to_signed_int(buffer, start);
|
276
|
+
this->zone_config_[index].y1 = ld2450::hex_to_signed_int(buffer, start + 2);
|
277
|
+
this->zone_config_[index].x2 = ld2450::hex_to_signed_int(buffer, start + 4);
|
278
|
+
this->zone_config_[index].y2 = ld2450::hex_to_signed_int(buffer, start + 6);
|
279
|
+
#ifdef USE_NUMBER
|
280
|
+
// only one null check as all coordinates are required for a single zone
|
281
|
+
if (this->zone_numbers_[index].x1 != nullptr) {
|
282
|
+
this->zone_numbers_[index].x1->publish_state(this->zone_config_[index].x1);
|
283
|
+
this->zone_numbers_[index].y1->publish_state(this->zone_config_[index].y1);
|
284
|
+
this->zone_numbers_[index].x2->publish_state(this->zone_config_[index].x2);
|
285
|
+
this->zone_numbers_[index].y2->publish_state(this->zone_config_[index].y2);
|
286
|
+
}
|
287
|
+
#endif
|
288
|
+
}
|
289
|
+
}
|
290
|
+
|
291
|
+
// Read all info from LD2450 buffer
|
292
|
+
void LD2450Component::read_all_info() {
|
293
|
+
this->set_config_mode_(true);
|
294
|
+
this->get_version_();
|
295
|
+
this->get_mac_();
|
296
|
+
this->query_target_tracking_mode_();
|
297
|
+
this->query_zone_();
|
298
|
+
this->set_config_mode_(false);
|
299
|
+
#ifdef USE_SELECT
|
300
|
+
const auto baud_rate = std::to_string(this->parent_->get_baud_rate());
|
301
|
+
if (this->baud_rate_select_ != nullptr && this->baud_rate_select_->state != baud_rate) {
|
302
|
+
this->baud_rate_select_->publish_state(baud_rate);
|
303
|
+
}
|
304
|
+
this->publish_zone_type();
|
305
|
+
#endif
|
306
|
+
}
|
307
|
+
|
308
|
+
// Read zone info from LD2450 buffer
|
309
|
+
void LD2450Component::query_zone_info() {
|
310
|
+
this->set_config_mode_(true);
|
311
|
+
this->query_zone_();
|
312
|
+
this->set_config_mode_(false);
|
313
|
+
}
|
314
|
+
|
315
|
+
// Restart LD2450 and read all info from buffer
|
316
|
+
void LD2450Component::restart_and_read_all_info() {
|
317
|
+
this->set_config_mode_(true);
|
318
|
+
this->restart_();
|
319
|
+
this->set_timeout(1500, [this]() { this->read_all_info(); });
|
320
|
+
}
|
321
|
+
|
322
|
+
// Send command with values to LD2450
|
323
|
+
void LD2450Component::send_command_(uint8_t command, const uint8_t *command_value, uint8_t command_value_len) {
|
324
|
+
ESP_LOGV(TAG, "Sending command %02X", command);
|
325
|
+
// frame header
|
326
|
+
this->write_array(CMD_FRAME_HEADER, 4);
|
327
|
+
// length bytes
|
328
|
+
int len = 2;
|
329
|
+
if (command_value != nullptr) {
|
330
|
+
len += command_value_len;
|
331
|
+
}
|
332
|
+
this->write_byte(lowbyte(len));
|
333
|
+
this->write_byte(highbyte(len));
|
334
|
+
// command
|
335
|
+
this->write_byte(lowbyte(command));
|
336
|
+
this->write_byte(highbyte(command));
|
337
|
+
// command value bytes
|
338
|
+
if (command_value != nullptr) {
|
339
|
+
for (int i = 0; i < command_value_len; i++) {
|
340
|
+
this->write_byte(command_value[i]);
|
341
|
+
}
|
342
|
+
}
|
343
|
+
// footer
|
344
|
+
this->write_array(CMD_FRAME_END, 4);
|
345
|
+
// FIXME to remove
|
346
|
+
delay(50); // NOLINT
|
347
|
+
}
|
348
|
+
|
349
|
+
// LD2450 Radar data message:
|
350
|
+
// [AA FF 03 00] [0E 03 B1 86 10 00 40 01] [00 00 00 00 00 00 00 00] [00 00 00 00 00 00 00 00] [55 CC]
|
351
|
+
// Header Target 1 Target 2 Target 3 End
|
352
|
+
void LD2450Component::handle_periodic_data_(uint8_t *buffer, uint8_t len) {
|
353
|
+
if (len < 29) { // header (4 bytes) + 8 x 3 target data + footer (2 bytes)
|
354
|
+
ESP_LOGE(TAG, "Periodic data: invalid message length");
|
355
|
+
return;
|
356
|
+
}
|
357
|
+
if (buffer[0] != 0xAA || buffer[1] != 0xFF || buffer[2] != 0x03 || buffer[3] != 0x00) { // header
|
358
|
+
ESP_LOGE(TAG, "Periodic data: invalid message header");
|
359
|
+
return;
|
360
|
+
}
|
361
|
+
if (buffer[len - 2] != 0x55 || buffer[len - 1] != 0xCC) { // footer
|
362
|
+
ESP_LOGE(TAG, "Periodic data: invalid message footer");
|
363
|
+
return;
|
364
|
+
}
|
365
|
+
|
366
|
+
auto current_millis = millis();
|
367
|
+
if (current_millis - this->last_periodic_millis_ < this->throttle_) {
|
368
|
+
ESP_LOGV(TAG, "Throttling: %d", this->throttle_);
|
369
|
+
return;
|
370
|
+
}
|
371
|
+
|
372
|
+
this->last_periodic_millis_ = current_millis;
|
373
|
+
|
374
|
+
int16_t target_count = 0;
|
375
|
+
int16_t still_target_count = 0;
|
376
|
+
int16_t moving_target_count = 0;
|
377
|
+
int16_t start = 0;
|
378
|
+
int16_t val = 0;
|
379
|
+
uint8_t index = 0;
|
380
|
+
int16_t tx = 0;
|
381
|
+
int16_t ty = 0;
|
382
|
+
int16_t td = 0;
|
383
|
+
int16_t ts = 0;
|
384
|
+
int16_t angle = 0;
|
385
|
+
std::string direction{};
|
386
|
+
bool is_moving = false;
|
387
|
+
|
388
|
+
#if defined(USE_BINARY_SENSOR) || defined(USE_SENSOR) || defined(USE_TEXT_SENSOR)
|
389
|
+
// Loop thru targets
|
390
|
+
for (index = 0; index < MAX_TARGETS; index++) {
|
391
|
+
#ifdef USE_SENSOR
|
392
|
+
// X
|
393
|
+
start = TARGET_X + index * 8;
|
394
|
+
is_moving = false;
|
395
|
+
sensor::Sensor *sx = this->move_x_sensors_[index];
|
396
|
+
if (sx != nullptr) {
|
397
|
+
val = ld2450::decode_coordinate(buffer[start], buffer[start + 1]);
|
398
|
+
tx = val;
|
399
|
+
sx->publish_state(val);
|
400
|
+
}
|
401
|
+
// Y
|
402
|
+
start = TARGET_Y + index * 8;
|
403
|
+
sensor::Sensor *sy = this->move_y_sensors_[index];
|
404
|
+
if (sy != nullptr) {
|
405
|
+
val = ld2450::decode_coordinate(buffer[start], buffer[start + 1]);
|
406
|
+
ty = val;
|
407
|
+
sy->publish_state(val);
|
408
|
+
}
|
409
|
+
// RESOLUTION
|
410
|
+
start = TARGET_RESOLUTION + index * 8;
|
411
|
+
sensor::Sensor *sr = this->move_resolution_sensors_[index];
|
412
|
+
if (sr != nullptr) {
|
413
|
+
val = (buffer[start + 1] << 8) | buffer[start];
|
414
|
+
sr->publish_state(val);
|
415
|
+
}
|
416
|
+
#endif
|
417
|
+
// SPEED
|
418
|
+
start = TARGET_SPEED + index * 8;
|
419
|
+
val = ld2450::decode_speed(buffer[start], buffer[start + 1]);
|
420
|
+
ts = val;
|
421
|
+
if (val) {
|
422
|
+
is_moving = true;
|
423
|
+
moving_target_count++;
|
424
|
+
}
|
425
|
+
#ifdef USE_SENSOR
|
426
|
+
sensor::Sensor *ss = this->move_speed_sensors_[index];
|
427
|
+
if (ss != nullptr) {
|
428
|
+
ss->publish_state(val);
|
429
|
+
}
|
430
|
+
#endif
|
431
|
+
// DISTANCE
|
432
|
+
val = (uint16_t) sqrt(
|
433
|
+
pow(ld2450::decode_coordinate(buffer[TARGET_X + index * 8], buffer[(TARGET_X + index * 8) + 1]), 2) +
|
434
|
+
pow(ld2450::decode_coordinate(buffer[TARGET_Y + index * 8], buffer[(TARGET_Y + index * 8) + 1]), 2));
|
435
|
+
td = val;
|
436
|
+
if (val > 0) {
|
437
|
+
target_count++;
|
438
|
+
}
|
439
|
+
#ifdef USE_SENSOR
|
440
|
+
sensor::Sensor *sd = this->move_distance_sensors_[index];
|
441
|
+
if (sd != nullptr) {
|
442
|
+
sd->publish_state(val);
|
443
|
+
}
|
444
|
+
// ANGLE
|
445
|
+
angle = calculate_angle(static_cast<float>(ty), static_cast<float>(td));
|
446
|
+
if (tx > 0) {
|
447
|
+
angle = angle * -1;
|
448
|
+
}
|
449
|
+
sensor::Sensor *sa = this->move_angle_sensors_[index];
|
450
|
+
if (sa != nullptr) {
|
451
|
+
sa->publish_state(angle);
|
452
|
+
}
|
453
|
+
#endif
|
454
|
+
#ifdef USE_TEXT_SENSOR
|
455
|
+
// DIRECTION
|
456
|
+
direction = get_direction(ts);
|
457
|
+
if (td == 0) {
|
458
|
+
direction = "NA";
|
459
|
+
}
|
460
|
+
text_sensor::TextSensor *tsd = this->direction_text_sensors_[index];
|
461
|
+
if (tsd != nullptr) {
|
462
|
+
tsd->publish_state(direction);
|
463
|
+
}
|
464
|
+
#endif
|
465
|
+
|
466
|
+
// Store target info for zone target count
|
467
|
+
this->target_info_[index].x = tx;
|
468
|
+
this->target_info_[index].y = ty;
|
469
|
+
this->target_info_[index].is_moving = is_moving;
|
470
|
+
|
471
|
+
} // End loop thru targets
|
472
|
+
|
473
|
+
still_target_count = target_count - moving_target_count;
|
474
|
+
#endif
|
475
|
+
|
476
|
+
#ifdef USE_SENSOR
|
477
|
+
// Loop thru zones
|
478
|
+
uint8_t zone_still_targets = 0;
|
479
|
+
uint8_t zone_moving_targets = 0;
|
480
|
+
uint8_t zone_all_targets = 0;
|
481
|
+
for (index = 0; index < MAX_ZONES; index++) {
|
482
|
+
zone_still_targets = this->count_targets_in_zone_(this->zone_config_[index], false);
|
483
|
+
zone_moving_targets = this->count_targets_in_zone_(this->zone_config_[index], true);
|
484
|
+
zone_all_targets = zone_still_targets + zone_moving_targets;
|
485
|
+
|
486
|
+
// Publish Still Target Count in Zones
|
487
|
+
sensor::Sensor *szstc = this->zone_still_target_count_sensors_[index];
|
488
|
+
if (szstc != nullptr) {
|
489
|
+
szstc->publish_state(zone_still_targets);
|
490
|
+
}
|
491
|
+
// Publish Moving Target Count in Zones
|
492
|
+
sensor::Sensor *szmtc = this->zone_moving_target_count_sensors_[index];
|
493
|
+
if (szmtc != nullptr) {
|
494
|
+
szmtc->publish_state(zone_moving_targets);
|
495
|
+
}
|
496
|
+
// Publish All Target Count in Zones
|
497
|
+
sensor::Sensor *sztc = this->zone_target_count_sensors_[index];
|
498
|
+
if (sztc != nullptr) {
|
499
|
+
sztc->publish_state(zone_all_targets);
|
500
|
+
}
|
501
|
+
|
502
|
+
} // End loop thru zones
|
503
|
+
|
504
|
+
// Target Count
|
505
|
+
if (this->target_count_sensor_ != nullptr) {
|
506
|
+
this->target_count_sensor_->publish_state(target_count);
|
507
|
+
}
|
508
|
+
// Still Target Count
|
509
|
+
if (this->still_target_count_sensor_ != nullptr) {
|
510
|
+
this->still_target_count_sensor_->publish_state(still_target_count);
|
511
|
+
}
|
512
|
+
// Moving Target Count
|
513
|
+
if (this->moving_target_count_sensor_ != nullptr) {
|
514
|
+
this->moving_target_count_sensor_->publish_state(moving_target_count);
|
515
|
+
}
|
516
|
+
#endif
|
517
|
+
|
518
|
+
#ifdef USE_BINARY_SENSOR
|
519
|
+
// Target Presence
|
520
|
+
if (this->target_binary_sensor_ != nullptr) {
|
521
|
+
if (target_count > 0) {
|
522
|
+
this->target_binary_sensor_->publish_state(true);
|
523
|
+
} else {
|
524
|
+
if (this->get_timeout_status_(this->presence_millis_)) {
|
525
|
+
this->target_binary_sensor_->publish_state(false);
|
526
|
+
} else {
|
527
|
+
ESP_LOGV(TAG, "Clear presence waiting timeout: %d", this->timeout_);
|
528
|
+
}
|
529
|
+
}
|
530
|
+
}
|
531
|
+
// Moving Target Presence
|
532
|
+
if (this->moving_target_binary_sensor_ != nullptr) {
|
533
|
+
if (moving_target_count > 0) {
|
534
|
+
this->moving_target_binary_sensor_->publish_state(true);
|
535
|
+
} else {
|
536
|
+
if (this->get_timeout_status_(this->moving_presence_millis_)) {
|
537
|
+
this->moving_target_binary_sensor_->publish_state(false);
|
538
|
+
}
|
539
|
+
}
|
540
|
+
}
|
541
|
+
// Still Target Presence
|
542
|
+
if (this->still_target_binary_sensor_ != nullptr) {
|
543
|
+
if (still_target_count > 0) {
|
544
|
+
this->still_target_binary_sensor_->publish_state(true);
|
545
|
+
} else {
|
546
|
+
if (this->get_timeout_status_(this->still_presence_millis_)) {
|
547
|
+
this->still_target_binary_sensor_->publish_state(false);
|
548
|
+
}
|
549
|
+
}
|
550
|
+
}
|
551
|
+
#endif
|
552
|
+
#ifdef USE_SENSOR
|
553
|
+
// For presence timeout check
|
554
|
+
if (target_count > 0) {
|
555
|
+
this->presence_millis_ = millis();
|
556
|
+
}
|
557
|
+
if (moving_target_count > 0) {
|
558
|
+
this->moving_presence_millis_ = millis();
|
559
|
+
}
|
560
|
+
if (still_target_count > 0) {
|
561
|
+
this->still_presence_millis_ = millis();
|
562
|
+
}
|
563
|
+
#endif
|
564
|
+
}
|
565
|
+
|
566
|
+
bool LD2450Component::handle_ack_data_(uint8_t *buffer, uint8_t len) {
|
567
|
+
ESP_LOGV(TAG, "Handling ack data for command %02X", buffer[COMMAND]);
|
568
|
+
if (len < 10) {
|
569
|
+
ESP_LOGE(TAG, "Ack data: invalid length");
|
570
|
+
return true;
|
571
|
+
}
|
572
|
+
if (buffer[0] != 0xFD || buffer[1] != 0xFC || buffer[2] != 0xFB || buffer[3] != 0xFA) { // frame header
|
573
|
+
ESP_LOGE(TAG, "Ack data: invalid header (command %02X)", buffer[COMMAND]);
|
574
|
+
return true;
|
575
|
+
}
|
576
|
+
if (buffer[COMMAND_STATUS] != 0x01) {
|
577
|
+
ESP_LOGE(TAG, "Ack data: invalid status");
|
578
|
+
return true;
|
579
|
+
}
|
580
|
+
if (buffer[8] || buffer[9]) {
|
581
|
+
ESP_LOGE(TAG, "Ack data: last buffer was %u, %u", buffer[8], buffer[9]);
|
582
|
+
return true;
|
583
|
+
}
|
584
|
+
|
585
|
+
switch (buffer[COMMAND]) {
|
586
|
+
case lowbyte(CMD_ENABLE_CONF):
|
587
|
+
ESP_LOGV(TAG, "Got enable conf command");
|
588
|
+
break;
|
589
|
+
case lowbyte(CMD_DISABLE_CONF):
|
590
|
+
ESP_LOGV(TAG, "Got disable conf command");
|
591
|
+
break;
|
592
|
+
case lowbyte(CMD_SET_BAUD_RATE):
|
593
|
+
ESP_LOGV(TAG, "Got baud rate change command");
|
594
|
+
#ifdef USE_SELECT
|
595
|
+
if (this->baud_rate_select_ != nullptr) {
|
596
|
+
ESP_LOGV(TAG, "Change baud rate to %s", this->baud_rate_select_->state.c_str());
|
597
|
+
}
|
598
|
+
#endif
|
599
|
+
break;
|
600
|
+
case lowbyte(CMD_VERSION):
|
601
|
+
this->version_ = ld2450::format_version(buffer);
|
602
|
+
ESP_LOGV(TAG, "Firmware version: %s", this->version_.c_str());
|
603
|
+
#ifdef USE_TEXT_SENSOR
|
604
|
+
if (this->version_text_sensor_ != nullptr) {
|
605
|
+
this->version_text_sensor_->publish_state(this->version_);
|
606
|
+
}
|
607
|
+
#endif
|
608
|
+
break;
|
609
|
+
case lowbyte(CMD_MAC):
|
610
|
+
if (len < 20) {
|
611
|
+
return false;
|
612
|
+
}
|
613
|
+
this->mac_ = ld2450::format_mac(buffer);
|
614
|
+
ESP_LOGV(TAG, "MAC address: %s", this->mac_.c_str());
|
615
|
+
#ifdef USE_TEXT_SENSOR
|
616
|
+
if (this->mac_text_sensor_ != nullptr) {
|
617
|
+
this->mac_text_sensor_->publish_state(this->mac_);
|
618
|
+
}
|
619
|
+
#endif
|
620
|
+
#ifdef USE_SWITCH
|
621
|
+
if (this->bluetooth_switch_ != nullptr) {
|
622
|
+
this->bluetooth_switch_->publish_state(this->mac_ != UNKNOWN_MAC);
|
623
|
+
}
|
624
|
+
#endif
|
625
|
+
break;
|
626
|
+
case lowbyte(CMD_BLUETOOTH):
|
627
|
+
ESP_LOGV(TAG, "Got Bluetooth command");
|
628
|
+
break;
|
629
|
+
case lowbyte(CMD_SINGLE_TARGET_MODE):
|
630
|
+
ESP_LOGV(TAG, "Got single target conf command");
|
631
|
+
#ifdef USE_SWITCH
|
632
|
+
if (this->multi_target_switch_ != nullptr) {
|
633
|
+
this->multi_target_switch_->publish_state(false);
|
634
|
+
}
|
635
|
+
#endif
|
636
|
+
break;
|
637
|
+
case lowbyte(CMD_MULTI_TARGET_MODE):
|
638
|
+
ESP_LOGV(TAG, "Got multi target conf command");
|
639
|
+
#ifdef USE_SWITCH
|
640
|
+
if (this->multi_target_switch_ != nullptr) {
|
641
|
+
this->multi_target_switch_->publish_state(true);
|
642
|
+
}
|
643
|
+
#endif
|
644
|
+
break;
|
645
|
+
case lowbyte(CMD_QUERY_TARGET_MODE):
|
646
|
+
ESP_LOGV(TAG, "Got query target tracking mode command");
|
647
|
+
#ifdef USE_SWITCH
|
648
|
+
if (this->multi_target_switch_ != nullptr) {
|
649
|
+
this->multi_target_switch_->publish_state(buffer[10] == 0x02);
|
650
|
+
}
|
651
|
+
#endif
|
652
|
+
break;
|
653
|
+
case lowbyte(CMD_QUERY_ZONE):
|
654
|
+
ESP_LOGV(TAG, "Got query zone conf command");
|
655
|
+
this->zone_type_ = std::stoi(std::to_string(buffer[10]), nullptr, 16);
|
656
|
+
this->publish_zone_type();
|
657
|
+
#ifdef USE_SELECT
|
658
|
+
if (this->zone_type_select_ != nullptr) {
|
659
|
+
ESP_LOGV(TAG, "Change zone type to: %s", this->zone_type_select_->state.c_str());
|
660
|
+
}
|
661
|
+
#endif
|
662
|
+
if (buffer[10] == 0x00) {
|
663
|
+
ESP_LOGV(TAG, "Zone: Disabled");
|
664
|
+
}
|
665
|
+
if (buffer[10] == 0x01) {
|
666
|
+
ESP_LOGV(TAG, "Zone: Area detection");
|
667
|
+
}
|
668
|
+
if (buffer[10] == 0x02) {
|
669
|
+
ESP_LOGV(TAG, "Zone: Area filter");
|
670
|
+
}
|
671
|
+
this->process_zone_(buffer);
|
672
|
+
break;
|
673
|
+
case lowbyte(CMD_SET_ZONE):
|
674
|
+
ESP_LOGV(TAG, "Got set zone conf command");
|
675
|
+
this->query_zone_info();
|
676
|
+
break;
|
677
|
+
default:
|
678
|
+
break;
|
679
|
+
}
|
680
|
+
return true;
|
681
|
+
}
|
682
|
+
|
683
|
+
// Read LD2450 buffer data
|
684
|
+
void LD2450Component::readline_(int readch, uint8_t *buffer, uint8_t len) {
|
685
|
+
if (readch < 0) {
|
686
|
+
return;
|
687
|
+
}
|
688
|
+
if (this->buffer_pos_ < len - 1) {
|
689
|
+
buffer[this->buffer_pos_++] = readch;
|
690
|
+
buffer[this->buffer_pos_] = 0;
|
691
|
+
} else {
|
692
|
+
this->buffer_pos_ = 0;
|
693
|
+
}
|
694
|
+
if (this->buffer_pos_ < 4) {
|
695
|
+
return;
|
696
|
+
}
|
697
|
+
if (buffer[this->buffer_pos_ - 2] == 0x55 && buffer[this->buffer_pos_ - 1] == 0xCC) {
|
698
|
+
ESP_LOGV(TAG, "Handle periodic radar data");
|
699
|
+
this->handle_periodic_data_(buffer, this->buffer_pos_);
|
700
|
+
this->buffer_pos_ = 0; // Reset position index for next frame
|
701
|
+
} else if (buffer[this->buffer_pos_ - 4] == 0x04 && buffer[this->buffer_pos_ - 3] == 0x03 &&
|
702
|
+
buffer[this->buffer_pos_ - 2] == 0x02 && buffer[this->buffer_pos_ - 1] == 0x01) {
|
703
|
+
ESP_LOGV(TAG, "Handle command ack data");
|
704
|
+
if (this->handle_ack_data_(buffer, this->buffer_pos_)) {
|
705
|
+
this->buffer_pos_ = 0; // Reset position index for next frame
|
706
|
+
} else {
|
707
|
+
ESP_LOGV(TAG, "Command ack data invalid");
|
708
|
+
}
|
709
|
+
}
|
710
|
+
}
|
711
|
+
|
712
|
+
// Set Config Mode - Pre-requisite sending commands
|
713
|
+
void LD2450Component::set_config_mode_(bool enable) {
|
714
|
+
uint8_t cmd = enable ? CMD_ENABLE_CONF : CMD_DISABLE_CONF;
|
715
|
+
uint8_t cmd_value[2] = {0x01, 0x00};
|
716
|
+
this->send_command_(cmd, enable ? cmd_value : nullptr, 2);
|
717
|
+
}
|
718
|
+
|
719
|
+
// Set Bluetooth Enable/Disable
|
720
|
+
void LD2450Component::set_bluetooth(bool enable) {
|
721
|
+
this->set_config_mode_(true);
|
722
|
+
uint8_t enable_cmd_value[2] = {0x01, 0x00};
|
723
|
+
uint8_t disable_cmd_value[2] = {0x00, 0x00};
|
724
|
+
this->send_command_(CMD_BLUETOOTH, enable ? enable_cmd_value : disable_cmd_value, 2);
|
725
|
+
this->set_timeout(200, [this]() { this->restart_and_read_all_info(); });
|
726
|
+
}
|
727
|
+
|
728
|
+
// Set Baud rate
|
729
|
+
void LD2450Component::set_baud_rate(const std::string &state) {
|
730
|
+
this->set_config_mode_(true);
|
731
|
+
uint8_t cmd_value[2] = {BAUD_RATE_ENUM_TO_INT.at(state), 0x00};
|
732
|
+
this->send_command_(CMD_SET_BAUD_RATE, cmd_value, 2);
|
733
|
+
this->set_timeout(200, [this]() { this->restart_(); });
|
734
|
+
}
|
735
|
+
|
736
|
+
// Set Zone Type - one of: Disabled, Detection, Filter
|
737
|
+
void LD2450Component::set_zone_type(const std::string &state) {
|
738
|
+
ESP_LOGV(TAG, "Set zone type: %s", state.c_str());
|
739
|
+
uint8_t zone_type = ZONE_TYPE_ENUM_TO_INT.at(state);
|
740
|
+
this->zone_type_ = zone_type;
|
741
|
+
this->send_set_zone_command_();
|
742
|
+
}
|
743
|
+
|
744
|
+
// Publish Zone Type to Select component
|
745
|
+
void LD2450Component::publish_zone_type() {
|
746
|
+
#ifdef USE_SELECT
|
747
|
+
std::string zone_type = ZONE_TYPE_INT_TO_ENUM.at(static_cast<ZoneTypeStructure>(this->zone_type_));
|
748
|
+
if (this->zone_type_select_ != nullptr) {
|
749
|
+
this->zone_type_select_->publish_state(zone_type);
|
750
|
+
}
|
751
|
+
#endif
|
752
|
+
}
|
753
|
+
|
754
|
+
// Set Single/Multiplayer target detection
|
755
|
+
void LD2450Component::set_multi_target(bool enable) {
|
756
|
+
this->set_config_mode_(true);
|
757
|
+
uint8_t cmd = enable ? CMD_MULTI_TARGET_MODE : CMD_SINGLE_TARGET_MODE;
|
758
|
+
this->send_command_(cmd, nullptr, 0);
|
759
|
+
this->set_config_mode_(false);
|
760
|
+
}
|
761
|
+
|
762
|
+
// LD2450 factory reset
|
763
|
+
void LD2450Component::factory_reset() {
|
764
|
+
this->set_config_mode_(true);
|
765
|
+
this->send_command_(CMD_RESET, nullptr, 0);
|
766
|
+
this->set_timeout(200, [this]() { this->restart_and_read_all_info(); });
|
767
|
+
}
|
768
|
+
|
769
|
+
// Restart LD2450 module
|
770
|
+
void LD2450Component::restart_() { this->send_command_(CMD_RESTART, nullptr, 0); }
|
771
|
+
|
772
|
+
// Get LD2450 firmware version
|
773
|
+
void LD2450Component::get_version_() { this->send_command_(CMD_VERSION, nullptr, 0); }
|
774
|
+
|
775
|
+
// Get LD2450 mac address
|
776
|
+
void LD2450Component::get_mac_() {
|
777
|
+
uint8_t cmd_value[2] = {0x01, 0x00};
|
778
|
+
this->send_command_(CMD_MAC, cmd_value, 2);
|
779
|
+
}
|
780
|
+
|
781
|
+
// Query for target tracking mode
|
782
|
+
void LD2450Component::query_target_tracking_mode_() { this->send_command_(CMD_QUERY_TARGET_MODE, nullptr, 0); }
|
783
|
+
|
784
|
+
// Query for zone info
|
785
|
+
void LD2450Component::query_zone_() { this->send_command_(CMD_QUERY_ZONE, nullptr, 0); }
|
786
|
+
|
787
|
+
#ifdef USE_SENSOR
|
788
|
+
void LD2450Component::set_move_x_sensor(uint8_t target, sensor::Sensor *s) { this->move_x_sensors_[target] = s; }
|
789
|
+
void LD2450Component::set_move_y_sensor(uint8_t target, sensor::Sensor *s) { this->move_y_sensors_[target] = s; }
|
790
|
+
void LD2450Component::set_move_speed_sensor(uint8_t target, sensor::Sensor *s) {
|
791
|
+
this->move_speed_sensors_[target] = s;
|
792
|
+
}
|
793
|
+
void LD2450Component::set_move_angle_sensor(uint8_t target, sensor::Sensor *s) {
|
794
|
+
this->move_angle_sensors_[target] = s;
|
795
|
+
}
|
796
|
+
void LD2450Component::set_move_distance_sensor(uint8_t target, sensor::Sensor *s) {
|
797
|
+
this->move_distance_sensors_[target] = s;
|
798
|
+
}
|
799
|
+
void LD2450Component::set_move_resolution_sensor(uint8_t target, sensor::Sensor *s) {
|
800
|
+
this->move_resolution_sensors_[target] = s;
|
801
|
+
}
|
802
|
+
void LD2450Component::set_zone_target_count_sensor(uint8_t zone, sensor::Sensor *s) {
|
803
|
+
this->zone_target_count_sensors_[zone] = s;
|
804
|
+
}
|
805
|
+
void LD2450Component::set_zone_still_target_count_sensor(uint8_t zone, sensor::Sensor *s) {
|
806
|
+
this->zone_still_target_count_sensors_[zone] = s;
|
807
|
+
}
|
808
|
+
void LD2450Component::set_zone_moving_target_count_sensor(uint8_t zone, sensor::Sensor *s) {
|
809
|
+
this->zone_moving_target_count_sensors_[zone] = s;
|
810
|
+
}
|
811
|
+
#endif
|
812
|
+
#ifdef USE_TEXT_SENSOR
|
813
|
+
void LD2450Component::set_direction_text_sensor(uint8_t target, text_sensor::TextSensor *s) {
|
814
|
+
this->direction_text_sensors_[target] = s;
|
815
|
+
}
|
816
|
+
#endif
|
817
|
+
|
818
|
+
// Send Zone coordinates data to LD2450
|
819
|
+
#ifdef USE_NUMBER
|
820
|
+
void LD2450Component::set_zone_coordinate(uint8_t zone) {
|
821
|
+
number::Number *x1sens = this->zone_numbers_[zone].x1;
|
822
|
+
number::Number *y1sens = this->zone_numbers_[zone].y1;
|
823
|
+
number::Number *x2sens = this->zone_numbers_[zone].x2;
|
824
|
+
number::Number *y2sens = this->zone_numbers_[zone].y2;
|
825
|
+
if (!x1sens->has_state() || !y1sens->has_state() || !x2sens->has_state() || !y2sens->has_state()) {
|
826
|
+
return;
|
827
|
+
}
|
828
|
+
this->zone_config_[zone].x1 = static_cast<int>(x1sens->state);
|
829
|
+
this->zone_config_[zone].y1 = static_cast<int>(y1sens->state);
|
830
|
+
this->zone_config_[zone].x2 = static_cast<int>(x2sens->state);
|
831
|
+
this->zone_config_[zone].y2 = static_cast<int>(y2sens->state);
|
832
|
+
this->send_set_zone_command_();
|
833
|
+
}
|
834
|
+
|
835
|
+
void LD2450Component::set_zone_numbers(uint8_t zone, number::Number *x1, number::Number *y1, number::Number *x2,
|
836
|
+
number::Number *y2) {
|
837
|
+
if (zone < MAX_ZONES) {
|
838
|
+
this->zone_numbers_[zone].x1 = x1;
|
839
|
+
this->zone_numbers_[zone].y1 = y1;
|
840
|
+
this->zone_numbers_[zone].x2 = x2;
|
841
|
+
this->zone_numbers_[zone].y2 = y2;
|
842
|
+
}
|
843
|
+
}
|
844
|
+
#endif
|
845
|
+
|
846
|
+
// Set Presence Timeout load and save from flash
|
847
|
+
#ifdef USE_NUMBER
|
848
|
+
void LD2450Component::set_presence_timeout() {
|
849
|
+
if (this->presence_timeout_number_ != nullptr) {
|
850
|
+
if (this->presence_timeout_number_->state == 0) {
|
851
|
+
float timeout = this->restore_from_flash_();
|
852
|
+
this->presence_timeout_number_->publish_state(timeout);
|
853
|
+
this->timeout_ = ld2450::convert_seconds_to_ms(timeout);
|
854
|
+
}
|
855
|
+
if (this->presence_timeout_number_->has_state()) {
|
856
|
+
this->save_to_flash_(this->presence_timeout_number_->state);
|
857
|
+
this->timeout_ = ld2450::convert_seconds_to_ms(this->presence_timeout_number_->state);
|
858
|
+
}
|
859
|
+
}
|
860
|
+
}
|
861
|
+
|
862
|
+
// Save Presence Timeout to flash
|
863
|
+
void LD2450Component::save_to_flash_(float value) { this->pref_.save(&value); }
|
864
|
+
|
865
|
+
// Load Presence Timeout from flash
|
866
|
+
float LD2450Component::restore_from_flash_() {
|
867
|
+
float value;
|
868
|
+
if (!this->pref_.load(&value)) {
|
869
|
+
value = DEFAULT_PRESENCE_TIMEOUT;
|
870
|
+
}
|
871
|
+
return value;
|
872
|
+
}
|
873
|
+
#endif
|
874
|
+
|
875
|
+
} // namespace ld2450
|
876
|
+
} // namespace esphome
|