diff --git a/esphome/components/nfc/nfc.cpp b/esphome/components/nfc/nfc.cpp index cf5a7f5ef1..71ef842b37 100644 --- a/esphome/components/nfc/nfc.cpp +++ b/esphome/components/nfc/nfc.cpp @@ -31,11 +31,36 @@ std::string format_bytes(std::vector &bytes) { return std::string(buf); } -uint8_t guess_tag_type(uint8_t uid_length) { +uint8_t is_ntag(const std::vector &first_page) { + // NTAG typically has a capability container (CC) starting at byte 3 + // The CC for NTAG is usually 0xE1 0x10 followed by a type-specific byte + if (first_page.size() >= 16 && first_page[3] == 0xE1 && first_page[4] == 0x10) { + switch (first_page[5]) { + case 0x11: + return TAG_TYPE_NTAG_213; + case 0x12: + return TAG_TYPE_NTAG_215; + case 0x13: + return TAG_TYPE_NTAG_216; + default: + return TAG_TYPE_UNKNOWN; + } + } + return TAG_TYPE_UNKNOWN; +} + +uint8_t guess_tag_type(uint8_t uid_length, const std::vector &first_page) { if (uid_length == 4) { return TAG_TYPE_MIFARE_CLASSIC; + } else if (uid_length == 7) { + uint8_t ntag_type = is_ntag(first_page); + if (ntag_type != TAG_TYPE_UNKNOWN) { + return ntag_type; + } else { + return TAG_TYPE_2; // Could be MIFARE Ultralight or other Type 2 tag + } } else { - return TAG_TYPE_2; + return TAG_TYPE_UNKNOWN; } } diff --git a/esphome/components/nfc/nfc.h b/esphome/components/nfc/nfc.h index 23bfdd8ef0..78422f7e3c 100644 --- a/esphome/components/nfc/nfc.h +++ b/esphome/components/nfc/nfc.h @@ -28,8 +28,16 @@ static const uint8_t TAG_TYPE_1 = 1; static const uint8_t TAG_TYPE_2 = 2; static const uint8_t TAG_TYPE_3 = 3; static const uint8_t TAG_TYPE_4 = 4; +static const uint8_t TAG_TYPE_NTAG_213 = 5; +static const uint8_t TAG_TYPE_NTAG_215 = 6; +static const uint8_t TAG_TYPE_NTAG_216 = 7; static const uint8_t TAG_TYPE_UNKNOWN = 99; +static const uint8_t NTAG_PAGE_SIZE = 4; +static const uint8_t NTAG_213_MAX_PAGE = 45; // NTAG213 has 180 bytes of memory (45 pages * 4 bytes per page) +static const uint8_t NTAG_215_MAX_PAGE = 135; // NTAG215 has 540 bytes of memory (135 pages * 4 bytes per page) +static const uint8_t NTAG_216_MAX_PAGE = 231; // NTAG216 has 924 bytes of memory (231 pages * 4 bytes per page) + // Mifare Commands static const uint8_t MIFARE_CMD_AUTH_A = 0x60; static const uint8_t MIFARE_CMD_AUTH_B = 0x61; @@ -56,7 +64,8 @@ static const uint8_t MAD_KEY[6] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}; std::string format_uid(std::vector &uid); std::string format_bytes(std::vector &bytes); -uint8_t guess_tag_type(uint8_t uid_length); +// uint8_t guess_tag_type(uint8_t uid_length);//TODO: deprecate guess_tag_type +uint8_t guess_tag_type(uint8_t uid_length, const std::vector &first_page); uint8_t get_mifare_classic_ndef_start_index(std::vector &data); bool decode_mifare_classic_tlv(std::vector &data, uint32_t &message_length, uint8_t &message_start_index); uint32_t get_mifare_classic_buffer_size(uint32_t message_length); @@ -66,6 +75,10 @@ bool mifare_classic_is_trailer_block(uint8_t block_num); uint32_t get_mifare_ultralight_buffer_size(uint32_t message_length); +bool is_ntag(const std::vector &first_page); +uint32_t get_ntag_buffer_size(uint32_t message_length); +bool decode_ntag_tlv(const std::vector &data, uint32_t &message_length, uint8_t &message_start_index); + class NfcTagListener { public: virtual void tag_off(NfcTag &tag) {}