13static constexpr uint8_t TF_SOF = 0x01;
14static constexpr uint32_t SETUP_DELAY_MS = 100;
17static constexpr uint16_t TYPE_CONTROL = 0x0201;
18static constexpr uint16_t TYPE_SET_AREA = 0x0202;
19static constexpr uint16_t TYPE_SET_HOLD_DELAY = 0x0203;
20static constexpr uint16_t TYPE_SET_Z_RANGE = 0x0204;
21static constexpr uint16_t TYPE_SET_LOW_POWER_SLEEP = 0x0205;
23static constexpr uint16_t TYPE_REPORT_TARGET = 0x0A04;
24static constexpr uint16_t TYPE_REPORT_POINT_CLOUD = 0x0A08;
25static constexpr uint16_t TYPE_REPORT_AREA_PRESENCE = 0x0A0A;
26static constexpr uint16_t TYPE_REPORT_INTERFERENCE_AREAS = 0x0A0B;
27static constexpr uint16_t TYPE_REPORT_DETECTION_AREAS = 0x0A0C;
28static constexpr uint16_t TYPE_REPORT_DELAY = 0x0A0D;
29static constexpr uint16_t TYPE_REPORT_SENSITIVITY = 0x0A0E;
30static constexpr uint16_t TYPE_REPORT_TRIGGER = 0x0A0F;
31static constexpr uint16_t TYPE_REPORT_Z_RANGE = 0x0A10;
32static constexpr uint16_t TYPE_REPORT_INSTALLATION = 0x0A11;
33static constexpr uint16_t TYPE_REPORT_LOW_POWER = 0x0A12;
34static constexpr uint16_t TYPE_REPORT_LOW_POWER_SLEEP = 0x0A13;
35static constexpr uint16_t TYPE_REPORT_WORK_MODE = 0x0A14;
36static constexpr uint16_t TYPE_QUERY_VERSION = 0xFFFF;
39static constexpr uint32_t CMD_AUTO_INTERFERENCE = 0x01;
40static constexpr uint32_t CMD_GET_AREAS = 0x02;
41static constexpr uint32_t CMD_CLEAR_INTERFERENCE = 0x03;
42static constexpr uint32_t CMD_RESET_DETECTION_AREA = 0x04;
43static constexpr uint32_t CMD_GET_DELAY = 0x05;
44static constexpr uint32_t CMD_POINT_CLOUD_ON = 0x06;
45static constexpr uint32_t CMD_POINT_CLOUD_OFF = 0x07;
46static constexpr uint32_t CMD_TARGET_DISPLAY_ON = 0x08;
47static constexpr uint32_t CMD_TARGET_DISPLAY_OFF = 0x09;
48static constexpr uint32_t CMD_SENSITIVITY_LOW = 0x0A;
49static constexpr uint32_t CMD_SENSITIVITY_MEDIUM = 0x0B;
50static constexpr uint32_t CMD_SENSITIVITY_HIGH = 0x0C;
51static constexpr uint32_t CMD_GET_SENSITIVITY = 0x0D;
52static constexpr uint32_t CMD_TRIGGER_SLOW = 0x0E;
53static constexpr uint32_t CMD_TRIGGER_MEDIUM = 0x0F;
54static constexpr uint32_t CMD_TRIGGER_FAST = 0x10;
55static constexpr uint32_t CMD_GET_TRIGGER = 0x11;
56static constexpr uint32_t CMD_GET_Z_RANGE = 0x12;
57static constexpr uint32_t CMD_INSTALL_TOP = 0x13;
58static constexpr uint32_t CMD_INSTALL_SIDE = 0x14;
59static constexpr uint32_t CMD_GET_INSTALLATION = 0x15;
60static constexpr uint32_t CMD_LOW_POWER_ON = 0x16;
61static constexpr uint32_t CMD_LOW_POWER_OFF = 0x17;
62static constexpr uint32_t CMD_GET_LOW_POWER = 0x18;
63static constexpr uint32_t CMD_GET_LOW_POWER_SLEEP = 0x19;
64static constexpr uint32_t CMD_RESET_UNATTENDED = 0x1A;
66static constexpr uint16_t TARGET_DATA_LEN = 20;
67static constexpr uint16_t AREA_DATA_LEN = 24;
68static constexpr uint16_t AREA_CONFIG_LEN = 28;
69static constexpr uint16_t AREA_PRESENCE_ENTRY_LEN = 4;
71static constexpr uint8_t AREA_ID_DEFAULT = 4;
73static constexpr uint8_t VERSION_QUERY_DATA[] = {0x01, 0x01, 0x00, 0x00};
75#ifdef ESPHOME_LOG_HAS_VERBOSE
76static const char *control_command_name(
uint32_t command) {
78 case CMD_AUTO_INTERFERENCE:
79 return "auto_interference";
82 case CMD_CLEAR_INTERFERENCE:
83 return "clear_interference";
84 case CMD_RESET_DETECTION_AREA:
85 return "reset_detection_area";
88 case CMD_POINT_CLOUD_ON:
89 return "point_cloud_on";
90 case CMD_POINT_CLOUD_OFF:
91 return "point_cloud_off";
92 case CMD_TARGET_DISPLAY_ON:
93 return "target_display_on";
94 case CMD_TARGET_DISPLAY_OFF:
95 return "target_display_off";
96 case CMD_SENSITIVITY_LOW:
97 return "sensitivity_low";
98 case CMD_SENSITIVITY_MEDIUM:
99 return "sensitivity_medium";
100 case CMD_SENSITIVITY_HIGH:
101 return "sensitivity_high";
102 case CMD_GET_SENSITIVITY:
103 return "get_sensitivity";
104 case CMD_TRIGGER_SLOW:
105 return "trigger_slow";
106 case CMD_TRIGGER_MEDIUM:
107 return "trigger_medium";
108 case CMD_TRIGGER_FAST:
109 return "trigger_fast";
110 case CMD_GET_TRIGGER:
111 return "get_trigger";
112 case CMD_GET_Z_RANGE:
113 return "get_z_range";
114 case CMD_INSTALL_TOP:
115 return "install_top";
116 case CMD_INSTALL_SIDE:
117 return "install_side";
118 case CMD_GET_INSTALLATION:
119 return "get_installation";
120 case CMD_LOW_POWER_ON:
121 return "low_power_on";
122 case CMD_LOW_POWER_OFF:
123 return "low_power_off";
124 case CMD_GET_LOW_POWER:
125 return "get_low_power";
126 case CMD_GET_LOW_POWER_SLEEP:
127 return "get_low_power_sleep";
128 case CMD_RESET_UNATTENDED:
129 return "reset_unattended";
135static const char *frame_type_name(uint16_t
type) {
141 case TYPE_SET_HOLD_DELAY:
142 return "set_hold_delay";
143 case TYPE_SET_Z_RANGE:
144 return "set_z_range";
145 case TYPE_SET_LOW_POWER_SLEEP:
146 return "set_low_power_sleep";
147 case TYPE_REPORT_TARGET:
148 return "report_target";
149 case TYPE_REPORT_POINT_CLOUD:
150 return "report_point_cloud";
151 case TYPE_REPORT_AREA_PRESENCE:
152 return "report_area_presence";
153 case TYPE_REPORT_INTERFERENCE_AREAS:
154 return "report_interference_areas";
155 case TYPE_REPORT_DETECTION_AREAS:
156 return "report_detection_areas";
157 case TYPE_REPORT_DELAY:
158 return "report_delay";
159 case TYPE_REPORT_SENSITIVITY:
160 return "report_sensitivity";
161 case TYPE_REPORT_TRIGGER:
162 return "report_trigger";
163 case TYPE_REPORT_Z_RANGE:
164 return "report_z_range";
165 case TYPE_REPORT_INSTALLATION:
166 return "report_installation";
167 case TYPE_REPORT_LOW_POWER:
168 return "report_low_power";
169 case TYPE_REPORT_LOW_POWER_SLEEP:
170 return "report_low_power_sleep";
171 case TYPE_REPORT_WORK_MODE:
172 return "report_work_mode";
173 case TYPE_QUERY_VERSION:
174 return "query_version";
180static bool is_expected_control_report(
uint32_t command, uint16_t
type) {
183 return type == TYPE_REPORT_INTERFERENCE_AREAS ||
type == TYPE_REPORT_DETECTION_AREAS;
185 return type == TYPE_REPORT_DELAY;
186 case CMD_GET_SENSITIVITY:
187 return type == TYPE_REPORT_SENSITIVITY;
188 case CMD_GET_TRIGGER:
189 return type == TYPE_REPORT_TRIGGER;
190 case CMD_GET_Z_RANGE:
191 return type == TYPE_REPORT_Z_RANGE;
192 case CMD_GET_INSTALLATION:
193 return type == TYPE_REPORT_INSTALLATION;
194 case CMD_GET_LOW_POWER:
195 case CMD_LOW_POWER_ON:
196 case CMD_LOW_POWER_OFF:
197 return type == TYPE_REPORT_LOW_POWER;
198 case CMD_GET_LOW_POWER_SLEEP:
199 return type == TYPE_REPORT_LOW_POWER_SLEEP;
209 return static_cast<uint32_t>(data[0]) | (
static_cast<uint32_t>(data[1]) << 8) |
210 (
static_cast<uint32_t>(data[2]) << 16) | (
static_cast<uint32_t>(data[3]) << 24);
216 std::memcpy(&value, &
raw,
sizeof(value));
223 std::memcpy(&value, &
raw,
sizeof(value));
228 data[0] = value & 0xFF;
229 data[1] = (value >> 8) & 0xFF;
230 data[2] = (value >> 16) & 0xFF;
231 data[3] = (value >> 24) & 0xFF;
240 std::memcpy(&
raw, &value,
sizeof(
raw));
246 bool point_cloud_configured =
false;
253 this->
max_data_len_ = point_cloud_configured ? DEFAULT_MAX_DATA_LEN_POINT_CLOUD : DEFAULT_MAX_DATA_LEN;
258 this->
mark_failed(LOG_STR(
"Failed to allocate frame buffer"));
267 bool want_target_stream =
false;
270 if (!want_target_stream) {
271 for (
const auto &target : this->
targets_) {
272 if (target.x !=
nullptr || target.y !=
nullptr || target.z !=
nullptr || target.dop_idx !=
nullptr ||
273 target.cluster_id !=
nullptr) {
274 want_target_stream =
true;
280#ifdef USE_BINARY_SENSOR
282 if (!want_target_stream) {
284 if (sensor !=
nullptr) {
285 want_target_stream =
true;
291#ifdef USE_TEXT_SENSOR
298 bool target_display_controlled =
false;
301 target_display_controlled =
true;
310 if (!target_display_controlled) {
315 if (want_target_stream) {
320 bool point_cloud_controlled =
false;
323 point_cloud_controlled =
true;
330 if (!point_cloud_controlled) {
333 bool want_point_cloud =
false;
365 if (want_low_power) {
373 bool want_low_power =
false;
375#ifdef USE_TEXT_SENSOR
378 if (want_low_power) {
382 bool want_area_report =
false;
385 if (area.x_min !=
nullptr || area.x_max !=
nullptr || area.y_min !=
nullptr || area.y_max !=
nullptr ||
386 area.z_min !=
nullptr || area.z_max !=
nullptr) {
387 want_area_report =
true;
391 if (!want_area_report) {
393 if (area.x_min !=
nullptr || area.x_max !=
nullptr || area.y_min !=
nullptr || area.y_max !=
nullptr ||
394 area.z_min !=
nullptr || area.z_max !=
nullptr) {
395 want_area_report =
true;
405 want_area_report =
true;
408 if (want_area_report) {
415#ifdef USE_TEXT_SENSOR
417 this->
queue_command_(TYPE_QUERY_VERSION, VERSION_QUERY_DATA,
sizeof(VERSION_QUERY_DATA));
427 " Max data length: %u",
428 this->
auto_wake_ ? LOG_STR_LITERAL(
"true") : LOG_STR_LITERAL(
"false"),
437 for (
auto &target : this->
targets_) {
438 LOG_SENSOR(
" ",
"Target X", target.x);
439 LOG_SENSOR(
" ",
"Target Y", target.y);
440 LOG_SENSOR(
" ",
"Target Z", target.z);
441 LOG_SENSOR(
" ",
"Target Doppler Index", target.dop_idx);
442 LOG_SENSOR(
" ",
"Target Cluster ID", target.cluster_id);
445 LOG_SENSOR(
" ",
"Interference Area X Min", area.x_min);
446 LOG_SENSOR(
" ",
"Interference Area X Max", area.x_max);
447 LOG_SENSOR(
" ",
"Interference Area Y Min", area.y_min);
448 LOG_SENSOR(
" ",
"Interference Area Y Max", area.y_max);
449 LOG_SENSOR(
" ",
"Interference Area Z Min", area.z_min);
450 LOG_SENSOR(
" ",
"Interference Area Z Max", area.z_max);
453 LOG_SENSOR(
" ",
"Detection Area X Min", area.x_min);
454 LOG_SENSOR(
" ",
"Detection Area X Max", area.x_max);
455 LOG_SENSOR(
" ",
"Detection Area Y Min", area.y_min);
456 LOG_SENSOR(
" ",
"Detection Area Y Max", area.y_max);
457 LOG_SENSOR(
" ",
"Detection Area Z Min", area.z_min);
458 LOG_SENSOR(
" ",
"Detection Area Z Max", area.z_max);
461#ifdef USE_BINARY_SENSOR
463 for (uint8_t i = 0; i < MAX_TARGETS; i++) {
466 for (uint8_t i = 0; i < AREA_COUNT; i++) {
467 LOG_BINARY_SENSOR(
" ",
"Detection Area Presence", this->
area_presence_[i]);
470#ifdef USE_TEXT_SENSOR
501 uint8_t
byte = this->
read();
554 uint8_t expected =
static_cast<uint8_t
>(~this->header_xor_);
555 if (
byte != expected) {
556 ESP_LOGV(TAG,
"Header checksum mismatch");
561 ESP_LOGW(TAG,
"Frame too large: %u", this->
data_len_);
585 uint8_t expected =
static_cast<uint8_t
>(~this->data_xor_);
586 if (
byte == expected) {
589 ESP_LOGV(TAG,
"Data checksum mismatch");
605 ESP_LOGV(TAG,
"Ignoring ACK for command 0x%04X from an earlier attempt (module frame 0x%04X)",
type,
610 ESP_LOGV(TAG,
"ACK for command 0x%04X (module frame 0x%04X)",
type, this->
frame_id_);
628#ifdef ESPHOME_LOG_HAS_VERBOSE
629 const uint32_t active_control_command =
633 if (active_control_command != 0 && is_expected_control_report(active_control_command,
type)) {
634 ESP_LOGV(TAG,
"Received %s (0x%04X) while waiting for %s (0x%02" PRIX32
") ACK", frame_type_name(
type),
type,
635 control_command_name(active_control_command), active_control_command);
640 case TYPE_REPORT_TARGET:
643 case TYPE_REPORT_POINT_CLOUD:
646 case TYPE_REPORT_AREA_PRESENCE:
649 case TYPE_REPORT_INTERFERENCE_AREAS:
652 case TYPE_REPORT_DETECTION_AREAS:
655 case TYPE_REPORT_DELAY:
658 case TYPE_REPORT_SENSITIVITY:
661 case TYPE_REPORT_TRIGGER:
664 case TYPE_REPORT_Z_RANGE:
667 case TYPE_REPORT_INSTALLATION:
670 case TYPE_REPORT_LOW_POWER:
673 case TYPE_REPORT_LOW_POWER_SLEEP:
676 case TYPE_REPORT_WORK_MODE:
679 case TYPE_QUERY_VERSION:
701 uint8_t
count =
static_cast<uint8_t
>(std::min<uint32_t>(reported, MAX_TARGETS));
704 std::array<int32_t, MAX_TARGETS> wire_cluster{};
705 std::array<bool, MAX_TARGETS> wire_placed{};
706 std::array<bool, MAX_TARGETS> slot_seen{};
707 std::array<uint8_t, MAX_TARGETS> slot_wire{};
708 for (uint8_t i = 0; i <
count; i++) {
709 uint16_t cluster_offset = 4 + (i * TARGET_DATA_LEN) + 16;
710 wire_cluster[i] =
static_cast<int32_t
>(
read_u32_le(data + cluster_offset));
712 for (uint8_t i = 0; i <
count; i++) {
713 for (uint8_t s = 0; s < MAX_TARGETS; s++) {
716 wire_placed[i] =
true;
722 for (uint8_t s = 0; s < MAX_TARGETS; s++) {
727 for (uint8_t i = 0; i <
count; i++) {
728 if (wire_placed[i]) {
731 for (uint8_t s = 0; s < MAX_TARGETS; s++) {
751#ifdef USE_BINARY_SENSOR
759 for (uint8_t i = 0; i < MAX_TARGETS; i++) {
763 uint16_t offset = 4 + (slot_wire[i] * TARGET_DATA_LEN);
770 if (target.
x !=
nullptr) {
773 if (target.
y !=
nullptr) {
776 if (target.
z !=
nullptr) {
779 if (target.
dop_idx !=
nullptr) {
795#ifdef USE_BINARY_SENSOR
832 const uint16_t needed = AREA_COUNT * AREA_PRESENCE_ENTRY_LEN;
837 for (uint8_t i = 0; i < AREA_COUNT; i++) {
839 bool present =
state != 0;
841#ifdef USE_BINARY_SENSOR
848#ifdef USE_BINARY_SENSOR
858 uint16_t needed = AREA_COUNT * AREA_DATA_LEN;
862 for (uint8_t i = 0; i < AREA_COUNT; i++) {
863 uint16_t offset = i * AREA_DATA_LEN;
873 if (area.
x_min !=
nullptr)
875 if (area.
x_max !=
nullptr)
877 if (area.
y_min !=
nullptr)
879 if (area.
y_max !=
nullptr)
881 if (area.
z_min !=
nullptr)
883 if (area.
z_max !=
nullptr)
896 bool selected_interference = selected_id < AREA_COUNT;
897 uint8_t selected_index = selected_interference ? selected_id :
static_cast<uint8_t
>(selected_id - AREA_COUNT);
898 if (selected_interference == interference && selected_index == i) {
920 uint8_t value = data[0];
933 uint8_t value = data[0];
959 uint8_t value = data[0];
969 bool enabled = data[0] != 0;
994 const bool low_power = (data[0] == 0);
995#ifdef USE_TEXT_SENSOR
1013#ifdef USE_TEXT_SENSOR
1029#ifdef USE_TEXT_SENSOR
1044 if (number ==
nullptr)
1046 if (std::isnan(value)) {
1060 if (value < min_value || value > max_value) {
1061 ESP_LOGW(TAG,
"'%s': module reported %.1f, clamped to %.1f..%.1f", number->
get_name().
c_str(), value, min_value,
1063 value = std::clamp(value, min_value, max_value);
1072#ifdef USE_TEXT_SENSOR
1075 uint8_t project = data[0];
1076 uint8_t major = data[1];
1077 uint8_t minor = data[2];
1078 uint8_t patch = data[3];
1081 std::snprintf(buf,
sizeof(buf),
"%u.%u.%u", major, minor, patch);
1083 std::snprintf(buf,
sizeof(buf),
"p%u %u.%u.%u", project, major, minor, patch);
1091 if (
len > CMD_MAX_DATA_LEN) {
1092 ESP_LOGW(TAG,
"Command data too large: %u",
len);
1096 ESP_LOGW(TAG,
"Command queue full, dropping command 0x%04X",
type);
1103 if (
len > 0 && data !=
nullptr) {
1104 std::memcpy(cmd.
data.data(), data,
len);
1119 const uint32_t active_control_command =
1124#ifdef ESPHOME_LOG_HAS_VERBOSE
1125 if (active_control_command != 0) {
1126 ESP_LOGV(TAG,
"Retrying %s (0x%02" PRIX32
"), %u attempt(s) remaining",
1127 control_command_name(active_control_command), active_control_command, this->
retries_left_);
1130 ESP_LOGV(TAG,
"Retrying command 0x%04X, %u attempt(s) remaining", this->
active_command_.
type,
1131 this->retries_left_);
1139 if (active_control_command != 0) {
1140 ESP_LOGW(TAG,
"Command 0x%04X subcommand 0x%02" PRIX32
" timed out", this->
active_command_.
type,
1141 active_control_command);
1155 ESP_LOGW(TAG,
"Area read timed out, dropping deferred area apply");
1164 this->
stale_ack_count_ =
static_cast<uint8_t
>(std::min<uint16_t>(owed, 255));
1200 if (
len > CMD_MAX_DATA_LEN) {
1201 ESP_LOGW(TAG,
"Command data too large: %u",
len);
1214 if (len > 0 && data !=
nullptr) {
1242 uint8_t header_xor = 0;
1243 auto write_header = [&](uint8_t b) {
1248 write_header(TF_SOF);
1249 write_header((frame_id >> 8) & 0xFF);
1250 write_header(frame_id & 0xFF);
1251 write_header((
len >> 8) & 0xFF);
1252 write_header(
len & 0xFF);
1253 write_header((
type >> 8) & 0xFF);
1254 write_header(
type & 0xFF);
1256 this->
write_byte(
static_cast<uint8_t
>(~header_xor));
1258 if (
len > 0 && data !=
nullptr) {
1259 uint8_t data_xor = 0;
1260 for (uint8_t i = 0; i <
len; i++) {
1262 data_xor ^= data[i];
1264 this->
write_byte(
static_cast<uint8_t
>(~data_xor));
1287 if (std::isnan(this->
z_min_) || std::isnan(this->
z_max_)) {
1288 ESP_LOGW(TAG,
"Z range not written, other bound unknown");
1293 ESP_LOGW(TAG,
"Z range not written, min above max");
1304 ESP_LOGW(TAG,
"Area ID not selected; ignoring apply");
1307 if (this->
area_id_ >= AREA_ID_COUNT) {
1308 ESP_LOGW(TAG,
"Invalid area id: %u", this->
area_id_);
1312 const bool interference = this->
area_id_ < AREA_COUNT;
1313 const uint8_t index = interference ? this->
area_id_ :
static_cast<uint8_t
>(this->
area_id_ - AREA_COUNT);
1328 if (std::isnan(desired.
x_min) || std::isnan(desired.
x_max) || std::isnan(desired.
y_min) ||
1329 std::isnan(desired.
y_max) || std::isnan(desired.
z_min) || std::isnan(desired.
z_max)) {
1333 ESP_LOGW(TAG,
"Area read not queued; area config left unapplied");
1351 ESP_LOGI(TAG,
"Area config incomplete; requesting current areas before applying");
1392 this->
queue_command_(TYPE_SET_LOW_POWER_SLEEP, data,
sizeof(data));
1427 }
else if (index == 1) {
1429 }
else if (index == 2) {
1436 }
else if (index == 1) {
1438 }
else if (index == 2) {
1445 }
else if (index == 1) {
1450 this->
area_id_ =
static_cast<uint8_t
>(index);
1463 if (std::isnan(edits.
x_min))
1465 if (std::isnan(edits.
x_max))
1467 if (std::isnan(edits.
y_min))
1469 if (std::isnan(edits.
y_max))
1471 if (std::isnan(edits.
z_min))
1473 if (std::isnan(edits.
z_max))
1492 if (area_id >= AREA_ID_COUNT)
1494 const bool interference = area_id < AREA_COUNT;
1495 const uint8_t index = interference ? area_id :
static_cast<uint8_t
>(area_id - AREA_COUNT);
1509 ESP_LOGW(TAG,
"Area %u not written, min above max", area_id);
1512 uint8_t data[AREA_CONFIG_LEN];
1529 const bool interference = area_id < AREA_COUNT;
1530 const uint8_t index = interference ? area_id :
static_cast<uint8_t
>(area_id - AREA_COUNT);
1537 if (area_id == selected_id) {
1552 const uint8_t index =
1569 if (std::isnan(desired.
x_min) || std::isnan(desired.
x_max) || std::isnan(desired.
y_min) ||
1570 std::isnan(desired.
y_max) || std::isnan(desired.
z_min) || std::isnan(desired.
z_max)) {
1574 if (reported_interference == interference) {
1577 ESP_LOGW(TAG,
"Dropping deferred area apply, area report incomplete");
1604 value = AREA_ID_DEFAULT;
1623#ifdef USE_TEXT_SENSOR
1632 pref.value[
sizeof(pref.value) - 1] =
'\0';
1639#ifdef USE_TEXT_SENSOR
1644 std::strncpy(pref.value, value,
sizeof(pref.value) - 1);
1645 pref.value[
sizeof(pref.value) - 1] =
'\0';
1656 if (target.
x !=
nullptr) {
1659 if (target.
y !=
nullptr) {
1662 if (target.
z !=
nullptr) {
1665 if (target.
dop_idx !=
nullptr) {
1731#ifdef USE_BINARY_SENSOR
1732 for (uint8_t i = 0; i < AREA_COUNT; i++) {
1750 for (uint8_t i = 0; i < MAX_TARGETS; i++) {
1757#ifdef USE_BINARY_SENSOR
1774#ifdef USE_BINARY_SENSOR
void mark_failed()
Mark this component as failed.
bool cancel_timeout(const char *name)
Cancel a timeout function.
void set_timeout(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a const char* name.
const StringRef & get_name() const
ESPPreferenceObject make_entity_preference(uint32_t version=0)
Create a preference object for storing this entity's state/settings.
virtual void digital_write(bool value)=0
An STL allocator that uses SPI or internal RAM.
constexpr const char * c_str() const
void publish_state(bool new_state)
Publish a new state to the front-end.
text_sensor::TextSensor * work_mode_text_sensor_
select::Select * area_id_select_
bool queue_area_config_(uint8_t area_id, const AreaConfig &desired)
binary_sensor::BinarySensor * presence_binary_sensor_
number::Number * area_z_min_number_
void handle_target_report_(const uint8_t *data, uint16_t len)
text_sensor::TextSensor * ota_version_text_sensor_
std::array< uint8_t, CMD_MAX_DATA_LEN > wake_scratch_
static constexpr uint8_t CMD_QUEUE_SIZE
void clear_target_state_()
number::Number * area_z_max_number_
static void write_int32_le(uint8_t *data, int32_t value)
bool last_work_mode_low_power_
void set_select_value(SelectType type, size_t index)
void save_area_id_pref_(uint8_t value)
number::Number * z_min_number_
static void write_u32_le(uint8_t *data, uint32_t value)
std::array< PendingCommand, CMD_QUEUE_SIZE > cmd_queue_
bool version_pref_initialized_
static float read_f32_le(const uint8_t *data)
uint32_t wakeup_pulse_ms_
ESPPreferenceObject version_pref_
void handle_installation_report_(const uint8_t *data, uint16_t len)
number::Number * z_max_number_
void set_switch_state(SwitchType type, bool state)
std::array< bool, MAX_TARGETS > last_cluster_id_valid_
std::array< int32_t, MAX_TARGETS > last_cluster_id_
void set_number_value(NumberType type, float value)
void handle_trigger_speed_report_(const uint8_t *data, uint16_t len)
select::Select * installation_select_
bool target_display_enabled_
std::array< AreaSensors, AREA_COUNT > detection_areas_
select::Select * trigger_speed_select_
void init_area_id_pref_()
static uint32_t read_u32_le(const uint8_t *data)
void publish_area_numbers_()
bool target_presence_any_
bool last_work_mode_valid_
void save_version_pref_(const char *value)
number::Number * area_x_max_number_
PendingCommand active_command_
sensor::Sensor * point_count_sensor_
static constexpr uint8_t CMD_MAX_RETRIES
void update_area_numbers_for_id_(uint8_t area_id)
void update_area_numbers_(const AreaConfig &area)
AreaConfig pending_area_updates_
void dump_config() override
uint32_t last_target_count_
std::array< AreaConfig, AREA_COUNT > interference_area_values_
void handle_version_report_(const uint8_t *data, uint16_t len)
static constexpr uint32_t WAKE_BUTTON_TIMEOUT_ID
number::Number * area_y_max_number_
switch_::Switch * target_display_switch_
void send_command_internal_(uint16_t type, const uint8_t *data, uint8_t len, bool track)
static uint16_t read_u16_be(const uint8_t *data)
void handle_area_presence_(const uint8_t *data, uint16_t len)
void publish_number_clamped_(number::Number *number, float value)
select::Select * sensitivity_select_
number::Number * hold_delay_number_
static constexpr uint32_t MODULE_AWAKE_MS
bool area_write_in_flight_
static constexpr uint32_t CMD_FIRST_ACK_TIMEOUT_MS
uint32_t discard_remaining_
void init_version_pref_()
static int32_t read_int32_le(const uint8_t *data)
void handle_area_report_(bool interference, const uint8_t *data, uint16_t len)
std::array< bool, MAX_TARGETS > slot_occupied_
void handle_low_power_report_(const uint8_t *data, uint16_t len)
std::array< AreaConfig, AREA_COUNT > detection_area_values_
static constexpr uint32_t CMD_ACK_TIMEOUT_MS
static constexpr uint32_t AREA_REFRESH_TIMEOUT_ID
bool deferred_apply_pending_
std::array< int32_t, MAX_TARGETS > slot_cluster_
void clear_area_presence_()
std::array< binary_sensor::BinarySensor *, AREA_COUNT > area_presence_
void handle_delay_report_(const uint8_t *data, uint16_t len)
std::array< AreaSensors, AREA_COUNT > interference_areas_
void apply_area_config_()
void handle_sensitivity_report_(const uint8_t *data, uint16_t len)
bool area_id_pref_initialized_
void parse_byte_(uint8_t byte)
bool point_cloud_enabled_
std::array< TargetSensors, MAX_TARGETS > targets_
void handle_frame_(uint16_t type, const uint8_t *data, uint16_t len)
void send_command_(uint16_t type, const uint8_t *data, uint8_t len)
switch_::Switch * low_power_switch_
void restore_deferred_edits_()
sensor::Sensor * target_count_sensor_
switch_::Switch * point_cloud_switch_
std::array< bool, MAX_TARGETS > last_target_presence_
uint32_t last_point_count_
number::Number * area_y_min_number_
void publish_work_mode_(bool low_power)
void write_frame_(uint16_t type, const uint8_t *data, uint8_t len, bool track)
std::array< binary_sensor::BinarySensor *, MAX_TARGETS > target_presence_
void handle_low_power_sleep_report_(const uint8_t *data, uint16_t len)
void handle_work_mode_report_(const uint8_t *data, uint16_t len)
void press_button(ButtonType type)
number::Number * area_x_min_number_
void try_apply_pending_area_(bool reported_interference)
void process_command_queue_()
bool queue_command_(uint16_t type, const uint8_t *data, uint8_t len)
void clear_target_slot_(uint8_t index)
number::Number * low_power_sleep_number_
static constexpr uint32_t STALE_ACK_MAX_AGE_MS
ESPPreferenceObject area_id_pref_
bool send_control_command_(uint32_t command)
void handle_point_cloud_(const uint8_t *data, uint16_t len)
void handle_z_range_report_(const uint8_t *data, uint16_t len)
static void write_f32_le(uint8_t *data, float value)
void update_work_mode_fallback_()
uint32_t last_traffic_ms_
Base-class for all numbers.
void publish_state(float state)
float get_min_value() const
float get_max_value() const
void publish_state(const std::string &state)
void publish_state(float state)
Publish a new state to the front-end.
void publish_state(bool state)
Publish a state to the front-end from the back-end.
optional< bool > get_initial_state_with_restore_mode()
Returns the initial state of the switch, after applying restore mode rules.
void control(bool target_state)
Control this switch using a boolean state value.
void publish_state(const std::string &state)
void write_byte(uint8_t data)
ESPHOME_LOG_TAG(TAG, "ld6002b")
@ GET_LOW_POWER_SLEEP_TIME
void HOT delay(uint32_t ms)
uint32_t IRAM_ATTR HOT millis()
std::array< uint8_t, CMD_MAX_DATA_LEN > data
sensor::Sensor * cluster_id