mirror of
https://github.com/esphome/esphome.git
synced 2026-09-23 18:58:52 +08:00
Add rc522 i2c (#1432)
* split to spi and i2c * fix binary_sensor * i2c comms ready * fix rc522_spi binary sensor compat * lint * lint * add test and codeowners * fix refactor
This commit is contained in:
@@ -55,6 +55,8 @@ esphome/components/pn532/* @OttoWinter @jesserockz
|
||||
esphome/components/pn532_i2c/* @OttoWinter @jesserockz
|
||||
esphome/components/pn532_spi/* @OttoWinter @jesserockz
|
||||
esphome/components/power_supply/* @esphome/core
|
||||
esphome/components/rc522/* @glmnet
|
||||
esphome/components/rc522_i2c/* @glmnet
|
||||
esphome/components/rc522_spi/* @glmnet
|
||||
esphome/components/restart/* @esphome/core
|
||||
esphome/components/rf_bridge/* @jesserockz
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import automation, pins
|
||||
from esphome.components import i2c
|
||||
from esphome.const import CONF_ON_TAG, CONF_TRIGGER_ID, CONF_RESET_PIN
|
||||
from esphome.core import coroutine
|
||||
|
||||
CODEOWNERS = ['@glmnet']
|
||||
AUTO_LOAD = ['binary_sensor']
|
||||
MULTI_CONF = True
|
||||
|
||||
CONF_RC522_ID = 'rc522_id'
|
||||
|
||||
rc522_ns = cg.esphome_ns.namespace('rc522')
|
||||
RC522 = rc522_ns.class_('RC522', cg.PollingComponent, i2c.I2CDevice)
|
||||
RC522Trigger = rc522_ns.class_('RC522Trigger', automation.Trigger.template(cg.std_string))
|
||||
|
||||
RC522_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_id(RC522),
|
||||
cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
|
||||
cv.Optional(CONF_ON_TAG): automation.validate_automation({
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(RC522Trigger),
|
||||
}),
|
||||
}).extend(cv.polling_component_schema('1s'))
|
||||
|
||||
|
||||
@coroutine
|
||||
def setup_rc522(var, config):
|
||||
yield cg.register_component(var, config)
|
||||
|
||||
if CONF_RESET_PIN in config:
|
||||
reset = yield cg.gpio_pin_expression(config[CONF_RESET_PIN])
|
||||
cg.add(var.set_reset_pin(reset))
|
||||
|
||||
for conf in config.get(CONF_ON_TAG, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID])
|
||||
cg.add(var.register_trigger(trigger))
|
||||
yield automation.build_automation(trigger, [(cg.std_string, 'x')], conf)
|
||||
@@ -0,0 +1,43 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import binary_sensor
|
||||
from esphome.const import CONF_UID, CONF_ID
|
||||
from esphome.core import HexInt, coroutine
|
||||
from . import rc522_ns, RC522, CONF_RC522_ID
|
||||
|
||||
DEPENDENCIES = ['rc522']
|
||||
|
||||
|
||||
def validate_uid(value):
|
||||
value = cv.string_strict(value)
|
||||
for x in value.split('-'):
|
||||
if len(x) != 2:
|
||||
raise cv.Invalid("Each part (separated by '-') of the UID must be two characters "
|
||||
"long.")
|
||||
try:
|
||||
x = int(x, 16)
|
||||
except ValueError as err:
|
||||
raise cv.Invalid("Valid characters for parts of a UID are 0123456789ABCDEF.") from err
|
||||
if x < 0 or x > 255:
|
||||
raise cv.Invalid("Valid values for UID parts (separated by '-') are 00 to FF")
|
||||
return value
|
||||
|
||||
|
||||
RC522BinarySensor = rc522_ns.class_('RC522BinarySensor', binary_sensor.BinarySensor)
|
||||
|
||||
CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_id(RC522BinarySensor),
|
||||
cv.GenerateID(CONF_RC522_ID): cv.use_id(RC522),
|
||||
cv.Required(CONF_UID): validate_uid,
|
||||
})
|
||||
|
||||
|
||||
@coroutine
|
||||
def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield binary_sensor.register_binary_sensor(var, config)
|
||||
|
||||
hub = yield cg.get_variable(config[CONF_RC522_ID])
|
||||
cg.add(hub.register_tag(var))
|
||||
addr = [HexInt(int(x, 16)) for x in config[CONF_UID].split('-')]
|
||||
cg.add(var.set_uid(addr))
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,284 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace rc522 {
|
||||
|
||||
class RC522BinarySensor;
|
||||
class RC522Trigger;
|
||||
class RC522 : public PollingComponent {
|
||||
public:
|
||||
void setup() override;
|
||||
|
||||
void dump_config() override;
|
||||
|
||||
void update() override;
|
||||
float get_setup_priority() const override { return setup_priority::DATA; };
|
||||
|
||||
void loop() override;
|
||||
|
||||
void register_tag(RC522BinarySensor *tag) { this->binary_sensors_.push_back(tag); }
|
||||
void register_trigger(RC522Trigger *trig) { this->triggers_.push_back(trig); }
|
||||
|
||||
void set_reset_pin(GPIOPin *reset) { this->reset_pin_ = reset; }
|
||||
|
||||
protected:
|
||||
enum PcdRegister : uint8_t {
|
||||
// Page 0: Command and status
|
||||
// 0x00 // reserved for future use
|
||||
COMMAND_REG = 0x01 << 1, // starts and stops command execution
|
||||
COM_I_EN_REG = 0x02 << 1, // enable and disable interrupt request control bits
|
||||
DIV_I_EN_REG = 0x03 << 1, // enable and disable interrupt request control bits
|
||||
COM_IRQ_REG = 0x04 << 1, // interrupt request bits
|
||||
DIV_IRQ_REG = 0x05 << 1, // interrupt request bits
|
||||
ERROR_REG = 0x06 << 1, // error bits showing the error status of the last command executed
|
||||
STATUS1_REG = 0x07 << 1, // communication status bits
|
||||
STATUS2_REG = 0x08 << 1, // receiver and transmitter status bits
|
||||
FIFO_DATA_REG = 0x09 << 1, // input and output of 64 uint8_t FIFO buffer
|
||||
FIFO_LEVEL_REG = 0x0A << 1, // number of uint8_ts stored in the FIFO buffer
|
||||
WATER_LEVEL_REG = 0x0B << 1, // level for FIFO underflow and overflow warning
|
||||
CONTROL_REG = 0x0C << 1, // miscellaneous control registers
|
||||
BIT_FRAMING_REG = 0x0D << 1, // adjustments for bit-oriented frames
|
||||
COLL_REG = 0x0E << 1, // bit position of the first bit-collision detected on the RF interface
|
||||
// 0x0F // reserved for future use
|
||||
|
||||
// Page 1: Command
|
||||
// 0x10 // reserved for future use
|
||||
MODE_REG = 0x11 << 1, // defines general modes for transmitting and receiving
|
||||
TX_MODE_REG = 0x12 << 1, // defines transmission data rate and framing
|
||||
RX_MODE_REG = 0x13 << 1, // defines reception data rate and framing
|
||||
TX_CONTROL_REG = 0x14 << 1, // controls the logical behavior of the antenna driver pins TX1 and TX2
|
||||
TX_ASK_REG = 0x15 << 1, // controls the setting of the transmission modulation
|
||||
TX_SEL_REG = 0x16 << 1, // selects the internal sources for the antenna driver
|
||||
RX_SEL_REG = 0x17 << 1, // selects internal receiver settings
|
||||
RX_THRESHOLD_REG = 0x18 << 1, // selects thresholds for the bit decoder
|
||||
DEMOD_REG = 0x19 << 1, // defines demodulator settings
|
||||
// 0x1A // reserved for future use
|
||||
// 0x1B // reserved for future use
|
||||
MF_TX_REG = 0x1C << 1, // controls some MIFARE communication transmit parameters
|
||||
MF_RX_REG = 0x1D << 1, // controls some MIFARE communication receive parameters
|
||||
// 0x1E // reserved for future use
|
||||
SERIAL_SPEED_REG = 0x1F << 1, // selects the speed of the serial UART interface
|
||||
|
||||
// Page 2: Configuration
|
||||
// 0x20 // reserved for future use
|
||||
CRC_RESULT_REG_H = 0x21 << 1, // shows the MSB and LSB values of the CRC calculation
|
||||
CRC_RESULT_REG_L = 0x22 << 1,
|
||||
// 0x23 // reserved for future use
|
||||
MOD_WIDTH_REG = 0x24 << 1, // controls the ModWidth setting?
|
||||
// 0x25 // reserved for future use
|
||||
RF_CFG_REG = 0x26 << 1, // configures the receiver gain
|
||||
GS_N_REG = 0x27 << 1, // selects the conductance of the antenna driver pins TX1 and TX2 for modulation
|
||||
CW_GS_P_REG = 0x28 << 1, // defines the conductance of the p-driver output during periods of no modulation
|
||||
MOD_GS_P_REG = 0x29 << 1, // defines the conductance of the p-driver output during periods of modulation
|
||||
T_MODE_REG = 0x2A << 1, // defines settings for the internal timer
|
||||
T_PRESCALER_REG = 0x2B << 1, // the lower 8 bits of the TPrescaler value. The 4 high bits are in TModeReg.
|
||||
T_RELOAD_REG_H = 0x2C << 1, // defines the 16-bit timer reload value
|
||||
T_RELOAD_REG_L = 0x2D << 1,
|
||||
T_COUNTER_VALUE_REG_H = 0x2E << 1, // shows the 16-bit timer value
|
||||
T_COUNTER_VALUE_REG_L = 0x2F << 1,
|
||||
|
||||
// Page 3: Test Registers
|
||||
// 0x30 // reserved for future use
|
||||
TEST_SEL1_REG = 0x31 << 1, // general test signal configuration
|
||||
TEST_SEL2_REG = 0x32 << 1, // general test signal configuration
|
||||
TEST_PIN_EN_REG = 0x33 << 1, // enables pin output driver on pins D1 to D7
|
||||
TEST_PIN_VALUE_REG = 0x34 << 1, // defines the values for D1 to D7 when it is used as an I/O bus
|
||||
TEST_BUS_REG = 0x35 << 1, // shows the status of the internal test bus
|
||||
AUTO_TEST_REG = 0x36 << 1, // controls the digital self-test
|
||||
VERSION_REG = 0x37 << 1, // shows the software version
|
||||
ANALOG_TEST_REG = 0x38 << 1, // controls the pins AUX1 and AUX2
|
||||
TEST_DA_C1_REG = 0x39 << 1, // defines the test value for TestDAC1
|
||||
TEST_DA_C2_REG = 0x3A << 1, // defines the test value for TestDAC2
|
||||
TEST_ADC_REG = 0x3B << 1 // shows the value of ADC I and Q channels
|
||||
// 0x3C // reserved for production tests
|
||||
// 0x3D // reserved for production tests
|
||||
// 0x3E // reserved for production tests
|
||||
// 0x3F // reserved for production tests
|
||||
};
|
||||
|
||||
// MFRC522 commands. Described in chapter 10 of the datasheet.
|
||||
enum PcdCommand : uint8_t {
|
||||
PCD_IDLE = 0x00, // no action, cancels current command execution
|
||||
PCD_MEM = 0x01, // stores 25 uint8_ts into the internal buffer
|
||||
PCD_GENERATE_RANDOM_ID = 0x02, // generates a 10-uint8_t random ID number
|
||||
PCD_CALC_CRC = 0x03, // activates the CRC coprocessor or performs a self-test
|
||||
PCD_TRANSMIT = 0x04, // transmits data from the FIFO buffer
|
||||
PCD_NO_CMD_CHANGE = 0x07, // no command change, can be used to modify the CommandReg register bits without
|
||||
// affecting the command, for example, the PowerDown bit
|
||||
PCD_RECEIVE = 0x08, // activates the receiver circuits
|
||||
PCD_TRANSCEIVE =
|
||||
0x0C, // transmits data from FIFO buffer to antenna and automatically activates the receiver after transmission
|
||||
PCD_MF_AUTHENT = 0x0E, // performs the MIFARE standard authentication as a reader
|
||||
PCD_SOFT_RESET = 0x0F // resets the MFRC522
|
||||
};
|
||||
|
||||
// Commands sent to the PICC.
|
||||
enum PiccCommand : uint8_t {
|
||||
// The commands used by the PCD to manage communication with several PICCs (ISO 14443-3, Type A, section 6.4)
|
||||
PICC_CMD_REQA = 0x26, // REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for
|
||||
// anticollision or selection. 7 bit frame.
|
||||
PICC_CMD_WUPA = 0x52, // Wake-UP command, Type A. Invites PICCs in state IDLE and HALT to go to READY(*) and
|
||||
// prepare for anticollision or selection. 7 bit frame.
|
||||
PICC_CMD_CT = 0x88, // Cascade Tag. Not really a command, but used during anti collision.
|
||||
PICC_CMD_SEL_CL1 = 0x93, // Anti collision/Select, Cascade Level 1
|
||||
PICC_CMD_SEL_CL2 = 0x95, // Anti collision/Select, Cascade Level 2
|
||||
PICC_CMD_SEL_CL3 = 0x97, // Anti collision/Select, Cascade Level 3
|
||||
PICC_CMD_HLTA = 0x50, // HaLT command, Type A. Instructs an ACTIVE PICC to go to state HALT.
|
||||
PICC_CMD_RATS = 0xE0, // Request command for Answer To Reset.
|
||||
// The commands used for MIFARE Classic (from http://www.mouser.com/ds/2/302/MF1S503x-89574.pdf, Section 9)
|
||||
// Use PCD_MFAuthent to authenticate access to a sector, then use these commands to read/write/modify the blocks on
|
||||
// the sector.
|
||||
// The read/write commands can also be used for MIFARE Ultralight.
|
||||
PICC_CMD_MF_AUTH_KEY_A = 0x60, // Perform authentication with Key A
|
||||
PICC_CMD_MF_AUTH_KEY_B = 0x61, // Perform authentication with Key B
|
||||
PICC_CMD_MF_READ =
|
||||
0x30, // Reads one 16 uint8_t block from the authenticated sector of the PICC. Also used for MIFARE Ultralight.
|
||||
PICC_CMD_MF_WRITE = 0xA0, // Writes one 16 uint8_t block to the authenticated sector of the PICC. Called
|
||||
// "COMPATIBILITY WRITE" for MIFARE Ultralight.
|
||||
PICC_CMD_MF_DECREMENT =
|
||||
0xC0, // Decrements the contents of a block and stores the result in the internal data register.
|
||||
PICC_CMD_MF_INCREMENT =
|
||||
0xC1, // Increments the contents of a block and stores the result in the internal data register.
|
||||
PICC_CMD_MF_RESTORE = 0xC2, // Reads the contents of a block into the internal data register.
|
||||
PICC_CMD_MF_TRANSFER = 0xB0, // Writes the contents of the internal data register to a block.
|
||||
// The commands used for MIFARE Ultralight (from http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf, Section 8.6)
|
||||
// The PICC_CMD_MF_READ and PICC_CMD_MF_WRITE can also be used for MIFARE Ultralight.
|
||||
PICC_CMD_UL_WRITE = 0xA2 // Writes one 4 uint8_t page to the PICC.
|
||||
};
|
||||
|
||||
// Return codes from the functions in this class. Remember to update GetStatusCodeName() if you add more.
|
||||
// last value set to 0xff, then compiler uses less ram, it seems some optimisations are triggered
|
||||
enum StatusCode : uint8_t {
|
||||
STATUS_OK, // Success
|
||||
STATUS_ERROR, // Error in communication
|
||||
STATUS_COLLISION, // Collission detected
|
||||
STATUS_TIMEOUT, // Timeout in communication.
|
||||
STATUS_NO_ROOM, // A buffer is not big enough.
|
||||
STATUS_INTERNAL_ERROR, // Internal error in the code. Should not happen ;-)
|
||||
STATUS_INVALID, // Invalid argument.
|
||||
STATUS_CRC_WRONG, // The CRC_A does not match
|
||||
STATUS_MIFARE_NACK = 0xff // A MIFARE PICC responded with NAK.
|
||||
};
|
||||
|
||||
// A struct used for passing the UID of a PICC.
|
||||
using Uid = struct {
|
||||
uint8_t size; // Number of uint8_ts in the UID. 4, 7 or 10.
|
||||
uint8_t uiduint8_t[10];
|
||||
uint8_t sak; // The SAK (Select acknowledge) uint8_t returned from the PICC after successful selection.
|
||||
};
|
||||
|
||||
Uid uid_;
|
||||
uint32_t update_wait_{0};
|
||||
|
||||
void pcd_reset_();
|
||||
void initialize_();
|
||||
void pcd_antenna_on_();
|
||||
virtual uint8_t pcd_read_register(PcdRegister reg ///< The register to read from. One of the PCD_Register enums.
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Reads a number of uint8_ts from the specified register in the MFRC522 chip.
|
||||
* The interface is described in the datasheet section 8.1.2.
|
||||
*/
|
||||
virtual void pcd_read_register(PcdRegister reg, ///< The register to read from. One of the PCD_Register enums.
|
||||
uint8_t count, ///< The number of uint8_ts to read
|
||||
uint8_t *values, ///< uint8_t array to store the values in.
|
||||
uint8_t rx_align ///< Only bit positions rxAlign..7 in values[0] are updated.
|
||||
) = 0;
|
||||
virtual void pcd_write_register(PcdRegister reg, ///< The register to write to. One of the PCD_Register enums.
|
||||
uint8_t value ///< The value to write.
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Writes a number of uint8_ts to the specified register in the MFRC522 chip.
|
||||
* The interface is described in the datasheet section 8.1.2.
|
||||
*/
|
||||
virtual void pcd_write_register(PcdRegister reg, ///< The register to write to. One of the PCD_Register enums.
|
||||
uint8_t count, ///< The number of uint8_ts to write to the register
|
||||
uint8_t *values ///< The values to write. uint8_t array.
|
||||
) = 0;
|
||||
|
||||
StatusCode picc_request_a_(
|
||||
uint8_t *buffer_atqa, ///< The buffer to store the ATQA (Answer to request) in
|
||||
uint8_t *buffer_size ///< Buffer size, at least two uint8_ts. Also number of uint8_ts returned if STATUS_OK.
|
||||
);
|
||||
StatusCode picc_reqa_or_wupa_(
|
||||
uint8_t command, ///< The command to send - PICC_CMD_REQA or PICC_CMD_WUPA
|
||||
uint8_t *buffer_atqa, ///< The buffer to store the ATQA (Answer to request) in
|
||||
uint8_t *buffer_size ///< Buffer size, at least two uint8_ts. Also number of uint8_ts returned if STATUS_OK.
|
||||
);
|
||||
void pcd_set_register_bit_mask_(PcdRegister reg, ///< The register to update. One of the PCD_Register enums.
|
||||
uint8_t mask ///< The bits to set.
|
||||
);
|
||||
void pcd_clear_register_bit_mask_(PcdRegister reg, ///< The register to update. One of the PCD_Register enums.
|
||||
uint8_t mask ///< The bits to clear.
|
||||
);
|
||||
|
||||
StatusCode pcd_transceive_data_(uint8_t *send_data, uint8_t send_len, uint8_t *back_data, uint8_t *back_len,
|
||||
uint8_t *valid_bits = nullptr, uint8_t rx_align = 0, bool check_crc = false);
|
||||
StatusCode pcd_communicate_with_picc_(uint8_t command, uint8_t wait_i_rq, uint8_t *send_data, uint8_t send_len,
|
||||
uint8_t *back_data = nullptr, uint8_t *back_len = nullptr,
|
||||
uint8_t *valid_bits = nullptr, uint8_t rx_align = 0, bool check_crc = false);
|
||||
StatusCode pcd_calculate_crc_(
|
||||
uint8_t *data, ///< In: Pointer to the data to transfer to the FIFO for CRC calculation.
|
||||
uint8_t length, ///< In: The number of uint8_ts to transfer.
|
||||
uint8_t *result ///< Out: Pointer to result buffer. Result is written to result[0..1], low uint8_t first.
|
||||
);
|
||||
RC522::StatusCode picc_is_new_card_present_();
|
||||
bool picc_read_card_serial_();
|
||||
StatusCode picc_select_(
|
||||
Uid *uid, ///< Pointer to Uid struct. Normally output, but can also be used to supply a known UID.
|
||||
uint8_t valid_bits = 0 ///< The number of known UID bits supplied in *uid. Normally 0. If set you must also
|
||||
///< supply uid->size.
|
||||
);
|
||||
|
||||
/** Read a data frame from the RC522 and return the result as a vector.
|
||||
*
|
||||
* Note that is_ready needs to be checked first before requesting this method.
|
||||
*
|
||||
* On failure, an empty vector is returned.
|
||||
*/
|
||||
std::vector<uint8_t> r_c522_read_data_();
|
||||
|
||||
GPIOPin *reset_pin_{nullptr};
|
||||
uint8_t reset_count_{0};
|
||||
uint32_t reset_timeout_{0};
|
||||
bool initialize_pending_{false};
|
||||
std::vector<RC522BinarySensor *> binary_sensors_;
|
||||
std::vector<RC522Trigger *> triggers_;
|
||||
|
||||
enum RC522Error {
|
||||
NONE = 0,
|
||||
RESET_FAILED,
|
||||
} error_code_{NONE};
|
||||
};
|
||||
|
||||
class RC522BinarySensor : public binary_sensor::BinarySensor {
|
||||
public:
|
||||
void set_uid(const std::vector<uint8_t> &uid) { uid_ = uid; }
|
||||
|
||||
bool process(const uint8_t *data, uint8_t len);
|
||||
|
||||
void on_scan_end() {
|
||||
if (!this->found_) {
|
||||
this->publish_state(false);
|
||||
}
|
||||
this->found_ = false;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::vector<uint8_t> uid_;
|
||||
bool found_{false};
|
||||
};
|
||||
|
||||
class RC522Trigger : public Trigger<std::string> {
|
||||
public:
|
||||
void process(const uint8_t *uid, uint8_t uid_length);
|
||||
};
|
||||
|
||||
} // namespace rc522
|
||||
} // namespace esphome
|
||||
@@ -0,0 +1,22 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import i2c, rc522
|
||||
from esphome.const import CONF_ID
|
||||
|
||||
CODEOWNERS = ['@glmnet']
|
||||
DEPENDENCIES = ['i2c']
|
||||
AUTO_LOAD = ['rc522']
|
||||
|
||||
|
||||
rc522_i2c_ns = cg.esphome_ns.namespace('rc522_i2c')
|
||||
RC522I2C = rc522_i2c_ns.class_('RC522I2C', rc522.RC522, i2c.I2CDevice)
|
||||
|
||||
CONFIG_SCHEMA = cv.All(rc522.RC522_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_id(RC522I2C),
|
||||
}).extend(i2c.i2c_device_schema(0x2c)))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield rc522.setup_rc522(var, config)
|
||||
yield i2c.register_i2c_device(var, config)
|
||||
@@ -0,0 +1,99 @@
|
||||
#include "rc522_i2c.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace rc522_i2c {
|
||||
|
||||
static const char *TAG = "rc522_i2c";
|
||||
|
||||
void RC522I2C::dump_config() {
|
||||
RC522::dump_config();
|
||||
LOG_I2C_DEVICE(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a uint8_t from the specified register in the MFRC522 chip.
|
||||
* The interface is described in the datasheet section 8.1.2.
|
||||
*/
|
||||
uint8_t RC522I2C::pcd_read_register(PcdRegister reg ///< The register to read from. One of the PCD_Register enums.
|
||||
) {
|
||||
uint8_t value;
|
||||
read_byte(reg >> 1, &value);
|
||||
ESP_LOGVV(TAG, "read_register_(%x) -> %x", reg, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a number of uint8_ts from the specified register in the MFRC522 chip.
|
||||
* The interface is described in the datasheet section 8.1.2.
|
||||
*/
|
||||
void RC522I2C::pcd_read_register(PcdRegister reg, ///< The register to read from. One of the PCD_Register enums.
|
||||
uint8_t count, ///< The number of uint8_ts to read
|
||||
uint8_t *values, ///< uint8_t array to store the values in.
|
||||
uint8_t rx_align ///< Only bit positions rxAlign..7 in values[0] are updated.
|
||||
) {
|
||||
if (count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string buf;
|
||||
buf = "Rx";
|
||||
char cstrb[20];
|
||||
|
||||
uint8_t b = values[0];
|
||||
read_bytes(reg >> 1, values, count);
|
||||
|
||||
if (rx_align) // Only update bit positions rxAlign..7 in values[0]
|
||||
{
|
||||
// Create bit mask for bit positions rxAlign..7
|
||||
uint8_t mask = 0xFF << rx_align;
|
||||
// Apply mask to both current value of values[0] and the new data in values array.
|
||||
values[0] = (b & ~mask) | (values[0] & mask);
|
||||
}
|
||||
}
|
||||
|
||||
void RC522I2C::pcd_write_register(PcdRegister reg, ///< The register to write to. One of the PCD_Register enums.
|
||||
uint8_t value ///< The value to write.
|
||||
) {
|
||||
this->write_byte(reg >> 1, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a number of uint8_ts to the specified register in the MFRC522 chip.
|
||||
* The interface is described in the datasheet section 8.1.2.
|
||||
*/
|
||||
void RC522I2C::pcd_write_register(PcdRegister reg, ///< The register to write to. One of the PCD_Register enums.
|
||||
uint8_t count, ///< The number of uint8_ts to write to the register
|
||||
uint8_t *values ///< The values to write. uint8_t array.
|
||||
) {
|
||||
write_bytes(reg >> 1, values, count);
|
||||
}
|
||||
|
||||
// bool RC522I2C::write_data(const std::vector<uint8_t> &data) {
|
||||
// return this->write_bytes_raw(data.data(), data.size()); }
|
||||
|
||||
// bool RC522I2C::read_data(std::vector<uint8_t> &data, uint8_t len) {
|
||||
// delay(5);
|
||||
|
||||
// std::vector<uint8_t> ready;
|
||||
// ready.resize(1);
|
||||
// uint32_t start_time = millis();
|
||||
// while (true) {
|
||||
// if (this->read_bytes_raw(ready.data(), 1)) {
|
||||
// if (ready[0] == 0x01)
|
||||
// break;
|
||||
// }
|
||||
|
||||
// if (millis() - start_time > 100) {
|
||||
// ESP_LOGV(TAG, "Timed out waiting for readiness from RC522!");
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
// data.resize(len + 1);
|
||||
// this->read_bytes_raw(data.data(), len + 1);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
} // namespace rc522_i2c
|
||||
} // namespace esphome
|
||||
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/rc522/rc522.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace rc522_i2c {
|
||||
|
||||
class RC522I2C : public rc522::RC522, public i2c::I2CDevice {
|
||||
public:
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
uint8_t pcd_read_register(PcdRegister reg ///< The register to read from. One of the PCD_Register enums.
|
||||
) override;
|
||||
|
||||
/**
|
||||
* Reads a number of uint8_ts from the specified register in the MFRC522 chip.
|
||||
* The interface is described in the datasheet section 8.1.2.
|
||||
*/
|
||||
void pcd_read_register(PcdRegister reg, ///< The register to read from. One of the PCD_Register enums.
|
||||
uint8_t count, ///< The number of uint8_ts to read
|
||||
uint8_t *values, ///< uint8_t array to store the values in.
|
||||
uint8_t rx_align ///< Only bit positions rxAlign..7 in values[0] are updated.
|
||||
) override;
|
||||
void pcd_write_register(PcdRegister reg, ///< The register to write to. One of the PCD_Register enums.
|
||||
uint8_t value ///< The value to write.
|
||||
) override;
|
||||
|
||||
/**
|
||||
* Writes a number of uint8_ts to the specified register in the MFRC522 chip.
|
||||
* The interface is described in the datasheet section 8.1.2.
|
||||
*/
|
||||
void pcd_write_register(PcdRegister reg, ///< The register to write to. One of the PCD_Register enums.
|
||||
uint8_t count, ///< The number of uint8_ts to write to the register
|
||||
uint8_t *values ///< The values to write. uint8_t array.
|
||||
) override;
|
||||
};
|
||||
|
||||
} // namespace rc522_i2c
|
||||
} // namespace esphome
|
||||
@@ -1,39 +1,21 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import automation, pins
|
||||
from esphome.components import spi
|
||||
from esphome.const import CONF_ID, CONF_ON_TAG, CONF_TRIGGER_ID, CONF_RESET_PIN, CONF_CS_PIN
|
||||
from esphome.components import spi, rc522
|
||||
from esphome.const import CONF_ID
|
||||
|
||||
CODEOWNERS = ['@glmnet']
|
||||
DEPENDENCIES = ['spi']
|
||||
AUTO_LOAD = ['binary_sensor']
|
||||
MULTI_CONF = True
|
||||
|
||||
AUTO_LOAD = ['rc522']
|
||||
|
||||
rc522_spi_ns = cg.esphome_ns.namespace('rc522_spi')
|
||||
RC522 = rc522_spi_ns.class_('RC522', cg.PollingComponent, spi.SPIDevice)
|
||||
RC522Trigger = rc522_spi_ns.class_('RC522Trigger', automation.Trigger.template(cg.std_string))
|
||||
RC522Spi = rc522_spi_ns.class_('RC522Spi', rc522.RC522, spi.SPIDevice)
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_id(RC522),
|
||||
cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
|
||||
cv.Required(CONF_CS_PIN): pins.gpio_output_pin_schema,
|
||||
cv.Optional(CONF_ON_TAG): automation.validate_automation({
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(RC522Trigger),
|
||||
}),
|
||||
}).extend(cv.polling_component_schema('1s')).extend(spi.spi_device_schema())
|
||||
CONFIG_SCHEMA = cv.All(rc522.RC522_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_id(RC522Spi),
|
||||
}).extend(spi.spi_device_schema(cs_pin_required=True)))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield cg.register_component(var, config)
|
||||
yield rc522.setup_rc522(var, config)
|
||||
yield spi.register_spi_device(var, config)
|
||||
|
||||
if CONF_RESET_PIN in config:
|
||||
reset = yield cg.gpio_pin_expression(config[CONF_RESET_PIN])
|
||||
cg.add(var.set_reset_pin(reset))
|
||||
|
||||
for conf in config.get(CONF_ON_TAG, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID])
|
||||
cg.add(var.register_trigger(trigger))
|
||||
yield automation.build_automation(trigger, [(cg.std_string, 'x')], conf)
|
||||
|
||||
@@ -1,44 +1,9 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import binary_sensor
|
||||
from esphome.const import CONF_UID, CONF_ID
|
||||
from esphome.core import HexInt
|
||||
from . import rc522_spi_ns, RC522
|
||||
import esphome.components.rc522.binary_sensor as rc522_binary_sensor
|
||||
|
||||
DEPENDENCIES = ['rc522_spi']
|
||||
DEPENDENCIES = ['rc522']
|
||||
|
||||
CONF_RC522_ID = 'rc522_id'
|
||||
|
||||
|
||||
def validate_uid(value):
|
||||
value = cv.string_strict(value)
|
||||
for x in value.split('-'):
|
||||
if len(x) != 2:
|
||||
raise cv.Invalid("Each part (separated by '-') of the UID must be two characters "
|
||||
"long.")
|
||||
try:
|
||||
x = int(x, 16)
|
||||
except ValueError as err:
|
||||
raise cv.Invalid("Valid characters for parts of a UID are 0123456789ABCDEF.") from err
|
||||
if x < 0 or x > 255:
|
||||
raise cv.Invalid("Valid values for UID parts (separated by '-') are 00 to FF")
|
||||
return value
|
||||
|
||||
|
||||
RC522BinarySensor = rc522_spi_ns.class_('RC522BinarySensor', binary_sensor.BinarySensor)
|
||||
|
||||
CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_id(RC522BinarySensor),
|
||||
cv.GenerateID(CONF_RC522_ID): cv.use_id(RC522),
|
||||
cv.Required(CONF_UID): validate_uid,
|
||||
})
|
||||
CONFIG_SCHEMA = rc522_binary_sensor.CONFIG_SCHEMA
|
||||
|
||||
|
||||
def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield binary_sensor.register_binary_sensor(var, config)
|
||||
|
||||
hub = yield cg.get_variable(config[CONF_RC522_ID])
|
||||
cg.add(hub.register_tag(var))
|
||||
addr = [HexInt(int(x, 16)) for x in config[CONF_UID].split('-')]
|
||||
cg.add(var.set_uid(addr))
|
||||
yield rc522_binary_sensor.to_code(config)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,292 +10,46 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||
#include "esphome/components/rc522/rc522.h"
|
||||
#include "esphome/components/spi/spi.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace rc522_spi {
|
||||
|
||||
class RC522BinarySensor;
|
||||
class RC522Trigger;
|
||||
|
||||
class RC522 : public PollingComponent,
|
||||
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_LEADING,
|
||||
spi::DATA_RATE_4MHZ> {
|
||||
class RC522Spi : public rc522::RC522,
|
||||
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_LEADING,
|
||||
spi::DATA_RATE_4MHZ> {
|
||||
public:
|
||||
void setup() override;
|
||||
|
||||
void dump_config() override;
|
||||
|
||||
void update() override;
|
||||
float get_setup_priority() const override { return setup_priority::DATA; };
|
||||
|
||||
void loop() override;
|
||||
|
||||
void register_tag(RC522BinarySensor *tag) { this->binary_sensors_.push_back(tag); }
|
||||
void register_trigger(RC522Trigger *trig) { this->triggers_.push_back(trig); }
|
||||
|
||||
void set_reset_pin(GPIOPin *reset) { this->reset_pin_ = reset; }
|
||||
|
||||
protected:
|
||||
enum PcdRegister : uint8_t {
|
||||
// Page 0: Command and status
|
||||
// 0x00 // reserved for future use
|
||||
COMMAND_REG = 0x01 << 1, // starts and stops command execution
|
||||
COM_I_EN_REG = 0x02 << 1, // enable and disable interrupt request control bits
|
||||
DIV_I_EN_REG = 0x03 << 1, // enable and disable interrupt request control bits
|
||||
COM_IRQ_REG = 0x04 << 1, // interrupt request bits
|
||||
DIV_IRQ_REG = 0x05 << 1, // interrupt request bits
|
||||
ERROR_REG = 0x06 << 1, // error bits showing the error status of the last command executed
|
||||
STATUS1_REG = 0x07 << 1, // communication status bits
|
||||
STATUS2_REG = 0x08 << 1, // receiver and transmitter status bits
|
||||
FIFO_DATA_REG = 0x09 << 1, // input and output of 64 uint8_t FIFO buffer
|
||||
FIFO_LEVEL_REG = 0x0A << 1, // number of uint8_ts stored in the FIFO buffer
|
||||
WATER_LEVEL_REG = 0x0B << 1, // level for FIFO underflow and overflow warning
|
||||
CONTROL_REG = 0x0C << 1, // miscellaneous control registers
|
||||
BIT_FRAMING_REG = 0x0D << 1, // adjustments for bit-oriented frames
|
||||
COLL_REG = 0x0E << 1, // bit position of the first bit-collision detected on the RF interface
|
||||
// 0x0F // reserved for future use
|
||||
|
||||
// Page 1: Command
|
||||
// 0x10 // reserved for future use
|
||||
MODE_REG = 0x11 << 1, // defines general modes for transmitting and receiving
|
||||
TX_MODE_REG = 0x12 << 1, // defines transmission data rate and framing
|
||||
RX_MODE_REG = 0x13 << 1, // defines reception data rate and framing
|
||||
TX_CONTROL_REG = 0x14 << 1, // controls the logical behavior of the antenna driver pins TX1 and TX2
|
||||
TX_ASK_REG = 0x15 << 1, // controls the setting of the transmission modulation
|
||||
TX_SEL_REG = 0x16 << 1, // selects the internal sources for the antenna driver
|
||||
RX_SEL_REG = 0x17 << 1, // selects internal receiver settings
|
||||
RX_THRESHOLD_REG = 0x18 << 1, // selects thresholds for the bit decoder
|
||||
DEMOD_REG = 0x19 << 1, // defines demodulator settings
|
||||
// 0x1A // reserved for future use
|
||||
// 0x1B // reserved for future use
|
||||
MF_TX_REG = 0x1C << 1, // controls some MIFARE communication transmit parameters
|
||||
MF_RX_REG = 0x1D << 1, // controls some MIFARE communication receive parameters
|
||||
// 0x1E // reserved for future use
|
||||
SERIAL_SPEED_REG = 0x1F << 1, // selects the speed of the serial UART interface
|
||||
|
||||
// Page 2: Configuration
|
||||
// 0x20 // reserved for future use
|
||||
CRC_RESULT_REG_H = 0x21 << 1, // shows the MSB and LSB values of the CRC calculation
|
||||
CRC_RESULT_REG_L = 0x22 << 1,
|
||||
// 0x23 // reserved for future use
|
||||
MOD_WIDTH_REG = 0x24 << 1, // controls the ModWidth setting?
|
||||
// 0x25 // reserved for future use
|
||||
RF_CFG_REG = 0x26 << 1, // configures the receiver gain
|
||||
GS_N_REG = 0x27 << 1, // selects the conductance of the antenna driver pins TX1 and TX2 for modulation
|
||||
CW_GS_P_REG = 0x28 << 1, // defines the conductance of the p-driver output during periods of no modulation
|
||||
MOD_GS_P_REG = 0x29 << 1, // defines the conductance of the p-driver output during periods of modulation
|
||||
T_MODE_REG = 0x2A << 1, // defines settings for the internal timer
|
||||
T_PRESCALER_REG = 0x2B << 1, // the lower 8 bits of the TPrescaler value. The 4 high bits are in TModeReg.
|
||||
T_RELOAD_REG_H = 0x2C << 1, // defines the 16-bit timer reload value
|
||||
T_RELOAD_REG_L = 0x2D << 1,
|
||||
T_COUNTER_VALUE_REG_H = 0x2E << 1, // shows the 16-bit timer value
|
||||
T_COUNTER_VALUE_REG_L = 0x2F << 1,
|
||||
|
||||
// Page 3: Test Registers
|
||||
// 0x30 // reserved for future use
|
||||
TEST_SEL1_REG = 0x31 << 1, // general test signal configuration
|
||||
TEST_SEL2_REG = 0x32 << 1, // general test signal configuration
|
||||
TEST_PIN_EN_REG = 0x33 << 1, // enables pin output driver on pins D1 to D7
|
||||
TEST_PIN_VALUE_REG = 0x34 << 1, // defines the values for D1 to D7 when it is used as an I/O bus
|
||||
TEST_BUS_REG = 0x35 << 1, // shows the status of the internal test bus
|
||||
AUTO_TEST_REG = 0x36 << 1, // controls the digital self-test
|
||||
VERSION_REG = 0x37 << 1, // shows the software version
|
||||
ANALOG_TEST_REG = 0x38 << 1, // controls the pins AUX1 and AUX2
|
||||
TEST_DA_C1_REG = 0x39 << 1, // defines the test value for TestDAC1
|
||||
TEST_DA_C2_REG = 0x3A << 1, // defines the test value for TestDAC2
|
||||
TEST_ADC_REG = 0x3B << 1 // shows the value of ADC I and Q channels
|
||||
// 0x3C // reserved for production tests
|
||||
// 0x3D // reserved for production tests
|
||||
// 0x3E // reserved for production tests
|
||||
// 0x3F // reserved for production tests
|
||||
};
|
||||
|
||||
// MFRC522 commands. Described in chapter 10 of the datasheet.
|
||||
enum PcdCommand : uint8_t {
|
||||
PCD_IDLE = 0x00, // no action, cancels current command execution
|
||||
PCD_MEM = 0x01, // stores 25 uint8_ts into the internal buffer
|
||||
PCD_GENERATE_RANDOM_ID = 0x02, // generates a 10-uint8_t random ID number
|
||||
PCD_CALC_CRC = 0x03, // activates the CRC coprocessor or performs a self-test
|
||||
PCD_TRANSMIT = 0x04, // transmits data from the FIFO buffer
|
||||
PCD_NO_CMD_CHANGE = 0x07, // no command change, can be used to modify the CommandReg register bits without
|
||||
// affecting the command, for example, the PowerDown bit
|
||||
PCD_RECEIVE = 0x08, // activates the receiver circuits
|
||||
PCD_TRANSCEIVE =
|
||||
0x0C, // transmits data from FIFO buffer to antenna and automatically activates the receiver after transmission
|
||||
PCD_MF_AUTHENT = 0x0E, // performs the MIFARE standard authentication as a reader
|
||||
PCD_SOFT_RESET = 0x0F // resets the MFRC522
|
||||
};
|
||||
|
||||
// Commands sent to the PICC.
|
||||
enum PiccCommand : uint8_t {
|
||||
// The commands used by the PCD to manage communication with several PICCs (ISO 14443-3, Type A, section 6.4)
|
||||
PICC_CMD_REQA = 0x26, // REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for
|
||||
// anticollision or selection. 7 bit frame.
|
||||
PICC_CMD_WUPA = 0x52, // Wake-UP command, Type A. Invites PICCs in state IDLE and HALT to go to READY(*) and
|
||||
// prepare for anticollision or selection. 7 bit frame.
|
||||
PICC_CMD_CT = 0x88, // Cascade Tag. Not really a command, but used during anti collision.
|
||||
PICC_CMD_SEL_CL1 = 0x93, // Anti collision/Select, Cascade Level 1
|
||||
PICC_CMD_SEL_CL2 = 0x95, // Anti collision/Select, Cascade Level 2
|
||||
PICC_CMD_SEL_CL3 = 0x97, // Anti collision/Select, Cascade Level 3
|
||||
PICC_CMD_HLTA = 0x50, // HaLT command, Type A. Instructs an ACTIVE PICC to go to state HALT.
|
||||
PICC_CMD_RATS = 0xE0, // Request command for Answer To Reset.
|
||||
// The commands used for MIFARE Classic (from http://www.mouser.com/ds/2/302/MF1S503x-89574.pdf, Section 9)
|
||||
// Use PCD_MFAuthent to authenticate access to a sector, then use these commands to read/write/modify the blocks on
|
||||
// the sector.
|
||||
// The read/write commands can also be used for MIFARE Ultralight.
|
||||
PICC_CMD_MF_AUTH_KEY_A = 0x60, // Perform authentication with Key A
|
||||
PICC_CMD_MF_AUTH_KEY_B = 0x61, // Perform authentication with Key B
|
||||
PICC_CMD_MF_READ =
|
||||
0x30, // Reads one 16 uint8_t block from the authenticated sector of the PICC. Also used for MIFARE Ultralight.
|
||||
PICC_CMD_MF_WRITE = 0xA0, // Writes one 16 uint8_t block to the authenticated sector of the PICC. Called
|
||||
// "COMPATIBILITY WRITE" for MIFARE Ultralight.
|
||||
PICC_CMD_MF_DECREMENT =
|
||||
0xC0, // Decrements the contents of a block and stores the result in the internal data register.
|
||||
PICC_CMD_MF_INCREMENT =
|
||||
0xC1, // Increments the contents of a block and stores the result in the internal data register.
|
||||
PICC_CMD_MF_RESTORE = 0xC2, // Reads the contents of a block into the internal data register.
|
||||
PICC_CMD_MF_TRANSFER = 0xB0, // Writes the contents of the internal data register to a block.
|
||||
// The commands used for MIFARE Ultralight (from http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf, Section 8.6)
|
||||
// The PICC_CMD_MF_READ and PICC_CMD_MF_WRITE can also be used for MIFARE Ultralight.
|
||||
PICC_CMD_UL_WRITE = 0xA2 // Writes one 4 uint8_t page to the PICC.
|
||||
};
|
||||
|
||||
// Return codes from the functions in this class. Remember to update GetStatusCodeName() if you add more.
|
||||
// last value set to 0xff, then compiler uses less ram, it seems some optimisations are triggered
|
||||
enum StatusCode : uint8_t {
|
||||
STATUS_OK, // Success
|
||||
STATUS_ERROR, // Error in communication
|
||||
STATUS_COLLISION, // Collission detected
|
||||
STATUS_TIMEOUT, // Timeout in communication.
|
||||
STATUS_NO_ROOM, // A buffer is not big enough.
|
||||
STATUS_INTERNAL_ERROR, // Internal error in the code. Should not happen ;-)
|
||||
STATUS_INVALID, // Invalid argument.
|
||||
STATUS_CRC_WRONG, // The CRC_A does not match
|
||||
STATUS_MIFARE_NACK = 0xff // A MIFARE PICC responded with NAK.
|
||||
};
|
||||
|
||||
// A struct used for passing the UID of a PICC.
|
||||
using Uid = struct {
|
||||
uint8_t size; // Number of uint8_ts in the UID. 4, 7 or 10.
|
||||
uint8_t uiduint8_t[10];
|
||||
uint8_t sak; // The SAK (Select acknowledge) uint8_t returned from the PICC after successful selection.
|
||||
};
|
||||
|
||||
Uid uid_;
|
||||
uint32_t update_wait_{0};
|
||||
|
||||
void pcd_reset_();
|
||||
void initialize_();
|
||||
void pcd_antenna_on_();
|
||||
uint8_t pcd_read_register_(PcdRegister reg ///< The register to read from. One of the PCD_Register enums.
|
||||
);
|
||||
uint8_t pcd_read_register(PcdRegister reg ///< The register to read from. One of the PCD_Register enums.
|
||||
) override;
|
||||
|
||||
/**
|
||||
* Reads a number of uint8_ts from the specified register in the MFRC522 chip.
|
||||
* The interface is described in the datasheet section 8.1.2.
|
||||
*/
|
||||
void pcd_read_register_(PcdRegister reg, ///< The register to read from. One of the PCD_Register enums.
|
||||
uint8_t count, ///< The number of uint8_ts to read
|
||||
uint8_t *values, ///< uint8_t array to store the values in.
|
||||
uint8_t rx_align ///< Only bit positions rxAlign..7 in values[0] are updated.
|
||||
);
|
||||
void pcd_write_register_(PcdRegister reg, ///< The register to write to. One of the PCD_Register enums.
|
||||
uint8_t value ///< The value to write.
|
||||
);
|
||||
void pcd_read_register(PcdRegister reg, ///< The register to read from. One of the PCD_Register enums.
|
||||
uint8_t count, ///< The number of uint8_ts to read
|
||||
uint8_t *values, ///< uint8_t array to store the values in.
|
||||
uint8_t rx_align ///< Only bit positions rxAlign..7 in values[0] are updated.
|
||||
) override;
|
||||
void pcd_write_register(PcdRegister reg, ///< The register to write to. One of the PCD_Register enums.
|
||||
uint8_t value ///< The value to write.
|
||||
) override;
|
||||
|
||||
/**
|
||||
* Writes a number of uint8_ts to the specified register in the MFRC522 chip.
|
||||
* The interface is described in the datasheet section 8.1.2.
|
||||
*/
|
||||
void pcd_write_register_(PcdRegister reg, ///< The register to write to. One of the PCD_Register enums.
|
||||
uint8_t count, ///< The number of uint8_ts to write to the register
|
||||
uint8_t *values ///< The values to write. uint8_t array.
|
||||
);
|
||||
|
||||
StatusCode picc_request_a_(
|
||||
uint8_t *buffer_atqa, ///< The buffer to store the ATQA (Answer to request) in
|
||||
uint8_t *buffer_size ///< Buffer size, at least two uint8_ts. Also number of uint8_ts returned if STATUS_OK.
|
||||
);
|
||||
StatusCode picc_reqa_or_wupa_(
|
||||
uint8_t command, ///< The command to send - PICC_CMD_REQA or PICC_CMD_WUPA
|
||||
uint8_t *buffer_atqa, ///< The buffer to store the ATQA (Answer to request) in
|
||||
uint8_t *buffer_size ///< Buffer size, at least two uint8_ts. Also number of uint8_ts returned if STATUS_OK.
|
||||
);
|
||||
void pcd_set_register_bit_mask_(PcdRegister reg, ///< The register to update. One of the PCD_Register enums.
|
||||
uint8_t mask ///< The bits to set.
|
||||
);
|
||||
void pcd_clear_register_bit_mask_(PcdRegister reg, ///< The register to update. One of the PCD_Register enums.
|
||||
uint8_t mask ///< The bits to clear.
|
||||
);
|
||||
|
||||
StatusCode pcd_transceive_data_(uint8_t *send_data, uint8_t send_len, uint8_t *back_data, uint8_t *back_len,
|
||||
uint8_t *valid_bits = nullptr, uint8_t rx_align = 0, bool check_crc = false);
|
||||
StatusCode pcd_communicate_with_picc_(uint8_t command, uint8_t wait_i_rq, uint8_t *send_data, uint8_t send_len,
|
||||
uint8_t *back_data = nullptr, uint8_t *back_len = nullptr,
|
||||
uint8_t *valid_bits = nullptr, uint8_t rx_align = 0, bool check_crc = false);
|
||||
StatusCode pcd_calculate_crc_(
|
||||
uint8_t *data, ///< In: Pointer to the data to transfer to the FIFO for CRC calculation.
|
||||
uint8_t length, ///< In: The number of uint8_ts to transfer.
|
||||
uint8_t *result ///< Out: Pointer to result buffer. Result is written to result[0..1], low uint8_t first.
|
||||
);
|
||||
RC522::StatusCode picc_is_new_card_present_();
|
||||
bool picc_read_card_serial_();
|
||||
StatusCode picc_select_(
|
||||
Uid *uid, ///< Pointer to Uid struct. Normally output, but can also be used to supply a known UID.
|
||||
uint8_t valid_bits = 0 ///< The number of known UID bits supplied in *uid. Normally 0. If set you must also
|
||||
///< supply uid->size.
|
||||
);
|
||||
|
||||
/** Read a data frame from the RC522 and return the result as a vector.
|
||||
*
|
||||
* Note that is_ready needs to be checked first before requesting this method.
|
||||
*
|
||||
* On failure, an empty vector is returned.
|
||||
*/
|
||||
std::vector<uint8_t> r_c522_read_data_();
|
||||
|
||||
GPIOPin *reset_pin_{nullptr};
|
||||
uint8_t reset_count_{0};
|
||||
uint32_t reset_timeout_{0};
|
||||
bool initialize_pending_{false};
|
||||
std::vector<RC522BinarySensor *> binary_sensors_;
|
||||
std::vector<RC522Trigger *> triggers_;
|
||||
|
||||
enum RC522Error {
|
||||
NONE = 0,
|
||||
RESET_FAILED,
|
||||
} error_code_{NONE};
|
||||
void pcd_write_register(PcdRegister reg, ///< The register to write to. One of the PCD_Register enums.
|
||||
uint8_t count, ///< The number of uint8_ts to write to the register
|
||||
uint8_t *values ///< The values to write. uint8_t array.
|
||||
) override;
|
||||
};
|
||||
|
||||
class RC522BinarySensor : public binary_sensor::BinarySensor {
|
||||
public:
|
||||
void set_uid(const std::vector<uint8_t> &uid) { uid_ = uid; }
|
||||
|
||||
bool process(const uint8_t *data, uint8_t len);
|
||||
|
||||
void on_scan_end() {
|
||||
if (!this->found_) {
|
||||
this->publish_state(false);
|
||||
}
|
||||
this->found_ = false;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::vector<uint8_t> uid_;
|
||||
bool found_{false};
|
||||
};
|
||||
|
||||
class RC522Trigger : public Trigger<std::string> {
|
||||
public:
|
||||
void process(const uint8_t *uid, uint8_t uid_length);
|
||||
};
|
||||
|
||||
#ifndef MFRC522_SPICLOCK
|
||||
#define MFRC522_SPICLOCK SPI_CLOCK_DIV4 // MFRC522 accept upto 10MHz
|
||||
#endif
|
||||
|
||||
} // namespace rc522_spi
|
||||
} // namespace esphome
|
||||
|
||||
+24
-18
@@ -201,7 +201,7 @@ mcp23s08:
|
||||
- id: 'mcp23s08_hub'
|
||||
cs_pin: GPIO12
|
||||
deviceaddress: 0
|
||||
|
||||
|
||||
mcp23s17:
|
||||
- id: 'mcp23s17_hub'
|
||||
cs_pin: GPIO12
|
||||
@@ -813,7 +813,7 @@ esp32_touch:
|
||||
|
||||
binary_sensor:
|
||||
- platform: gpio
|
||||
name: "MCP23S08 Pin #1"
|
||||
name: 'MCP23S08 Pin #1'
|
||||
pin:
|
||||
mcp23s08: mcp23s08_hub
|
||||
# Use pin number 1
|
||||
@@ -822,7 +822,7 @@ binary_sensor:
|
||||
mode: INPUT_PULLUP
|
||||
inverted: False
|
||||
- platform: gpio
|
||||
name: "MCP23S17 Pin #1"
|
||||
name: 'MCP23S17 Pin #1'
|
||||
pin:
|
||||
mcp23s17: mcp23s17_hub
|
||||
# Use pin number 1
|
||||
@@ -1391,7 +1391,7 @@ climate:
|
||||
|
||||
switch:
|
||||
- platform: gpio
|
||||
name: "MCP23S08 Pin #0"
|
||||
name: 'MCP23S08 Pin #0'
|
||||
pin:
|
||||
mcp23s08: mcp23s08_hub
|
||||
# Use pin number 0
|
||||
@@ -1399,7 +1399,7 @@ switch:
|
||||
mode: OUTPUT
|
||||
inverted: False
|
||||
- platform: gpio
|
||||
name: "MCP23S17 Pin #0"
|
||||
name: 'MCP23S17 Pin #0'
|
||||
pin:
|
||||
mcp23s17: mcp23s17_hub
|
||||
# Use pin number 0
|
||||
@@ -1823,6 +1823,12 @@ rc522_spi:
|
||||
- lambda: |-
|
||||
ESP_LOGD("main", "Found tag %s", x.c_str());
|
||||
|
||||
rc522_i2c:
|
||||
update_interval: 1s
|
||||
on_tag:
|
||||
- lambda: |-
|
||||
ESP_LOGD("main", "Found tag %s", x.c_str());
|
||||
|
||||
gps:
|
||||
|
||||
time:
|
||||
@@ -1933,7 +1939,7 @@ text_sensor:
|
||||
value: '0'
|
||||
- canbus.send:
|
||||
can_id: 23
|
||||
data: [ 0x10, 0x20, 0x30 ]
|
||||
data: [0x10, 0x20, 0x30]
|
||||
- platform: template
|
||||
name: Template Text Sensor
|
||||
id: template_text
|
||||
@@ -1967,15 +1973,15 @@ canbus:
|
||||
can_id: 4
|
||||
bit_rate: 50kbps
|
||||
on_frame:
|
||||
- can_id: 500
|
||||
then:
|
||||
- lambda: |-
|
||||
std::string b(x.begin(), x.end());
|
||||
ESP_LOGD("canid 500", "%s", &b[0] );
|
||||
- can_id: 23
|
||||
then:
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return x[0] == 0x11;'
|
||||
then:
|
||||
light.toggle: living_room_lights
|
||||
- can_id: 500
|
||||
then:
|
||||
- lambda: |-
|
||||
std::string b(x.begin(), x.end());
|
||||
ESP_LOGD("canid 500", "%s", &b[0] );
|
||||
- can_id: 23
|
||||
then:
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return x[0] == 0x11;'
|
||||
then:
|
||||
light.toggle: living_room_lights
|
||||
|
||||
Reference in New Issue
Block a user