mirror of
https://github.com/esphome/esphome.git
synced 2026-01-24 20:09:12 -07:00
Compare commits
7 Commits
nfc_stv
...
prefs_enca
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8188caaff1 | ||
|
|
42698eedee | ||
|
|
ae57e3e52f | ||
|
|
70f95cb6a8 | ||
|
|
195301f9fc | ||
|
|
dd98b6a3a7 | ||
|
|
139042acbe |
@@ -9,7 +9,7 @@ static const char *const TAG = "bl0940.number";
|
||||
void CalibrationNumber::setup() {
|
||||
float value = 0.0f;
|
||||
if (this->restore_value_) {
|
||||
this->pref_ = global_preferences->make_preference<float>(this->get_preference_hash());
|
||||
this->pref_ = this->make_entity_preference<float>();
|
||||
if (!this->pref_.load(&value)) {
|
||||
value = 0.0f;
|
||||
}
|
||||
|
||||
@@ -360,8 +360,7 @@ void Climate::add_on_control_callback(std::function<void(ClimateCall &)> &&callb
|
||||
static const uint32_t RESTORE_STATE_VERSION = 0x848EA6ADUL;
|
||||
|
||||
optional<ClimateDeviceRestoreState> Climate::restore_state_() {
|
||||
this->rtc_ = global_preferences->make_preference<ClimateDeviceRestoreState>(this->get_preference_hash() ^
|
||||
RESTORE_STATE_VERSION);
|
||||
this->rtc_ = this->make_entity_preference<ClimateDeviceRestoreState>(RESTORE_STATE_VERSION);
|
||||
ClimateDeviceRestoreState recovered{};
|
||||
if (!this->rtc_.load(&recovered))
|
||||
return {};
|
||||
|
||||
@@ -187,7 +187,7 @@ void Cover::publish_state(bool save) {
|
||||
}
|
||||
}
|
||||
optional<CoverRestoreState> Cover::restore_state_() {
|
||||
this->rtc_ = global_preferences->make_preference<CoverRestoreState>(this->get_preference_hash());
|
||||
this->rtc_ = this->make_entity_preference<CoverRestoreState>();
|
||||
CoverRestoreState recovered{};
|
||||
if (!this->rtc_.load(&recovered))
|
||||
return {};
|
||||
|
||||
@@ -41,7 +41,7 @@ void DutyTimeSensor::setup() {
|
||||
uint32_t seconds = 0;
|
||||
|
||||
if (this->restore_) {
|
||||
this->pref_ = global_preferences->make_preference<uint32_t>(this->get_preference_hash());
|
||||
this->pref_ = this->make_entity_preference<uint32_t>();
|
||||
this->pref_.load(&seconds);
|
||||
}
|
||||
|
||||
|
||||
@@ -227,8 +227,7 @@ void Fan::publish_state() {
|
||||
constexpr uint32_t RESTORE_STATE_VERSION = 0x71700ABA;
|
||||
optional<FanRestoreState> Fan::restore_state_() {
|
||||
FanRestoreState recovered{};
|
||||
this->rtc_ =
|
||||
global_preferences->make_preference<FanRestoreState>(this->get_preference_hash() ^ RESTORE_STATE_VERSION);
|
||||
this->rtc_ = this->make_entity_preference<FanRestoreState>(RESTORE_STATE_VERSION);
|
||||
bool restored = this->rtc_.load(&recovered);
|
||||
|
||||
switch (this->restore_mode_) {
|
||||
|
||||
@@ -350,8 +350,7 @@ ClimateTraits HaierClimateBase::traits() { return traits_; }
|
||||
|
||||
void HaierClimateBase::initialization() {
|
||||
constexpr uint32_t restore_settings_version = 0xA77D21EF;
|
||||
this->base_rtc_ =
|
||||
global_preferences->make_preference<HaierBaseSettings>(this->get_preference_hash() ^ restore_settings_version);
|
||||
this->base_rtc_ = this->make_entity_preference<HaierBaseSettings>(restore_settings_version);
|
||||
HaierBaseSettings recovered;
|
||||
if (!this->base_rtc_.load(&recovered)) {
|
||||
recovered = {false, true};
|
||||
|
||||
@@ -515,8 +515,7 @@ haier_protocol::HaierMessage HonClimate::get_power_message(bool state) {
|
||||
void HonClimate::initialization() {
|
||||
HaierClimateBase::initialization();
|
||||
constexpr uint32_t restore_settings_version = 0x57EB59DDUL;
|
||||
this->hon_rtc_ =
|
||||
global_preferences->make_preference<HonSettings>(this->get_preference_hash() ^ restore_settings_version);
|
||||
this->hon_rtc_ = this->make_entity_preference<HonSettings>(restore_settings_version);
|
||||
HonSettings recovered;
|
||||
if (this->hon_rtc_.load(&recovered)) {
|
||||
this->settings_ = recovered;
|
||||
|
||||
@@ -10,7 +10,7 @@ static const char *const TAG = "integration";
|
||||
|
||||
void IntegrationSensor::setup() {
|
||||
if (this->restore_) {
|
||||
this->pref_ = global_preferences->make_preference<float>(this->get_preference_hash());
|
||||
this->pref_ = this->make_entity_preference<float>();
|
||||
float preference_value = 0;
|
||||
this->pref_.load(&preference_value);
|
||||
this->result_ = preference_value;
|
||||
|
||||
@@ -184,7 +184,7 @@ static inline bool validate_header_footer(const uint8_t *header_footer, const ui
|
||||
void LD2450Component::setup() {
|
||||
#ifdef USE_NUMBER
|
||||
if (this->presence_timeout_number_ != nullptr) {
|
||||
this->pref_ = global_preferences->make_preference<float>(this->presence_timeout_number_->get_preference_hash());
|
||||
this->pref_ = this->presence_timeout_number_->make_entity_preference<float>();
|
||||
this->set_presence_timeout();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -44,7 +44,7 @@ void LightState::setup() {
|
||||
case LIGHT_RESTORE_DEFAULT_ON:
|
||||
case LIGHT_RESTORE_INVERTED_DEFAULT_OFF:
|
||||
case LIGHT_RESTORE_INVERTED_DEFAULT_ON:
|
||||
this->rtc_ = global_preferences->make_preference<LightStateRTCState>(this->get_preference_hash());
|
||||
this->rtc_ = this->make_entity_preference<LightStateRTCState>();
|
||||
// Attempt to load from preferences, else fall back to default values
|
||||
if (!this->rtc_.load(&recovered)) {
|
||||
recovered.state = (this->restore_mode_ == LIGHT_RESTORE_DEFAULT_ON ||
|
||||
@@ -57,7 +57,7 @@ void LightState::setup() {
|
||||
break;
|
||||
case LIGHT_RESTORE_AND_OFF:
|
||||
case LIGHT_RESTORE_AND_ON:
|
||||
this->rtc_ = global_preferences->make_preference<LightStateRTCState>(this->get_preference_hash());
|
||||
this->rtc_ = this->make_entity_preference<LightStateRTCState>();
|
||||
this->rtc_.load(&recovered);
|
||||
recovered.state = (this->restore_mode_ == LIGHT_RESTORE_AND_ON);
|
||||
break;
|
||||
|
||||
@@ -21,7 +21,7 @@ class LVGLNumber : public number::Number, public Component {
|
||||
void setup() override {
|
||||
float value = this->value_lambda_();
|
||||
if (this->restore_) {
|
||||
this->pref_ = global_preferences->make_preference<float>(this->get_preference_hash());
|
||||
this->pref_ = this->make_entity_preference<float>();
|
||||
if (this->pref_.load(&value)) {
|
||||
this->control_lambda_(value);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ class LVGLSelect : public select::Select, public Component {
|
||||
this->set_options_();
|
||||
if (this->restore_) {
|
||||
size_t index;
|
||||
this->pref_ = global_preferences->make_preference<size_t>(this->get_preference_hash());
|
||||
this->pref_ = this->make_entity_preference<size_t>();
|
||||
if (this->pref_.load(&index))
|
||||
this->widget_->set_selected_index(index, LV_ANIM_OFF);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ void NfcTagBinarySensor::set_tag_name(const std::string &str) {
|
||||
this->match_tag_name_ = true;
|
||||
}
|
||||
|
||||
void NfcTagBinarySensor::set_uid(const NfcTagUid &uid) { this->uid_ = uid; }
|
||||
void NfcTagBinarySensor::set_uid(const std::vector<uint8_t> &uid) { this->uid_ = uid; }
|
||||
|
||||
bool NfcTagBinarySensor::tag_match_ndef_string(const std::shared_ptr<NdefMessage> &msg) {
|
||||
for (const auto &record : msg->get_records()) {
|
||||
@@ -63,7 +63,7 @@ bool NfcTagBinarySensor::tag_match_tag_name(const std::shared_ptr<NdefMessage> &
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NfcTagBinarySensor::tag_match_uid(const NfcTagUid &data) {
|
||||
bool NfcTagBinarySensor::tag_match_uid(const std::vector<uint8_t> &data) {
|
||||
if (data.size() != this->uid_.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -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 NfcTagUid &uid);
|
||||
void set_uid(const std::vector<uint8_t> &uid);
|
||||
|
||||
bool tag_match_ndef_string(const std::shared_ptr<NdefMessage> &msg);
|
||||
bool tag_match_tag_name(const std::shared_ptr<NdefMessage> &msg);
|
||||
bool tag_match_uid(const NfcTagUid &data);
|
||||
bool tag_match_uid(const std::vector<uint8_t> &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_;
|
||||
NfcTagUid uid_;
|
||||
std::vector<uint8_t> uid_;
|
||||
};
|
||||
|
||||
} // namespace nfc
|
||||
|
||||
@@ -8,23 +8,19 @@ namespace nfc {
|
||||
|
||||
static const char *const TAG = "nfc";
|
||||
|
||||
char *format_uid_to(char *buffer, std::span<const uint8_t> uid) {
|
||||
char *format_uid_to(char *buffer, const std::vector<uint8_t> &uid) {
|
||||
return format_hex_pretty_to(buffer, FORMAT_UID_BUFFER_SIZE, uid.data(), uid.size(), '-');
|
||||
}
|
||||
|
||||
char *format_bytes_to(char *buffer, std::span<const uint8_t> bytes) {
|
||||
char *format_bytes_to(char *buffer, const std::vector<uint8_t> &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(std::span<const uint8_t> uid) {
|
||||
return format_hex_pretty(uid.data(), uid.size(), '-', false); // NOLINT
|
||||
}
|
||||
std::string format_bytes(std::span<const uint8_t> bytes) {
|
||||
return format_hex_pretty(bytes.data(), bytes.size(), ' ', false); // NOLINT
|
||||
}
|
||||
std::string format_uid(const std::vector<uint8_t> &uid) { return format_hex_pretty(uid, '-', false); } // NOLINT
|
||||
std::string format_bytes(const std::vector<uint8_t> &bytes) { return format_hex_pretty(bytes, ' ', false); } // NOLINT
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
uint8_t guess_tag_type(uint8_t uid_length) {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "ndef_record.h"
|
||||
#include "nfc_tag.h"
|
||||
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
namespace esphome {
|
||||
@@ -57,19 +56,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, std::span<const uint8_t> uid);
|
||||
char *format_uid_to(char *buffer, const std::vector<uint8_t> &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, std::span<const uint8_t> bytes);
|
||||
char *format_bytes_to(char *buffer, const std::vector<uint8_t> &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(std::span<const uint8_t> uid);
|
||||
std::string format_uid(const std::vector<uint8_t> &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(std::span<const uint8_t> bytes);
|
||||
std::string format_bytes(const std::vector<uint8_t> &bytes);
|
||||
|
||||
uint8_t guess_tag_type(uint8_t uid_length);
|
||||
uint8_t get_mifare_classic_ndef_start_index(std::vector<uint8_t> &data);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
@@ -9,27 +10,26 @@
|
||||
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<uint8_t, NFC_UID_MAX_LENGTH>;
|
||||
|
||||
class NfcTag {
|
||||
public:
|
||||
NfcTag() { this->tag_type_ = "Unknown"; };
|
||||
NfcTag(NfcTagUid &uid) {
|
||||
NfcTag() {
|
||||
this->uid_ = {};
|
||||
this->tag_type_ = "Unknown";
|
||||
};
|
||||
NfcTag(std::vector<uint8_t> &uid) {
|
||||
this->uid_ = uid;
|
||||
this->tag_type_ = "Unknown";
|
||||
};
|
||||
NfcTag(NfcTagUid &uid, const std::string &tag_type) {
|
||||
NfcTag(std::vector<uint8_t> &uid, const std::string &tag_type) {
|
||||
this->uid_ = uid;
|
||||
this->tag_type_ = tag_type;
|
||||
};
|
||||
NfcTag(NfcTagUid &uid, const std::string &tag_type, std::unique_ptr<nfc::NdefMessage> ndef_message) {
|
||||
NfcTag(std::vector<uint8_t> &uid, const std::string &tag_type, std::unique_ptr<nfc::NdefMessage> ndef_message) {
|
||||
this->uid_ = uid;
|
||||
this->tag_type_ = tag_type;
|
||||
this->ndef_message_ = std::move(ndef_message);
|
||||
};
|
||||
NfcTag(NfcTagUid &uid, const std::string &tag_type, std::vector<uint8_t> &ndef_data) {
|
||||
NfcTag(std::vector<uint8_t> &uid, const std::string &tag_type, std::vector<uint8_t> &ndef_data) {
|
||||
this->uid_ = uid;
|
||||
this->tag_type_ = tag_type;
|
||||
this->ndef_message_ = make_unique<NdefMessage>(ndef_data);
|
||||
@@ -41,14 +41,14 @@ class NfcTag {
|
||||
ndef_message_ = make_unique<NdefMessage>(*rhs.ndef_message_);
|
||||
}
|
||||
|
||||
NfcTagUid &get_uid() { return this->uid_; };
|
||||
std::vector<uint8_t> &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<NdefMessage> &get_ndef_message() { return this->ndef_message_; };
|
||||
void set_ndef_message(std::unique_ptr<NdefMessage> ndef_message) { this->ndef_message_ = std::move(ndef_message); };
|
||||
|
||||
protected:
|
||||
NfcTagUid uid_;
|
||||
std::vector<uint8_t> uid_;
|
||||
std::string tag_type_;
|
||||
std::shared_ptr<NdefMessage> ndef_message_;
|
||||
};
|
||||
|
||||
@@ -14,8 +14,7 @@ void ValueRangeTrigger::setup() {
|
||||
float local_min = this->min_.value(0.0);
|
||||
float local_max = this->max_.value(0.0);
|
||||
convert hash = {.from = (local_max - local_min)};
|
||||
uint32_t myhash = hash.to ^ this->parent_->get_preference_hash();
|
||||
this->rtc_ = global_preferences->make_preference<bool>(myhash);
|
||||
this->rtc_ = this->parent_->make_entity_preference<bool>(hash.to);
|
||||
bool initial_state;
|
||||
if (this->rtc_.load(&initial_state)) {
|
||||
this->previous_in_range_ = initial_state;
|
||||
|
||||
@@ -17,7 +17,7 @@ void OpenthermNumber::setup() {
|
||||
if (!this->restore_value_) {
|
||||
value = this->initial_value_;
|
||||
} else {
|
||||
this->pref_ = global_preferences->make_preference<float>(this->get_preference_hash());
|
||||
this->pref_ = this->make_entity_preference<float>();
|
||||
if (!this->pref_.load(&value)) {
|
||||
if (!std::isnan(this->initial_value_)) {
|
||||
value = this->initial_value_;
|
||||
|
||||
@@ -168,7 +168,7 @@ void PN532::loop() {
|
||||
}
|
||||
|
||||
uint8_t nfcid_length = read[5];
|
||||
nfc::NfcTagUid nfcid(read.begin() + 6, read.begin() + 6 + nfcid_length);
|
||||
std::vector<uint8_t> nfcid(read.begin() + 6, read.begin() + 6 + nfcid_length);
|
||||
if (read.size() < 6U + nfcid_length) {
|
||||
// oops, pn532 returned invalid data
|
||||
return;
|
||||
@@ -358,7 +358,7 @@ void PN532::turn_off_rf_() {
|
||||
});
|
||||
}
|
||||
|
||||
std::unique_ptr<nfc::NfcTag> PN532::read_tag_(nfc::NfcTagUid &uid) {
|
||||
std::unique_ptr<nfc::NfcTag> PN532::read_tag_(std::vector<uint8_t> &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_(nfc::NfcTagUid &uid) {
|
||||
bool PN532::clean_tag_(std::vector<uint8_t> &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_(nfc::NfcTagUid &uid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PN532::format_tag_(nfc::NfcTagUid &uid) {
|
||||
bool PN532::format_tag_(std::vector<uint8_t> &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_(nfc::NfcTagUid &uid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PN532::write_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message) {
|
||||
bool PN532::write_tag_(std::vector<uint8_t> &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(nfc::NfcTagUid &data) {
|
||||
bool PN532BinarySensor::process(std::vector<uint8_t> &data) {
|
||||
if (data.size() != this->uid_.size())
|
||||
return false;
|
||||
|
||||
|
||||
@@ -69,28 +69,28 @@ class PN532 : public PollingComponent {
|
||||
virtual bool read_data(std::vector<uint8_t> &data, uint8_t len) = 0;
|
||||
virtual bool read_response(uint8_t command, std::vector<uint8_t> &data) = 0;
|
||||
|
||||
std::unique_ptr<nfc::NfcTag> read_tag_(nfc::NfcTagUid &uid);
|
||||
std::unique_ptr<nfc::NfcTag> read_tag_(std::vector<uint8_t> &uid);
|
||||
|
||||
bool format_tag_(nfc::NfcTagUid &uid);
|
||||
bool clean_tag_(nfc::NfcTagUid &uid);
|
||||
bool write_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message);
|
||||
bool format_tag_(std::vector<uint8_t> &uid);
|
||||
bool clean_tag_(std::vector<uint8_t> &uid);
|
||||
bool write_tag_(std::vector<uint8_t> &uid, nfc::NdefMessage *message);
|
||||
|
||||
std::unique_ptr<nfc::NfcTag> read_mifare_classic_tag_(nfc::NfcTagUid &uid);
|
||||
std::unique_ptr<nfc::NfcTag> read_mifare_classic_tag_(std::vector<uint8_t> &uid);
|
||||
bool read_mifare_classic_block_(uint8_t block_num, std::vector<uint8_t> &data);
|
||||
bool write_mifare_classic_block_(uint8_t block_num, std::vector<uint8_t> &data);
|
||||
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);
|
||||
bool auth_mifare_classic_block_(std::vector<uint8_t> &uid, uint8_t block_num, uint8_t key_num, const uint8_t *key);
|
||||
bool format_mifare_classic_mifare_(std::vector<uint8_t> &uid);
|
||||
bool format_mifare_classic_ndef_(std::vector<uint8_t> &uid);
|
||||
bool write_mifare_classic_tag_(std::vector<uint8_t> &uid, nfc::NdefMessage *message);
|
||||
|
||||
std::unique_ptr<nfc::NfcTag> read_mifare_ultralight_tag_(nfc::NfcTagUid &uid);
|
||||
std::unique_ptr<nfc::NfcTag> read_mifare_ultralight_tag_(std::vector<uint8_t> &uid);
|
||||
bool read_mifare_ultralight_bytes_(uint8_t start_page, uint16_t num_bytes, std::vector<uint8_t> &data);
|
||||
bool is_mifare_ultralight_formatted_(const std::vector<uint8_t> &page_3_to_6);
|
||||
uint16_t read_mifare_ultralight_capacity_();
|
||||
bool find_mifare_ultralight_ndef_(const std::vector<uint8_t> &page_3_to_6, uint8_t &message_length,
|
||||
uint8_t &message_start_index);
|
||||
bool write_mifare_ultralight_page_(uint8_t page_num, std::vector<uint8_t> &write_data);
|
||||
bool write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message);
|
||||
bool write_mifare_ultralight_tag_(std::vector<uint8_t> &uid, nfc::NdefMessage *message);
|
||||
bool clean_mifare_ultralight_();
|
||||
|
||||
bool updates_enabled_{true};
|
||||
@@ -98,7 +98,7 @@ class PN532 : public PollingComponent {
|
||||
std::vector<PN532BinarySensor *> binary_sensors_;
|
||||
std::vector<nfc::NfcOnTagTrigger *> triggers_ontag_;
|
||||
std::vector<nfc::NfcOnTagTrigger *> triggers_ontagremoved_;
|
||||
nfc::NfcTagUid current_uid_;
|
||||
std::vector<uint8_t> 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 nfc::NfcTagUid &uid) { uid_ = uid; }
|
||||
void set_uid(const std::vector<uint8_t> &uid) { uid_ = uid; }
|
||||
|
||||
bool process(nfc::NfcTagUid &data);
|
||||
bool process(std::vector<uint8_t> &data);
|
||||
|
||||
void on_scan_end() {
|
||||
if (!this->found_) {
|
||||
@@ -130,7 +130,7 @@ class PN532BinarySensor : public binary_sensor::BinarySensor {
|
||||
}
|
||||
|
||||
protected:
|
||||
nfc::NfcTagUid uid_;
|
||||
std::vector<uint8_t> uid_;
|
||||
bool found_{false};
|
||||
};
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace pn532 {
|
||||
|
||||
static const char *const TAG = "pn532.mifare_classic";
|
||||
|
||||
std::unique_ptr<nfc::NfcTag> PN532::read_mifare_classic_tag_(nfc::NfcTagUid &uid) {
|
||||
std::unique_ptr<nfc::NfcTag> PN532::read_mifare_classic_tag_(std::vector<uint8_t> &uid) {
|
||||
uint8_t current_block = 4;
|
||||
uint8_t message_start_index = 0;
|
||||
uint32_t message_length = 0;
|
||||
@@ -82,7 +82,8 @@ bool PN532::read_mifare_classic_block_(uint8_t block_num, std::vector<uint8_t> &
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PN532::auth_mifare_classic_block_(nfc::NfcTagUid &uid, uint8_t block_num, uint8_t key_num, const uint8_t *key) {
|
||||
bool PN532::auth_mifare_classic_block_(std::vector<uint8_t> &uid, uint8_t block_num, uint8_t key_num,
|
||||
const uint8_t *key) {
|
||||
std::vector<uint8_t> data({
|
||||
PN532_COMMAND_INDATAEXCHANGE,
|
||||
0x01, // One card
|
||||
@@ -105,7 +106,7 @@ bool PN532::auth_mifare_classic_block_(nfc::NfcTagUid &uid, uint8_t block_num, u
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PN532::format_mifare_classic_mifare_(nfc::NfcTagUid &uid) {
|
||||
bool PN532::format_mifare_classic_mifare_(std::vector<uint8_t> &uid) {
|
||||
std::vector<uint8_t> blank_buffer(
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
|
||||
std::vector<uint8_t> trailer_buffer(
|
||||
@@ -140,7 +141,7 @@ bool PN532::format_mifare_classic_mifare_(nfc::NfcTagUid &uid) {
|
||||
return !error;
|
||||
}
|
||||
|
||||
bool PN532::format_mifare_classic_ndef_(nfc::NfcTagUid &uid) {
|
||||
bool PN532::format_mifare_classic_ndef_(std::vector<uint8_t> &uid) {
|
||||
std::vector<uint8_t> empty_ndef_message(
|
||||
{0x03, 0x03, 0xD0, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
|
||||
std::vector<uint8_t> blank_block(
|
||||
@@ -215,7 +216,7 @@ bool PN532::write_mifare_classic_block_(uint8_t block_num, std::vector<uint8_t>
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PN532::write_mifare_classic_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message) {
|
||||
bool PN532::write_mifare_classic_tag_(std::vector<uint8_t> &uid, nfc::NdefMessage *message) {
|
||||
auto encoded = message->encode();
|
||||
|
||||
uint32_t message_length = encoded.size();
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace pn532 {
|
||||
|
||||
static const char *const TAG = "pn532.mifare_ultralight";
|
||||
|
||||
std::unique_ptr<nfc::NfcTag> PN532::read_mifare_ultralight_tag_(nfc::NfcTagUid &uid) {
|
||||
std::unique_ptr<nfc::NfcTag> PN532::read_mifare_ultralight_tag_(std::vector<uint8_t> &uid) {
|
||||
std::vector<uint8_t> 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<uint8_t> &page_3_to_6
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PN532::write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message) {
|
||||
bool PN532::write_mifare_ultralight_tag_(std::vector<uint8_t> &uid, nfc::NdefMessage *message) {
|
||||
uint32_t capacity = this->read_mifare_ultralight_capacity_();
|
||||
|
||||
auto encoded = message->encode();
|
||||
|
||||
@@ -478,7 +478,7 @@ uint8_t PN7150::read_endpoint_data_(nfc::NfcTag &tag) {
|
||||
return nfc::STATUS_FAILED;
|
||||
}
|
||||
|
||||
uint8_t PN7150::clean_endpoint_(nfc::NfcTagUid &uid) {
|
||||
uint8_t PN7150::clean_endpoint_(std::vector<uint8_t> &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_(nfc::NfcTagUid &uid) {
|
||||
return nfc::STATUS_FAILED;
|
||||
}
|
||||
|
||||
uint8_t PN7150::format_endpoint_(nfc::NfcTagUid &uid) {
|
||||
uint8_t PN7150::format_endpoint_(std::vector<uint8_t> &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_(nfc::NfcTagUid &uid) {
|
||||
return nfc::STATUS_FAILED;
|
||||
}
|
||||
|
||||
uint8_t PN7150::write_endpoint_(nfc::NfcTagUid &uid, std::shared_ptr<nfc::NdefMessage> &message) {
|
||||
uint8_t PN7150::write_endpoint_(std::vector<uint8_t> &uid, std::shared_ptr<nfc::NdefMessage> &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<nfc::NfcTag> PN7150::build_tag_(const uint8_t mode_tech, const s
|
||||
ESP_LOGE(TAG, "UID length cannot be zero");
|
||||
return nullptr;
|
||||
}
|
||||
nfc::NfcTagUid uid(data.begin() + 3, data.begin() + 3 + uid_length);
|
||||
std::vector<uint8_t> 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<nfc::NfcTag>(uid, tag_type_str);
|
||||
@@ -543,7 +543,7 @@ std::unique_ptr<nfc::NfcTag> PN7150::build_tag_(const uint8_t mode_tech, const s
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
optional<size_t> PN7150::find_tag_uid_(const nfc::NfcTagUid &uid) {
|
||||
optional<size_t> PN7150::find_tag_uid_(const std::vector<uint8_t> &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();
|
||||
|
||||
@@ -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_(nfc::NfcTagUid &uid);
|
||||
uint8_t format_endpoint_(nfc::NfcTagUid &uid);
|
||||
uint8_t write_endpoint_(nfc::NfcTagUid &uid, std::shared_ptr<nfc::NdefMessage> &message);
|
||||
uint8_t clean_endpoint_(std::vector<uint8_t> &uid);
|
||||
uint8_t format_endpoint_(std::vector<uint8_t> &uid);
|
||||
uint8_t write_endpoint_(std::vector<uint8_t> &uid, std::shared_ptr<nfc::NdefMessage> &message);
|
||||
|
||||
std::unique_ptr<nfc::NfcTag> build_tag_(uint8_t mode_tech, const std::vector<uint8_t> &data);
|
||||
optional<size_t> find_tag_uid_(const nfc::NfcTagUid &uid);
|
||||
optional<size_t> find_tag_uid_(const std::vector<uint8_t> &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<uint8_t> &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<uint8_t> &write_data);
|
||||
uint8_t write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, const std::shared_ptr<nfc::NdefMessage> &message);
|
||||
uint8_t write_mifare_ultralight_tag_(std::vector<uint8_t> &uid, const std::shared_ptr<nfc::NdefMessage> &message);
|
||||
uint8_t clean_mifare_ultralight_();
|
||||
|
||||
enum NfcTask : uint8_t {
|
||||
|
||||
@@ -115,7 +115,8 @@ uint8_t PN7150::find_mifare_ultralight_ndef_(const std::vector<uint8_t> &page_3_
|
||||
return nfc::STATUS_FAILED;
|
||||
}
|
||||
|
||||
uint8_t PN7150::write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, const std::shared_ptr<nfc::NdefMessage> &message) {
|
||||
uint8_t PN7150::write_mifare_ultralight_tag_(std::vector<uint8_t> &uid,
|
||||
const std::shared_ptr<nfc::NdefMessage> &message) {
|
||||
uint32_t capacity = this->read_mifare_ultralight_capacity_();
|
||||
|
||||
auto encoded = message->encode();
|
||||
|
||||
@@ -506,7 +506,7 @@ uint8_t PN7160::read_endpoint_data_(nfc::NfcTag &tag) {
|
||||
return nfc::STATUS_FAILED;
|
||||
}
|
||||
|
||||
uint8_t PN7160::clean_endpoint_(nfc::NfcTagUid &uid) {
|
||||
uint8_t PN7160::clean_endpoint_(std::vector<uint8_t> &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_(nfc::NfcTagUid &uid) {
|
||||
return nfc::STATUS_FAILED;
|
||||
}
|
||||
|
||||
uint8_t PN7160::format_endpoint_(nfc::NfcTagUid &uid) {
|
||||
uint8_t PN7160::format_endpoint_(std::vector<uint8_t> &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_(nfc::NfcTagUid &uid) {
|
||||
return nfc::STATUS_FAILED;
|
||||
}
|
||||
|
||||
uint8_t PN7160::write_endpoint_(nfc::NfcTagUid &uid, std::shared_ptr<nfc::NdefMessage> &message) {
|
||||
uint8_t PN7160::write_endpoint_(std::vector<uint8_t> &uid, std::shared_ptr<nfc::NdefMessage> &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<nfc::NfcTag> PN7160::build_tag_(const uint8_t mode_tech, const s
|
||||
ESP_LOGE(TAG, "UID length cannot be zero");
|
||||
return nullptr;
|
||||
}
|
||||
nfc::NfcTagUid uid(data.begin() + 3, data.begin() + 3 + uid_length);
|
||||
std::vector<uint8_t> 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<nfc::NfcTag>(uid, tag_type_str);
|
||||
@@ -571,7 +571,7 @@ std::unique_ptr<nfc::NfcTag> PN7160::build_tag_(const uint8_t mode_tech, const s
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
optional<size_t> PN7160::find_tag_uid_(const nfc::NfcTagUid &uid) {
|
||||
optional<size_t> PN7160::find_tag_uid_(const std::vector<uint8_t> &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();
|
||||
|
||||
@@ -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_(nfc::NfcTagUid &uid);
|
||||
uint8_t format_endpoint_(nfc::NfcTagUid &uid);
|
||||
uint8_t write_endpoint_(nfc::NfcTagUid &uid, std::shared_ptr<nfc::NdefMessage> &message);
|
||||
uint8_t clean_endpoint_(std::vector<uint8_t> &uid);
|
||||
uint8_t format_endpoint_(std::vector<uint8_t> &uid);
|
||||
uint8_t write_endpoint_(std::vector<uint8_t> &uid, std::shared_ptr<nfc::NdefMessage> &message);
|
||||
|
||||
std::unique_ptr<nfc::NfcTag> build_tag_(uint8_t mode_tech, const std::vector<uint8_t> &data);
|
||||
optional<size_t> find_tag_uid_(const nfc::NfcTagUid &uid);
|
||||
optional<size_t> find_tag_uid_(const std::vector<uint8_t> &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<uint8_t> &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<uint8_t> &write_data);
|
||||
uint8_t write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, const std::shared_ptr<nfc::NdefMessage> &message);
|
||||
uint8_t write_mifare_ultralight_tag_(std::vector<uint8_t> &uid, const std::shared_ptr<nfc::NdefMessage> &message);
|
||||
uint8_t clean_mifare_ultralight_();
|
||||
|
||||
enum NfcTask : uint8_t {
|
||||
|
||||
@@ -115,7 +115,8 @@ uint8_t PN7160::find_mifare_ultralight_ndef_(const std::vector<uint8_t> &page_3_
|
||||
return nfc::STATUS_FAILED;
|
||||
}
|
||||
|
||||
uint8_t PN7160::write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, const std::shared_ptr<nfc::NdefMessage> &message) {
|
||||
uint8_t PN7160::write_mifare_ultralight_tag_(std::vector<uint8_t> &uid,
|
||||
const std::shared_ptr<nfc::NdefMessage> &message) {
|
||||
uint32_t capacity = this->read_mifare_ultralight_capacity_();
|
||||
|
||||
auto encoded = message->encode();
|
||||
|
||||
@@ -132,7 +132,7 @@ void RotaryEncoderSensor::setup() {
|
||||
int32_t initial_value = 0;
|
||||
switch (this->restore_mode_) {
|
||||
case ROTARY_ENCODER_RESTORE_DEFAULT_ZERO:
|
||||
this->rtc_ = global_preferences->make_preference<int32_t>(this->get_preference_hash());
|
||||
this->rtc_ = this->make_entity_preference<int32_t>();
|
||||
if (!this->rtc_.load(&initial_value)) {
|
||||
initial_value = 0;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ class ValueRangeTrigger : public Trigger<float>, public Component {
|
||||
template<typename V> void set_max(V max) { this->max_ = max; }
|
||||
|
||||
void setup() override {
|
||||
this->rtc_ = global_preferences->make_preference<bool>(this->parent_->get_preference_hash());
|
||||
this->rtc_ = this->parent_->make_entity_preference<bool>();
|
||||
bool initial_state;
|
||||
if (this->rtc_.load(&initial_state)) {
|
||||
this->previous_in_range_ = initial_state;
|
||||
|
||||
@@ -55,7 +55,7 @@ void SpeakerMediaPlayer::setup() {
|
||||
|
||||
this->media_control_command_queue_ = xQueueCreate(MEDIA_CONTROLS_QUEUE_LENGTH, sizeof(MediaCallCommand));
|
||||
|
||||
this->pref_ = global_preferences->make_preference<VolumeRestoreState>(this->get_preference_hash());
|
||||
this->pref_ = this->make_entity_preference<VolumeRestoreState>();
|
||||
|
||||
VolumeRestoreState volume_restore_state;
|
||||
if (this->pref_.load(&volume_restore_state)) {
|
||||
|
||||
@@ -16,7 +16,7 @@ void SprinklerControllerNumber::setup() {
|
||||
if (!this->restore_value_) {
|
||||
value = this->initial_value_;
|
||||
} else {
|
||||
this->pref_ = global_preferences->make_preference<float>(this->get_preference_hash());
|
||||
this->pref_ = this->make_entity_preference<float>();
|
||||
if (!this->pref_.load(&value)) {
|
||||
if (!std::isnan(this->initial_value_)) {
|
||||
value = this->initial_value_;
|
||||
|
||||
@@ -34,7 +34,7 @@ optional<bool> Switch::get_initial_state() {
|
||||
if (!(restore_mode & RESTORE_MODE_PERSISTENT_MASK))
|
||||
return {};
|
||||
|
||||
this->rtc_ = global_preferences->make_preference<bool>(this->get_preference_hash());
|
||||
this->rtc_ = this->make_entity_preference<bool>();
|
||||
bool initial_state;
|
||||
if (!this->rtc_.load(&initial_state))
|
||||
return {};
|
||||
|
||||
@@ -82,7 +82,7 @@ void TemplateAlarmControlPanel::setup() {
|
||||
this->current_state_ = ACP_STATE_DISARMED;
|
||||
if (this->restore_mode_ == ALARM_CONTROL_PANEL_RESTORE_DEFAULT_DISARMED) {
|
||||
uint8_t value;
|
||||
this->pref_ = global_preferences->make_preference<uint8_t>(this->get_preference_hash());
|
||||
this->pref_ = this->make_entity_preference<uint8_t>();
|
||||
if (this->pref_.load(&value)) {
|
||||
this->current_state_ = static_cast<alarm_control_panel::AlarmControlPanelState>(value);
|
||||
}
|
||||
|
||||
@@ -18,8 +18,7 @@ void TemplateDate::setup() {
|
||||
state = this->initial_value_;
|
||||
} else {
|
||||
datetime::DateEntityRestoreState temp;
|
||||
this->pref_ =
|
||||
global_preferences->make_preference<datetime::DateEntityRestoreState>(194434030U ^ this->get_preference_hash());
|
||||
this->pref_ = this->make_entity_preference<datetime::DateEntityRestoreState>(194434030U);
|
||||
if (this->pref_.load(&temp)) {
|
||||
temp.apply(this);
|
||||
return;
|
||||
|
||||
@@ -18,8 +18,7 @@ void TemplateDateTime::setup() {
|
||||
state = this->initial_value_;
|
||||
} else {
|
||||
datetime::DateTimeEntityRestoreState temp;
|
||||
this->pref_ = global_preferences->make_preference<datetime::DateTimeEntityRestoreState>(
|
||||
194434090U ^ this->get_preference_hash());
|
||||
this->pref_ = this->make_entity_preference<datetime::DateTimeEntityRestoreState>(194434090U);
|
||||
if (this->pref_.load(&temp)) {
|
||||
temp.apply(this);
|
||||
return;
|
||||
|
||||
@@ -18,8 +18,7 @@ void TemplateTime::setup() {
|
||||
state = this->initial_value_;
|
||||
} else {
|
||||
datetime::TimeEntityRestoreState temp;
|
||||
this->pref_ =
|
||||
global_preferences->make_preference<datetime::TimeEntityRestoreState>(194434060U ^ this->get_preference_hash());
|
||||
this->pref_ = this->make_entity_preference<datetime::TimeEntityRestoreState>(194434060U);
|
||||
if (this->pref_.load(&temp)) {
|
||||
temp.apply(this);
|
||||
return;
|
||||
|
||||
@@ -13,7 +13,7 @@ void TemplateNumber::setup() {
|
||||
if (!this->restore_value_) {
|
||||
value = this->initial_value_;
|
||||
} else {
|
||||
this->pref_ = global_preferences->make_preference<float>(this->get_preference_hash());
|
||||
this->pref_ = this->make_entity_preference<float>();
|
||||
if (!this->pref_.load(&value)) {
|
||||
if (!std::isnan(this->initial_value_)) {
|
||||
value = this->initial_value_;
|
||||
|
||||
@@ -11,7 +11,7 @@ void TemplateSelect::setup() {
|
||||
|
||||
size_t index = this->initial_option_index_;
|
||||
if (this->restore_value_) {
|
||||
this->pref_ = global_preferences->make_preference<size_t>(this->get_preference_hash());
|
||||
this->pref_ = this->make_entity_preference<size_t>();
|
||||
size_t restored_index;
|
||||
if (this->pref_.load(&restored_index) && this->has_index(restored_index)) {
|
||||
index = restored_index;
|
||||
|
||||
@@ -20,7 +20,14 @@ void TemplateText::setup() {
|
||||
|
||||
// Need std::string for pref_->setup() to fill from flash
|
||||
std::string value{this->initial_value_ != nullptr ? this->initial_value_ : ""};
|
||||
// For future hash migration: use migrate_entity_preference_() with:
|
||||
// old_key = get_preference_hash() + extra
|
||||
// new_key = get_preference_hash_v2() + extra
|
||||
// See: https://github.com/esphome/backlog/issues/85
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
uint32_t key = this->get_preference_hash();
|
||||
#pragma GCC diagnostic pop
|
||||
key += this->traits.get_min_length() << 2;
|
||||
key += this->traits.get_max_length() << 4;
|
||||
key += fnv1_hash(this->traits.get_pattern_c_str()) << 6;
|
||||
|
||||
@@ -10,7 +10,7 @@ void TotalDailyEnergy::setup() {
|
||||
float initial_value = 0;
|
||||
|
||||
if (this->restore_) {
|
||||
this->pref_ = global_preferences->make_preference<float>(this->get_preference_hash());
|
||||
this->pref_ = this->make_entity_preference<float>();
|
||||
this->pref_.load(&initial_value);
|
||||
}
|
||||
this->publish_state_and_save(initial_value);
|
||||
|
||||
@@ -8,7 +8,7 @@ static const char *const TAG = "tuya.number";
|
||||
|
||||
void TuyaNumber::setup() {
|
||||
if (this->restore_value_) {
|
||||
this->pref_ = global_preferences->make_preference<float>(this->get_preference_hash());
|
||||
this->pref_ = this->make_entity_preference<float>();
|
||||
}
|
||||
|
||||
this->parent_->register_listener(this->number_id_, [this](const TuyaDatapoint &datapoint) {
|
||||
|
||||
@@ -161,7 +161,7 @@ void Valve::publish_state(bool save) {
|
||||
}
|
||||
}
|
||||
optional<ValveRestoreState> Valve::restore_state_() {
|
||||
this->rtc_ = global_preferences->make_preference<ValveRestoreState>(this->get_preference_hash());
|
||||
this->rtc_ = this->make_entity_preference<ValveRestoreState>();
|
||||
ValveRestoreState recovered{};
|
||||
if (!this->rtc_.load(&recovered))
|
||||
return {};
|
||||
|
||||
@@ -146,9 +146,7 @@ void WaterHeaterCall::validate_() {
|
||||
}
|
||||
}
|
||||
|
||||
void WaterHeater::setup() {
|
||||
this->pref_ = global_preferences->make_preference<SavedWaterHeaterState>(this->get_preference_hash());
|
||||
}
|
||||
void WaterHeater::setup() { this->pref_ = this->make_entity_preference<SavedWaterHeaterState>(); }
|
||||
|
||||
void WaterHeater::publish_state() {
|
||||
auto traits = this->get_traits();
|
||||
|
||||
@@ -92,6 +92,45 @@ StringRef EntityBase::get_object_id_to(std::span<char, OBJECT_ID_MAX_LEN> buf) c
|
||||
|
||||
uint32_t EntityBase::get_object_id_hash() { return this->object_id_hash_; }
|
||||
|
||||
// Migrate preference data from old_key to new_key if they differ.
|
||||
// This helper is exposed so callers with custom key computation (like TextPrefs)
|
||||
// can use it for manual migration. See: https://github.com/esphome/backlog/issues/85
|
||||
//
|
||||
// FUTURE IMPLEMENTATION:
|
||||
// This will require raw load/save methods on ESPPreferenceObject that take uint8_t* and size.
|
||||
// void EntityBase::migrate_entity_preference_(size_t size, uint32_t old_key, uint32_t new_key) {
|
||||
// if (old_key == new_key)
|
||||
// return;
|
||||
// auto old_pref = global_preferences->make_preference(size, old_key);
|
||||
// auto new_pref = global_preferences->make_preference(size, new_key);
|
||||
// SmallBufferWithHeapFallback<64> buffer(size);
|
||||
// if (old_pref.load(buffer.data(), size)) {
|
||||
// new_pref.save(buffer.data(), size);
|
||||
// }
|
||||
// }
|
||||
|
||||
ESPPreferenceObject EntityBase::make_entity_preference_(size_t size, uint32_t version) {
|
||||
// This helper centralizes preference creation to enable fixing hash collisions.
|
||||
// See: https://github.com/esphome/backlog/issues/85
|
||||
//
|
||||
// COLLISION PROBLEM: get_preference_hash() uses fnv1_hash on sanitized object_id.
|
||||
// Multiple entity names can sanitize to the same object_id:
|
||||
// - "Living Room" and "living_room" both become "living_room"
|
||||
// - UTF-8 names like "温度" and "湿度" both become "__" (underscores)
|
||||
// This causes entities to overwrite each other's stored preferences.
|
||||
//
|
||||
// FUTURE MIGRATION: When implementing get_preference_hash_v2() that hashes
|
||||
// the original entity name (not sanitized object_id):
|
||||
//
|
||||
// uint32_t old_key = this->get_preference_hash() ^ version;
|
||||
// uint32_t new_key = this->get_preference_hash_v2() ^ version;
|
||||
// this->migrate_entity_preference_(size, old_key, new_key);
|
||||
// return global_preferences->make_preference(size, new_key);
|
||||
//
|
||||
uint32_t key = this->get_preference_hash() ^ version;
|
||||
return global_preferences->make_preference(size, key);
|
||||
}
|
||||
|
||||
std::string EntityBase_DeviceClass::get_device_class() {
|
||||
if (this->device_class_ == nullptr) {
|
||||
return "";
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "string_ref.h"
|
||||
#include "helpers.h"
|
||||
#include "log.h"
|
||||
#include "preferences.h"
|
||||
|
||||
#ifdef USE_DEVICES
|
||||
#include "device.h"
|
||||
@@ -138,7 +139,12 @@ class EntityBase {
|
||||
* from previous versions, so existing single-device configurations will continue to work.
|
||||
*
|
||||
* @return uint32_t The unique hash for preferences, including device_id if available.
|
||||
* @deprecated Use make_entity_preference<T>() instead, or preferences won't be migrated.
|
||||
* See https://github.com/esphome/backlog/issues/85
|
||||
*/
|
||||
ESPDEPRECATED("Use make_entity_preference<T>() instead, or preferences won't be migrated. "
|
||||
"See https://github.com/esphome/backlog/issues/85. Will be removed in 2027.1.0.",
|
||||
"2026.7.0")
|
||||
uint32_t get_preference_hash() {
|
||||
#ifdef USE_DEVICES
|
||||
// Combine object_id_hash with device_id to ensure uniqueness across devices
|
||||
@@ -151,7 +157,19 @@ class EntityBase {
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Create a preference object for storing this entity's state/settings.
|
||||
/// @tparam T The type of data to store (must be trivially copyable)
|
||||
/// @param version Optional version hash XORed with preference key (change when struct layout changes)
|
||||
template<typename T> ESPPreferenceObject make_entity_preference(uint32_t version = 0) {
|
||||
static_assert(std::is_trivially_copyable<T>::value, "T must be trivially copyable");
|
||||
return this->make_entity_preference_(sizeof(T), version);
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Non-template helper for make_entity_preference() to avoid code bloat.
|
||||
/// When preference hash algorithm changes, migration logic goes here.
|
||||
ESPPreferenceObject make_entity_preference_(size_t size, uint32_t version);
|
||||
|
||||
void calc_object_id_();
|
||||
|
||||
StringRef name_;
|
||||
|
||||
@@ -148,25 +148,6 @@ template<typename T, size_t N> class StaticVector {
|
||||
size_t count_{0};
|
||||
|
||||
public:
|
||||
// Default constructor
|
||||
StaticVector() = default;
|
||||
|
||||
// Iterator range constructor
|
||||
template<typename InputIt> StaticVector(InputIt first, InputIt last) {
|
||||
while (first != last && count_ < N) {
|
||||
data_[count_++] = *first++;
|
||||
}
|
||||
}
|
||||
|
||||
// Initializer list constructor
|
||||
StaticVector(std::initializer_list<T> 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) {
|
||||
@@ -174,17 +155,6 @@ template<typename T, size_t N> class StaticVector {
|
||||
}
|
||||
}
|
||||
|
||||
// Clear all elements
|
||||
void clear() { count_ = 0; }
|
||||
|
||||
// Assign from iterator range
|
||||
template<typename InputIt> 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) {
|
||||
|
||||
Reference in New Issue
Block a user