mirror of https://github.com/arendst/Tasmota.git
Merge pull request #5162 from andrethomas/pn532
PN532: Change from I2C to HSU (Serial)
This commit is contained in:
commit
fda1f1bd9b
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "А"
|
||||
|
|
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "А"
|
||||
|
|
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "安"
|
||||
|
|
|
@ -553,6 +553,8 @@
|
|||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "安"
|
||||
|
|
|
@ -326,9 +326,6 @@
|
|||
// #define USE_DS3231 // Enable DS3231 external RTC in case no Wifi is avaliable. See docs in the source file (+1k2 code)
|
||||
// #define USE_RTC_ADDR 0x68 // Default I2C address 0x68
|
||||
// #define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem)
|
||||
// #define USE_PN532_I2C // Enable PN532 - Near Field Communication (NFC) controller (+1k7 code, 164 bytes of mem)
|
||||
// #define USE_PN532_DATA_FUNCTION // Enable PN532 DATA Usage using Sensor15 command (+1k6 code, 316 bytes of mem)
|
||||
// #define USE_PN532_CAUSE_EVENTS // Enable PN532 driver to cause event's on card read in addition to immediate telemetry (+64 bytes code, 48 bytes mem)
|
||||
// #define USE_MAX44009 // Enable MAX44009 Ambient Light sensor (I2C addresses 0x4A and 0x4B) (+0k8 code)
|
||||
|
||||
// #define USE_DISPLAY // Add I2C Display Support (+2k code)
|
||||
|
@ -378,6 +375,9 @@
|
|||
#define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code)
|
||||
#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer
|
||||
//#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger (+1k6 code)
|
||||
//#define USE_PN532_HSU // Add support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem)
|
||||
// #define USE_PN532_DATA_FUNCTION // Add sensor40 command support for erase, setting data block content (+1k7 code, 388 bytes mem)
|
||||
// #define USE_PN532_DATA_RAW // Allow DATA block to be used by non-alpha-numberic data (+ 80 bytes code, 48 bytes ram)
|
||||
|
||||
// Power monitoring sensors -----------------------
|
||||
#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code)
|
||||
|
|
|
@ -162,6 +162,8 @@ enum UserSelectablePins {
|
|||
GPIO_MCP39F5_TX, // MCP39F501 Serial interface (Shelly2)
|
||||
GPIO_MCP39F5_RX, // MCP39F501 Serial interface (Shelly2)
|
||||
GPIO_MCP39F5_RST, // MCP39F501 Reset (Shelly2)
|
||||
GPIO_PN532_RXD, // PN532 NFC Serial Rx
|
||||
GPIO_PN532_TXD, // PN532 NFC Serial Tx
|
||||
GPIO_SENSOR_END };
|
||||
|
||||
// Programmer selectable GPIO functionality offset by user selectable GPIOs
|
||||
|
@ -227,6 +229,7 @@ const char kSensorNames[] PROGMEM =
|
|||
D_SENSOR_BUTTON "1in|" D_SENSOR_BUTTON "2in|" D_SENSOR_BUTTON "3in|" D_SENSOR_BUTTON "4in|"
|
||||
D_SENSOR_NRG_SEL "|" D_SENSOR_NRG_SEL "i|" D_SENSOR_NRG_CF1 "|" D_SENSOR_HLW_CF "|" D_SENSOR_HJL_CF "|"
|
||||
D_SENSOR_MCP39F5_TX "|" D_SENSOR_MCP39F5_RX "|" D_SENSOR_MCP39F5_RST
|
||||
D_SENSOR_PN532_TX "|" D_SENSOR_PN532_RX
|
||||
;
|
||||
|
||||
/********************************************************************************************/
|
||||
|
@ -546,6 +549,10 @@ const uint8_t kGpioNiceList[] PROGMEM = {
|
|||
GPIO_MAX31855CLK, // MAX31855 Serial interface
|
||||
GPIO_MAX31855DO, // MAX31855 Serial interface
|
||||
#endif
|
||||
#ifdef USE_PN532_HSU
|
||||
GPIO_PN532_RXD, // PN532 HSU Rx
|
||||
GPIO_PN532_TXD, // PN532 HSU Tx
|
||||
#endif
|
||||
};
|
||||
|
||||
const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = {
|
||||
|
|
|
@ -0,0 +1,615 @@
|
|||
/*
|
||||
xsns_40_pn532.ino - Support for PN532 (HSU) NFC Tag Reader
|
||||
|
||||
Copyright (C) 2019 Andre Thomas and Theo Arends
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_PN532_HSU
|
||||
|
||||
#define XSNS_40 40
|
||||
|
||||
#include <TasmotaSerial.h>
|
||||
|
||||
TasmotaSerial *PN532_Serial;
|
||||
|
||||
#define PN532_INVALID_ACK -1
|
||||
#define PN532_TIMEOUT -2
|
||||
#define PN532_INVALID_FRAME -3
|
||||
#define PN532_NO_SPACE -4
|
||||
|
||||
#define PN532_PREAMBLE 0x00
|
||||
#define PN532_STARTCODE1 0x00
|
||||
#define PN532_STARTCODE2 0xFF
|
||||
#define PN532_POSTAMBLE 0x00
|
||||
|
||||
#define PN532_HOSTTOPN532 0xD4
|
||||
#define PN532_PN532TOHOST 0xD5
|
||||
|
||||
#define PN532_ACK_WAIT_TIME 0x0A
|
||||
|
||||
#define PN532_COMMAND_GETFIRMWAREVERSION 0x02
|
||||
#define PN532_COMMAND_SAMCONFIGURATION 0x14
|
||||
#define PN532_COMMAND_RFCONFIGURATION 0x32
|
||||
#define PN532_COMMAND_INDATAEXCHANGE 0x40
|
||||
#define PN532_COMMAND_INLISTPASSIVETARGET 0x4A
|
||||
|
||||
#define PN532_MIFARE_ISO14443A 0x00
|
||||
#define MIFARE_CMD_READ 0x30
|
||||
#define MIFARE_CMD_AUTH_A 0x60
|
||||
#define MIFARE_CMD_AUTH_B 0x61
|
||||
#define MIFARE_CMD_WRITE 0xA0
|
||||
|
||||
uint8_t pn532_model = 0; // Used to maintain detection flag
|
||||
uint8_t pn532_command = 0; // Used to carry command code between functions
|
||||
uint8_t pn532_scantimer = 0; // Used to prevent multiple successful reads within 2 second window
|
||||
|
||||
uint8_t pn532_packetbuffer[64]; // Global buffer used to store packet
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
uint8_t pn532_function = 0;
|
||||
uint8_t pn532_newdata[16];
|
||||
uint8_t pn532_newdata_len = 0;
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
void PN532_Init(void)
|
||||
{
|
||||
if ((pin[GPIO_PN532_RXD] < 99) && (pin[GPIO_PN532_TXD] < 99)) {
|
||||
PN532_Serial = new TasmotaSerial(pin[GPIO_PN532_RXD], pin[GPIO_PN532_TXD], 1);
|
||||
if (PN532_Serial->begin(115200)) {
|
||||
if (PN532_Serial->hardwareSerial()) { ClaimSerial(); }
|
||||
PN532_wakeup();
|
||||
uint32_t ver = PN532_getFirmwareVersion();
|
||||
if (ver) {
|
||||
PN532_setPassiveActivationRetries(0xFF);
|
||||
PN532_SAMConfig();
|
||||
pn532_model = 1;
|
||||
snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC Reader detected (V%u.%u)",(ver>>16) & 0xFF, (ver>>8) & 0xFF);
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int8_t PN532_receive(uint8_t *buf, int len, uint16_t timeout)
|
||||
{
|
||||
int read_bytes = 0;
|
||||
int ret;
|
||||
unsigned long start_millis;
|
||||
while (read_bytes < len) {
|
||||
start_millis = millis();
|
||||
do {
|
||||
ret = PN532_Serial->read();
|
||||
if (ret >= 0) {
|
||||
break;
|
||||
}
|
||||
} while((timeout == 0) || ((millis()- start_millis ) < timeout));
|
||||
|
||||
if (ret < 0) {
|
||||
if (read_bytes) {
|
||||
return read_bytes;
|
||||
} else {
|
||||
return PN532_TIMEOUT;
|
||||
}
|
||||
}
|
||||
buf[read_bytes] = (uint8_t)ret;
|
||||
read_bytes++;
|
||||
}
|
||||
return read_bytes;
|
||||
}
|
||||
|
||||
int8_t PN532_readAckFrame(void)
|
||||
{
|
||||
const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0};
|
||||
uint8_t ackBuf[sizeof(PN532_ACK)];
|
||||
|
||||
if (PN532_receive(ackBuf, sizeof(PN532_ACK), PN532_ACK_WAIT_TIME) <= 0) {
|
||||
return PN532_TIMEOUT;
|
||||
}
|
||||
|
||||
if (memcmp(&ackBuf, &PN532_ACK, sizeof(PN532_ACK))) {
|
||||
return PN532_INVALID_ACK;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t PN532_writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0)
|
||||
{
|
||||
// Clear the serial buffer just in case
|
||||
while(PN532_Serial->available()) { PN532_Serial->read(); }
|
||||
|
||||
pn532_command = header[0];
|
||||
PN532_Serial->write((uint8_t)PN532_PREAMBLE);
|
||||
PN532_Serial->write((uint8_t)PN532_STARTCODE1);
|
||||
PN532_Serial->write(PN532_STARTCODE2);
|
||||
|
||||
uint8_t length = hlen + blen + 1; // length of data field: TFI + DATA
|
||||
PN532_Serial->write(length);
|
||||
PN532_Serial->write(~length + 1); // checksum of length
|
||||
|
||||
PN532_Serial->write(PN532_HOSTTOPN532);
|
||||
uint8_t sum = PN532_HOSTTOPN532; // sum of TFI + DATA
|
||||
|
||||
PN532_Serial->write(header, hlen);
|
||||
for (uint8_t i = 0; i < hlen; i++) {
|
||||
sum += header[i];
|
||||
}
|
||||
|
||||
PN532_Serial->write(body, blen);
|
||||
for (uint8_t i = 0; i < blen; i++) {
|
||||
sum += body[i];
|
||||
}
|
||||
|
||||
uint8_t checksum = ~sum + 1; // checksum of TFI + DATA
|
||||
PN532_Serial->write(checksum);
|
||||
PN532_Serial->write((uint8_t)PN532_POSTAMBLE);
|
||||
|
||||
return PN532_readAckFrame();
|
||||
}
|
||||
|
||||
int16_t PN532_readResponse(uint8_t buf[], uint8_t len, uint16_t timeout = 50)
|
||||
{
|
||||
uint8_t tmp[3];
|
||||
|
||||
// Read preamble and start code
|
||||
if (PN532_receive(tmp, 3, timeout)<=0) {
|
||||
return PN532_TIMEOUT;
|
||||
}
|
||||
if (0 != tmp[0] || 0!= tmp[1] || 0xFF != tmp[2]) {
|
||||
return PN532_INVALID_FRAME;
|
||||
}
|
||||
|
||||
// Get length of data to be received
|
||||
uint8_t length[2];
|
||||
if (PN532_receive(length, 2, timeout) <= 0) {
|
||||
return PN532_TIMEOUT;
|
||||
}
|
||||
// Validate that frame is valid
|
||||
if (0 != (uint8_t)(length[0] + length[1])) {
|
||||
return PN532_INVALID_FRAME;
|
||||
}
|
||||
length[0] -= 2;
|
||||
if (length[0] > len) { // If this happens, then pn532_packetbuffer is not large enough
|
||||
return PN532_NO_SPACE;
|
||||
}
|
||||
|
||||
// Get the command byte
|
||||
uint8_t cmd = pn532_command + 1;
|
||||
if (PN532_receive(tmp, 2, timeout) <= 0) { // Time out while receiving
|
||||
return PN532_TIMEOUT;
|
||||
}
|
||||
if (PN532_PN532TOHOST != tmp[0] || cmd != tmp[1]) { // Invalid frame received
|
||||
return PN532_INVALID_FRAME;
|
||||
}
|
||||
|
||||
if (PN532_receive(buf, length[0], timeout) != length[0]) { // Timed out
|
||||
return PN532_TIMEOUT;
|
||||
}
|
||||
|
||||
uint8_t sum = PN532_PN532TOHOST + cmd;
|
||||
for (uint8_t i=0; i<length[0]; i++) {
|
||||
sum += buf[i];
|
||||
}
|
||||
|
||||
// Checksum & postamble
|
||||
if (PN532_receive(tmp, 2, timeout) <= 0) {
|
||||
return PN532_TIMEOUT;
|
||||
}
|
||||
if (0 != (uint8_t)(sum + tmp[0]) || 0 != tmp[1]) { // Checksum fail, so frame must be invalid
|
||||
return PN532_INVALID_FRAME;
|
||||
}
|
||||
|
||||
return length[0];
|
||||
}
|
||||
|
||||
uint32_t PN532_getFirmwareVersion(void)
|
||||
{
|
||||
uint32_t response;
|
||||
|
||||
pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION;
|
||||
|
||||
if (PN532_writeCommand(pn532_packetbuffer, 1)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read data packet
|
||||
int16_t status = PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer));
|
||||
if (0 > status) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
response = pn532_packetbuffer[0];
|
||||
response <<= 8;
|
||||
response |= pn532_packetbuffer[1];
|
||||
response <<= 8;
|
||||
response |= pn532_packetbuffer[2];
|
||||
response <<= 8;
|
||||
response |= pn532_packetbuffer[3];
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
void PN532_wakeup(void)
|
||||
{
|
||||
uint8_t wakeup[5] = {0x55, 0x55, 0, 0, 0 };
|
||||
PN532_Serial->write(wakeup,sizeof(wakeup));
|
||||
|
||||
// Flush the serial buffer just in case there's garbage in there
|
||||
while(PN532_Serial->available()) { PN532_Serial->read(); }
|
||||
}
|
||||
|
||||
bool PN532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout = 50)
|
||||
{
|
||||
pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
|
||||
pn532_packetbuffer[1] = 1; // max 1 cards at once (we can set this to 2 later)
|
||||
pn532_packetbuffer[2] = cardbaudrate;
|
||||
if (PN532_writeCommand(pn532_packetbuffer, 3)) {
|
||||
return 0x0; // command failed
|
||||
}
|
||||
// read data packet
|
||||
if (PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout) < 0) {
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
/* Check some basic stuff
|
||||
b0 Tags Found
|
||||
b1 Tag Number (only one used in this example)
|
||||
b2..3 SENS_RES
|
||||
b4 SEL_RES
|
||||
b5 NFCID Length
|
||||
b6..NFCIDLen NFCID
|
||||
*/
|
||||
|
||||
if (pn532_packetbuffer[0] != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t sens_res = pn532_packetbuffer[2];
|
||||
sens_res <<= 8;
|
||||
sens_res |= pn532_packetbuffer[3];
|
||||
|
||||
/* Card appears to be Mifare Classic */
|
||||
*uidLength = pn532_packetbuffer[5];
|
||||
|
||||
for (uint8_t i = 0; i < pn532_packetbuffer[5]; i++) {
|
||||
uid[i] = pn532_packetbuffer[6 + i];
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool PN532_setPassiveActivationRetries(uint8_t maxRetries)
|
||||
{
|
||||
pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION;
|
||||
pn532_packetbuffer[1] = 5; // Config item 5 (MaxRetries)
|
||||
pn532_packetbuffer[2] = 0xFF; // MxRtyATR (default = 0xFF)
|
||||
pn532_packetbuffer[3] = 0x01; // MxRtyPSL (default = 0x01)
|
||||
pn532_packetbuffer[4] = maxRetries;
|
||||
if (PN532_writeCommand(pn532_packetbuffer, 5)) {
|
||||
return 0; // no ACK
|
||||
}
|
||||
return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
|
||||
}
|
||||
|
||||
bool PN532_SAMConfig(void)
|
||||
{
|
||||
pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION;
|
||||
pn532_packetbuffer[1] = 0x01; // normal mode
|
||||
pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second
|
||||
pn532_packetbuffer[3] = 0x00; // we don't need the external IRQ pin
|
||||
if (PN532_writeCommand(pn532_packetbuffer, 4)) {
|
||||
return false;
|
||||
}
|
||||
return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
|
||||
}
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
|
||||
uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t _key[6];
|
||||
uint8_t _uid[7];
|
||||
uint8_t _uidLen;
|
||||
|
||||
// Hang on to the key and uid data
|
||||
memcpy(&_key, keyData, 6);
|
||||
memcpy(&_uid, uid, uidLen);
|
||||
_uidLen = uidLen;
|
||||
|
||||
// Prepare the authentication command //
|
||||
pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; /* Data Exchange Header */
|
||||
pn532_packetbuffer[1] = 1; /* Max card numbers */
|
||||
pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A;
|
||||
pn532_packetbuffer[3] = blockNumber; /* Block Number (1K = 0..63, 4K = 0..255 */
|
||||
memcpy(&pn532_packetbuffer[4], &_key, 6);
|
||||
for (i = 0; i < _uidLen; i++) {
|
||||
pn532_packetbuffer[10 + i] = _uid[i]; /* 4 bytes card ID */
|
||||
}
|
||||
|
||||
if (PN532_writeCommand(pn532_packetbuffer, 10 + _uidLen)) { return 0; }
|
||||
|
||||
// Read the response packet
|
||||
PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer));
|
||||
|
||||
// Check if the response is valid and we are authenticated???
|
||||
// for an auth success it should be bytes 5-7: 0xD5 0x41 0x00
|
||||
// Mifare auth error is technically byte 7: 0x14 but anything other and 0x00 is not good
|
||||
if (pn532_packetbuffer[0] != 0x00) {
|
||||
// Authentification failed
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data)
|
||||
{
|
||||
/* Prepare the command */
|
||||
pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
|
||||
pn532_packetbuffer[1] = 1; /* Card number */
|
||||
pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */
|
||||
pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */
|
||||
|
||||
/* Send the command */
|
||||
if (PN532_writeCommand(pn532_packetbuffer, 4)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the response packet */
|
||||
PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer));
|
||||
|
||||
/* If byte 8 isn't 0x00 we probably have an error */
|
||||
if (pn532_packetbuffer[0] != 0x00) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy the 16 data bytes to the output buffer */
|
||||
/* Block content starts at byte 9 of a valid response */
|
||||
memcpy (data, &pn532_packetbuffer[1], 16);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data)
|
||||
{
|
||||
/* Prepare the first command */
|
||||
pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
|
||||
pn532_packetbuffer[1] = 1; /* Card number */
|
||||
pn532_packetbuffer[2] = MIFARE_CMD_WRITE; /* Mifare Write command = 0xA0 */
|
||||
pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */
|
||||
memcpy(&pn532_packetbuffer[4], data, 16); /* Data Payload */
|
||||
|
||||
/* Send the command */
|
||||
if (PN532_writeCommand(pn532_packetbuffer, 20)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the response packet */
|
||||
return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
|
||||
}
|
||||
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
void PN532_ScanForTag(void)
|
||||
{
|
||||
if (!pn532_model) { return; }
|
||||
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };
|
||||
uint8_t uid_len = 0;
|
||||
uint8_t card_data[16];
|
||||
bool erase_success = false;
|
||||
bool set_success = false;
|
||||
if (PN532_readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uid_len)) {
|
||||
char uids[15];
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
char card_datas[34];
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
sprintf(uids,"");
|
||||
for (uint8_t i = 0;i < uid_len;i++) {
|
||||
sprintf(uids,"%s%02X",uids,uid[i]);
|
||||
}
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
if (uid_len == 4) { // Lets try to read block 1 of the mifare classic card for more information
|
||||
uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
if (mifareclassic_AuthenticateBlock (uid, uid_len, 1, 1, keyuniversal)) {
|
||||
if (mifareclassic_ReadDataBlock(1, card_data)) {
|
||||
#ifdef USE_PN532_DATA_RAW
|
||||
memcpy(&card_datas,&card_data,sizeof(card_data));
|
||||
#else
|
||||
for (uint8_t i = 0;i < sizeof(card_data);i++) {
|
||||
if ((isalpha(card_data[i])) || ((isdigit(card_data[i])))) {
|
||||
card_datas[i] = char(card_data[i]);
|
||||
} else {
|
||||
card_datas[i] = '\0';
|
||||
}
|
||||
}
|
||||
#endif // USE_PN532_DATA_RAW
|
||||
}
|
||||
if (pn532_function == 1) { // erase block 1 of card
|
||||
for (uint8_t i = 0;i<16;i++) {
|
||||
card_data[i] = 0x00;
|
||||
}
|
||||
if (mifareclassic_WriteDataBlock(1, card_data)) {
|
||||
erase_success = true;
|
||||
snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Erase success");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string
|
||||
}
|
||||
}
|
||||
if (pn532_function == 2) {
|
||||
#ifdef USE_PN532_DATA_RAW
|
||||
memcpy(&card_data,&pn532_newdata,sizeof(card_data));
|
||||
if (mifareclassic_WriteDataBlock(1, card_data)) {
|
||||
set_success = true;
|
||||
snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Data write successful");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string
|
||||
}
|
||||
#else
|
||||
bool IsAlphaNumeric = true;
|
||||
for (uint8_t i = 0;i < pn532_newdata_len;i++) {
|
||||
if ((!isalpha(pn532_newdata[i])) && (!isdigit(pn532_newdata[i]))) {
|
||||
IsAlphaNumeric = false;
|
||||
}
|
||||
}
|
||||
if (IsAlphaNumeric) {
|
||||
memcpy(&card_data,&pn532_newdata,pn532_newdata_len);
|
||||
card_data[pn532_newdata_len] = '\0'; // Enforce null termination
|
||||
if (mifareclassic_WriteDataBlock(1, card_data)) {
|
||||
set_success = true;
|
||||
snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Data write successful");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string
|
||||
}
|
||||
} else {
|
||||
snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Data must be alphanumeric");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
}
|
||||
#endif // USE_PN532_DATA_RAW
|
||||
}
|
||||
} else {
|
||||
sprintf(card_datas,"AUTHFAIL");
|
||||
}
|
||||
}
|
||||
switch (pn532_function) {
|
||||
case 0x01:
|
||||
if (!erase_success) {
|
||||
snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Erase fail - exiting erase mode");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
}
|
||||
break;
|
||||
case 0x02:
|
||||
if (!set_success) {
|
||||
snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Write failed - exiting set mode");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pn532_function = 0;
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), mqtt_data, uids, card_datas);
|
||||
#else
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\"}}"), mqtt_data, uids);
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||
|
||||
#ifdef USE_PN532_CAUSE_EVENTS
|
||||
|
||||
char command[71];
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
sprintf(command,"backlog event PN532_UID=%s;event PN532_DATA=%s",uids,card_datas);
|
||||
#else
|
||||
sprintf(command,"event PN532_UID=%s",uids);
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
ExecuteCommand(command, SRC_RULE);
|
||||
#endif // USE_PN532_CAUSE_EVENTS
|
||||
|
||||
pn532_scantimer = 7; // Ignore tags found for two seconds
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
|
||||
bool PN532_Command(void)
|
||||
{
|
||||
bool serviced = true;
|
||||
uint8_t paramcount = 0;
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
paramcount=1;
|
||||
} else {
|
||||
serviced = false;
|
||||
return serviced;
|
||||
}
|
||||
char sub_string[XdrvMailbox.data_len];
|
||||
char sub_string_tmp[XdrvMailbox.data_len];
|
||||
for (uint8_t ca=0;ca<XdrvMailbox.data_len;ca++) {
|
||||
if ((' ' == XdrvMailbox.data[ca]) || ('=' == XdrvMailbox.data[ca])) { XdrvMailbox.data[ca] = ','; }
|
||||
if (',' == XdrvMailbox.data[ca]) { paramcount++; }
|
||||
}
|
||||
UpperCase(XdrvMailbox.data,XdrvMailbox.data);
|
||||
if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"E")) {
|
||||
pn532_function = 1; // Block 1 of next card/tag will be reset to 0x00...
|
||||
snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Next scanned tag data block 1 will be erased");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"COMMAND\":\"E\"\"}}"), mqtt_data);
|
||||
return serviced;
|
||||
}
|
||||
if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"S")) {
|
||||
if (paramcount > 1) {
|
||||
if (XdrvMailbox.data[XdrvMailbox.data_len-1] == ',') {
|
||||
serviced = false;
|
||||
return serviced;
|
||||
}
|
||||
sprintf(sub_string_tmp,subStr(sub_string, XdrvMailbox.data, ",", 2));
|
||||
pn532_newdata_len = strlen(sub_string_tmp);
|
||||
if (pn532_newdata_len > 15) { pn532_newdata_len = 15; }
|
||||
memcpy(&pn532_newdata,&sub_string_tmp,pn532_newdata_len);
|
||||
pn532_newdata[pn532_newdata_len] = 0x00; // Null terminate the string
|
||||
pn532_function = 2;
|
||||
snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Next scanned tag data block 1 will be set to '%s'",pn532_newdata);
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"COMMAND\":\"S\"\"}}"), mqtt_data);
|
||||
return serviced;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
bool Xsns40(uint8_t function)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
switch (function) {
|
||||
case FUNC_INIT:
|
||||
PN532_Init();
|
||||
result = true;
|
||||
break;
|
||||
case FUNC_EVERY_50_MSECOND:
|
||||
break;
|
||||
case FUNC_EVERY_100_MSECOND:
|
||||
break;
|
||||
case FUNC_EVERY_250_MSECOND:
|
||||
if (pn532_scantimer > 0) {
|
||||
pn532_scantimer--;
|
||||
} else {
|
||||
PN532_ScanForTag();
|
||||
}
|
||||
break;
|
||||
case FUNC_EVERY_SECOND:
|
||||
break;
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
case FUNC_COMMAND:
|
||||
if (XSNS_40 == XdrvMailbox.index) {
|
||||
result = PN532_Command();
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_PN532_HSU
|
|
@ -1,606 +0,0 @@
|
|||
/*
|
||||
xsns_40_pn532.ino - Support for PN532 (I2C) NFC Tag Reader
|
||||
|
||||
Copyright (C) 2019 Andre Thomas and Theo Arends
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_I2C
|
||||
#ifdef USE_PN532_I2C
|
||||
|
||||
/*********************************************************************************************\
|
||||
* PN532 - Near Field Communication (NFC) controller
|
||||
*
|
||||
* Datasheet at https://www.nxp.com/docs/en/nxp/data-sheets/PN532_C1.pdf
|
||||
*
|
||||
* I2C Address: 0x24
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_40 40
|
||||
|
||||
#define PN532_I2C_ADDRESS 0x24
|
||||
|
||||
#define PN532_COMMAND_GETFIRMWAREVERSION 0x02
|
||||
#define PN532_COMMAND_SAMCONFIGURATION 0x14
|
||||
#define PN532_COMMAND_INDATAEXCHANGE 0x40
|
||||
#define PN532_COMMAND_INLISTPASSIVETARGET 0x4A
|
||||
|
||||
#define MIFARE_CMD_READ 0x30
|
||||
#define MIFARE_CMD_AUTH_A 0x60
|
||||
#define MIFARE_CMD_AUTH_B 0x61
|
||||
#define MIFARE_CMD_WRITE 0xA0
|
||||
|
||||
#define PN532_PREAMBLE 0x00
|
||||
#define PN532_STARTCODE1 0x00
|
||||
#define PN532_STARTCODE2 0xFF
|
||||
#define PN532_POSTAMBLE 0x00
|
||||
|
||||
#define PN532_HOSTTOPN532 0xD4
|
||||
#define PN532_PN532TOHOST 0xD5
|
||||
|
||||
#define PN532_INVALID_ACK -1
|
||||
#define PN532_TIMEOUT -2
|
||||
#define PN532_INVALID_FRAME -3
|
||||
#define PN532_NO_SPACE -4
|
||||
|
||||
#define PN532_MIFARE_ISO14443A 0x00
|
||||
|
||||
uint8_t pn532_i2c_detected = 0;
|
||||
uint8_t pn532_i2c_packetbuffer[64];
|
||||
uint8_t pn532_i2c_scan_defer_report = 0; // If a valid card was found we will not scan for one again in the same two seconds so we set this to 19 if a card was found
|
||||
uint8_t pn532_i2c_command = 0;
|
||||
|
||||
uint8_t pn532_i2c_disable = 0;
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
uint8_t pn532_i2c_function = 0;
|
||||
uint8_t pn532_i2c_newdata[16];
|
||||
uint8_t pn532_i2c_newdata_len = 0;
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
const uint8_t PROGMEM pn532_global_timeout = 10;
|
||||
|
||||
int16_t PN532_getResponseLength(uint8_t buf[], uint8_t len) {
|
||||
const uint8_t PN532_NACK[] = {0, 0, 0xFF, 0xFF, 0, 0};
|
||||
uint8_t time = 0;
|
||||
do {
|
||||
if (Wire.requestFrom(PN532_I2C_ADDRESS, 6)) {
|
||||
if (Wire.read() & 1) { // check first byte --- status
|
||||
break; // PN532 is ready
|
||||
}
|
||||
}
|
||||
delay(1);
|
||||
time++;
|
||||
if (time > pn532_global_timeout) {
|
||||
return -1;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
if ((0x00 != Wire.read()) || (0x00 != Wire.read()) || (0xFF != Wire.read())) { // PREAMBLE || STARTCODE1 || STARTCODE2
|
||||
return PN532_INVALID_FRAME;
|
||||
}
|
||||
|
||||
uint8_t length = Wire.read();
|
||||
|
||||
// request for last respond msg again
|
||||
Wire.beginTransmission(PN532_I2C_ADDRESS);
|
||||
for (uint16_t i = 0;i < sizeof(PN532_NACK); ++i) {
|
||||
Wire.write(PN532_NACK[i]);
|
||||
}
|
||||
Wire.endTransmission();
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
int16_t PN532_readResponse(uint8_t buf[], uint8_t len)
|
||||
{
|
||||
uint8_t time = 0;
|
||||
uint8_t length;
|
||||
|
||||
length = PN532_getResponseLength(buf, len);
|
||||
|
||||
// [RDY] 00 00 FF LEN LCS (TFI PD0 ... PDn) DCS 00
|
||||
|
||||
do {
|
||||
if (Wire.requestFrom(PN532_I2C_ADDRESS, 6 + length + 2)) {
|
||||
if (Wire.read() & 1) { // check first byte --- status
|
||||
break; // PN532 is ready
|
||||
}
|
||||
}
|
||||
delay(1);
|
||||
time++;
|
||||
if (time > pn532_global_timeout) {
|
||||
return -1;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
if ((0x00 != Wire.read()) || (0x00 != Wire.read()) || (0xFF != Wire.read())) { // PREAMBLE || STARTCODE1 || STARTCODE2
|
||||
return PN532_INVALID_FRAME;
|
||||
}
|
||||
|
||||
length = Wire.read();
|
||||
|
||||
if (0 != (uint8_t)(length + Wire.read())) { // checksum of length
|
||||
return PN532_INVALID_FRAME;
|
||||
}
|
||||
|
||||
uint8_t cmd = pn532_i2c_command + 1; // response command
|
||||
if ((PN532_PN532TOHOST != Wire.read()) || ((cmd) != Wire.read())) {
|
||||
return PN532_INVALID_FRAME;
|
||||
}
|
||||
length -= 2;
|
||||
if (length > len) {
|
||||
return PN532_NO_SPACE; // not enough space
|
||||
}
|
||||
uint8_t sum = PN532_PN532TOHOST + cmd;
|
||||
for (uint8_t i = 0; i < length; i++) {
|
||||
buf[i] = Wire.read();
|
||||
sum += buf[i];
|
||||
}
|
||||
uint8_t checksum = Wire.read();
|
||||
if (0 != (uint8_t)(sum + checksum)) {
|
||||
return PN532_INVALID_FRAME;
|
||||
}
|
||||
Wire.read(); // POSTAMBLE
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
int8_t PN532_readAckFrame(void)
|
||||
{
|
||||
const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0};
|
||||
uint8_t ackBuf[sizeof(PN532_ACK)];
|
||||
|
||||
uint8_t time = 0;
|
||||
|
||||
do {
|
||||
if (Wire.requestFrom(PN532_I2C_ADDRESS, sizeof(PN532_ACK) + 1)) {
|
||||
if (Wire.read() & 1) { // check first byte --- status
|
||||
break; // PN532 is ready
|
||||
}
|
||||
}
|
||||
delay(1);
|
||||
time++;
|
||||
if (time > pn532_global_timeout) { // We time out after 10ms
|
||||
return PN532_TIMEOUT;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
for (uint8_t i = 0; i < sizeof(PN532_ACK); i++) {
|
||||
ackBuf[i] = Wire.read();
|
||||
}
|
||||
|
||||
if (memcmp(ackBuf, PN532_ACK, sizeof(PN532_ACK))) {
|
||||
return PN532_INVALID_ACK;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t PN532_writeCommand(const uint8_t *header, uint8_t hlen)
|
||||
{
|
||||
pn532_i2c_command = header[0];
|
||||
Wire.beginTransmission(PN532_I2C_ADDRESS);
|
||||
Wire.write(PN532_PREAMBLE);
|
||||
Wire.write(PN532_STARTCODE1);
|
||||
Wire.write(PN532_STARTCODE2);
|
||||
uint8_t length = hlen + 1; // TFI + DATA
|
||||
Wire.write(length);
|
||||
Wire.write(~length + 1); // checksum of length
|
||||
Wire.write(PN532_HOSTTOPN532);
|
||||
uint8_t sum = PN532_HOSTTOPN532; // Sum of TFI + DATA
|
||||
for (uint8_t i = 0; i < hlen; i++) {
|
||||
if (Wire.write(header[i])) {
|
||||
sum += header[i];
|
||||
} else {
|
||||
return PN532_INVALID_FRAME;
|
||||
}
|
||||
}
|
||||
uint8_t checksum = ~sum + 1; // Checksum of TFI + DATA
|
||||
Wire.write(checksum);
|
||||
Wire.write(PN532_POSTAMBLE);
|
||||
Wire.endTransmission();
|
||||
return PN532_readAckFrame();
|
||||
}
|
||||
|
||||
uint32_t PN532_getFirmwareVersion(void)
|
||||
{
|
||||
uint32_t response;
|
||||
pn532_i2c_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION;
|
||||
if (PN532_writeCommand(pn532_i2c_packetbuffer, 1)) {
|
||||
return 0;
|
||||
}
|
||||
int16_t status = PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer));
|
||||
if (0 > status) {
|
||||
return 0;
|
||||
}
|
||||
response = pn532_i2c_packetbuffer[0];
|
||||
response <<= 8;
|
||||
response |= pn532_i2c_packetbuffer[1];
|
||||
response <<= 8;
|
||||
response |= pn532_i2c_packetbuffer[2];
|
||||
response <<= 8;
|
||||
response |= pn532_i2c_packetbuffer[3];
|
||||
return response;
|
||||
}
|
||||
|
||||
bool PN532_SAMConfig(void)
|
||||
{
|
||||
pn532_i2c_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION;
|
||||
pn532_i2c_packetbuffer[1] = 0x01; // normal mode;
|
||||
pn532_i2c_packetbuffer[2] = 0x01; // timeout 50ms * 1 = 50ms
|
||||
pn532_i2c_packetbuffer[3] = 0x00; // Disable IRQ pin
|
||||
|
||||
if (PN532_writeCommand(pn532_i2c_packetbuffer, 4))
|
||||
return false;
|
||||
|
||||
return (0 < PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer)));
|
||||
}
|
||||
|
||||
void PN532_Detect(void)
|
||||
{
|
||||
if ((pn532_i2c_detected) || (pn532_i2c_disable)) { return; }
|
||||
|
||||
Wire.setClockStretchLimit(1000); // Enable 1ms clock stretch as per datasheet Table 12.25 (Timing for the I2C interface)
|
||||
|
||||
uint32_t ver = PN532_getFirmwareVersion();
|
||||
if (ver) {
|
||||
pn532_i2c_detected = 1;
|
||||
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "PN532 NFC Reader (V%u.%u)", PN532_I2C_ADDRESS);
|
||||
snprintf_P(log_data, sizeof(log_data), log_data, (ver>>16) & 0xFF, (ver>>8) & 0xFF);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
PN532_SAMConfig();
|
||||
}
|
||||
}
|
||||
|
||||
bool PN532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength)
|
||||
{
|
||||
pn532_i2c_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
|
||||
pn532_i2c_packetbuffer[1] = 1;
|
||||
pn532_i2c_packetbuffer[2] = cardbaudrate;
|
||||
|
||||
if (PN532_writeCommand(pn532_i2c_packetbuffer, 3)) {
|
||||
return false; // command failed
|
||||
}
|
||||
|
||||
if (PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer)) < 0) { // No data packet so no tag was found
|
||||
Wire.beginTransmission(PN532_I2C_ADDRESS);
|
||||
Wire.endTransmission();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pn532_i2c_packetbuffer[0] != 1) { return false; } // Not a valid tag
|
||||
|
||||
*uidLength = pn532_i2c_packetbuffer[5];
|
||||
for (uint8_t i = 0;i < pn532_i2c_packetbuffer[5]; i++) {
|
||||
uid[i] = pn532_i2c_packetbuffer[6 + i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
|
||||
uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t _key[6];
|
||||
uint8_t _uid[7];
|
||||
uint8_t _uidLen;
|
||||
|
||||
// Hang on to the key and uid data
|
||||
memcpy (_key, keyData, 6);
|
||||
memcpy (_uid, uid, uidLen);
|
||||
_uidLen = uidLen;
|
||||
|
||||
// Prepare the authentication command //
|
||||
pn532_i2c_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; /* Data Exchange Header */
|
||||
pn532_i2c_packetbuffer[1] = 1; /* Max card numbers */
|
||||
pn532_i2c_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A;
|
||||
pn532_i2c_packetbuffer[3] = blockNumber; /* Block Number (1K = 0..63, 4K = 0..255 */
|
||||
memcpy (&pn532_i2c_packetbuffer[4], _key, 6);
|
||||
for (i = 0; i < _uidLen; i++) {
|
||||
pn532_i2c_packetbuffer[10 + i] = _uid[i]; /* 4 bytes card ID */
|
||||
}
|
||||
|
||||
if (PN532_writeCommand(pn532_i2c_packetbuffer, 10 + _uidLen))
|
||||
return 0;
|
||||
|
||||
// Read the response packet
|
||||
PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer));
|
||||
|
||||
// Check if the response is valid and we are authenticated???
|
||||
// for an auth success it should be bytes 5-7: 0xD5 0x41 0x00
|
||||
// Mifare auth error is technically byte 7: 0x14 but anything other and 0x00 is not good
|
||||
if (pn532_i2c_packetbuffer[0] != 0x00) {
|
||||
// Authentification failed
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data)
|
||||
{
|
||||
/* Prepare the command */
|
||||
pn532_i2c_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
|
||||
pn532_i2c_packetbuffer[1] = 1; /* Card number */
|
||||
pn532_i2c_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */
|
||||
pn532_i2c_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */
|
||||
|
||||
/* Send the command */
|
||||
if (PN532_writeCommand(pn532_i2c_packetbuffer, 4)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the response packet */
|
||||
PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer));
|
||||
|
||||
/* If byte 8 isn't 0x00 we probably have an error */
|
||||
if (pn532_i2c_packetbuffer[0] != 0x00) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy the 16 data bytes to the output buffer */
|
||||
/* Block content starts at byte 9 of a valid response */
|
||||
memcpy (data, &pn532_i2c_packetbuffer[1], 16);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data)
|
||||
{
|
||||
/* Prepare the first command */
|
||||
pn532_i2c_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
|
||||
pn532_i2c_packetbuffer[1] = 1; /* Card number */
|
||||
pn532_i2c_packetbuffer[2] = MIFARE_CMD_WRITE; /* Mifare Write command = 0xA0 */
|
||||
pn532_i2c_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */
|
||||
memcpy(&pn532_i2c_packetbuffer[4], data, 16); /* Data Payload */
|
||||
|
||||
/* Send the command */
|
||||
if (PN532_writeCommand(pn532_i2c_packetbuffer, 20)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the response packet */
|
||||
return (0 < PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer)));
|
||||
}
|
||||
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
void PN532_ScanForTag(void)
|
||||
{
|
||||
if (pn532_i2c_disable) { return; }
|
||||
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };
|
||||
uint8_t uid_len = 0;
|
||||
uint8_t card_data[16];
|
||||
bool erase_success = false;
|
||||
bool set_success = false;
|
||||
if (PN532_readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uid_len)) {
|
||||
if (pn532_i2c_scan_defer_report > 0) {
|
||||
pn532_i2c_scan_defer_report--;
|
||||
} else {
|
||||
char uids[15];
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
char card_datas[34];
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
sprintf(uids,"");
|
||||
for (uint8_t i = 0;i < uid_len;i++) {
|
||||
sprintf(uids,"%s%02X",uids,uid[i]);
|
||||
}
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
if (uid_len == 4) { // Lets try to read block 0 of the mifare classic card for more information
|
||||
uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
if (mifareclassic_AuthenticateBlock (uid, uid_len, 1, 1, keyuniversal)) {
|
||||
if (mifareclassic_ReadDataBlock(1, card_data)) {
|
||||
#ifdef USE_PN532_DATA_RAW
|
||||
memcpy(&card_datas,&card_data,sizeof(card_data));
|
||||
#else
|
||||
for (uint8_t i = 0;i < sizeof(card_data);i++) {
|
||||
if ((isalpha(card_data[i])) || ((isdigit(card_data[i])))) {
|
||||
card_datas[i] = char(card_data[i]);
|
||||
} else {
|
||||
card_datas[i] = '\0';
|
||||
}
|
||||
}
|
||||
#endif // USE_PN532_DATA_RAW
|
||||
}
|
||||
if (pn532_i2c_function == 1) { // erase block 1 of card
|
||||
for (uint8_t i = 0;i<16;i++) {
|
||||
card_data[i] = 0x00;
|
||||
}
|
||||
if (mifareclassic_WriteDataBlock(1, card_data)) {
|
||||
erase_success = true;
|
||||
snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Erase success");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string
|
||||
}
|
||||
}
|
||||
if (pn532_i2c_function == 2) {
|
||||
#ifdef USE_PN532_DATA_RAW
|
||||
memcpy(&card_data,&pn532_i2c_newdata,sizeof(card_data));
|
||||
if (mifareclassic_WriteDataBlock(1, card_data)) {
|
||||
set_success = true;
|
||||
snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data write successful");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string
|
||||
}
|
||||
#else
|
||||
bool IsAlphaNumeric = true;
|
||||
for (uint8_t i = 0;i < pn532_i2c_newdata_len;i++) {
|
||||
if ((!isalpha(pn532_i2c_newdata[i])) && (!isdigit(pn532_i2c_newdata[i]))) {
|
||||
IsAlphaNumeric = false;
|
||||
}
|
||||
}
|
||||
if (IsAlphaNumeric) {
|
||||
memcpy(&card_data,&pn532_i2c_newdata,pn532_i2c_newdata_len);
|
||||
card_data[pn532_i2c_newdata_len] = '\0'; // Enforce null termination
|
||||
if (mifareclassic_WriteDataBlock(1, card_data)) {
|
||||
set_success = true;
|
||||
snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data write successful");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string
|
||||
}
|
||||
} else {
|
||||
snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data must be alphanumeric");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
}
|
||||
#endif // USE_PN532_DATA_RAW
|
||||
}
|
||||
} else {
|
||||
sprintf(card_datas,"AUTHFAIL");
|
||||
}
|
||||
}
|
||||
switch (pn532_i2c_function) {
|
||||
case 0x01:
|
||||
if (!erase_success) {
|
||||
snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Erase fail - exiting erase mode");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
}
|
||||
break;
|
||||
case 0x02:
|
||||
if (!set_success) {
|
||||
snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Write failed - exiting set mode");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pn532_i2c_function = 0;
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), mqtt_data, uids, card_datas);
|
||||
#else
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\"}}"), mqtt_data, uids);
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||
|
||||
#ifdef USE_PN532_CAUSE_EVENTS
|
||||
|
||||
char command[71];
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
sprintf(command,"backlog event PN532_UID=%s;event PN532_DATA=%s",uids,card_datas);
|
||||
#else
|
||||
sprintf(command,"event PN532_UID=%s",uids);
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
ExecuteCommand(command, SRC_RULE);
|
||||
#endif // USE_PN532_CAUSE_EVENTS
|
||||
|
||||
pn532_i2c_scan_defer_report = 7; // Ignore tags found for two seconds
|
||||
}
|
||||
} else {
|
||||
if (pn532_i2c_scan_defer_report > 0) { pn532_i2c_scan_defer_report--; }
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
|
||||
bool PN532_Command(void)
|
||||
{
|
||||
bool serviced = true;
|
||||
uint8_t paramcount = 0;
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
paramcount=1;
|
||||
} else {
|
||||
serviced = false;
|
||||
return serviced;
|
||||
}
|
||||
char sub_string[XdrvMailbox.data_len];
|
||||
char sub_string_tmp[XdrvMailbox.data_len];
|
||||
for (uint8_t ca=0;ca<XdrvMailbox.data_len;ca++) {
|
||||
if ((' ' == XdrvMailbox.data[ca]) || ('=' == XdrvMailbox.data[ca])) { XdrvMailbox.data[ca] = ','; }
|
||||
if (',' == XdrvMailbox.data[ca]) { paramcount++; }
|
||||
}
|
||||
UpperCase(XdrvMailbox.data,XdrvMailbox.data);
|
||||
if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"E")) {
|
||||
pn532_i2c_function = 1; // Block 0 of next card/tag will be reset to 0x00...
|
||||
snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Next scanned tag data block 1 will be erased");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"COMMAND\":\"E\"\"}}"), mqtt_data);
|
||||
return serviced;
|
||||
}
|
||||
if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"S")) {
|
||||
if (paramcount > 1) {
|
||||
if (XdrvMailbox.data[XdrvMailbox.data_len-1] == ',') {
|
||||
serviced = false;
|
||||
return serviced;
|
||||
}
|
||||
sprintf(sub_string_tmp,subStr(sub_string, XdrvMailbox.data, ",", 2));
|
||||
pn532_i2c_newdata_len = strlen(sub_string_tmp);
|
||||
if (pn532_i2c_newdata_len > 15) { pn532_i2c_newdata_len = 15; }
|
||||
memcpy(&pn532_i2c_newdata,&sub_string_tmp,pn532_i2c_newdata_len);
|
||||
pn532_i2c_newdata[pn532_i2c_newdata_len] = 0x00; // Null terminate the string
|
||||
pn532_i2c_function = 2;
|
||||
snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Next scanned tag data block 1 will be set to '%s'",pn532_i2c_newdata);
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"COMMAND\":\"S\"\"}}"), mqtt_data);
|
||||
return serviced;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool Xsns40(uint8_t function)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (i2c_flg) {
|
||||
switch (function) {
|
||||
case FUNC_EVERY_250_MSECOND:
|
||||
if (pn532_i2c_detected) {
|
||||
PN532_ScanForTag();
|
||||
}
|
||||
break;
|
||||
case FUNC_EVERY_SECOND:
|
||||
PN532_Detect();
|
||||
break;
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
case FUNC_COMMAND:
|
||||
if (XSNS_40 == XdrvMailbox.index) {
|
||||
result = PN532_Command();
|
||||
}
|
||||
break;
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
case FUNC_SAVE_BEFORE_RESTART:
|
||||
if (!pn532_i2c_disable) {
|
||||
pn532_i2c_disable = 1;
|
||||
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "PN532 NFC Reader - Disabling for reboot", PN532_I2C_ADDRESS);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_PN532_I2C
|
||||
#endif // USE_I2C
|
Loading…
Reference in New Issue