17static const char *
const TAG =
"pn532";
22 ESP_LOGW(TAG,
"Error sending version command, trying again");
24 ESP_LOGE(TAG,
"Error sending version command");
32 if (!this->
read_response(PN532_COMMAND_VERSION_DATA, version_data) || version_data.
size() < 3) {
33 ESP_LOGE(TAG,
"Error getting version");
37 ESP_LOGD(TAG,
"Found chip PN5%02X, Firmware v%d.%d", version_data[0], version_data[1], version_data[2]);
40 PN532_COMMAND_SAMCONFIGURATION,
45 ESP_LOGE(TAG,
"No wakeup ack");
51 if (!this->
read_response(PN532_COMMAND_SAMCONFIGURATION, wakeup_result)) {
60 PN532_COMMAND_SAMCONFIGURATION,
71 if (!this->
read_response(PN532_COMMAND_SAMCONFIGURATION, sam_result)) {
72 ESP_LOGV(TAG,
"Invalid SAM result: (%u)", sam_result.
size());
73 for (uint8_t dat : sam_result) {
74 ESP_LOGV(TAG,
" 0x%02X", dat);
87 ESP_LOGI(TAG,
"Powering down PN532");
88 if (!this->
write_command_({PN532_COMMAND_POWERDOWN, 0b10100000})) {
89 ESP_LOGE(TAG,
"Error writing powerdown command to PN532");
93 if (!this->
read_response(PN532_COMMAND_POWERDOWN, response)) {
94 ESP_LOGE(TAG,
"Error reading PN532 powerdown response");
97 if (response.
empty() || response[0] != 0x00) {
98 ESP_LOGE(TAG,
"Powerdown error: %02x", response.
empty() ? 0xFF : response[0]);
101 ESP_LOGV(TAG,
"Powerdown successful");
110#ifdef PN532_BINARY_SENSOR_COUNT
116 PN532_COMMAND_INLISTPASSIVETARGET,
120 ESP_LOGW(TAG,
"Requesting tag read failed!");
136 bool success =
false;
139 if (ready ==
READY) {
140 success = this->
read_response(PN532_COMMAND_INLISTPASSIVETARGET, read);
149#ifdef PN532_ON_TAG_REMOVED_TRIGGER_COUNT
151 auto tag = make_unique<nfc::NfcTag>(this->
current_uid_);
153 trigger->process(tag);
161 uint8_t num_targets = read.
empty() ? 0 : read[0];
162 if (num_targets != 1) {
164#ifdef PN532_ON_TAG_REMOVED_TRIGGER_COUNT
166 auto tag = make_unique<nfc::NfcTag>(this->
current_uid_);
168 trigger->process(tag);
177 if (read.
size() < 6) {
181 const uint8_t sel_res = read[4];
182 uint8_t nfcid_length = read[5];
183 if (nfcid_length == 0 || nfcid_length > nfc::NFC_UID_MAX_LENGTH || read.
size() < 6U + nfcid_length) {
192#ifdef PN532_BINARY_SENSOR_COUNT
194 if (bin_sens->process(nfcid)) {
200 if (nfcid.
size() == this->current_uid_.size()) {
201 bool same_uid =
true;
202 for (
size_t i = 0; i < nfcid.
size(); i++)
211 auto tag = this->
read_tag_(nfcid, tag_type);
212#ifdef PN532_ON_TAG_TRIGGER_COUNT
214 trigger->process(tag);
218 char uid_buf[nfc::FORMAT_UID_BUFFER_SIZE];
220 if (tag->has_ndef_message()) {
221 const auto &
message = tag->get_ndef_message();
222 const auto &records =
message->get_records();
223 ESP_LOGD(TAG,
" NDEF formatted records:");
224 for (
const auto &record : records) {
225 ESP_LOGD(TAG,
" %s - %s", record->get_type().c_str(), record->get_payload().c_str());
230 ESP_LOGD(TAG,
" Tag cleaning");
232 ESP_LOGE(TAG,
" Tag was not fully cleaned successfully");
234 ESP_LOGD(TAG,
" Tag cleaned!");
236 ESP_LOGD(TAG,
" Tag formatting");
238 ESP_LOGE(TAG,
"Error formatting tag as NDEF");
240 ESP_LOGD(TAG,
" Tag formatted!");
243 ESP_LOGD(TAG,
" Tag writing");
244 ESP_LOGD(TAG,
" Tag formatting");
246 ESP_LOGE(TAG,
" Tag could not be formatted for writing");
248 ESP_LOGD(TAG,
" Writing NDEF data");
250 ESP_LOGE(TAG,
" Failed to write message to tag");
252 ESP_LOGD(TAG,
" Finished writing NDEF data");
265 if (data.size() > PN532_FRAME_MAX_DATA_SIZE) {
277 const uint8_t real_length = data.size() + 1;
289 for (uint8_t dat : data) {
305 ESP_LOGV(TAG,
"Reading ACK");
308 if (!this->
read_data(data, 6) || data.size() < 7) {
312 bool matches = (data[1] == 0x00 &&
314 data[3] == 0xFF && data[4] == 0x00 &&
315 data[5] == 0xFF && data[6] == 0x00);
316 ESP_LOGV(TAG,
"ACK valid: %s", YESNO(matches));
321 static constexpr std::array<uint8_t, 6> ACK_FRAME = {0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00};
322 ESP_LOGV(TAG,
"Sending ACK for abort");
327 static constexpr std::array<uint8_t, 6> NACK_FRAME = {0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00};
328 ESP_LOGV(TAG,
"Sending NACK for retransmit");
356 if (now - rd_start_time > 100) {
357 ESP_LOGV(TAG,
"Timed out waiting for readiness from PN532!");
379 ESP_LOGV(TAG,
"Turning RF field OFF");
381 PN532_COMMAND_RFCONFIGURATION,
388 if (tag_type == nfc::TAG_TYPE_MIFARE_CLASSIC) {
389 ESP_LOGD(TAG,
"Mifare classic");
391 }
else if (tag_type == nfc::TAG_TYPE_2) {
392 ESP_LOGD(TAG,
"Mifare ultralight");
395 ESP_LOGV(TAG,
"Reading tag type %u is not supported", tag_type);
396 return make_unique<nfc::NfcTag>(uid);
401 ESP_LOGD(TAG,
"Waiting to read next tag");
405 ESP_LOGD(TAG,
"Waiting to clean next tag");
409 ESP_LOGD(TAG,
"Waiting to format next tag");
414 ESP_LOGD(TAG,
"Waiting to write next tag");
418 if (tag_type == nfc::TAG_TYPE_MIFARE_CLASSIC) {
420 }
else if (tag_type == nfc::TAG_TYPE_2) {
423 ESP_LOGE(TAG,
"Unsupported Tag for formatting");
428 if (tag_type == nfc::TAG_TYPE_MIFARE_CLASSIC) {
430 }
else if (tag_type == nfc::TAG_TYPE_2) {
433 ESP_LOGE(TAG,
"Unsupported Tag for formatting");
438 if (tag_type == nfc::TAG_TYPE_MIFARE_CLASSIC) {
440 }
else if (tag_type == nfc::TAG_TYPE_2) {
443 ESP_LOGE(TAG,
"Unsupported Tag for writing");
454 if (!this->
read_response(PN532_COMMAND_INDATAEXCHANGE, response) || response.
empty()) {
457 if (response[0] != 0x00) {
458 ESP_LOGV(TAG,
"InDataExchange failed, status 0x%02X", response[0]);
461 std::copy(response.
begin() + 1, response.
end(), response.
begin());
470 PN532_COMMAND_INDATAEXCHANGE,
472 nfc::MIFARE_CMD_READ,
476 response.
size() != data.size()) {
479 std::copy(response.
begin(), response.
end(), data.begin());
484 ESP_LOGCONFIG(TAG,
"PN532:");
489 ESP_LOGE(TAG,
"Wake Up command failed!");
492 ESP_LOGE(TAG,
"SAM command failed!");
496 LOG_UPDATE_INTERVAL(
this);
498#ifdef PN532_BINARY_SENSOR_COUNT
500 LOG_BINARY_SENSOR(
" ",
"Tag", child);
506 if (data.size() != this->uid_.size())
509 for (
size_t i = 0; i < data.size(); i++) {
510 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.
void status_set_warning()
void status_clear_warning()
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.
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.