mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	Add NDEF reading and writing to PN532 (#1351)
This commit is contained in:
		
							
								
								
									
										7
									
								
								esphome/components/nfc/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								esphome/components/nfc/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| import esphome.codegen as cg | ||||
|  | ||||
| CODEOWNERS = ['@jesserockz'] | ||||
|  | ||||
| nfc_ns = cg.esphome_ns.namespace('nfc') | ||||
|  | ||||
| NfcTag = nfc_ns.class_('NfcTag') | ||||
							
								
								
									
										106
									
								
								esphome/components/nfc/ndef_message.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								esphome/components/nfc/ndef_message.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,106 @@ | ||||
| #include "ndef_message.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace nfc { | ||||
|  | ||||
| static const char *TAG = "nfc.ndef_message"; | ||||
|  | ||||
| NdefMessage::NdefMessage(std::vector<uint8_t> &data) { | ||||
|   ESP_LOGV(TAG, "Building NdefMessage with %zu bytes", data.size()); | ||||
|   uint8_t index = 0; | ||||
|   while (index <= data.size()) { | ||||
|     uint8_t tnf_byte = data[index++]; | ||||
|     bool me = tnf_byte & 0x40; | ||||
|     bool sr = tnf_byte & 0x10; | ||||
|     bool il = tnf_byte & 0x08; | ||||
|     uint8_t tnf = tnf_byte & 0x07; | ||||
|  | ||||
|     ESP_LOGVV(TAG, "me=%s, sr=%s, il=%s, tnf=%d", YESNO(me), YESNO(sr), YESNO(il), tnf); | ||||
|  | ||||
|     auto record = new NdefRecord(); | ||||
|     record->set_tnf(tnf); | ||||
|  | ||||
|     uint8_t type_length = data[index++]; | ||||
|     uint32_t payload_length = 0; | ||||
|     if (sr) { | ||||
|       payload_length = data[index++]; | ||||
|     } else { | ||||
|       payload_length = (static_cast<uint32_t>(data[index]) << 24) | (static_cast<uint32_t>(data[index + 1]) << 16) | | ||||
|                        (static_cast<uint32_t>(data[index + 2]) << 8) | static_cast<uint32_t>(data[index + 3]); | ||||
|       index += 4; | ||||
|     } | ||||
|  | ||||
|     uint8_t id_length = 0; | ||||
|     if (il) { | ||||
|       id_length = data[index++]; | ||||
|     } | ||||
|  | ||||
|     ESP_LOGVV(TAG, "Lengths: type=%d, payload=%d, id=%d", type_length, payload_length, id_length); | ||||
|  | ||||
|     std::string type_str(data.begin() + index, data.begin() + index + type_length); | ||||
|     record->set_type(type_str); | ||||
|     index += type_length; | ||||
|  | ||||
|     if (il) { | ||||
|       std::string id_str(data.begin() + index, data.begin() + index + id_length); | ||||
|       record->set_id(id_str); | ||||
|       index += id_length; | ||||
|     } | ||||
|  | ||||
|     uint8_t payload_identifier = 0x00; | ||||
|     if (type_str == "U") { | ||||
|       payload_identifier = data[index++]; | ||||
|       payload_length -= 1; | ||||
|     } | ||||
|  | ||||
|     std::string payload_str(data.begin() + index, data.begin() + index + payload_length); | ||||
|  | ||||
|     if (payload_identifier > 0x00 && payload_identifier <= PAYLOAD_IDENTIFIERS_COUNT) { | ||||
|       payload_str.insert(0, PAYLOAD_IDENTIFIERS[payload_identifier]); | ||||
|     } | ||||
|  | ||||
|     record->set_payload(payload_str); | ||||
|     index += payload_length; | ||||
|  | ||||
|     this->add_record(record); | ||||
|     ESP_LOGV(TAG, "Adding record type %s = %s", record->get_type().c_str(), record->get_payload().c_str()); | ||||
|  | ||||
|     if (me) | ||||
|       break; | ||||
|   } | ||||
| } | ||||
|  | ||||
| bool NdefMessage::add_record(NdefRecord *record) { | ||||
|   if (this->records_.size() >= MAX_NDEF_RECORDS) { | ||||
|     ESP_LOGE(TAG, "Too many records. Max: %d", MAX_NDEF_RECORDS); | ||||
|     return false; | ||||
|   } | ||||
|   this->records_.push_back(record); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| bool NdefMessage::add_text_record(const std::string &text) { return this->add_text_record(text, "en"); }; | ||||
|  | ||||
| bool NdefMessage::add_text_record(const std::string &text, const std::string &encoding) { | ||||
|   std::string payload = to_string(text.length()) + encoding + text; | ||||
|   auto r = new NdefRecord(TNF_WELL_KNOWN, "T", payload); | ||||
|   return this->add_record(r); | ||||
| } | ||||
|  | ||||
| bool NdefMessage::add_uri_record(const std::string &uri) { | ||||
|   auto r = new NdefRecord(TNF_WELL_KNOWN, "U", uri); | ||||
|   return this->add_record(r); | ||||
| } | ||||
|  | ||||
| std::vector<uint8_t> NdefMessage::encode() { | ||||
|   std::vector<uint8_t> data; | ||||
|  | ||||
|   for (uint8_t i = 0; i < this->records_.size(); i++) { | ||||
|     auto encoded_record = this->records_[i]->encode(i == 0, (i + 1) == this->records_.size()); | ||||
|     data.insert(data.end(), encoded_record.begin(), encoded_record.end()); | ||||
|   } | ||||
|   return data; | ||||
| } | ||||
|  | ||||
| }  // namespace nfc | ||||
| }  // namespace esphome | ||||
							
								
								
									
										31
									
								
								esphome/components/nfc/ndef_message.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								esphome/components/nfc/ndef_message.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "esphome/core/helpers.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "ndef_record.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace nfc { | ||||
|  | ||||
| static const uint8_t MAX_NDEF_RECORDS = 4; | ||||
|  | ||||
| class NdefMessage { | ||||
|  public: | ||||
|   NdefMessage(){}; | ||||
|   NdefMessage(std::vector<uint8_t> &data); | ||||
|  | ||||
|   std::vector<NdefRecord *> get_records() { return this->records_; }; | ||||
|  | ||||
|   bool add_record(NdefRecord *record); | ||||
|   bool add_text_record(const std::string &text); | ||||
|   bool add_text_record(const std::string &text, const std::string &encoding); | ||||
|   bool add_uri_record(const std::string &uri); | ||||
|  | ||||
|   std::vector<uint8_t> encode(); | ||||
|  | ||||
|  protected: | ||||
|   std::vector<NdefRecord *> records_; | ||||
| }; | ||||
|  | ||||
| }  // namespace nfc | ||||
| }  // namespace esphome | ||||
							
								
								
									
										85
									
								
								esphome/components/nfc/ndef_record.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								esphome/components/nfc/ndef_record.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| #include "ndef_record.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace nfc { | ||||
|  | ||||
| static const char* TAG = "nfc.ndef_record"; | ||||
|  | ||||
| uint32_t NdefRecord::get_encoded_size() { | ||||
|   uint32_t size = 2; | ||||
|   if (this->payload_.length() > 255) { | ||||
|     size += 4; | ||||
|   } else { | ||||
|     size += 1; | ||||
|   } | ||||
|   if (this->id_.length()) { | ||||
|     size += 1; | ||||
|   } | ||||
|   size += (this->type_.length() + this->payload_.length() + this->id_.length()); | ||||
|   return size; | ||||
| } | ||||
|  | ||||
| std::vector<uint8_t> NdefRecord::encode(bool first, bool last) { | ||||
|   std::vector<uint8_t> data; | ||||
|  | ||||
|   data.push_back(this->get_tnf_byte(first, last)); | ||||
|  | ||||
|   data.push_back(this->type_.length()); | ||||
|  | ||||
|   uint8_t payload_prefix = 0x00; | ||||
|   uint8_t payload_prefix_length = 0x00; | ||||
|   for (uint8_t i = 1; i < PAYLOAD_IDENTIFIERS_COUNT; i++) { | ||||
|     std::string prefix = PAYLOAD_IDENTIFIERS[i]; | ||||
|     if (this->payload_.substr(0, prefix.length()).find(prefix) != std::string::npos) { | ||||
|       payload_prefix = i; | ||||
|       payload_prefix_length = prefix.length(); | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   uint32_t payload_length = this->payload_.length() - payload_prefix_length + 1; | ||||
|  | ||||
|   if (payload_length <= 255) { | ||||
|     data.push_back(payload_length); | ||||
|   } else { | ||||
|     data.push_back(0); | ||||
|     data.push_back(0); | ||||
|     data.push_back((payload_length >> 8) & 0xFF); | ||||
|     data.push_back(payload_length & 0xFF); | ||||
|   } | ||||
|  | ||||
|   if (this->id_.length()) { | ||||
|     data.push_back(this->id_.length()); | ||||
|   } | ||||
|  | ||||
|   data.insert(data.end(), this->type_.begin(), this->type_.end()); | ||||
|  | ||||
|   if (this->id_.length()) { | ||||
|     data.insert(data.end(), this->id_.begin(), this->id_.end()); | ||||
|   } | ||||
|  | ||||
|   data.push_back(payload_prefix); | ||||
|  | ||||
|   data.insert(data.end(), this->payload_.begin() + payload_prefix_length, this->payload_.end()); | ||||
|   return data; | ||||
| } | ||||
|  | ||||
| uint8_t NdefRecord::get_tnf_byte(bool first, bool last) { | ||||
|   uint8_t value = this->tnf_; | ||||
|   if (first) { | ||||
|     value = value | 0x80; | ||||
|   } | ||||
|   if (last) { | ||||
|     value = value | 0x40; | ||||
|   } | ||||
|   if (this->payload_.length() <= 255) { | ||||
|     value = value | 0x10; | ||||
|   } | ||||
|   if (this->id_.length()) { | ||||
|     value = value | 0x08; | ||||
|   } | ||||
|   return value; | ||||
| }; | ||||
|  | ||||
| }  // namespace nfc | ||||
| }  // namespace esphome | ||||
							
								
								
									
										101
									
								
								esphome/components/nfc/ndef_record.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								esphome/components/nfc/ndef_record.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/helpers.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace nfc { | ||||
|  | ||||
| static const uint8_t TNF_EMPTY = 0x00; | ||||
| static const uint8_t TNF_WELL_KNOWN = 0x01; | ||||
| static const uint8_t TNF_MIME_MEDIA = 0x02; | ||||
| static const uint8_t TNF_ABSOLUTE_URI = 0x03; | ||||
| static const uint8_t TNF_EXTERNAL_TYPE = 0x04; | ||||
| static const uint8_t TNF_UNKNOWN = 0x05; | ||||
| static const uint8_t TNF_UNCHANGED = 0x06; | ||||
| static const uint8_t TNF_RESERVED = 0x07; | ||||
|  | ||||
| static const uint8_t PAYLOAD_IDENTIFIERS_COUNT = 0x23; | ||||
| static const char *PAYLOAD_IDENTIFIERS[] = {"", | ||||
|                                             "http://www.", | ||||
|                                             "https://www.", | ||||
|                                             "http://", | ||||
|                                             "https://", | ||||
|                                             "tel:", | ||||
|                                             "mailto:", | ||||
|                                             "ftp://anonymous:anonymous@", | ||||
|                                             "ftp://ftp.", | ||||
|                                             "ftps://", | ||||
|                                             "sftp://", | ||||
|                                             "smb://", | ||||
|                                             "nfs://", | ||||
|                                             "ftp://", | ||||
|                                             "dav://", | ||||
|                                             "news:", | ||||
|                                             "telnet://", | ||||
|                                             "imap:", | ||||
|                                             "rtsp://", | ||||
|                                             "urn:", | ||||
|                                             "pop:", | ||||
|                                             "sip:", | ||||
|                                             "sips:", | ||||
|                                             "tftp:", | ||||
|                                             "btspp://", | ||||
|                                             "btl2cap://", | ||||
|                                             "btgoep://", | ||||
|                                             "tcpobex://", | ||||
|                                             "irdaobex://", | ||||
|                                             "file://", | ||||
|                                             "urn:epc:id:", | ||||
|                                             "urn:epc:tag:", | ||||
|                                             "urn:epc:pat:", | ||||
|                                             "urn:epc:raw:", | ||||
|                                             "urn:epc:", | ||||
|                                             "urn:nfc:"}; | ||||
|  | ||||
| class NdefRecord { | ||||
|  public: | ||||
|   NdefRecord(){}; | ||||
|   NdefRecord(uint8_t tnf, const std::string &type, const std::string &payload) { | ||||
|     this->tnf_ = tnf; | ||||
|     this->type_ = type; | ||||
|     this->set_payload(payload); | ||||
|   }; | ||||
|   NdefRecord(uint8_t tnf, const std::string &type, const std::string &payload, const std::string &id) { | ||||
|     this->tnf_ = tnf; | ||||
|     this->type_ = type; | ||||
|     this->set_payload(payload); | ||||
|     this->id_ = id; | ||||
|   }; | ||||
|   NdefRecord(const NdefRecord &rhs) { | ||||
|     this->tnf_ = rhs.tnf_; | ||||
|     this->type_ = rhs.type_; | ||||
|     this->payload_ = rhs.payload_; | ||||
|     this->payload_identifier_ = rhs.payload_identifier_; | ||||
|     this->id_ = rhs.id_; | ||||
|   }; | ||||
|   void set_tnf(uint8_t tnf) { this->tnf_ = tnf; }; | ||||
|   void set_type(const std::string &type) { this->type_ = type; }; | ||||
|   void set_payload_identifier(uint8_t payload_identifier) { this->payload_identifier_ = payload_identifier; }; | ||||
|   void set_payload(const std::string &payload) { this->payload_ = payload; }; | ||||
|   void set_id(const std::string &id) { this->id_ = id; }; | ||||
|  | ||||
|   uint32_t get_encoded_size(); | ||||
|  | ||||
|   std::vector<uint8_t> encode(bool first, bool last); | ||||
|   uint8_t get_tnf_byte(bool first, bool last); | ||||
|  | ||||
|   const std::string &get_type() { return this->type_; }; | ||||
|   const std::string &get_id() { return this->id_; }; | ||||
|   const std::string &get_payload() { return this->payload_; }; | ||||
|  | ||||
|  protected: | ||||
|   uint8_t tnf_; | ||||
|   std::string type_; | ||||
|   uint8_t payload_identifier_; | ||||
|   std::string payload_; | ||||
|   std::string id_; | ||||
| }; | ||||
|  | ||||
| }  // namespace nfc | ||||
| }  // namespace esphome | ||||
							
								
								
									
										107
									
								
								esphome/components/nfc/nfc.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								esphome/components/nfc/nfc.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,107 @@ | ||||
| #include "nfc.h" | ||||
| #include "esphome/core/log.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace nfc { | ||||
|  | ||||
| static const char *TAG = "nfc"; | ||||
|  | ||||
| std::string format_uid(std::vector<uint8_t> &uid) { | ||||
|   char buf[(uid.size() * 2) + uid.size() - 1]; | ||||
|   int offset = 0; | ||||
|   for (uint8_t i = 0; i < uid.size(); i++) { | ||||
|     const char *format = "%02X"; | ||||
|     if (i + 1 < uid.size()) | ||||
|       format = "%02X-"; | ||||
|     offset += sprintf(buf + offset, format, uid[i]); | ||||
|   } | ||||
|   return std::string(buf); | ||||
| } | ||||
|  | ||||
| std::string format_bytes(std::vector<uint8_t> &bytes) { | ||||
|   char buf[(bytes.size() * 2) + bytes.size() - 1]; | ||||
|   int offset = 0; | ||||
|   for (uint8_t i = 0; i < bytes.size(); i++) { | ||||
|     const char *format = "%02X"; | ||||
|     if (i + 1 < bytes.size()) | ||||
|       format = "%02X "; | ||||
|     offset += sprintf(buf + offset, format, bytes[i]); | ||||
|   } | ||||
|   return std::string(buf); | ||||
| } | ||||
|  | ||||
| uint8_t guess_tag_type(uint8_t uid_length) { | ||||
|   if (uid_length == 4) { | ||||
|     return TAG_TYPE_MIFARE_CLASSIC; | ||||
|   } else { | ||||
|     return TAG_TYPE_2; | ||||
|   } | ||||
| } | ||||
|  | ||||
| uint8_t get_mifare_classic_ndef_start_index(std::vector<uint8_t> &data) { | ||||
|   for (uint8_t i = 0; i < MIFARE_CLASSIC_BLOCK_SIZE; i++) { | ||||
|     if (data[i] == 0x00) { | ||||
|       // Do nothing, skip | ||||
|     } else if (data[i] == 0x03) { | ||||
|       return i; | ||||
|     } else { | ||||
|       return -2; | ||||
|     } | ||||
|   } | ||||
|   return -1; | ||||
| } | ||||
|  | ||||
| bool decode_mifare_classic_tlv(std::vector<uint8_t> &data, uint32_t &message_length, uint8_t &message_start_index) { | ||||
|   uint8_t i = get_mifare_classic_ndef_start_index(data); | ||||
|   if (i < 0 || data[i] != 0x03) { | ||||
|     ESP_LOGE(TAG, "Error, Can't decode message length."); | ||||
|     return false; | ||||
|   } | ||||
|   if (data[i + 1] == 0xFF) { | ||||
|     message_length = ((0xFF & data[i + 2]) << 8) | (0xFF & data[i + 3]); | ||||
|     message_start_index = i + MIFARE_CLASSIC_LONG_TLV_SIZE; | ||||
|   } else { | ||||
|     message_length = data[i + 1]; | ||||
|     message_start_index = i + MIFARE_CLASSIC_SHORT_TLV_SIZE; | ||||
|   } | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| uint32_t get_mifare_ultralight_buffer_size(uint32_t message_length) { | ||||
|   uint32_t buffer_size = message_length + 2 + 1; | ||||
|   if (buffer_size % MIFARE_ULTRALIGHT_READ_SIZE != 0) | ||||
|     buffer_size = ((buffer_size / MIFARE_ULTRALIGHT_READ_SIZE) + 1) * MIFARE_ULTRALIGHT_READ_SIZE; | ||||
|   return buffer_size; | ||||
| } | ||||
|  | ||||
| uint32_t get_mifare_classic_buffer_size(uint32_t message_length) { | ||||
|   uint32_t buffer_size = message_length; | ||||
|   if (message_length < 255) { | ||||
|     buffer_size += MIFARE_CLASSIC_SHORT_TLV_SIZE + 1; | ||||
|   } else { | ||||
|     buffer_size += MIFARE_CLASSIC_LONG_TLV_SIZE + 1; | ||||
|   } | ||||
|   if (buffer_size % MIFARE_CLASSIC_BLOCK_SIZE != 0) { | ||||
|     buffer_size = ((buffer_size / MIFARE_CLASSIC_BLOCK_SIZE) + 1) * MIFARE_CLASSIC_BLOCK_SIZE; | ||||
|   } | ||||
|   return buffer_size; | ||||
| } | ||||
|  | ||||
| bool mifare_classic_is_first_block(uint8_t block_num) { | ||||
|   if (block_num < 128) { | ||||
|     return (block_num % 4 == 0); | ||||
|   } else { | ||||
|     return (block_num % 16 == 0); | ||||
|   } | ||||
| } | ||||
|  | ||||
| bool mifare_classic_is_trailer_block(uint8_t block_num) { | ||||
|   if (block_num < 128) { | ||||
|     return ((block_num + 1) % 4 == 0); | ||||
|   } else { | ||||
|     return ((block_num + 1) % 16 == 0); | ||||
|   } | ||||
| } | ||||
|  | ||||
| }  // namespace nfc | ||||
| }  // namespace esphome | ||||
							
								
								
									
										57
									
								
								esphome/components/nfc/nfc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								esphome/components/nfc/nfc.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/helpers.h" | ||||
| #include "ndef_record.h" | ||||
| #include "ndef_message.h" | ||||
| #include "nfc_tag.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace nfc { | ||||
|  | ||||
| static const uint8_t MIFARE_CLASSIC_BLOCK_SIZE = 16; | ||||
| static const uint8_t MIFARE_CLASSIC_LONG_TLV_SIZE = 4; | ||||
| static const uint8_t MIFARE_CLASSIC_SHORT_TLV_SIZE = 2; | ||||
|  | ||||
| static const uint8_t MIFARE_ULTRALIGHT_PAGE_SIZE = 4; | ||||
| static const uint8_t MIFARE_ULTRALIGHT_READ_SIZE = 4; | ||||
| static const uint8_t MIFARE_ULTRALIGHT_DATA_START_PAGE = 4; | ||||
| static const uint8_t MIFARE_ULTRALIGHT_MAX_PAGE = 63; | ||||
|  | ||||
| static const uint8_t TAG_TYPE_MIFARE_CLASSIC = 0; | ||||
| 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_UNKNOWN = 99; | ||||
|  | ||||
| // Mifare Commands | ||||
| static const uint8_t MIFARE_CMD_AUTH_A = 0x60; | ||||
| static const uint8_t MIFARE_CMD_AUTH_B = 0x61; | ||||
| static const uint8_t MIFARE_CMD_READ = 0x30; | ||||
| static const uint8_t MIFARE_CMD_WRITE = 0xA0; | ||||
| static const uint8_t MIFARE_CMD_WRITE_ULTRALIGHT = 0xA2; | ||||
|  | ||||
| static const char *MIFARE_CLASSIC = "Mifare Classic"; | ||||
| static const char *NFC_FORUM_TYPE_2 = "NFC Forum Type 2"; | ||||
| static const char *ERROR = "Error"; | ||||
|  | ||||
| static const uint8_t DEFAULT_KEY[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; | ||||
| static const uint8_t NDEF_KEY[6] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7}; | ||||
| static const uint8_t MAD_KEY[6] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}; | ||||
|  | ||||
| std::string format_uid(std::vector<uint8_t> &uid); | ||||
| std::string format_bytes(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); | ||||
| bool decode_mifare_classic_tlv(std::vector<uint8_t> &data, uint32_t &message_length, uint8_t &message_start_index); | ||||
| uint32_t get_mifare_classic_buffer_size(uint32_t message_length); | ||||
|  | ||||
| bool mifare_classic_is_first_block(uint8_t block_num); | ||||
| bool mifare_classic_is_trailer_block(uint8_t block_num); | ||||
|  | ||||
| uint32_t get_mifare_ultralight_buffer_size(uint32_t message_length); | ||||
|  | ||||
| }  // namespace nfc | ||||
| }  // namespace esphome | ||||
							
								
								
									
										9
									
								
								esphome/components/nfc/nfc_tag.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								esphome/components/nfc/nfc_tag.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| #include "nfc_tag.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace nfc { | ||||
|  | ||||
| static const char *TAG = "nfc.tag"; | ||||
|  | ||||
| }  // namespace nfc | ||||
| }  // namespace esphome | ||||
							
								
								
									
										47
									
								
								esphome/components/nfc/nfc_tag.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								esphome/components/nfc/nfc_tag.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "esphome/core/log.h" | ||||
| #include "ndef_message.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace nfc { | ||||
|  | ||||
| class NfcTag { | ||||
|  public: | ||||
|   NfcTag() { | ||||
|     this->uid_ = {}; | ||||
|     this->tag_type_ = "Unknown"; | ||||
|   }; | ||||
|   NfcTag(std::vector<uint8_t> &uid) { | ||||
|     this->uid_ = uid; | ||||
|     this->tag_type_ = "Unknown"; | ||||
|   }; | ||||
|   NfcTag(std::vector<uint8_t> &uid, const std::string &tag_type) { | ||||
|     this->uid_ = uid; | ||||
|     this->tag_type_ = tag_type; | ||||
|   }; | ||||
|   NfcTag(std::vector<uint8_t> &uid, const std::string &tag_type, nfc::NdefMessage *ndef_message) { | ||||
|     this->uid_ = uid; | ||||
|     this->tag_type_ = tag_type; | ||||
|     this->ndef_message_ = ndef_message; | ||||
|   }; | ||||
|   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_ = new NdefMessage(ndef_data); | ||||
|   }; | ||||
|  | ||||
|   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; }; | ||||
|   NdefMessage *get_ndef_message() { return this->ndef_message_; }; | ||||
|   void set_ndef_message(NdefMessage *ndef_message) { this->ndef_message_ = ndef_message; }; | ||||
|  | ||||
|  protected: | ||||
|   std::vector<uint8_t> uid_; | ||||
|   std::string tag_type_; | ||||
|   NdefMessage *ndef_message_{nullptr}; | ||||
| }; | ||||
|  | ||||
| }  // namespace nfc | ||||
| }  // namespace esphome | ||||
		Reference in New Issue
	
	Block a user