2021-01-14 21:29:55 +01:00
|
|
|
#include "ndef_message.h"
|
|
|
|
|
|
|
|
namespace esphome {
|
|
|
|
namespace nfc {
|
|
|
|
|
2021-06-10 22:19:44 +02:00
|
|
|
static const char *const TAG = "nfc.ndef_message";
|
2021-01-14 21:29:55 +01:00
|
|
|
|
|
|
|
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++];
|
2021-09-26 22:38:08 +02:00
|
|
|
bool me = tnf_byte & 0x40; // Message End bit (is set if this is the last record of the message)
|
|
|
|
bool sr = tnf_byte & 0x10; // Short record bit (is set if payload size is less or equal to 255 bytes)
|
|
|
|
bool il = tnf_byte & 0x08; // ID length bit (is set if ID Length field exists)
|
|
|
|
uint8_t tnf = tnf_byte & 0x07; // Type Name Format
|
2021-01-14 21:29:55 +01:00
|
|
|
|
|
|
|
ESP_LOGVV(TAG, "me=%s, sr=%s, il=%s, tnf=%d", YESNO(me), YESNO(sr), YESNO(il), 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);
|
2021-09-26 22:38:08 +02:00
|
|
|
|
2021-01-14 21:29:55 +01:00
|
|
|
index += type_length;
|
|
|
|
|
2021-09-26 22:38:08 +02:00
|
|
|
std::string id_str = "";
|
2021-01-14 21:29:55 +01:00
|
|
|
if (il) {
|
2021-09-26 22:38:08 +02:00
|
|
|
id_str = std::string(data.begin() + index, data.begin() + index + id_length);
|
2021-01-14 21:29:55 +01:00
|
|
|
index += id_length;
|
|
|
|
}
|
|
|
|
|
2021-09-26 22:38:08 +02:00
|
|
|
std::vector<uint8_t> payload_data(data.begin() + index, data.begin() + index + payload_length);
|
2021-01-14 21:29:55 +01:00
|
|
|
|
2021-09-26 22:38:08 +02:00
|
|
|
std::unique_ptr<NdefRecord> record;
|
2021-01-14 21:29:55 +01:00
|
|
|
|
2021-09-26 22:38:08 +02:00
|
|
|
// Based on tnf and type, create a more specific NdefRecord object
|
|
|
|
// constructed from the payload data
|
|
|
|
if (tnf == TNF_WELL_KNOWN && type_str == "U") {
|
|
|
|
record = make_unique<NdefRecordUri>(payload_data);
|
|
|
|
} else if (tnf == TNF_WELL_KNOWN && type_str == "T") {
|
|
|
|
record = make_unique<NdefRecordText>(payload_data);
|
|
|
|
} else {
|
|
|
|
// Could not recognize the record, so store as generic one.
|
|
|
|
record = make_unique<NdefRecord>(payload_data);
|
|
|
|
record->set_tnf(tnf);
|
|
|
|
record->set_type(type_str);
|
2021-01-14 21:29:55 +01:00
|
|
|
}
|
|
|
|
|
2021-09-26 22:38:08 +02:00
|
|
|
record->set_id(id_str);
|
|
|
|
|
2021-01-14 21:29:55 +01:00
|
|
|
index += payload_length;
|
|
|
|
|
|
|
|
ESP_LOGV(TAG, "Adding record type %s = %s", record->get_type().c_str(), record->get_payload().c_str());
|
2021-09-13 11:31:02 +02:00
|
|
|
this->add_record(std::move(record));
|
2021-01-14 21:29:55 +01:00
|
|
|
|
|
|
|
if (me)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-13 11:31:02 +02:00
|
|
|
bool NdefMessage::add_record(std::unique_ptr<NdefRecord> record) {
|
2021-01-14 21:29:55 +01:00
|
|
|
if (this->records_.size() >= MAX_NDEF_RECORDS) {
|
|
|
|
ESP_LOGE(TAG, "Too many records. Max: %d", MAX_NDEF_RECORDS);
|
|
|
|
return false;
|
|
|
|
}
|
2021-09-13 11:31:02 +02:00
|
|
|
this->records_.emplace_back(std::move(record));
|
2021-01-14 21:29:55 +01:00
|
|
|
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) {
|
2021-09-26 22:38:08 +02:00
|
|
|
return this->add_record(make_unique<NdefRecordText>(encoding, text));
|
2021-01-14 21:29:55 +01:00
|
|
|
}
|
|
|
|
|
2021-09-26 22:38:08 +02:00
|
|
|
bool NdefMessage::add_uri_record(const std::string &uri) { return this->add_record(make_unique<NdefRecordUri>(uri)); }
|
2021-01-14 21:29:55 +01:00
|
|
|
|
|
|
|
std::vector<uint8_t> NdefMessage::encode() {
|
|
|
|
std::vector<uint8_t> data;
|
|
|
|
|
2021-12-01 21:03:51 +01:00
|
|
|
for (size_t i = 0; i < this->records_.size(); i++) {
|
2021-01-14 21:29:55 +01:00
|
|
|
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
|