Skip to content

Instantly share code, notes, and snippets.

@linuxgemini
Last active March 13, 2022 00:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save linuxgemini/9f089af171d5842eaaa4e0ae39f7d957 to your computer and use it in GitHub Desktop.
Save linuxgemini/9f089af171d5842eaaa4e0ae39f7d957 to your computer and use it in GitHub Desktop.
/**
WiegandNG Extended Demo for HID Readers
2021-08-06 linuxgemini
Released under GNU LGPL v2.1 (or later)
*/
// HID SEOS: FC 54, CC 64004
const unsigned char correctID[] = {0x00, 0x6D, 0xF4, 0x08};
// HID Prox: FC 95, CC 10491
const unsigned long correctHIDidFC = 95;
const unsigned long correctHIDidCC = 10491;
const unsigned long correctHIDidCN = 0;
#include <WiegandNG.h>
#define pinD0 2
#define pinD1 3
#define READER_RED 8
#define READER_GRN 9
#define READER_HLD 10
#define READER_BZR 11
#define READER_TMP 12
#define WIEGAND_BITS 50
#define WIEGAND_PACKETGAP 25
const int pins[] = {READER_RED, READER_GRN, READER_HLD, READER_BZR, READER_TMP};
const int pinModes[] = {OUTPUT, OUTPUT, OUTPUT, OUTPUT, INPUT};
const int pinDefaults[] = {HIGH, HIGH, HIGH, HIGH, 0};
WiegandNG wg;
unsigned long offMillis = 0;
unsigned long nextBuzzerMillis = 0;
unsigned long holdEnd = 0;
bool buzzerOn = false;
int buzzerCount = 0;
bool buzzerCont = false;
bool tamper = false;
bool tamperOpenedPrinted = false;
bool tamperClosedPrinted = true;
struct HIDcardObject {
unsigned long facilityCode;
unsigned long cardCode;
unsigned long cardNumber;
int isProcessed;
};
void setup() {
Serial.begin(9600);
for (int i = 0; i < (sizeof(pins) / sizeof(pins[0])); i++) {
Serial.print(F("Setting pin "));
Serial.print(pins[i]);
Serial.print(F(" to mode "));
Serial.print(pinModes[i]);
Serial.print(F(" with default value "));
Serial.println(pinDefaults[i]);
pinMode(pins[i], pinModes[i]);
if (pinModes[i] == OUTPUT) digitalWrite(pins[i], pinDefaults[i]);
}
if (!wg.begin(pinD0, pinD1, WIEGAND_BITS, WIEGAND_PACKETGAP)) {
Serial.println(F("Out of memory!"));
}
Serial.println(F("Ready to read."));
}
void PrintBinary(WiegandNG &tempwg) {
volatile unsigned char *wgbuffer = tempwg.getRawData();
unsigned int bufferSize = tempwg.getBufferSize();
unsigned int countedBits = tempwg.getBitCounted();
unsigned int countedBytes = (countedBits / 8);
if ((countedBits % 8) > 0) countedBytes++;
unsigned int regularFirstByteLocator = bufferSize - countedBytes;
unsigned char bits[countedBits];
unsigned int intoffset = 0;
for (unsigned int i = regularFirstByteLocator; i < bufferSize; i++) {
unsigned char bufByte = wgbuffer[i];
for (int x = 0; x < 8; x++) {
if ((((bufferSize - i) * 8) - x) <= countedBits) {
unsigned char bytebinary = 0;
if ((bufByte & 0x80)) {
bytebinary = 1;
}
bits[intoffset] = bytebinary;
intoffset++;
}
bufByte <<= 1;
}
}
for (int i = 0; i < countedBits; i++) {
Serial.print(bits[i]);
}
Serial.println();
}
void PrintHex(WiegandNG &tempwg) {
volatile unsigned char *wgbuffer = tempwg.getRawData();
unsigned int bufferSize = tempwg.getBufferSize();
unsigned int countedBits = tempwg.getBitCounted();
unsigned int countedBytes = (countedBits / 8);
if ((countedBits % 8) > 0) countedBytes++;
unsigned int regularFirstByteLocator = bufferSize - countedBytes;
unsigned int countedBytesRaw = (countedBits / 8);
unsigned int rawFirstByteLocator = bufferSize - countedBytesRaw;
Serial.print(F(" Hex: "));
for (unsigned int i = rawFirstByteLocator; i < bufferSize; i++) {
unsigned char bufByte = wgbuffer[i];
char tmp[2];
sprintf(tmp, "%.2X", bufByte);
Serial.print(tmp);
}
Serial.println();
Serial.print(F(" Reversed Hex: "));
if (rawFirstByteLocator > 0) {
for (unsigned int i = bufferSize - 1; i > rawFirstByteLocator - 1; i--) {
unsigned char bufByte = wgbuffer[i];
char tmp[2];
sprintf(tmp, "%.2X", bufByte);
Serial.print(tmp);
}
} else {
Serial.print("Failed to print");
}
Serial.println();
Serial.print(F(" Even Byte Friendly Hex: "));
for (unsigned int i = regularFirstByteLocator; i < bufferSize; i++) {
unsigned char bufByte = wgbuffer[i];
char tmp[2];
sprintf(tmp, "%.2X", bufByte);
Serial.print(tmp);
}
Serial.println();
Serial.print(F(" Even Byte Friendly Reversed Hex: "));
if (regularFirstByteLocator > 0) {
for (unsigned int i = bufferSize - 1; i > regularFirstByteLocator - 1; i--) {
unsigned char bufByte = wgbuffer[i];
char tmp[2];
sprintf(tmp, "%.2X", bufByte);
Serial.print(tmp);
}
} else {
Serial.print("Failed to print");
}
Serial.println();
}
void PrintHID(HIDcardObject HIDcard, unsigned int bc) {
Serial.print(F(" Decoded HID (or AWID) Card: "));
Serial.print(F("Card Type: "));
switch (bc) {
case 50:
Serial.print(F("AWID RBH50"));
break;
case 37:
if (HIDcard.facilityCode <= 65535 && HIDcard.cardCode <= 524287) {
Serial.print(F("H10302 or H10304"));
} else {
Serial.print(F("H10302"));
}
break;
case 35:
Serial.print(F("H5XXXX (HID Corporate 1000)"));
break;
case 34:
Serial.print(F("H10306"));
break;
case 26:
Serial.print(F("H10301"));
break;
default:
Serial.print(F("Unknown"));
break;
}
if ((HIDcard.facilityCode <= 65535 && HIDcard.cardCode <= 524287) || bc == 50) {
Serial.print(F(", FC: "));
Serial.print(HIDcard.facilityCode);
Serial.print(F(", CC: "));
Serial.print(HIDcard.cardCode);
}
if (bc == 37) {
Serial.print(F(", CN: "));
Serial.print(HIDcard.cardNumber);
}
Serial.println();
}
HIDcardObject Wiegand50ToAWID(unsigned char bits[]) {
HIDcardObject HIDcard;
unsigned long facilityCode = 0;
unsigned long cardCode = 0;
// 50 bit AWID RBH50 format
// facility code = bits 2 to 16
for (int i = 1; i < 17; i++) {
facilityCode <<= 1;
facilityCode |= bits[i];
}
// card code = bits 17 to 49
for (int i = 16; i < 49; i++) {
cardCode <<= 1;
cardCode |= bits[i];
}
HIDcard.facilityCode = facilityCode;
HIDcard.cardCode = cardCode;
HIDcard.cardNumber = (unsigned long)0;
HIDcard.isProcessed = 1;
return HIDcard;
}
HIDcardObject Wiegand37ToHID(unsigned char bits[]) {
HIDcardObject HIDcard;
unsigned long facilityCode = 0;
unsigned long cardCode = 0;
unsigned long cardNumber = 0; // this is for H10302
// 37 bit format (H10302 or H10304)
// H10304, FC and CC
// FC = bits 2 to 17
for (int i = 1; i < 17; i++) {
facilityCode <<= 1;
facilityCode |= bits[i];
}
// CC = bits 18 to 36
for (int i = 17; i < 36; i++) {
cardCode <<= 1;
cardCode |= bits[i];
}
// H10302, no FC or CC, CN is used
// bits 2 to 36
for (int i = 1; i < 36; i++) {
cardNumber <<= 1;
cardNumber |= bits[i];
}
HIDcard.facilityCode = facilityCode;
HIDcard.cardCode = cardCode;
HIDcard.cardNumber = cardNumber;
HIDcard.isProcessed = 1;
return HIDcard;
}
HIDcardObject Wiegand35ToHID(unsigned char bits[]) {
HIDcardObject HIDcard;
unsigned long facilityCode = 0;
unsigned long cardCode = 0;
// 35 bit HID Corporate 1000 format (H5XXXX)
// facility code = bits 2 to 14
for (int i = 1; i < 14; i++) {
facilityCode <<= 1;
facilityCode |= bits[i];
}
// card code = bits 15 to 34
for (int i = 14; i < 34; i++) {
cardCode <<= 1;
cardCode |= bits[i];
}
HIDcard.facilityCode = facilityCode;
HIDcard.cardCode = cardCode;
HIDcard.cardNumber = (unsigned long)0;
HIDcard.isProcessed = 1;
return HIDcard;
}
HIDcardObject Wiegand34ToHID(unsigned char bits[]) {
HIDcardObject HIDcard;
unsigned long facilityCode = 0;
unsigned long cardCode = 0;
// 34 bit format (H10306)
// FC = bits 2 to 17
for (int i = 1; i < 17; i++) {
facilityCode <<= 1;
facilityCode |= bits[i];
}
// CC = bits 18 to 33
for (int i = 17; i < 33; i++) {
cardCode <<= 1;
cardCode |= bits[i];
}
HIDcard.facilityCode = facilityCode;
HIDcard.cardCode = cardCode;
HIDcard.cardNumber = (unsigned long)0;
HIDcard.isProcessed = 1;
return HIDcard;
}
HIDcardObject Wiegand26ToHID(unsigned char bits[]) {
HIDcardObject HIDcard;
unsigned long facilityCode = 0;
unsigned long cardCode = 0;
// standard 26 bit format (H10301)
// facility code = bits 2 to 9
for (int i = 1; i < 9; i++) {
facilityCode <<= 1;
facilityCode |= bits[i];
}
// card code = bits 10 to 25
for (int i = 9; i < 25; i++) {
cardCode <<= 1;
cardCode |= bits[i];
}
HIDcard.facilityCode = facilityCode;
HIDcard.cardCode = cardCode;
HIDcard.cardNumber = (unsigned long)0;
HIDcard.isProcessed = 1;
return HIDcard;
}
HIDcardObject HandleHID(WiegandNG &tempwg) {
volatile unsigned char *wgbuffer = tempwg.getRawData();
unsigned int bufferSize = tempwg.getBufferSize();
unsigned int countedBits = tempwg.getBitCounted();
unsigned int countedBytes = (countedBits / 8);
if ((countedBits % 8) > 0) countedBytes++;
unsigned char bits[countedBits];
unsigned int intoffset = 0;
unsigned int regularFirstByteLocator = bufferSize - countedBytes;
for (unsigned int i = regularFirstByteLocator; i < bufferSize; i++) {
unsigned char bufByte = wgbuffer[i];
for (int x = 0; x < 8; x++) {
if ((((bufferSize - i) * 8) - x) <= countedBits) {
unsigned char bytebinary = 0;
if ((bufByte & 0x80)) {
bytebinary = 1;
}
bits[intoffset] = bytebinary;
intoffset++;
}
bufByte <<= 1;
}
}
HIDcardObject HIDcard;
HIDcard.facilityCode = 0;
HIDcard.cardCode = 0;
HIDcard.cardNumber = 0;
HIDcard.isProcessed = 0;
if (countedBits == 50) {
HIDcard = Wiegand50ToAWID(bits);
} else if (countedBits == 37) {
HIDcard = Wiegand37ToHID(bits);
} else if (countedBits == 35) {
HIDcard = Wiegand35ToHID(bits);
} else if (countedBits == 34) {
HIDcard = Wiegand34ToHID(bits);
} else if (countedBits == 26) {
HIDcard = Wiegand26ToHID(bits);
}
return HIDcard;
}
bool CheckID(WiegandNG &tempwg) {
volatile unsigned char *wgbuffer = tempwg.getRawData();
unsigned int bufferSize = tempwg.getBufferSize();
unsigned int countedBits = tempwg.getBitCounted();
unsigned int countedBytes = (countedBits / 8);
if ((countedBits % 8) > 0) countedBytes++;
unsigned int intoffset = 0;
unsigned int regularFirstByteLocator = bufferSize - countedBytes;
for (unsigned int i = regularFirstByteLocator; i < bufferSize; i++) {
unsigned char bufByte = wgbuffer[i];
if (bufByte != correctID[intoffset]) return false;
intoffset++;
}
return true;
}
bool CheckHIDid(HIDcardObject HIDcard) {
if (!HIDcard.isProcessed) return false;
bool ch1 = HIDcard.facilityCode == correctHIDidFC;
bool ch2 = HIDcard.cardCode == correctHIDidCC;
bool ch3 = HIDcard.cardNumber == correctHIDidCN;
return (ch1 && ch2 && ch3);
}
void SetLED(int ledPin) {
if (ledPin > 0) {
digitalWrite(ledPin, LOW);
offMillis = millis() + 1250;
} else {
digitalWrite(READER_RED, HIGH);
digitalWrite(READER_GRN, HIGH);
}
}
void loop() {
if (wg.available() && !tamper) {
delay(75);
wg.pause(); // pause Wiegand pin interrupts
Serial.println(F("Wiegand Data Obtained:"));
Serial.print(F(" Bitsize: "));
Serial.println(wg.getBitCounted());
Serial.print(F(" Raw Binary: "));
PrintBinary(wg);
PrintHex(wg);
HIDcardObject hidres = HandleHID(wg);
if (hidres.isProcessed) {
PrintHID(hidres, wg.getBitCounted());
}
Serial.println();
if (CheckID(wg) || CheckHIDid(hidres)) {
Serial.println(F("Card is validated, opening door..."));
SetLED(READER_GRN);
} else {
Serial.println(F("Card is not valid, buzzer is running..."));
SetLED(READER_RED);
buzzerOn = true;
buzzerCount = 0;
}
holdEnd = millis() + 3000;
Serial.println();
wg.clear();
}
if (tamper && !tamperOpenedPrinted) {
Serial.println(F("TAMPER OPEN, SOMETHING IS UP!"));
tamperOpenedPrinted = true;
tamperClosedPrinted = false;
} else if (!tamper && !tamperClosedPrinted) {
Serial.println(F("Tamper closed!"));
tamperOpenedPrinted = false;
tamperClosedPrinted = true;
}
if (!digitalRead(READER_TMP)) {
buzzerOn = true;
buzzerCont = true;
tamper = true;
SetLED(READER_GRN);
SetLED(READER_RED);
digitalWrite(READER_HLD, LOW);
} else {
buzzerCont = false;
tamper = false;
}
if (millis() > offMillis) {
SetLED(0);
}
if (millis() > nextBuzzerMillis && buzzerOn) {
if (buzzerCount >= 10 && !buzzerCont) {
buzzerOn = false;
SetLED(0);
}
digitalWrite(READER_BZR, buzzerOn ? buzzerCount % 2 : HIGH);
buzzerCount++;
nextBuzzerMillis = millis() + 90;
}
if (millis() > holdEnd && !tamper) digitalWrite(READER_HLD, HIGH);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment