Add NDEF reading and writing to PN532 (#1351)

This commit is contained in:
Jesse Hills
2021-01-15 09:29:55 +13:00
parent 28f2582256
commit 52e13164b4
16 changed files with 1206 additions and 55 deletions
+61 -5
View File
@@ -3,6 +3,8 @@
#include "esphome/core/component.h"
#include "esphome/core/automation.h"
#include "esphome/components/binary_sensor/binary_sensor.h"
#include "esphome/components/nfc/nfc_tag.h"
#include "esphome/components/nfc/nfc.h"
namespace esphome {
namespace pn532 {
@@ -14,7 +16,7 @@ static const uint8_t PN532_COMMAND_INDATAEXCHANGE = 0x40;
static const uint8_t PN532_COMMAND_INLISTPASSIVETARGET = 0x4A;
class PN532BinarySensor;
class PN532Trigger;
class PN532OnTagTrigger;
class PN532 : public PollingComponent {
public:
@@ -28,7 +30,18 @@ class PN532 : public PollingComponent {
void loop() override;
void register_tag(PN532BinarySensor *tag) { this->binary_sensors_.push_back(tag); }
void register_trigger(PN532Trigger *trig) { this->triggers_.push_back(trig); }
void register_trigger(PN532OnTagTrigger *trig) { this->triggers_.push_back(trig); }
void add_on_finished_write_callback(std::function<void()> callback) {
this->on_finished_write_callback_.add(std::move(callback));
}
bool is_writing() { return this->next_task_ != READ; };
void read_mode();
void clean_mode();
void format_mode();
void write_mode(nfc::NdefMessage *message);
protected:
void turn_off_rf_();
@@ -40,15 +53,46 @@ class PN532 : public PollingComponent {
virtual bool write_data(const std::vector<uint8_t> &data) = 0;
virtual bool read_data(std::vector<uint8_t> &data, uint8_t len) = 0;
nfc::NfcTag *read_tag_(std::vector<uint8_t> &uid);
bool format_tag_(std::vector<uint8_t> &uid);
bool clean_tag_(std::vector<uint8_t> &uid);
bool write_tag_(std::vector<uint8_t> &uid, nfc::NdefMessage *message);
nfc::NfcTag *read_mifare_classic_tag_(std::vector<uint8_t> &uid);
bool read_mifare_classic_block_(uint8_t block_num, std::vector<uint8_t> &data);
bool write_mifare_classic_block_(uint8_t block_num, std::vector<uint8_t> &data);
bool auth_mifare_classic_block_(std::vector<uint8_t> &uid, uint8_t block_num, uint8_t key_num, const uint8_t *key);
bool format_mifare_classic_mifare_(std::vector<uint8_t> &uid);
bool format_mifare_classic_ndef_(std::vector<uint8_t> &uid);
bool write_mifare_classic_tag_(std::vector<uint8_t> &uid, nfc::NdefMessage *message);
nfc::NfcTag *read_mifare_ultralight_tag_(std::vector<uint8_t> &uid);
bool read_mifare_ultralight_page_(uint8_t page_num, std::vector<uint8_t> &data);
bool is_mifare_ultralight_formatted_();
uint16_t read_mifare_ultralight_capacity_();
bool find_mifare_ultralight_ndef_(uint8_t &message_length, uint8_t &message_start_index);
bool write_mifare_ultralight_page_(uint8_t page_num, std::vector<uint8_t> &write_data);
bool write_mifare_ultralight_tag_(std::vector<uint8_t> &uid, nfc::NdefMessage *message);
bool clean_mifare_ultralight_();
bool requested_read_{false};
std::vector<PN532BinarySensor *> binary_sensors_;
std::vector<PN532Trigger *> triggers_;
std::vector<PN532OnTagTrigger *> triggers_;
std::vector<uint8_t> current_uid_;
nfc::NdefMessage *next_task_message_to_write_;
enum NfcTask {
READ = 0,
CLEAN,
FORMAT,
WRITE,
} next_task_{READ};
enum PN532Error {
NONE = 0,
WAKEUP_FAILED,
SAM_COMMAND_FAILED,
} error_code_{NONE};
CallbackManager<void()> on_finished_write_callback_;
};
class PN532BinarySensor : public binary_sensor::BinarySensor {
@@ -69,9 +113,21 @@ class PN532BinarySensor : public binary_sensor::BinarySensor {
bool found_{false};
};
class PN532Trigger : public Trigger<std::string> {
class PN532OnTagTrigger : public Trigger<std::string, nfc::NfcTag> {
public:
void process(std::vector<uint8_t> &data);
void process(nfc::NfcTag *tag);
};
class PN532OnFinishedWriteTrigger : public Trigger<> {
public:
explicit PN532OnFinishedWriteTrigger(PN532 *parent) {
parent->add_on_finished_write_callback([this]() { this->trigger(); });
}
};
template<typename... Ts> class PN532IsWritingCondition : public Condition<Ts...>, public Parented<PN532> {
public:
bool check(Ts... x) override { return this->parent_->is_writing(); }
};
} // namespace pn532