diff --git a/tasmota/xsns_51_rdm6300.ino b/tasmota/xsns_51_rdm6300.ino index de2714cb2..ebc9ab175 100644 --- a/tasmota/xsns_51_rdm6300.ino +++ b/tasmota/xsns_51_rdm6300.ino @@ -1,5 +1,5 @@ /* - xsns_51_rdm6300.ino - Support for RDM6300 NFC Tag Reader on Tasmota + xsns_51_rdm6300.ino - Support for RDM630(0) 125kHz NFC Tag Reader on Tasmota Copyright (C) 2020 Gerhard Mutz and Theo Arends @@ -17,136 +17,127 @@ along with this program. If not, see . */ - #ifdef USE_RDM6300 +/*********************************************************************************************\ + * Seeed studio Grove / RDM630 / RDM6300 125kHz rfid reader + * + * Expected 14 byte data: + * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 + * Hd ------ ASCII characters ----- Chksm Tl + * 02 31 34 30 30 38 45 43 37 39 33 43 45 03 = 02-14-008EC793-CE-03 + * Versn --------- Tag --------- +\*********************************************************************************************/ -#define XSNS_51 51 +#define XSNS_51 51 -#define RDM6300_BAUDRATE 9600 +#define RDM6300_BAUDRATE 9600 +#define RDM_TIMEOUT 100 +#define RDM6300_BLOCK 2 * 10 // 2 seconds block time #include +TasmotaSerial *RDM6300Serial = nullptr; -#define RDM_TIMEOUT 100 -char rdm_uid_str[10]; +struct { + uint32_t uid = 0; + uint8_t block_time = 0; +} Rdm; -// 2 seconds block time -#define RDM6300_BLOCK 2*10 +/********************************************************************************************/ -uint8_t rdm_blcnt; -TasmotaSerial *RDM6300_Serial = nullptr; +uint8_t RDM6300HexNibble(char chr) { + uint8_t rVal = 0; + if (isdigit(chr)) { rVal = chr - '0'; } + else if (chr >= 'A' && chr <= 'F') { rVal = chr + 10 - 'A'; } + else if (chr >= 'a' && chr <= 'f') { rVal = chr + 10 - 'a'; } + return rVal; +} -void RDM6300_Init() { +// Convert hex string to int array +void RDM6300HexStringToArray(uint8_t array[], uint8_t len, char buffer[]) { + char *cp = buffer; + for (uint32_t i = 0; i < len; i++) { + uint8_t val = RDM6300HexNibble(*cp++) << 4; + array[i] = val | RDM6300HexNibble(*cp++); + } +} + +/********************************************************************************************/ + +void RDM6300Init() { if (PinUsed(GPIO_RDM6300_RX)) { - RDM6300_Serial = new TasmotaSerial(Pin(GPIO_RDM6300_RX),-1,1); - if (RDM6300_Serial->begin(RDM6300_BAUDRATE)) { - if (RDM6300_Serial->hardwareSerial()) { + RDM6300Serial = new TasmotaSerial(Pin(GPIO_RDM6300_RX), -1, 1); + if (RDM6300Serial->begin(RDM6300_BAUDRATE)) { + if (RDM6300Serial->hardwareSerial()) { ClaimSerial(); } } } - rdm_blcnt=0; } -// 14 bytes payload; // RFID DATA FRAME FORMAT: 1byte head (value: 2), 10byte data (2byte version + 8byte tag), 2byte checksum, 1byte tail (value: 3) -void RDM6300_ScanForTag() { - char rdm_buffer[14]; - uint8_t rdm_index; - uint8_t rdm_array[6]; +void RDM6300ScanForTag() { + if (!RDM6300Serial) { return; } - if (!RDM6300_Serial) return; - - if (rdm_blcnt>0) { - rdm_blcnt--; - while (RDM6300_Serial->available()) RDM6300_Serial->read(); + if (Rdm.block_time > 0) { + Rdm.block_time--; + while (RDM6300Serial->available()) { + RDM6300Serial->read(); // Flush serial buffer + } return; } - if (RDM6300_Serial->available()) { + if (RDM6300Serial->available()) { + + char c = RDM6300Serial->read(); + if (c != 2) { return; } // Head marker - char c=RDM6300_Serial->read(); - if (c!=2) return; - // head detected // read rest of message 11 more bytes - rdm_index=0; - uint32_t cmillis=millis(); + char rdm_buffer[14]; + uint8_t rdm_index = 0; + + rdm_buffer[rdm_index++] = c; + + uint32_t cmillis = millis(); while (1) { - if (RDM6300_Serial->available()) { - char c=RDM6300_Serial->read(); - if (c==3) { - // tail marker - break; - } - rdm_buffer[rdm_index++]=c; - if (rdm_index>13) { - // illegal message - return; - } + if (RDM6300Serial->available()) { + c = RDM6300Serial->read(); + rdm_buffer[rdm_index++] = c; + + if (3 == c) { break; } // Tail marker + if (rdm_index > 14) { break; } // Illegal message } - if ((millis()-cmillis)>RDM_TIMEOUT) { - // timeout - return; + if ((millis() - cmillis) > RDM_TIMEOUT) { + return; // Timeout } } - // block for 2 seconds - rdm_blcnt=RDM6300_BLOCK; + AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t*)rdm_buffer, sizeof(rdm_buffer)); - // calc checksum, - rm6300_hstring_to_array(rdm_array,sizeof(rdm_array),rdm_buffer); - uint8_t accu=0; - for (uint8_t count=0;count<5;count++) { - accu^=rdm_array[count]; + if (rdm_buffer[13] != 3) { return; } // Tail marker + + Rdm.block_time = RDM6300_BLOCK; // Block for 2 seconds + + uint8_t rdm_array[6]; + RDM6300HexStringToArray(rdm_array, sizeof(rdm_array), (char*)rdm_buffer +1); + uint8_t accu = 0; + for (uint32_t count = 0; count < 5; count++) { + accu ^= rdm_array[count]; // Calc checksum, } - if (accu!=rdm_array[5]) { - // checksum error - return; + if (accu != rdm_array[5]) { return; } // Checksum error + + rdm_buffer[11] = '\0'; + uint32_t uid = strtoul(rdm_buffer +3, nullptr, 16); + if (uid > 0) { // Ignore false positive all zeros + Rdm.uid = uid; + ResponseTime_P(PSTR(",\"RDM6300\":{\"UID\":\"%08X\"}}"), Rdm.uid); + MqttPublishTeleSensor(); } - - // copy 4 hex bytes - memcpy(rdm_uid_str,&rdm_buffer[2],8); - rdm_uid_str[9]=0; - - ResponseTime_P(PSTR(",\"RDM6300\":{\"UID\":\"%s\"}}"), rdm_uid_str); - MqttPublishTeleSensor(); -/* - char command[24]; - sprintf(command,"event RDM6300=%s",rdm_uid_str); - ExecuteCommand(command, SRC_RULE); - */ - } - - -} - -uint8_t rm6300_hexnibble(char chr) { - uint8_t rVal = 0; - if (isdigit(chr)) { - rVal = chr - '0'; - } else { - if (chr >= 'A' && chr <= 'F') rVal = chr + 10 - 'A'; - if (chr >= 'a' && chr <= 'f') rVal = chr + 10 - 'a'; - } - return rVal; -} - -// convert hex string to int array -void rm6300_hstring_to_array(uint8_t array[], uint8_t len, char buffer[]) -{ - char *cp=buffer; - for (uint8_t i = 0; i < len; i++) { - uint8_t val = rm6300_hexnibble(*cp++) << 4; - array[i]= val | rm6300_hexnibble(*cp++); } } #ifdef USE_WEBSERVER -const char HTTP_RDM6300[] PROGMEM = - "{s}RDM6300 " "UID" "{m}%s" "{e}"; - -void RDM6300_Show(void) { - if (!RDM6300_Serial) return; - if (!rdm_uid_str[0]) strcpy(rdm_uid_str,"????"); - WSContentSend_PD(HTTP_RDM6300,rdm_uid_str); +void RDM6300Show(void) { + if (!RDM6300Serial) { return; } + WSContentSend_PD(PSTR("{s}RDM6300 UID{m}%08X {e}"), Rdm.uid); } #endif // USE_WEBSERVER @@ -154,24 +145,23 @@ void RDM6300_Show(void) { * Interface \*********************************************************************************************/ -bool Xsns51(byte function) -{ +bool Xsns51(byte function) { bool result = false; - switch (function) { - case FUNC_INIT: - RDM6300_Init(); - break; - case FUNC_EVERY_100_MSECOND: - RDM6300_ScanForTag(); - break; + switch (function) { + case FUNC_INIT: + RDM6300Init(); + break; + case FUNC_EVERY_100_MSECOND: + RDM6300ScanForTag(); + break; #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - RDM6300_Show(); - break; + case FUNC_WEB_SENSOR: + RDM6300Show(); + break; #endif // USE_WEBSERVER - } - return result; + } + return result; } #endif // USE_RDM6300