diff --git a/esphome/components/hlk_fm22x/hlk_fm22x.cpp b/esphome/components/hlk_fm22x/hlk_fm22x.cpp index c0f14c7105..c2e6e1f703 100644 --- a/esphome/components/hlk_fm22x/hlk_fm22x.cpp +++ b/esphome/components/hlk_fm22x/hlk_fm22x.cpp @@ -1,16 +1,12 @@ #include "hlk_fm22x.h" #include "esphome/core/log.h" #include "esphome/core/helpers.h" -#include #include namespace esphome::hlk_fm22x { static const char *const TAG = "hlk_fm22x"; -// Maximum response size is 36 bytes (VERIFY reply: face_id + 32-byte name) -static constexpr size_t HLK_FM22X_MAX_RESPONSE_SIZE = 36; - void HlkFm22xComponent::setup() { ESP_LOGCONFIG(TAG, "Setting up HLK-FM22X..."); this->set_enrolling_(false); @@ -35,7 +31,7 @@ void HlkFm22xComponent::update() { } void HlkFm22xComponent::enroll_face(const std::string &name, HlkFm22xFaceDirection direction) { - if (name.length() > 31) { + if (name.length() > HLK_FM22X_NAME_SIZE - 1) { ESP_LOGE(TAG, "enroll_face(): name too long '%s'", name.c_str()); return; } @@ -137,17 +133,21 @@ void HlkFm22xComponent::recv_command_() { checksum ^= byte; length |= byte; - std::vector data; - data.reserve(length); + if (length > HLK_FM22X_MAX_RESPONSE_SIZE) { + ESP_LOGE(TAG, "Response too large: %u bytes", length); + return; + } + for (uint16_t idx = 0; idx < length; ++idx) { byte = this->read(); checksum ^= byte; - data.push_back(byte); + this->recv_buf_[idx] = byte; } #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE char hex_buf[format_hex_pretty_size(HLK_FM22X_MAX_RESPONSE_SIZE)]; - ESP_LOGV(TAG, "Recv type: 0x%.2X, data: %s", response_type, format_hex_pretty_to(hex_buf, data.data(), data.size())); + ESP_LOGV(TAG, "Recv type: 0x%.2X, data: %s", response_type, + format_hex_pretty_to(hex_buf, this->recv_buf_.data(), length)); #endif byte = this->read(); @@ -157,10 +157,10 @@ void HlkFm22xComponent::recv_command_() { } switch (response_type) { case HlkFm22xResponseType::NOTE: - this->handle_note_(data); + this->handle_note_(this->recv_buf_.data(), length); break; case HlkFm22xResponseType::REPLY: - this->handle_reply_(data); + this->handle_reply_(this->recv_buf_.data(), length); break; default: ESP_LOGW(TAG, "Unexpected response type: 0x%.2X", response_type); @@ -168,11 +168,11 @@ void HlkFm22xComponent::recv_command_() { } } -void HlkFm22xComponent::handle_note_(const std::vector &data) { +void HlkFm22xComponent::handle_note_(const uint8_t *data, size_t length) { switch (data[0]) { case HlkFm22xNoteType::FACE_STATE: - if (data.size() < 17) { - ESP_LOGE(TAG, "Invalid face note data size: %u", data.size()); + if (length < 17) { + ESP_LOGE(TAG, "Invalid face note data size: %u", length); break; } { @@ -209,7 +209,7 @@ void HlkFm22xComponent::handle_note_(const std::vector &data) { } } -void HlkFm22xComponent::handle_reply_(const std::vector &data) { +void HlkFm22xComponent::handle_reply_(const uint8_t *data, size_t length) { auto expected = this->active_command_; this->active_command_ = HlkFm22xCommand::NONE; if (data[0] != (uint8_t) expected) { @@ -239,15 +239,15 @@ void HlkFm22xComponent::handle_reply_(const std::vector &data) { switch (expected) { case HlkFm22xCommand::VERIFY: { int16_t face_id = ((int16_t) data[2] << 8) | data[3]; - std::string name(data.begin() + 4, data.begin() + 36); - ESP_LOGD(TAG, "Face verified. ID: %d, name: %s", face_id, name.c_str()); + const char *name_ptr = reinterpret_cast(data + 4); + ESP_LOGD(TAG, "Face verified. ID: %d, name: %.*s", face_id, HLK_FM22X_NAME_SIZE, name_ptr); if (this->last_face_id_sensor_ != nullptr) { this->last_face_id_sensor_->publish_state(face_id); } if (this->last_face_name_text_sensor_ != nullptr) { - this->last_face_name_text_sensor_->publish_state(name); + this->last_face_name_text_sensor_->publish_state(name_ptr, HLK_FM22X_NAME_SIZE); } - this->face_scan_matched_callback_.call(face_id, name); + this->face_scan_matched_callback_.call(face_id, std::string(name_ptr, HLK_FM22X_NAME_SIZE)); break; } case HlkFm22xCommand::ENROLL: { @@ -267,8 +267,7 @@ void HlkFm22xComponent::handle_reply_(const std::vector &data) { break; case HlkFm22xCommand::GET_VERSION: if (this->version_text_sensor_ != nullptr) { - std::string version(data.begin() + 2, data.end()); - this->version_text_sensor_->publish_state(version); + this->version_text_sensor_->publish_state(reinterpret_cast(data + 2), length - 2); } this->defer([this]() { this->get_face_count_(); }); break; diff --git a/esphome/components/hlk_fm22x/hlk_fm22x.h b/esphome/components/hlk_fm22x/hlk_fm22x.h index 9c981d3c44..ff81d82ac2 100644 --- a/esphome/components/hlk_fm22x/hlk_fm22x.h +++ b/esphome/components/hlk_fm22x/hlk_fm22x.h @@ -7,12 +7,15 @@ #include "esphome/components/text_sensor/text_sensor.h" #include "esphome/components/uart/uart.h" +#include #include -#include namespace esphome::hlk_fm22x { static const uint16_t START_CODE = 0xEFAA; +static constexpr size_t HLK_FM22X_NAME_SIZE = 32; +// Maximum response size is 36 bytes (VERIFY reply: face_id + 32-byte name) +static constexpr size_t HLK_FM22X_MAX_RESPONSE_SIZE = 36; enum HlkFm22xCommand { NONE = 0x00, RESET = 0x10, @@ -118,10 +121,11 @@ class HlkFm22xComponent : public PollingComponent, public uart::UARTDevice { void get_face_count_(); void send_command_(HlkFm22xCommand command, const uint8_t *data = nullptr, size_t size = 0); void recv_command_(); - void handle_note_(const std::vector &data); - void handle_reply_(const std::vector &data); + void handle_note_(const uint8_t *data, size_t length); + void handle_reply_(const uint8_t *data, size_t length); void set_enrolling_(bool enrolling); + std::array recv_buf_; HlkFm22xCommand active_command_ = HlkFm22xCommand::NONE; uint16_t wait_cycles_ = 0; sensor::Sensor *face_count_sensor_{nullptr};