From b2474c6de9099ea8f36e84192d3fbfe49c32a7c4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 19:43:52 -1000 Subject: [PATCH] [nfc] Use StaticVector for NFC UID storage to eliminate heap allocation (#13507) --- .../nfc/binary_sensor/nfc_binary_sensor.cpp | 4 +-- .../nfc/binary_sensor/nfc_binary_sensor.h | 6 ++-- esphome/components/nfc/nfc.cpp | 12 ++++--- esphome/components/nfc/nfc.h | 9 ++--- esphome/components/nfc/nfc_tag.h | 21 ++++++------ esphome/components/pn532/pn532.cpp | 14 ++++---- esphome/components/pn532/pn532.h | 30 ++++++++-------- .../components/pn532/pn532_mifare_classic.cpp | 11 +++--- .../pn532/pn532_mifare_ultralight.cpp | 4 +-- esphome/components/pn7150/pn7150.cpp | 10 +++--- esphome/components/pn7150/pn7150.h | 10 +++--- .../pn7150/pn7150_mifare_ultralight.cpp | 3 +- esphome/components/pn7160/pn7160.cpp | 10 +++--- esphome/components/pn7160/pn7160.h | 10 +++--- .../pn7160/pn7160_mifare_ultralight.cpp | 3 +- esphome/core/helpers.h | 34 +++++++++++++++++++ 16 files changed, 114 insertions(+), 77 deletions(-) diff --git a/esphome/components/nfc/binary_sensor/nfc_binary_sensor.cpp b/esphome/components/nfc/binary_sensor/nfc_binary_sensor.cpp index b62b243cc6..524ad5a413 100644 --- a/esphome/components/nfc/binary_sensor/nfc_binary_sensor.cpp +++ b/esphome/components/nfc/binary_sensor/nfc_binary_sensor.cpp @@ -40,7 +40,7 @@ void NfcTagBinarySensor::set_tag_name(const std::string &str) { this->match_tag_name_ = true; } -void NfcTagBinarySensor::set_uid(const std::vector &uid) { this->uid_ = uid; } +void NfcTagBinarySensor::set_uid(const NfcTagUid &uid) { this->uid_ = uid; } bool NfcTagBinarySensor::tag_match_ndef_string(const std::shared_ptr &msg) { for (const auto &record : msg->get_records()) { @@ -63,7 +63,7 @@ bool NfcTagBinarySensor::tag_match_tag_name(const std::shared_ptr & return false; } -bool NfcTagBinarySensor::tag_match_uid(const std::vector &data) { +bool NfcTagBinarySensor::tag_match_uid(const NfcTagUid &data) { if (data.size() != this->uid_.size()) { return false; } diff --git a/esphome/components/nfc/binary_sensor/nfc_binary_sensor.h b/esphome/components/nfc/binary_sensor/nfc_binary_sensor.h index cc313c2f2b..0a7ca0ca76 100644 --- a/esphome/components/nfc/binary_sensor/nfc_binary_sensor.h +++ b/esphome/components/nfc/binary_sensor/nfc_binary_sensor.h @@ -19,11 +19,11 @@ class NfcTagBinarySensor : public binary_sensor::BinarySensor, void set_ndef_match_string(const std::string &str); void set_tag_name(const std::string &str); - void set_uid(const std::vector &uid); + void set_uid(const NfcTagUid &uid); bool tag_match_ndef_string(const std::shared_ptr &msg); bool tag_match_tag_name(const std::shared_ptr &msg); - bool tag_match_uid(const std::vector &data); + bool tag_match_uid(const NfcTagUid &data); void tag_off(NfcTag &tag) override; void tag_on(NfcTag &tag) override; @@ -31,7 +31,7 @@ class NfcTagBinarySensor : public binary_sensor::BinarySensor, protected: bool match_tag_name_{false}; std::string match_string_; - std::vector uid_; + NfcTagUid uid_; }; } // namespace nfc diff --git a/esphome/components/nfc/nfc.cpp b/esphome/components/nfc/nfc.cpp index f60d2671cd..8567b0969a 100644 --- a/esphome/components/nfc/nfc.cpp +++ b/esphome/components/nfc/nfc.cpp @@ -8,19 +8,23 @@ namespace nfc { static const char *const TAG = "nfc"; -char *format_uid_to(char *buffer, const std::vector &uid) { +char *format_uid_to(char *buffer, std::span uid) { return format_hex_pretty_to(buffer, FORMAT_UID_BUFFER_SIZE, uid.data(), uid.size(), '-'); } -char *format_bytes_to(char *buffer, const std::vector &bytes) { +char *format_bytes_to(char *buffer, std::span bytes) { return format_hex_pretty_to(buffer, FORMAT_BYTES_BUFFER_SIZE, bytes.data(), bytes.size(), ' '); } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" // Deprecated wrappers intentionally use heap-allocating version for backward compatibility -std::string format_uid(const std::vector &uid) { return format_hex_pretty(uid, '-', false); } // NOLINT -std::string format_bytes(const std::vector &bytes) { return format_hex_pretty(bytes, ' ', false); } // NOLINT +std::string format_uid(std::span uid) { + return format_hex_pretty(uid.data(), uid.size(), '-', false); // NOLINT +} +std::string format_bytes(std::span bytes) { + return format_hex_pretty(bytes.data(), bytes.size(), ' ', false); // NOLINT +} #pragma GCC diagnostic pop uint8_t guess_tag_type(uint8_t uid_length) { diff --git a/esphome/components/nfc/nfc.h b/esphome/components/nfc/nfc.h index 6568c60a85..5191904833 100644 --- a/esphome/components/nfc/nfc.h +++ b/esphome/components/nfc/nfc.h @@ -6,6 +6,7 @@ #include "ndef_record.h" #include "nfc_tag.h" +#include #include namespace esphome { @@ -56,19 +57,19 @@ static const uint8_t MAD_KEY[6] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}; /// Max UID size is 10 bytes, formatted as "XX-XX-XX-XX-XX-XX-XX-XX-XX-XX\0" = 30 chars static constexpr size_t FORMAT_UID_BUFFER_SIZE = 30; /// Format UID to buffer with '-' separator (e.g., "04-11-22-33"). Returns buffer for inline use. -char *format_uid_to(char *buffer, const std::vector &uid); +char *format_uid_to(char *buffer, std::span uid); /// Buffer size for format_bytes_to (64 bytes max = 192 chars with space separator) static constexpr size_t FORMAT_BYTES_BUFFER_SIZE = 192; /// Format bytes to buffer with ' ' separator (e.g., "04 11 22 33"). Returns buffer for inline use. -char *format_bytes_to(char *buffer, const std::vector &bytes); +char *format_bytes_to(char *buffer, std::span bytes); // Remove before 2026.6.0 ESPDEPRECATED("Use format_uid_to() with stack buffer instead. Removed in 2026.6.0", "2025.12.0") -std::string format_uid(const std::vector &uid); +std::string format_uid(std::span uid); // Remove before 2026.6.0 ESPDEPRECATED("Use format_bytes_to() with stack buffer instead. Removed in 2026.6.0", "2025.12.0") -std::string format_bytes(const std::vector &bytes); +std::string format_bytes(std::span bytes); uint8_t guess_tag_type(uint8_t uid_length); uint8_t get_mifare_classic_ndef_start_index(std::vector &data); diff --git a/esphome/components/nfc/nfc_tag.h b/esphome/components/nfc/nfc_tag.h index 55600c3bd9..0ded4cd6ee 100644 --- a/esphome/components/nfc/nfc_tag.h +++ b/esphome/components/nfc/nfc_tag.h @@ -10,26 +10,27 @@ namespace esphome { namespace nfc { +// NFC UIDs are 4, 7, or 10 bytes depending on tag type +static constexpr size_t NFC_UID_MAX_LENGTH = 10; +using NfcTagUid = StaticVector; + class NfcTag { public: - NfcTag() { - this->uid_ = {}; - this->tag_type_ = "Unknown"; - }; - NfcTag(std::vector &uid) { + NfcTag() { this->tag_type_ = "Unknown"; }; + NfcTag(const NfcTagUid &uid) { this->uid_ = uid; this->tag_type_ = "Unknown"; }; - NfcTag(std::vector &uid, const std::string &tag_type) { + NfcTag(const NfcTagUid &uid, const std::string &tag_type) { this->uid_ = uid; this->tag_type_ = tag_type; }; - NfcTag(std::vector &uid, const std::string &tag_type, std::unique_ptr ndef_message) { + NfcTag(const NfcTagUid &uid, const std::string &tag_type, std::unique_ptr ndef_message) { this->uid_ = uid; this->tag_type_ = tag_type; this->ndef_message_ = std::move(ndef_message); }; - NfcTag(std::vector &uid, const std::string &tag_type, std::vector &ndef_data) { + NfcTag(const NfcTagUid &uid, const std::string &tag_type, std::vector &ndef_data) { this->uid_ = uid; this->tag_type_ = tag_type; this->ndef_message_ = make_unique(ndef_data); @@ -41,14 +42,14 @@ class NfcTag { ndef_message_ = make_unique(*rhs.ndef_message_); } - std::vector &get_uid() { return this->uid_; }; + NfcTagUid &get_uid() { return this->uid_; }; const std::string &get_tag_type() { return this->tag_type_; }; bool has_ndef_message() { return this->ndef_message_ != nullptr; }; const std::shared_ptr &get_ndef_message() { return this->ndef_message_; }; void set_ndef_message(std::unique_ptr ndef_message) { this->ndef_message_ = std::move(ndef_message); }; protected: - std::vector uid_; + NfcTagUid uid_; std::string tag_type_; std::shared_ptr ndef_message_; }; diff --git a/esphome/components/pn532/pn532.cpp b/esphome/components/pn532/pn532.cpp index 8f0c5581d4..733810c242 100644 --- a/esphome/components/pn532/pn532.cpp +++ b/esphome/components/pn532/pn532.cpp @@ -168,11 +168,11 @@ void PN532::loop() { } uint8_t nfcid_length = read[5]; - std::vector nfcid(read.begin() + 6, read.begin() + 6 + nfcid_length); - if (read.size() < 6U + nfcid_length) { + if (nfcid_length > nfc::NFC_UID_MAX_LENGTH || read.size() < 6U + nfcid_length) { // oops, pn532 returned invalid data return; } + nfc::NfcTagUid nfcid(read.begin() + 6, read.begin() + 6 + nfcid_length); bool report = true; for (auto *bin_sens : this->binary_sensors_) { @@ -358,7 +358,7 @@ void PN532::turn_off_rf_() { }); } -std::unique_ptr PN532::read_tag_(std::vector &uid) { +std::unique_ptr PN532::read_tag_(nfc::NfcTagUid &uid) { uint8_t type = nfc::guess_tag_type(uid.size()); if (type == nfc::TAG_TYPE_MIFARE_CLASSIC) { @@ -393,7 +393,7 @@ void PN532::write_mode(nfc::NdefMessage *message) { ESP_LOGD(TAG, "Waiting to write next tag"); } -bool PN532::clean_tag_(std::vector &uid) { +bool PN532::clean_tag_(nfc::NfcTagUid &uid) { uint8_t type = nfc::guess_tag_type(uid.size()); if (type == nfc::TAG_TYPE_MIFARE_CLASSIC) { return this->format_mifare_classic_mifare_(uid); @@ -404,7 +404,7 @@ bool PN532::clean_tag_(std::vector &uid) { return false; } -bool PN532::format_tag_(std::vector &uid) { +bool PN532::format_tag_(nfc::NfcTagUid &uid) { uint8_t type = nfc::guess_tag_type(uid.size()); if (type == nfc::TAG_TYPE_MIFARE_CLASSIC) { return this->format_mifare_classic_ndef_(uid); @@ -415,7 +415,7 @@ bool PN532::format_tag_(std::vector &uid) { return false; } -bool PN532::write_tag_(std::vector &uid, nfc::NdefMessage *message) { +bool PN532::write_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message) { uint8_t type = nfc::guess_tag_type(uid.size()); if (type == nfc::TAG_TYPE_MIFARE_CLASSIC) { return this->write_mifare_classic_tag_(uid, message); @@ -448,7 +448,7 @@ void PN532::dump_config() { } } -bool PN532BinarySensor::process(std::vector &data) { +bool PN532BinarySensor::process(const nfc::NfcTagUid &data) { if (data.size() != this->uid_.size()) return false; diff --git a/esphome/components/pn532/pn532.h b/esphome/components/pn532/pn532.h index eeb15648fb..488ec4af3b 100644 --- a/esphome/components/pn532/pn532.h +++ b/esphome/components/pn532/pn532.h @@ -69,28 +69,28 @@ class PN532 : public PollingComponent { virtual bool read_data(std::vector &data, uint8_t len) = 0; virtual bool read_response(uint8_t command, std::vector &data) = 0; - std::unique_ptr read_tag_(std::vector &uid); + std::unique_ptr read_tag_(nfc::NfcTagUid &uid); - bool format_tag_(std::vector &uid); - bool clean_tag_(std::vector &uid); - bool write_tag_(std::vector &uid, nfc::NdefMessage *message); + bool format_tag_(nfc::NfcTagUid &uid); + bool clean_tag_(nfc::NfcTagUid &uid); + bool write_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message); - std::unique_ptr read_mifare_classic_tag_(std::vector &uid); + std::unique_ptr read_mifare_classic_tag_(nfc::NfcTagUid &uid); bool read_mifare_classic_block_(uint8_t block_num, std::vector &data); bool write_mifare_classic_block_(uint8_t block_num, std::vector &data); - bool auth_mifare_classic_block_(std::vector &uid, uint8_t block_num, uint8_t key_num, const uint8_t *key); - bool format_mifare_classic_mifare_(std::vector &uid); - bool format_mifare_classic_ndef_(std::vector &uid); - bool write_mifare_classic_tag_(std::vector &uid, nfc::NdefMessage *message); + bool auth_mifare_classic_block_(nfc::NfcTagUid &uid, uint8_t block_num, uint8_t key_num, const uint8_t *key); + bool format_mifare_classic_mifare_(nfc::NfcTagUid &uid); + bool format_mifare_classic_ndef_(nfc::NfcTagUid &uid); + bool write_mifare_classic_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message); - std::unique_ptr read_mifare_ultralight_tag_(std::vector &uid); + std::unique_ptr read_mifare_ultralight_tag_(nfc::NfcTagUid &uid); bool read_mifare_ultralight_bytes_(uint8_t start_page, uint16_t num_bytes, std::vector &data); bool is_mifare_ultralight_formatted_(const std::vector &page_3_to_6); uint16_t read_mifare_ultralight_capacity_(); bool find_mifare_ultralight_ndef_(const std::vector &page_3_to_6, uint8_t &message_length, uint8_t &message_start_index); bool write_mifare_ultralight_page_(uint8_t page_num, std::vector &write_data); - bool write_mifare_ultralight_tag_(std::vector &uid, nfc::NdefMessage *message); + bool write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message); bool clean_mifare_ultralight_(); bool updates_enabled_{true}; @@ -98,7 +98,7 @@ class PN532 : public PollingComponent { std::vector binary_sensors_; std::vector triggers_ontag_; std::vector triggers_ontagremoved_; - std::vector current_uid_; + nfc::NfcTagUid current_uid_; nfc::NdefMessage *next_task_message_to_write_; uint32_t rd_start_time_{0}; enum PN532ReadReady rd_ready_ { WOULDBLOCK }; @@ -118,9 +118,9 @@ class PN532 : public PollingComponent { class PN532BinarySensor : public binary_sensor::BinarySensor { public: - void set_uid(const std::vector &uid) { uid_ = uid; } + void set_uid(const nfc::NfcTagUid &uid) { uid_ = uid; } - bool process(std::vector &data); + bool process(const nfc::NfcTagUid &data); void on_scan_end() { if (!this->found_) { @@ -130,7 +130,7 @@ class PN532BinarySensor : public binary_sensor::BinarySensor { } protected: - std::vector uid_; + nfc::NfcTagUid uid_; bool found_{false}; }; diff --git a/esphome/components/pn532/pn532_mifare_classic.cpp b/esphome/components/pn532/pn532_mifare_classic.cpp index 28ab22e160..b762d5d936 100644 --- a/esphome/components/pn532/pn532_mifare_classic.cpp +++ b/esphome/components/pn532/pn532_mifare_classic.cpp @@ -8,7 +8,7 @@ namespace pn532 { static const char *const TAG = "pn532.mifare_classic"; -std::unique_ptr PN532::read_mifare_classic_tag_(std::vector &uid) { +std::unique_ptr PN532::read_mifare_classic_tag_(nfc::NfcTagUid &uid) { uint8_t current_block = 4; uint8_t message_start_index = 0; uint32_t message_length = 0; @@ -82,8 +82,7 @@ bool PN532::read_mifare_classic_block_(uint8_t block_num, std::vector & return true; } -bool PN532::auth_mifare_classic_block_(std::vector &uid, uint8_t block_num, uint8_t key_num, - const uint8_t *key) { +bool PN532::auth_mifare_classic_block_(nfc::NfcTagUid &uid, uint8_t block_num, uint8_t key_num, const uint8_t *key) { std::vector data({ PN532_COMMAND_INDATAEXCHANGE, 0x01, // One card @@ -106,7 +105,7 @@ bool PN532::auth_mifare_classic_block_(std::vector &uid, uint8_t block_ return true; } -bool PN532::format_mifare_classic_mifare_(std::vector &uid) { +bool PN532::format_mifare_classic_mifare_(nfc::NfcTagUid &uid) { std::vector blank_buffer( {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); std::vector trailer_buffer( @@ -141,7 +140,7 @@ bool PN532::format_mifare_classic_mifare_(std::vector &uid) { return !error; } -bool PN532::format_mifare_classic_ndef_(std::vector &uid) { +bool PN532::format_mifare_classic_ndef_(nfc::NfcTagUid &uid) { std::vector empty_ndef_message( {0x03, 0x03, 0xD0, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); std::vector blank_block( @@ -216,7 +215,7 @@ bool PN532::write_mifare_classic_block_(uint8_t block_num, std::vector return true; } -bool PN532::write_mifare_classic_tag_(std::vector &uid, nfc::NdefMessage *message) { +bool PN532::write_mifare_classic_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message) { auto encoded = message->encode(); uint32_t message_length = encoded.size(); diff --git a/esphome/components/pn532/pn532_mifare_ultralight.cpp b/esphome/components/pn532/pn532_mifare_ultralight.cpp index 0221ba31c5..01e41df5c0 100644 --- a/esphome/components/pn532/pn532_mifare_ultralight.cpp +++ b/esphome/components/pn532/pn532_mifare_ultralight.cpp @@ -8,7 +8,7 @@ namespace pn532 { static const char *const TAG = "pn532.mifare_ultralight"; -std::unique_ptr PN532::read_mifare_ultralight_tag_(std::vector &uid) { +std::unique_ptr PN532::read_mifare_ultralight_tag_(nfc::NfcTagUid &uid) { std::vector data; // pages 3 to 6 contain various info we are interested in -- do one read to grab it all if (!this->read_mifare_ultralight_bytes_(3, nfc::MIFARE_ULTRALIGHT_PAGE_SIZE * nfc::MIFARE_ULTRALIGHT_READ_SIZE, @@ -114,7 +114,7 @@ bool PN532::find_mifare_ultralight_ndef_(const std::vector &page_3_to_6 return false; } -bool PN532::write_mifare_ultralight_tag_(std::vector &uid, nfc::NdefMessage *message) { +bool PN532::write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message) { uint32_t capacity = this->read_mifare_ultralight_capacity_(); auto encoded = message->encode(); diff --git a/esphome/components/pn7150/pn7150.cpp b/esphome/components/pn7150/pn7150.cpp index e1ba3761d4..7bec1e08a9 100644 --- a/esphome/components/pn7150/pn7150.cpp +++ b/esphome/components/pn7150/pn7150.cpp @@ -478,7 +478,7 @@ uint8_t PN7150::read_endpoint_data_(nfc::NfcTag &tag) { return nfc::STATUS_FAILED; } -uint8_t PN7150::clean_endpoint_(std::vector &uid) { +uint8_t PN7150::clean_endpoint_(nfc::NfcTagUid &uid) { uint8_t type = nfc::guess_tag_type(uid.size()); switch (type) { case nfc::TAG_TYPE_MIFARE_CLASSIC: @@ -494,7 +494,7 @@ uint8_t PN7150::clean_endpoint_(std::vector &uid) { return nfc::STATUS_FAILED; } -uint8_t PN7150::format_endpoint_(std::vector &uid) { +uint8_t PN7150::format_endpoint_(nfc::NfcTagUid &uid) { uint8_t type = nfc::guess_tag_type(uid.size()); switch (type) { case nfc::TAG_TYPE_MIFARE_CLASSIC: @@ -510,7 +510,7 @@ uint8_t PN7150::format_endpoint_(std::vector &uid) { return nfc::STATUS_FAILED; } -uint8_t PN7150::write_endpoint_(std::vector &uid, std::shared_ptr &message) { +uint8_t PN7150::write_endpoint_(nfc::NfcTagUid &uid, std::shared_ptr &message) { uint8_t type = nfc::guess_tag_type(uid.size()); switch (type) { case nfc::TAG_TYPE_MIFARE_CLASSIC: @@ -534,7 +534,7 @@ std::unique_ptr PN7150::build_tag_(const uint8_t mode_tech, const s ESP_LOGE(TAG, "UID length cannot be zero"); return nullptr; } - std::vector uid(data.begin() + 3, data.begin() + 3 + uid_length); + nfc::NfcTagUid uid(data.begin() + 3, data.begin() + 3 + uid_length); const auto *tag_type_str = nfc::guess_tag_type(uid_length) == nfc::TAG_TYPE_MIFARE_CLASSIC ? nfc::MIFARE_CLASSIC : nfc::NFC_FORUM_TYPE_2; return make_unique(uid, tag_type_str); @@ -543,7 +543,7 @@ std::unique_ptr PN7150::build_tag_(const uint8_t mode_tech, const s return nullptr; } -optional PN7150::find_tag_uid_(const std::vector &uid) { +optional PN7150::find_tag_uid_(const nfc::NfcTagUid &uid) { if (!this->discovered_endpoint_.empty()) { for (size_t i = 0; i < this->discovered_endpoint_.size(); i++) { auto existing_tag_uid = this->discovered_endpoint_[i].tag->get_uid(); diff --git a/esphome/components/pn7150/pn7150.h b/esphome/components/pn7150/pn7150.h index 42cd7a6ef7..a5dcef9f99 100644 --- a/esphome/components/pn7150/pn7150.h +++ b/esphome/components/pn7150/pn7150.h @@ -203,12 +203,12 @@ class PN7150 : public nfc::Nfcc, public Component { void select_endpoint_(); uint8_t read_endpoint_data_(nfc::NfcTag &tag); - uint8_t clean_endpoint_(std::vector &uid); - uint8_t format_endpoint_(std::vector &uid); - uint8_t write_endpoint_(std::vector &uid, std::shared_ptr &message); + uint8_t clean_endpoint_(nfc::NfcTagUid &uid); + uint8_t format_endpoint_(nfc::NfcTagUid &uid); + uint8_t write_endpoint_(nfc::NfcTagUid &uid, std::shared_ptr &message); std::unique_ptr build_tag_(uint8_t mode_tech, const std::vector &data); - optional find_tag_uid_(const std::vector &uid); + optional find_tag_uid_(const nfc::NfcTagUid &uid); void purge_old_tags_(); void erase_tag_(uint8_t tag_index); @@ -251,7 +251,7 @@ class PN7150 : public nfc::Nfcc, public Component { uint8_t find_mifare_ultralight_ndef_(const std::vector &page_3_to_6, uint8_t &message_length, uint8_t &message_start_index); uint8_t write_mifare_ultralight_page_(uint8_t page_num, std::vector &write_data); - uint8_t write_mifare_ultralight_tag_(std::vector &uid, const std::shared_ptr &message); + uint8_t write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, const std::shared_ptr &message); uint8_t clean_mifare_ultralight_(); enum NfcTask : uint8_t { diff --git a/esphome/components/pn7150/pn7150_mifare_ultralight.cpp b/esphome/components/pn7150/pn7150_mifare_ultralight.cpp index ac15475bad..166065f6c1 100644 --- a/esphome/components/pn7150/pn7150_mifare_ultralight.cpp +++ b/esphome/components/pn7150/pn7150_mifare_ultralight.cpp @@ -115,8 +115,7 @@ uint8_t PN7150::find_mifare_ultralight_ndef_(const std::vector &page_3_ return nfc::STATUS_FAILED; } -uint8_t PN7150::write_mifare_ultralight_tag_(std::vector &uid, - const std::shared_ptr &message) { +uint8_t PN7150::write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, const std::shared_ptr &message) { uint32_t capacity = this->read_mifare_ultralight_capacity_(); auto encoded = message->encode(); diff --git a/esphome/components/pn7160/pn7160.cpp b/esphome/components/pn7160/pn7160.cpp index 1a38dce5fd..28907b8e30 100644 --- a/esphome/components/pn7160/pn7160.cpp +++ b/esphome/components/pn7160/pn7160.cpp @@ -506,7 +506,7 @@ uint8_t PN7160::read_endpoint_data_(nfc::NfcTag &tag) { return nfc::STATUS_FAILED; } -uint8_t PN7160::clean_endpoint_(std::vector &uid) { +uint8_t PN7160::clean_endpoint_(nfc::NfcTagUid &uid) { uint8_t type = nfc::guess_tag_type(uid.size()); switch (type) { case nfc::TAG_TYPE_MIFARE_CLASSIC: @@ -522,7 +522,7 @@ uint8_t PN7160::clean_endpoint_(std::vector &uid) { return nfc::STATUS_FAILED; } -uint8_t PN7160::format_endpoint_(std::vector &uid) { +uint8_t PN7160::format_endpoint_(nfc::NfcTagUid &uid) { uint8_t type = nfc::guess_tag_type(uid.size()); switch (type) { case nfc::TAG_TYPE_MIFARE_CLASSIC: @@ -538,7 +538,7 @@ uint8_t PN7160::format_endpoint_(std::vector &uid) { return nfc::STATUS_FAILED; } -uint8_t PN7160::write_endpoint_(std::vector &uid, std::shared_ptr &message) { +uint8_t PN7160::write_endpoint_(nfc::NfcTagUid &uid, std::shared_ptr &message) { uint8_t type = nfc::guess_tag_type(uid.size()); switch (type) { case nfc::TAG_TYPE_MIFARE_CLASSIC: @@ -562,7 +562,7 @@ std::unique_ptr PN7160::build_tag_(const uint8_t mode_tech, const s ESP_LOGE(TAG, "UID length cannot be zero"); return nullptr; } - std::vector uid(data.begin() + 3, data.begin() + 3 + uid_length); + nfc::NfcTagUid uid(data.begin() + 3, data.begin() + 3 + uid_length); const auto *tag_type_str = nfc::guess_tag_type(uid_length) == nfc::TAG_TYPE_MIFARE_CLASSIC ? nfc::MIFARE_CLASSIC : nfc::NFC_FORUM_TYPE_2; return make_unique(uid, tag_type_str); @@ -571,7 +571,7 @@ std::unique_ptr PN7160::build_tag_(const uint8_t mode_tech, const s return nullptr; } -optional PN7160::find_tag_uid_(const std::vector &uid) { +optional PN7160::find_tag_uid_(const nfc::NfcTagUid &uid) { if (!this->discovered_endpoint_.empty()) { for (size_t i = 0; i < this->discovered_endpoint_.size(); i++) { auto existing_tag_uid = this->discovered_endpoint_[i].tag->get_uid(); diff --git a/esphome/components/pn7160/pn7160.h b/esphome/components/pn7160/pn7160.h index fc00296a71..572fab3351 100644 --- a/esphome/components/pn7160/pn7160.h +++ b/esphome/components/pn7160/pn7160.h @@ -220,12 +220,12 @@ class PN7160 : public nfc::Nfcc, public Component { void select_endpoint_(); uint8_t read_endpoint_data_(nfc::NfcTag &tag); - uint8_t clean_endpoint_(std::vector &uid); - uint8_t format_endpoint_(std::vector &uid); - uint8_t write_endpoint_(std::vector &uid, std::shared_ptr &message); + uint8_t clean_endpoint_(nfc::NfcTagUid &uid); + uint8_t format_endpoint_(nfc::NfcTagUid &uid); + uint8_t write_endpoint_(nfc::NfcTagUid &uid, std::shared_ptr &message); std::unique_ptr build_tag_(uint8_t mode_tech, const std::vector &data); - optional find_tag_uid_(const std::vector &uid); + optional find_tag_uid_(const nfc::NfcTagUid &uid); void purge_old_tags_(); void erase_tag_(uint8_t tag_index); @@ -268,7 +268,7 @@ class PN7160 : public nfc::Nfcc, public Component { uint8_t find_mifare_ultralight_ndef_(const std::vector &page_3_to_6, uint8_t &message_length, uint8_t &message_start_index); uint8_t write_mifare_ultralight_page_(uint8_t page_num, std::vector &write_data); - uint8_t write_mifare_ultralight_tag_(std::vector &uid, const std::shared_ptr &message); + uint8_t write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, const std::shared_ptr &message); uint8_t clean_mifare_ultralight_(); enum NfcTask : uint8_t { diff --git a/esphome/components/pn7160/pn7160_mifare_ultralight.cpp b/esphome/components/pn7160/pn7160_mifare_ultralight.cpp index 584385f113..c473ff48d9 100644 --- a/esphome/components/pn7160/pn7160_mifare_ultralight.cpp +++ b/esphome/components/pn7160/pn7160_mifare_ultralight.cpp @@ -115,8 +115,7 @@ uint8_t PN7160::find_mifare_ultralight_ndef_(const std::vector &page_3_ return nfc::STATUS_FAILED; } -uint8_t PN7160::write_mifare_ultralight_tag_(std::vector &uid, - const std::shared_ptr &message) { +uint8_t PN7160::write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, const std::shared_ptr &message) { uint32_t capacity = this->read_mifare_ultralight_capacity_(); auto encoded = message->encode(); diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 81397668e8..6c5904ef25 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -148,6 +148,25 @@ template class StaticVector { size_t count_{0}; public: + // Default constructor + StaticVector() = default; + + // Iterator range constructor + template StaticVector(InputIt first, InputIt last) { + while (first != last && count_ < N) { + data_[count_++] = *first++; + } + } + + // Initializer list constructor + StaticVector(std::initializer_list init) { + for (const auto &val : init) { + if (count_ >= N) + break; + data_[count_++] = val; + } + } + // Minimal vector-compatible interface - only what we actually use void push_back(const T &value) { if (count_ < N) { @@ -155,6 +174,17 @@ template class StaticVector { } } + // Clear all elements + void clear() { count_ = 0; } + + // Assign from iterator range + template void assign(InputIt first, InputIt last) { + count_ = 0; + while (first != last && count_ < N) { + data_[count_++] = *first++; + } + } + // Return reference to next element and increment count (with bounds checking) T &emplace_next() { if (count_ >= N) { @@ -186,6 +216,10 @@ template class StaticVector { reverse_iterator rend() { return reverse_iterator(begin()); } const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + + // Conversion to std::span for compatibility with span-based APIs + operator std::span() { return std::span(data_.data(), count_); } + operator std::span() const { return std::span(data_.data(), count_); } }; /// Fixed-capacity vector - allocates once at runtime, never reallocates