mirror of
https://github.com/esphome/esphome.git
synced 2026-09-30 16:30:22 +00:00
[nfc] Pass tags to triggers by reference and keep the listener list in static storage (#19902)
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
6b465443bc
commit
662c7db222
@@ -7,7 +7,8 @@ nfc_ns = cg.esphome_ns.namespace("nfc")
|
||||
|
||||
Nfcc = nfc_ns.class_("Nfcc")
|
||||
NfcTag = nfc_ns.class_("NfcTag")
|
||||
NfcTagConstRef = NfcTag.operator("ref").operator("const")
|
||||
NfcTagListener = nfc_ns.class_("NfcTagListener")
|
||||
NfcOnTagTrigger = nfc_ns.class_(
|
||||
"NfcOnTagTrigger", automation.Trigger.template(cg.std_string, NfcTag)
|
||||
"NfcOnTagTrigger", automation.Trigger.template(cg.std_string, NfcTagConstRef)
|
||||
)
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
|
||||
namespace esphome::nfc {
|
||||
|
||||
class NfcOnTagTrigger final : public Trigger<std::string, NfcTag> {
|
||||
/// Fires with the formatted UID and the tag itself; the tag is passed by reference so no copy is made per trigger
|
||||
class NfcOnTagTrigger final : public Trigger<std::string, const NfcTag &> {
|
||||
public:
|
||||
void process(const std::unique_ptr<NfcTag> &tag);
|
||||
};
|
||||
|
||||
@@ -20,7 +20,6 @@ NfcTagBinarySensor = nfc_ns.class_(
|
||||
binary_sensor.BinarySensor,
|
||||
cg.Component,
|
||||
NfcTagListener,
|
||||
cg.Parented.template(Nfcc),
|
||||
)
|
||||
|
||||
|
||||
@@ -59,12 +58,15 @@ CONFIG_SCHEMA = cv.All(
|
||||
)
|
||||
|
||||
|
||||
_request_listener_slot = cg.slot_counter("NFC_TAG_LISTENER_COUNT")
|
||||
|
||||
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
var = await binary_sensor.new_binary_sensor(config)
|
||||
await cg.register_component(var, config)
|
||||
await cg.register_parented(var, config[CONF_NFCC_ID])
|
||||
|
||||
hub = await cg.get_variable(config[CONF_NFCC_ID])
|
||||
_request_listener_slot(str(hub))
|
||||
cg.add(hub.register_listener(var))
|
||||
if CONF_NDEF_CONTAINS in config:
|
||||
cg.add(var.set_ndef_match_string(config[CONF_NDEF_CONTAINS]))
|
||||
|
||||
@@ -7,10 +7,7 @@ namespace esphome::nfc {
|
||||
|
||||
static const char *const TAG = "nfc.binary_sensor";
|
||||
|
||||
void NfcTagBinarySensor::setup() {
|
||||
this->parent_->register_listener(this);
|
||||
this->publish_initial_state(false);
|
||||
}
|
||||
void NfcTagBinarySensor::setup() { this->publish_initial_state(false); }
|
||||
|
||||
void NfcTagBinarySensor::dump_config() {
|
||||
std::string match_str = "name";
|
||||
|
||||
@@ -8,10 +8,7 @@
|
||||
|
||||
namespace esphome::nfc {
|
||||
|
||||
class NfcTagBinarySensor final : public binary_sensor::BinarySensor,
|
||||
public Component,
|
||||
public NfcTagListener,
|
||||
public Parented<Nfcc> {
|
||||
class NfcTagBinarySensor final : public binary_sensor::BinarySensor, public Component, public NfcTagListener {
|
||||
public:
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
|
||||
@@ -83,10 +83,12 @@ class NfcTagListener {
|
||||
|
||||
class Nfcc {
|
||||
public:
|
||||
#ifdef NFC_TAG_LISTENER_COUNT
|
||||
void register_listener(NfcTagListener *listener) { this->tag_listeners_.push_back(listener); }
|
||||
|
||||
protected:
|
||||
std::vector<NfcTagListener *> tag_listeners_;
|
||||
StaticVector<NfcTagListener *, NFC_TAG_LISTENER_COUNT> tag_listeners_;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace esphome::nfc
|
||||
|
||||
@@ -4,14 +4,14 @@ namespace esphome::nfc {
|
||||
|
||||
static const char *const TAG = "nfc.helpers";
|
||||
|
||||
bool has_ha_tag_ndef(NfcTag &tag) { return !get_ha_tag_ndef(tag).empty(); }
|
||||
bool has_ha_tag_ndef(const NfcTag &tag) { return !get_ha_tag_ndef(tag).empty(); }
|
||||
|
||||
std::string get_ha_tag_ndef(NfcTag &tag) {
|
||||
std::string get_ha_tag_ndef(const NfcTag &tag) {
|
||||
if (!tag.has_ndef_message()) {
|
||||
return std::string();
|
||||
}
|
||||
auto message = tag.get_ndef_message();
|
||||
auto records = message->get_records();
|
||||
const auto &message = tag.get_ndef_message();
|
||||
const auto &records = message->get_records();
|
||||
for (const auto &record : records) {
|
||||
std::string payload = record->get_payload();
|
||||
size_t pos = payload.find(HA_TAG_ID_PREFIX);
|
||||
|
||||
@@ -8,8 +8,8 @@ static const char HA_TAG_ID_EXT_RECORD_TYPE[] = "android.com:pkg";
|
||||
static const char HA_TAG_ID_EXT_RECORD_PAYLOAD[] = "io.homeassistant.companion.android";
|
||||
static const char HA_TAG_ID_PREFIX[] = "https://www.home-assistant.io/tag/";
|
||||
|
||||
std::string get_ha_tag_ndef(NfcTag &tag);
|
||||
std::string get_ha_tag_ndef(const NfcTag &tag);
|
||||
std::string get_random_ha_tag_ndef();
|
||||
bool has_ha_tag_ndef(NfcTag &tag);
|
||||
bool has_ha_tag_ndef(const NfcTag &tag);
|
||||
|
||||
} // namespace esphome::nfc
|
||||
|
||||
@@ -42,9 +42,10 @@ class NfcTag {
|
||||
}
|
||||
|
||||
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<NdefMessage> &get_ndef_message() { return this->ndef_message_; };
|
||||
const NfcTagUid &get_uid() const { return this->uid_; };
|
||||
const std::string &get_tag_type() const { return this->tag_type_; };
|
||||
bool has_ndef_message() const { return this->ndef_message_ != nullptr; };
|
||||
const std::shared_ptr<NdefMessage> &get_ndef_message() const { return this->ndef_message_; };
|
||||
void set_ndef_message(std::unique_ptr<NdefMessage> ndef_message) { this->ndef_message_ = std::move(ndef_message); };
|
||||
|
||||
protected:
|
||||
|
||||
@@ -66,7 +66,7 @@ async def setup_pn532(var: MockObj, config: ConfigType) -> None:
|
||||
_request_ontag_trigger_slot(str(var))
|
||||
cg.add(var.register_ontag_trigger(trigger))
|
||||
await automation.build_automation(
|
||||
trigger, [(cg.std_string, "x"), (nfc.NfcTag, "tag")], conf
|
||||
trigger, [(cg.std_string, "x"), (nfc.NfcTagConstRef, "tag")], conf
|
||||
)
|
||||
|
||||
for conf in config.get(CONF_ON_TAG_REMOVED, []):
|
||||
@@ -74,7 +74,7 @@ async def setup_pn532(var: MockObj, config: ConfigType) -> None:
|
||||
_request_ontagremoved_trigger_slot(str(var))
|
||||
cg.add(var.register_ontagremoved_trigger(trigger))
|
||||
await automation.build_automation(
|
||||
trigger, [(cg.std_string, "x"), (nfc.NfcTag, "tag")], conf
|
||||
trigger, [(cg.std_string, "x"), (nfc.NfcTagConstRef, "tag")], conf
|
||||
)
|
||||
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
@@ -144,7 +144,7 @@ async def setup_pn71xx(var: MockObj, config: ConfigType) -> None:
|
||||
_request_ontag_trigger_slot(str(var))
|
||||
cg.add(var.register_ontag_trigger(trigger))
|
||||
await automation.build_automation(
|
||||
trigger, [(cg.std_string, "x"), (nfc.NfcTag, "tag")], conf
|
||||
trigger, [(cg.std_string, "x"), (nfc.NfcTagConstRef, "tag")], conf
|
||||
)
|
||||
|
||||
for conf in config.get(CONF_ON_TAG_REMOVED, []):
|
||||
@@ -152,7 +152,7 @@ async def setup_pn71xx(var: MockObj, config: ConfigType) -> None:
|
||||
_request_ontagremoved_trigger_slot(str(var))
|
||||
cg.add(var.register_ontagremoved_trigger(trigger))
|
||||
await automation.build_automation(
|
||||
trigger, [(cg.std_string, "x"), (nfc.NfcTag, "tag")], conf
|
||||
trigger, [(cg.std_string, "x"), (nfc.NfcTagConstRef, "tag")], conf
|
||||
)
|
||||
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
@@ -569,9 +569,11 @@ void PN71xx::erase_tag_(const uint8_t tag_index) {
|
||||
trigger->process(this->discovered_endpoint_[tag_index].tag);
|
||||
}
|
||||
#endif
|
||||
#ifdef NFC_TAG_LISTENER_COUNT
|
||||
for (auto *listener : this->tag_listeners_) {
|
||||
listener->tag_off(*this->discovered_endpoint_[tag_index].tag);
|
||||
}
|
||||
#endif
|
||||
char uid_buf[nfc::FORMAT_UID_BUFFER_SIZE];
|
||||
ESP_LOGI(TAG, "Tag %s removed", nfc::format_uid_to(uid_buf, this->discovered_endpoint_[tag_index].tag->get_uid()));
|
||||
// keep the remaining entries in order; selecting_endpoint_ indexes into this list
|
||||
@@ -908,9 +910,11 @@ void PN71xx::process_rf_intf_activated_oid_(nfc::NciMessage &rx) { // an endpoi
|
||||
trigger->process(working_endpoint.tag);
|
||||
}
|
||||
#endif
|
||||
#ifdef NFC_TAG_LISTENER_COUNT
|
||||
for (auto *listener : this->tag_listeners_) {
|
||||
listener->tag_on(*working_endpoint.tag);
|
||||
}
|
||||
#endif
|
||||
working_endpoint.trig_called = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -141,6 +141,7 @@
|
||||
#define MICRONOVA_LISTENER_COUNT 1
|
||||
#define USE_MICRONOVA_WRITER
|
||||
#define MK2PVROUTER_LISTENER_COUNT 1
|
||||
#define NFC_TAG_LISTENER_COUNT 1
|
||||
#define PN532_BINARY_SENSOR_COUNT 1
|
||||
#define PN532_ON_TAG_REMOVED_TRIGGER_COUNT 1
|
||||
#define PN532_ON_TAG_TRIGGER_COUNT 1
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
pn532_spi:
|
||||
id: pn532_nfcc_spi
|
||||
cs_pin: ${cs_pin}
|
||||
on_tag:
|
||||
then:
|
||||
- delay: 10ms
|
||||
- lambda: |-
|
||||
ESP_LOGD("test", "%s %zu %d %d", tag.get_tag_type().c_str(), tag.get_uid().size(), tag.has_ndef_message(),
|
||||
nfc::has_ha_tag_ndef(tag));
|
||||
on_tag_removed:
|
||||
then:
|
||||
- lambda: ESP_LOGD("test", "%s", tag.get_tag_type().c_str());
|
||||
|
||||
binary_sensor:
|
||||
- platform: pn532
|
||||
|
||||
@@ -24,8 +24,19 @@ pn7160_spi:
|
||||
emulation_message: https://www.home-assistant.io/tag/pulse_ce
|
||||
tag_ttl: 1000ms
|
||||
on_tag:
|
||||
- logger.log: "Tag"
|
||||
then:
|
||||
- delay: 10ms
|
||||
- lambda: |-
|
||||
ESP_LOGD("test", "%s %zu %d %s", tag.get_tag_type().c_str(), tag.get_uid().size(), tag.has_ndef_message(),
|
||||
nfc::get_ha_tag_ndef(tag).c_str());
|
||||
on_tag_removed:
|
||||
- logger.log: "Tag removed"
|
||||
then:
|
||||
- lambda: ESP_LOGD("test", "%s", tag.get_tag_type().c_str());
|
||||
on_emulated_tag_scan:
|
||||
- logger.log: "Tag emulated"
|
||||
|
||||
binary_sensor:
|
||||
- platform: nfc
|
||||
nfcc_id: nfcc_pn7160_spi
|
||||
name: Pulse tag
|
||||
ndef_contains: pulse
|
||||
|
||||
Reference in New Issue
Block a user