From 4de6648cd7eee73bfbf4f80dd1d032c0dc0dcf15 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 21 Jan 2021 16:12:44 +0100 Subject: [PATCH] Refactor wiegand rfid reader --- tasmota/i18n.h | 2 + tasmota/xsns_82_wiegand.ino | 156 +++++++++++++++++------------------- 2 files changed, 77 insertions(+), 81 deletions(-) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 3262bef09..f77a3571c 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -156,6 +156,7 @@ #define D_JSON_SERIALRECEIVED "SerialReceived" #define D_JSON_SET "Set" #define D_JSON_SIGNAL "Signal" +#define D_JSON_SIZE "Size" #define D_JSON_SPEED "Speed" #define D_JSON_SPEED_UNIT "SpeedUnit" #define D_JSON_SSID "SSId" @@ -180,6 +181,7 @@ #define D_JSON_TOTAL_START_TIME "TotalStartTime" #define D_JSON_TVOC "TVOC" #define D_JSON_TYPE "Type" +#define D_JSON_UID "UID" #define D_JSON_UPTIME "Uptime" #define D_JSON_UTC_TIME "UTC" #define D_JSON_UV_INDEX "UvIndex" diff --git a/tasmota/xsns_82_wiegand.ino b/tasmota/xsns_82_wiegand.ino index 0035f5225..d1105ff39 100644 --- a/tasmota/xsns_82_wiegand.ino +++ b/tasmota/xsns_82_wiegand.ino @@ -21,27 +21,31 @@ /*********************************************************************************************\ * Wiegand 24, 26, 32, 34 bit Rfid reader 125 kHz * - * Wire connections: - * Red Vdc - * Black Gnd - * Green D0 - * White D1 - * Yellow Buzzer - * Blue Led - * Grey 34-bit if connected to Gnd + * Wire connections for https://www.benselectronics.nl/wiegand-2634-bit-rfid-reader-125khze248d29925d602d.html + * Red Vdc + * Black Gnd + * Green D0 + * White D1 + * Yellow/Grey Sound Buzzer if connected to Gnd + * Blue Light Led if connected to Gnd + * Grey/Purple 34-bit if connected to Gnd * * MQTT: - * %prefix%/%topic%/SENSOR = {"Time":"2021-01-13T12:30:38","Wiegand":{"UID":"rfid tag"}} + * %prefix%/%topic%/SENSOR = {"Time":"2021-01-21T16:04:12","Wiegand":{"UID":7748328,"Size":26}} + * %prefix%/%topic%/SENSOR = {"Time":"2021-01-21T15:48:49","Wiegand":{"UID":4302741608,"Size":34}} + * + * Rule: + * on wiegand#uid=4302741608 do publish cmnd/ailight/power 2 endon \*********************************************************************************************/ #warning **** Wiegand interface enabled **** #define XSNS_82 82 -#define WIEGAND_BIT_TIMEOUT 25 //time to be wait after last bit detected. +#define WIEGAND_BIT_TIMEOUT 25 // Time in mSec to be wait after last bit detected. // Use only a randomly generate RFID for testing. using #define will save some space in the final code // DEV_WIEGAND_TEST_MODE 1 : testing with random rfid without hardware connected, but GPIOs set correctly -// DEV_WIEGAND_TEST_MODE 2 : testing with hardware corretly connected. +// DEV_WIEGAND_TEST_MODE 2 : testing with hardware correctly connected. #define DEV_WIEGAND_TEST_MODE 0 #ifdef DEV_WIEGAND_TEST_MODE @@ -63,7 +67,10 @@ class Wiegand { void ScanForTag(void); #ifdef USE_WEBSERVER void Show(void); -#endif +#endif // USE_WEBSERVER + + bool isInit = false; + uint8_t scanDelay; private: @@ -82,22 +89,20 @@ class Wiegand { static volatile uint16_t bitCount; static volatile uint32_t lastFoundTime; static volatile uint8_t timeOut; - bool isInit = false; #if (DEV_WIEGAND_TEST_MODE)==1 uint64_t GetRandomRfid(uint8_t); -#endif +#endif // DEV_WIEGAND_TEST_MODE==1 }; Wiegand* oWiegand = new Wiegand(); -uint8_t scanDelay; volatile uint64_t Wiegand::rfidBuffer; volatile uint16_t Wiegand::bitCount; volatile uint32_t Wiegand::lastFoundTime; volatile uint8_t Wiegand::timeOut; -Wiegand::Wiegand() { +Wiegand::Wiegand() { rfid = 0; lastFoundTime = 0; tagSize = 0; @@ -105,6 +110,7 @@ Wiegand::Wiegand() { bitCount = 0 ; timeOut = 0; isInit = false; + scanDelay = 1; } #if (DEV_WIEGAND_TEST_MODE)==1 @@ -136,7 +142,7 @@ uint64_t Wiegand::GetRandomRfid(uint8_t tag_size=34) { parities = CalculateParities(result, tag_size); result = (result << 1) | (parities & 0x01); // Set LSB parity - if (parities & 0x80) { // MSB parity is 1 + if (parities & 0x80) { // MSB parity is 1 switch (tag_size) { case 24: result |= 0x800000; @@ -155,9 +161,9 @@ uint64_t Wiegand::GetRandomRfid(uint8_t tag_size=34) { } } - return result; + return result; } -#endif +#endif // DEV_WIEGAND_TEST_MODE==1 void ICACHE_RAM_ATTR Wiegand::handleD1Interrupt() { // Receive a 1 bit. (D0=high & D1=low) rfidBuffer = (rfidBuffer << 1) | 1; // Leftshift + 1 bit @@ -173,28 +179,26 @@ void ICACHE_RAM_ATTR Wiegand::handleD0Interrupt() { // Receive a 0 bit. (D0=low void Wiegand::Init() { isInit = false; - if (PinUsed(GPIO_WIEGAND_D0) && PinUsed(GPIO_WIEGAND_D1)) { // Only start, if the Wiegang pins are + if (PinUsed(GPIO_WIEGAND_D0) && PinUsed(GPIO_WIEGAND_D1)) { // Only start, if the Wiegang pins are selected #if (DEV_WIEGAND_TEST_MODE)>0 AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: Init()")); -#endif +#endif // DEV_WIEGAND_TEST_MODE>0 pinMode(Pin(GPIO_WIEGAND_D0), INPUT_PULLUP); pinMode(Pin(GPIO_WIEGAND_D1), INPUT_PULLUP); attachInterrupt(Pin(GPIO_WIEGAND_D0), handleD0Interrupt, FALLING); attachInterrupt(Pin(GPIO_WIEGAND_D1), handleD1Interrupt, FALLING); - isInit = true; // Helps to run only if correctly setup + isInit = true; // Helps to run only if correctly setup #if (DEV_WIEGAND_TEST_MODE)>0 - AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: Testmode")); // For tests without reader attaiched - AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: D0:%u"),Pin(GPIO_WIEGAND_D0)); - AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: D1:%u"),Pin(GPIO_WIEGAND_D1)); + AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: Testmode, D0:%u, D1:%u"), Pin(GPIO_WIEGAND_D0), Pin(GPIO_WIEGAND_D1)); // For tests without reader attaiched #else - AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: D0=%u, D1=%u"),Pin(GPIO_WIEGAND_D0), Pin(GPIO_WIEGAND_D1)); -#endif + AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: Wiegand Rfid Reader detected")); +#endif // DEV_WIEGAND_TEST_MODE>0 } #if (DEV_WIEGAND_TEST_MODE)>0 else { AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: no GPIOs.")); } -#endif +#endif // DEV_WIEGAND_TEST_MODE>0 } uint64_t Wiegand::CheckAndConvertRfid(uint64_t rfidIn, uint16_t bitcount) { @@ -225,17 +229,17 @@ uint64_t Wiegand::CheckAndConvertRfid(uint64_t rfidIn, uint16_t bitcount) { default: break; } - calcParity = CalculateParities(rfidIn, bitCount); // check result on http://www.ccdesignworks.com/wiegand_calc.htm with raw tag as input - if (calcParity != (evenParityBit | oddParityBit)) { // Paritybit is wrong + calcParity = CalculateParities(rfidIn, bitCount); // Check result on http://www.ccdesignworks.com/wiegand_calc.htm with raw tag as input + if (calcParity != (evenParityBit | oddParityBit)) { // Parity bit is wrong rfidIn=0; - AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: %llu parity error"), rfidIn); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("WIE: %llu parity error"), rfidIn); } #if (DEV_WIEGAND_TEST_MODE)>0 AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: even (left) parity: %u "), (evenParityBit>>7)); AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: even (calc) parity: %u "), (calcParity & 0x80)>>7); AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: odd (right) parity: %u "), oddParityBit); AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: odd (calc) parity: %u "), (calcParity & 0x01)); -#endif +#endif // DEV_WIEGAND_TEST_MODE>0 return rfidIn; } @@ -289,24 +293,20 @@ bool Wiegand::WiegandConversion () { lastFoundTime = nowTick; return bRet; } - if (diffTicks > WIEGAND_BIT_TIMEOUT) { // Last bit found is WIEGAND_BIT_TIMEOUT ms ago + if (diffTicks > WIEGAND_BIT_TIMEOUT) { // Last bit found is WIEGAND_BIT_TIMEOUT ms ago #if (DEV_WIEGAND_TEST_MODE)>0 AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: Raw tag %llu, Bit count %u"), rfidBuffer, bitCount); -#endif +#endif // DEV_WIEGAND_TEST_MODE>0 if ((24 == bitCount) || (26 == bitCount) || (32 == bitCount) || (34 == bitCount)) { // 24, 26, 32, 34-bit Wiegand codes - rfid = CheckAndConvertRfid( rfidBuffer, bitCount); + rfid = CheckAndConvertRfid(rfidBuffer, bitCount); tagSize = bitCount; - bitCount = 0; - rfidBuffer = 0; bRet = true; } else if (4 == bitCount) { // 4-bit Wiegand codes for keypads rfid = (int)translateEnterEscapeKeyPress(rfidBuffer & 0x0000000F); tagSize = bitCount; - bitCount = 0; - rfidBuffer = 0; bRet = true; } else if (8 == bitCount) { @@ -323,26 +323,23 @@ bool Wiegand::WiegandConversion () { bRet = false; } tagSize = bitCount; - bitCount = 0; - rfidBuffer = 0; } else { // Time reached but unknown bitCount, clear and start again lastFoundTime = nowTick; - bitCount = 0; - rfidBuffer = 0; bRet = false; } + bitCount = 0; + rfidBuffer = 0; } else { - bRet = false; // watching time not finished + bRet = false; // Watching time not finished } #if (DEV_WIEGAND_TEST_MODE)>0 - AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: tag out %llu, tag size %u "), rfid, tagSize); -#endif + AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: Tag out %llu, tag size %u "), rfid, tagSize); +#endif // DEV_WIEGAND_TEST_MODE>0 return bRet; } void Wiegand::ScanForTag() { - if (!isInit) { return;} #if (DEV_WIEGAND_TEST_MODE)>0 AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: ScanForTag().")); #if (DEV_WIEGAND_TEST_MODE==1) @@ -363,21 +360,20 @@ void Wiegand::ScanForTag() { rfidBuffer = GetRandomRfid(34); break; } - AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: raw generated: %lX"), rfidBuffer); // for tests without reader attaiched -#endif -#endif + AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: Raw generated %lX"), rfidBuffer); // For tests without reader attaiched +#endif // DEV_WIEGAND_TEST_MODE==1 +#endif // DEV_WIEGAND_TEST_MODE>0 if (bitCount > 0) { uint64_t oldTag = rfid; bool validKey = WiegandConversion(); #if (DEV_WIEGAND_TEST_MODE)>0 - AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: previous tag: %llu"), oldTag); -#endif - // only in case of valid key do action. Issue#10585 - if (validKey) { - if (oldTag != rfid) { AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: new= %llu"), rfid); } - else { AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: prev= %llu"), rfid); } - AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: bits= %u"), tagSize); - ResponseTime_P(PSTR(",\"Wiegand\":{\"UID\":\"%0llu\"}}"), rfid); + AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: Previous tag %llu"), oldTag); +#endif // DEV_WIEGAND_TEST_MODE>0 + if (validKey) { // Only in case of valid key do action. Issue#10585 + if (oldTag == rfid) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("WIE: Old tag")); + } + ResponseTime_P(PSTR(",\"Wiegand\":{\"UID\":%0llu,\"" D_JSON_SIZE "\":%u}}"), rfid, tagSize); MqttPublishTeleSensor(); } } @@ -385,12 +381,10 @@ void Wiegand::ScanForTag() { #ifdef USE_WEBSERVER void Wiegand::Show(void) { - if (!isInit) { return; } WSContentSend_PD(PSTR("{s}Wiegand UID{m}%llu {e}"), rfid); #if (DEV_WIEGAND_TEST_MODE)>0 - AddLog_P(LOG_LEVEL_INFO,PSTR("WIE: Tag: %llu"), rfid); - AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: %u bits"), bitCount); -#endif + AddLog_P(LOG_LEVEL_INFO, PSTR("WIE: Tag %llu, Bits %u"), rfid, bitCount); +#endif // DEV_WIEGAND_TEST_MODE>0 } #endif // USE_WEBSERVER @@ -401,30 +395,30 @@ void Wiegand::Show(void) { bool Xsns82(byte function) { bool result = false; - switch (function) { - case FUNC_INIT: - oWiegand->Init(); - scanDelay = 1; - break; - - case FUNC_EVERY_250_MSECOND: // Some tags need more time, don't try shorter period + if (FUNC_INIT == function) { + oWiegand->Init(); + } + else if (oWiegand->isInit) { + switch (function) { + case FUNC_EVERY_250_MSECOND: // Some tags need more time, don't try shorter period #if (DEV_WIEGAND_TEST_MODE)==1 - if (scanDelay >= 4) // Give a second because of the log entries to be send. + if (oWiegand->scanDelay >= 4) // Give a second because of the log entries to be send. #else - if (scanDelay >= 2) // Only run every (delay * 250 ms) (every 250ms is too fast for some tags) + if (oWiegand->scanDelay >= 2) // Only run every (delay * 250 ms) (every 250ms is too fast for some tags) #endif - { - oWiegand->ScanForTag(); - scanDelay = 1; - } else { - scanDelay++; - } - break; + { + oWiegand->ScanForTag(); + oWiegand->scanDelay = 1; + } else { + oWiegand->scanDelay++; + } + break; #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - oWiegand->Show(); - break; + case FUNC_WEB_SENSOR: + oWiegand->Show(); + break; #endif // USE_WEBSERVER + } } return result; }