|
|
|
@@ -137,7 +137,7 @@ static const std::string OP_SIMPLE_MODE_STRING = "Simple";
|
|
|
|
|
// Memory-efficient lookup tables
|
|
|
|
|
struct StringToUint8 {
|
|
|
|
|
const char *str;
|
|
|
|
|
uint8_t value;
|
|
|
|
|
const uint8_t value;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static constexpr StringToUint8 OP_MODE_BY_STR[] = {
|
|
|
|
@@ -155,8 +155,9 @@ static constexpr const char *ERR_MESSAGE[] = {
|
|
|
|
|
// Helper function for lookups
|
|
|
|
|
template<size_t N> uint8_t find_uint8(const StringToUint8 (&arr)[N], const std::string &str) {
|
|
|
|
|
for (const auto &entry : arr) {
|
|
|
|
|
if (str == entry.str)
|
|
|
|
|
if (str == entry.str) {
|
|
|
|
|
return entry.value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0xFF; // Not found
|
|
|
|
|
}
|
|
|
|
@@ -326,15 +327,8 @@ void LD2420Component::revert_config_action() {
|
|
|
|
|
|
|
|
|
|
void LD2420Component::loop() {
|
|
|
|
|
// If there is a active send command do not process it here, the send command call will handle it.
|
|
|
|
|
if (!this->get_cmd_active_()) {
|
|
|
|
|
if (!this->available())
|
|
|
|
|
return;
|
|
|
|
|
static uint8_t buffer[2048];
|
|
|
|
|
static uint8_t rx_data;
|
|
|
|
|
while (this->available()) {
|
|
|
|
|
rx_data = this->read();
|
|
|
|
|
this->readline_(rx_data, buffer, sizeof(buffer));
|
|
|
|
|
}
|
|
|
|
|
while (!this->cmd_active_ && this->available()) {
|
|
|
|
|
this->readline_(this->read(), this->buffer_data_, MAX_LINE_LENGTH);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -365,8 +359,9 @@ void LD2420Component::auto_calibrate_sensitivity() {
|
|
|
|
|
|
|
|
|
|
// Store average and peak values
|
|
|
|
|
this->gate_avg[gate] = sum / CALIBRATE_SAMPLES;
|
|
|
|
|
if (this->gate_peak[gate] < peak)
|
|
|
|
|
if (this->gate_peak[gate] < peak) {
|
|
|
|
|
this->gate_peak[gate] = peak;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t calculated_value =
|
|
|
|
|
(static_cast<uint32_t>(this->gate_peak[gate]) + (move_factor * static_cast<uint32_t>(this->gate_peak[gate])));
|
|
|
|
@@ -403,8 +398,9 @@ void LD2420Component::set_operating_mode(const std::string &state) {
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Set the current data back so we don't have new data that can be applied in error.
|
|
|
|
|
if (this->get_calibration_())
|
|
|
|
|
if (this->get_calibration_()) {
|
|
|
|
|
memcpy(&this->new_config, &this->current_config, sizeof(this->current_config));
|
|
|
|
|
}
|
|
|
|
|
this->set_calibration_(false);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
@@ -414,30 +410,32 @@ void LD2420Component::set_operating_mode(const std::string &state) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LD2420Component::readline_(int rx_data, uint8_t *buffer, int len) {
|
|
|
|
|
static int pos = 0;
|
|
|
|
|
|
|
|
|
|
if (rx_data >= 0) {
|
|
|
|
|
if (pos < len - 1) {
|
|
|
|
|
buffer[pos++] = rx_data;
|
|
|
|
|
buffer[pos] = 0;
|
|
|
|
|
} else {
|
|
|
|
|
pos = 0;
|
|
|
|
|
}
|
|
|
|
|
if (pos >= 4) {
|
|
|
|
|
if (memcmp(&buffer[pos - 4], &CMD_FRAME_FOOTER, sizeof(CMD_FRAME_FOOTER)) == 0) {
|
|
|
|
|
this->set_cmd_active_(false); // Set command state to inactive after responce.
|
|
|
|
|
this->handle_ack_data_(buffer, pos);
|
|
|
|
|
pos = 0;
|
|
|
|
|
} else if ((buffer[pos - 2] == 0x0D && buffer[pos - 1] == 0x0A) &&
|
|
|
|
|
(this->get_mode_() == CMD_SYSTEM_MODE_SIMPLE)) {
|
|
|
|
|
this->handle_simple_mode_(buffer, pos);
|
|
|
|
|
pos = 0;
|
|
|
|
|
} else if ((memcmp(&buffer[pos - 4], &ENERGY_FRAME_FOOTER, sizeof(ENERGY_FRAME_FOOTER)) == 0) &&
|
|
|
|
|
(this->get_mode_() == CMD_SYSTEM_MODE_ENERGY)) {
|
|
|
|
|
this->handle_energy_mode_(buffer, pos);
|
|
|
|
|
pos = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (rx_data < 0) {
|
|
|
|
|
return; // No data available
|
|
|
|
|
}
|
|
|
|
|
if (this->buffer_pos_ < len - 1) {
|
|
|
|
|
buffer[this->buffer_pos_++] = rx_data;
|
|
|
|
|
buffer[this->buffer_pos_] = 0;
|
|
|
|
|
} else {
|
|
|
|
|
// We should never get here, but just in case...
|
|
|
|
|
ESP_LOGW(TAG, "Max command length exceeded; ignoring");
|
|
|
|
|
this->buffer_pos_ = 0;
|
|
|
|
|
}
|
|
|
|
|
if (this->buffer_pos_ < 4) {
|
|
|
|
|
return; // Not enough data to process yet
|
|
|
|
|
}
|
|
|
|
|
if (memcmp(&buffer[this->buffer_pos_ - 4], &CMD_FRAME_FOOTER, sizeof(CMD_FRAME_FOOTER)) == 0) {
|
|
|
|
|
this->cmd_active_ = false; // Set command state to inactive after response
|
|
|
|
|
this->handle_ack_data_(buffer, this->buffer_pos_);
|
|
|
|
|
this->buffer_pos_ = 0;
|
|
|
|
|
} else if ((buffer[this->buffer_pos_ - 2] == 0x0D && buffer[this->buffer_pos_ - 1] == 0x0A) &&
|
|
|
|
|
(this->get_mode_() == CMD_SYSTEM_MODE_SIMPLE)) {
|
|
|
|
|
this->handle_simple_mode_(buffer, this->buffer_pos_);
|
|
|
|
|
this->buffer_pos_ = 0;
|
|
|
|
|
} else if ((memcmp(&buffer[this->buffer_pos_ - 4], &ENERGY_FRAME_FOOTER, sizeof(ENERGY_FRAME_FOOTER)) == 0) &&
|
|
|
|
|
(this->get_mode_() == CMD_SYSTEM_MODE_ENERGY)) {
|
|
|
|
|
this->handle_energy_mode_(buffer, this->buffer_pos_);
|
|
|
|
|
this->buffer_pos_ = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -462,8 +460,9 @@ void LD2420Component::handle_energy_mode_(uint8_t *buffer, int len) {
|
|
|
|
|
|
|
|
|
|
// Resonable refresh rate for home assistant database size health
|
|
|
|
|
const int32_t current_millis = App.get_loop_component_start_time();
|
|
|
|
|
if (current_millis - this->last_periodic_millis < REFRESH_RATE_MS)
|
|
|
|
|
if (current_millis - this->last_periodic_millis < REFRESH_RATE_MS) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
this->last_periodic_millis = current_millis;
|
|
|
|
|
for (auto &listener : this->listeners_) {
|
|
|
|
|
listener->on_distance(this->get_distance_());
|
|
|
|
@@ -506,14 +505,16 @@ void LD2420Component::handle_simple_mode_(const uint8_t *inbuf, int len) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
outbuf[index] = '\0';
|
|
|
|
|
if (index > 1)
|
|
|
|
|
if (index > 1) {
|
|
|
|
|
this->set_distance_(strtol(outbuf, &endptr, 10));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this->get_mode_() == CMD_SYSTEM_MODE_SIMPLE) {
|
|
|
|
|
// Resonable refresh rate for home assistant database size health
|
|
|
|
|
const int32_t current_millis = App.get_loop_component_start_time();
|
|
|
|
|
if (current_millis - this->last_normal_periodic_millis < REFRESH_RATE_MS)
|
|
|
|
|
if (current_millis - this->last_normal_periodic_millis < REFRESH_RATE_MS) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
this->last_normal_periodic_millis = current_millis;
|
|
|
|
|
for (auto &listener : this->listeners_)
|
|
|
|
|
listener->on_distance(this->get_distance_());
|
|
|
|
@@ -593,11 +594,12 @@ void LD2420Component::handle_ack_data_(uint8_t *buffer, int len) {
|
|
|
|
|
int LD2420Component::send_cmd_from_array(CmdFrameT frame) {
|
|
|
|
|
uint32_t start_millis = millis();
|
|
|
|
|
uint8_t error = 0;
|
|
|
|
|
uint8_t ack_buffer[64];
|
|
|
|
|
uint8_t cmd_buffer[64];
|
|
|
|
|
uint8_t ack_buffer[MAX_LINE_LENGTH];
|
|
|
|
|
uint8_t cmd_buffer[MAX_LINE_LENGTH];
|
|
|
|
|
this->cmd_reply_.ack = false;
|
|
|
|
|
if (frame.command != CMD_RESTART)
|
|
|
|
|
this->set_cmd_active_(true); // Restart does not reply, thus no ack state required.
|
|
|
|
|
if (frame.command != CMD_RESTART) {
|
|
|
|
|
this->cmd_active_ = true;
|
|
|
|
|
} // Restart does not reply, thus no ack state required
|
|
|
|
|
uint8_t retry = 3;
|
|
|
|
|
while (retry) {
|
|
|
|
|
frame.length = 0;
|
|
|
|
@@ -619,9 +621,7 @@ int LD2420Component::send_cmd_from_array(CmdFrameT frame) {
|
|
|
|
|
|
|
|
|
|
memcpy(cmd_buffer + frame.length, &frame.footer, sizeof(frame.footer));
|
|
|
|
|
frame.length += sizeof(frame.footer);
|
|
|
|
|
for (uint16_t index = 0; index < frame.length; index++) {
|
|
|
|
|
this->write_byte(cmd_buffer[index]);
|
|
|
|
|
}
|
|
|
|
|
this->write_array(cmd_buffer, frame.length);
|
|
|
|
|
|
|
|
|
|
error = 0;
|
|
|
|
|
if (frame.command == CMD_RESTART) {
|
|
|
|
@@ -630,7 +630,7 @@ int LD2420Component::send_cmd_from_array(CmdFrameT frame) {
|
|
|
|
|
|
|
|
|
|
while (!this->cmd_reply_.ack) {
|
|
|
|
|
while (this->available()) {
|
|
|
|
|
this->readline_(read(), ack_buffer, sizeof(ack_buffer));
|
|
|
|
|
this->readline_(this->read(), ack_buffer, sizeof(ack_buffer));
|
|
|
|
|
}
|
|
|
|
|
delay_microseconds_safe(1450);
|
|
|
|
|
// Wait on an Rx from the LD2420 for up to 3 1 second loops, otherwise it could trigger a WDT.
|
|
|
|
@@ -641,10 +641,12 @@ int LD2420Component::send_cmd_from_array(CmdFrameT frame) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (this->cmd_reply_.ack)
|
|
|
|
|
if (this->cmd_reply_.ack) {
|
|
|
|
|
retry = 0;
|
|
|
|
|
if (this->cmd_reply_.error > 0)
|
|
|
|
|
}
|
|
|
|
|
if (this->cmd_reply_.error > 0) {
|
|
|
|
|
this->handle_cmd_error(error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
@@ -764,8 +766,9 @@ void LD2420Component::set_system_mode(uint16_t mode) {
|
|
|
|
|
cmd_frame.data_length += sizeof(unknown_parm);
|
|
|
|
|
cmd_frame.footer = CMD_FRAME_FOOTER;
|
|
|
|
|
ESP_LOGV(TAG, "Sending write system mode command: %2X", cmd_frame.command);
|
|
|
|
|
if (this->send_cmd_from_array(cmd_frame) == 0)
|
|
|
|
|
if (this->send_cmd_from_array(cmd_frame) == 0) {
|
|
|
|
|
this->set_mode_(mode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LD2420Component::get_firmware_version_() {
|
|
|
|
@@ -840,18 +843,24 @@ void LD2420Component::set_gate_threshold(uint8_t gate) {
|
|
|
|
|
|
|
|
|
|
#ifdef USE_NUMBER
|
|
|
|
|
void LD2420Component::init_gate_config_numbers() {
|
|
|
|
|
if (this->gate_timeout_number_ != nullptr)
|
|
|
|
|
if (this->gate_timeout_number_ != nullptr) {
|
|
|
|
|
this->gate_timeout_number_->publish_state(static_cast<uint16_t>(this->current_config.timeout));
|
|
|
|
|
if (this->gate_select_number_ != nullptr)
|
|
|
|
|
}
|
|
|
|
|
if (this->gate_select_number_ != nullptr) {
|
|
|
|
|
this->gate_select_number_->publish_state(0);
|
|
|
|
|
if (this->min_gate_distance_number_ != nullptr)
|
|
|
|
|
}
|
|
|
|
|
if (this->min_gate_distance_number_ != nullptr) {
|
|
|
|
|
this->min_gate_distance_number_->publish_state(static_cast<uint16_t>(this->current_config.min_gate));
|
|
|
|
|
if (this->max_gate_distance_number_ != nullptr)
|
|
|
|
|
}
|
|
|
|
|
if (this->max_gate_distance_number_ != nullptr) {
|
|
|
|
|
this->max_gate_distance_number_->publish_state(static_cast<uint16_t>(this->current_config.max_gate));
|
|
|
|
|
if (this->gate_move_sensitivity_factor_number_ != nullptr)
|
|
|
|
|
}
|
|
|
|
|
if (this->gate_move_sensitivity_factor_number_ != nullptr) {
|
|
|
|
|
this->gate_move_sensitivity_factor_number_->publish_state(this->gate_move_sensitivity_factor);
|
|
|
|
|
if (this->gate_still_sensitivity_factor_number_ != nullptr)
|
|
|
|
|
}
|
|
|
|
|
if (this->gate_still_sensitivity_factor_number_ != nullptr) {
|
|
|
|
|
this->gate_still_sensitivity_factor_number_->publish_state(this->gate_still_sensitivity_factor);
|
|
|
|
|
}
|
|
|
|
|
for (uint8_t gate = 0; gate < TOTAL_GATES; gate++) {
|
|
|
|
|
if (this->gate_still_threshold_numbers_[gate] != nullptr) {
|
|
|
|
|
this->gate_still_threshold_numbers_[gate]->publish_state(
|
|
|
|
|