22 ESP_LOGW(TAG,
"Error sending version command, trying again");
24 this->
mark_failed(LOG_STR(
"Error sending version command"));
31 if (!this->
read_response(PN532_COMMAND_VERSION_DATA, version_data) || version_data.
size() < 3) {
32 this->
mark_failed(LOG_STR(
"Error getting version"));
35 ESP_LOGD(TAG,
"Found chip PN5%02X, Firmware v%d.%d", version_data[0], version_data[1], version_data[2]);
38 PN532_COMMAND_SAMCONFIGURATION,
48 if (!this->
read_response(PN532_COMMAND_SAMCONFIGURATION, wakeup_result)) {
49 this->
mark_failed(LOG_STR(
"Wake Up command failed"));
56 PN532_COMMAND_SAMCONFIGURATION,
66 if (!this->
read_response(PN532_COMMAND_SAMCONFIGURATION, sam_result)) {
67 ESP_LOGV(TAG,
"Invalid SAM result: (%u)", sam_result.
size());
68 for (uint8_t dat : sam_result) {
69 ESP_LOGV(TAG,
" 0x%02X", dat);
81 ESP_LOGI(TAG,
"Powering down PN532");
82 if (!this->
write_command_({PN532_COMMAND_POWERDOWN, 0b10100000})) {
83 ESP_LOGE(TAG,
"Error writing powerdown command to PN532");
87 if (!this->
read_response(PN532_COMMAND_POWERDOWN, response)) {
88 ESP_LOGE(TAG,
"Error reading PN532 powerdown response");
91 if (response.
empty() || response[0] != 0x00) {
92 ESP_LOGE(TAG,
"Powerdown error: %02x", response.
empty() ? 0xFF : response[0]);
95 ESP_LOGV(TAG,
"Powerdown successful");
104#ifdef PN532_BINARY_SENSOR_COUNT
110 PN532_COMMAND_INLISTPASSIVETARGET,
115 ESP_LOGW(TAG,
"Requesting tag read failed!");
129 bool success =
false;
132 if (ready ==
READY) {
133 success = this->
read_response(PN532_COMMAND_INLISTPASSIVETARGET, read);
142#ifdef PN532_ON_TAG_REMOVED_TRIGGER_COUNT
144 auto tag = make_unique<nfc::NfcTag>(this->
current_uid_);
146 trigger->process(tag);
154 uint8_t num_targets = read.
empty() ? 0 : read[0];
155 if (num_targets != 1) {
157#ifdef PN532_ON_TAG_REMOVED_TRIGGER_COUNT
159 auto tag = make_unique<nfc::NfcTag>(this->
current_uid_);
161 trigger->process(tag);
170 if (read.
size() < 6) {
174 const uint8_t sel_res = read[4];
175 uint8_t nfcid_length = read[5];
176 if (nfcid_length == 0 || nfcid_length > nfc::NFC_UID_MAX_LENGTH || read.
size() < 6U + nfcid_length) {
185#ifdef PN532_BINARY_SENSOR_COUNT
187 if (bin_sens->process(nfcid)) {
193 if (nfcid.
size() == this->current_uid_.size()) {
194 bool same_uid =
true;
195 for (
size_t i = 0; i < nfcid.
size(); i++)
204 auto tag = this->
read_tag_(nfcid, tag_type);
205#ifdef PN532_ON_TAG_TRIGGER_COUNT
207 trigger->process(tag);
211 char uid_buf[nfc::FORMAT_UID_BUFFER_SIZE];
213 if (tag->has_ndef_message()) {
214 const auto &
message = tag->get_ndef_message();
215 const auto &records =
message->get_records();
216 ESP_LOGD(TAG,
" NDEF formatted records:");
217 for (
const auto &record : records) {
218 ESP_LOGD(TAG,
" %s - %s", record->get_type().c_str(), record->get_payload().c_str());
223 ESP_LOGD(TAG,
" Tag cleaning");
225 ESP_LOGE(TAG,
" Tag was not fully cleaned successfully");
227 ESP_LOGD(TAG,
" Tag cleaned!");
229 ESP_LOGD(TAG,
" Tag formatting");
231 ESP_LOGE(TAG,
"Error formatting tag as NDEF");
233 ESP_LOGD(TAG,
" Tag formatted!");
236 ESP_LOGD(TAG,
" Tag writing");
237 ESP_LOGD(TAG,
" Tag formatting");
239 ESP_LOGE(TAG,
" Tag could not be formatted for writing");
241 ESP_LOGD(TAG,
" Writing NDEF data");
243 ESP_LOGE(TAG,
" Failed to write message to tag");
245 ESP_LOGD(TAG,
" Finished writing NDEF data");
258 if (data.size() > PN532_FRAME_MAX_DATA_SIZE) {
270 const uint8_t real_length = data.size() + 1;
282 for (uint8_t dat : data) {
298 ESP_LOGV(TAG,
"Reading ACK");
301 if (!this->
read_data(data, 6) || data.size() < 7) {
305 bool matches = (data[1] == 0x00 &&
307 data[3] == 0xFF && data[4] == 0x00 &&
308 data[5] == 0xFF && data[6] == 0x00);
309 ESP_LOGV(TAG,
"ACK valid: %s", YESNO(matches));
314 static constexpr std::array<uint8_t, 6> ACK_FRAME = {0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00};
315 ESP_LOGV(TAG,
"Sending ACK for abort");
320 static constexpr std::array<uint8_t, 6> NACK_FRAME = {0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00};
321 ESP_LOGV(TAG,
"Sending NACK for retransmit");
349 if (now - rd_start_time > 100) {
350 ESP_LOGV(TAG,
"Timed out waiting for readiness from PN532!");
372 ESP_LOGV(TAG,
"Turning RF field OFF");
374 PN532_COMMAND_RFCONFIGURATION,
381 if (tag_type == nfc::TAG_TYPE_MIFARE_CLASSIC) {
382 ESP_LOGD(TAG,
"Mifare classic");
384 }
else if (tag_type == nfc::TAG_TYPE_2) {
385 ESP_LOGD(TAG,
"Mifare ultralight");
388 ESP_LOGV(TAG,
"Reading tag type %u is not supported", tag_type);
389 return make_unique<nfc::NfcTag>(uid);
394 ESP_LOGD(TAG,
"Waiting to read next tag");
398 ESP_LOGD(TAG,
"Waiting to clean next tag");
402 ESP_LOGD(TAG,
"Waiting to format next tag");
407 ESP_LOGD(TAG,
"Waiting to write next tag");
411 if (tag_type == nfc::TAG_TYPE_MIFARE_CLASSIC) {
413 }
else if (tag_type == nfc::TAG_TYPE_2) {
416 ESP_LOGE(TAG,
"Unsupported Tag for formatting");
421 if (tag_type == nfc::TAG_TYPE_MIFARE_CLASSIC) {
423 }
else if (tag_type == nfc::TAG_TYPE_2) {
426 ESP_LOGE(TAG,
"Unsupported Tag for formatting");
431 if (tag_type == nfc::TAG_TYPE_MIFARE_CLASSIC) {
433 }
else if (tag_type == nfc::TAG_TYPE_2) {
436 ESP_LOGE(TAG,
"Unsupported Tag for writing");
447 if (!this->
read_response(PN532_COMMAND_INDATAEXCHANGE, response) || response.
empty()) {
450 if (response[0] != 0x00) {
451 ESP_LOGV(TAG,
"InDataExchange failed, status 0x%02X", response[0]);
454 std::copy(response.
begin() + 1, response.
end(), response.
begin());
463 PN532_COMMAND_INDATAEXCHANGE,
465 nfc::MIFARE_CMD_READ,
469 response.
size() != data.size()) {
472 std::copy(response.
begin(), response.
end(), data.begin());
477 ESP_LOGCONFIG(TAG,
"PN532:");
479 LOG_UPDATE_INTERVAL(
this);
481#ifdef PN532_BINARY_SENSOR_COUNT
483 LOG_BINARY_SENSOR(
" ",
"Tag", child);
489 if (data.size() != this->uid_.size())
492 for (
size_t i = 0; i < data.size(); i++) {
493 if (data[i] != this->
uid_[i])
void feed_wdt()
Feed the task watchdog.
uint32_t IRAM_ATTR HOT get_loop_component_start_time() const
Get the cached time in milliseconds from when the current component started its loop execution.
void mark_failed()
Mark this component as failed.
bool status_comm_result(bool ok)
Clears the warning when ok, else sets it with message (default "Communication failed"); returns ok.
uint32_t update_interval_
Minimal static vector - saves memory by avoiding std::vector overhead.
void push_back(const T &value)
void publish_state(bool new_state)
Publish a new state to the front-end.
bool process(const nfc::NfcTagUid &data)
StaticVector< nfc::NfcOnTagTrigger *, PN532_ON_TAG_REMOVED_TRIGGER_COUNT > triggers_ontagremoved_
nfc::NfcTagUid current_uid_
virtual bool read_data(PN532Frame &data, size_t len)=0
Reads len frame bytes into data behind a leading status byte, so every bus presents the I2C layout.
enum PN532ReadReady read_ready_(bool block)
virtual bool is_read_ready()=0
bool mifare_read_(uint8_t address, MifareReadData &data)
Sends MIFARE READ for address and returns the 16 bytes the tag answers with.
LazyCallbackManager< void()> on_finished_write_callback_
bool format_mifare_classic_mifare_(nfc::NfcTagUid &uid)
std::unique_ptr< nfc::NfcTag > read_mifare_ultralight_tag_(nfc::NfcTagUid &uid)
StaticVector< PN532BinarySensor *, PN532_BINARY_SENSOR_COUNT > binary_sensors_
bool write_command_(std::span< const uint8_t > data)
bool format_mifare_classic_ndef_(nfc::NfcTagUid &uid)
virtual bool read_response(uint8_t command, PN532Frame &data)=0
Reads the response to command; on success data holds only the bytes that follow the response code.
void dump_config() override
bool write_mifare_classic_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message)
std::unique_ptr< nfc::NfcTag > read_mifare_classic_tag_(nfc::NfcTagUid &uid)
std::unique_ptr< nfc::NdefMessage > next_task_message_to_write_
bool clean_mifare_ultralight_()
void write_mode(nfc::NdefMessage *message)
bool write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message)
std::unique_ptr< nfc::NfcTag > read_tag_(nfc::NfcTagUid &uid, uint8_t tag_type)
virtual bool write_data(std::span< const uint8_t > data)=0
bool in_data_exchange_(std::span< const uint8_t > command, PN532Frame &response)
Sends an InDataExchange command and reads the response; returns false unless the status byte reports ...
StaticVector< nfc::NfcOnTagTrigger *, PN532_ON_TAG_TRIGGER_COUNT > triggers_ontag_
bool clean_tag_(nfc::NfcTagUid &uid, uint8_t tag_type)
bool write_tag_(nfc::NfcTagUid &uid, uint8_t tag_type, nfc::NdefMessage *message)
bool format_tag_(nfc::NfcTagUid &uid, uint8_t tag_type)
const LogString * message
char * format_uid_to(char *buffer, std::span< const uint8_t > uid)
Format UID to buffer with '-' separator (e.g., "04-11-22-33"). Returns buffer for inline use.
ESPHOME_LOG_TAG(TAG, "pn532")
uint8_t tag_type_from_sel_res(uint8_t sel_res)
Tag type (nfc::TAG_TYPE_*) from a type A target's SEL_RES byte.
std::array< uint8_t, MIFARE_READ_SIZE > MifareReadData
void HOT delay(uint32_t ms)
uint32_t IRAM_ATTR HOT millis()
Application App
Global storage of Application pointer - only one Application can exist.