HID-Scanner

Dit project is begonnen als een proof of concept voor de VVE vergaderingen. Het idee is om aanwezigheid van stemmen te tellen met de tag die ook gebruikt wordt voor toegang tot de flat.

De HID-scanner praat via het Wiegand-protocol met behulp van de D0- en D1-draden van de scanner. Deze signalen worden via een interrupt uitgelezen en omgezet naar kaartinformatie.


ICACHE_RAM_ATTR void ISR_D0() {
  cardData <<= 1;        // Voeg een 0-bit toe
  bitCount++;
  lastBitTime = millis();
}

ICACHE_RAM_ATTR void ISR_D1() {
  cardData <<= 1;
  cardData |= 1;         // Voeg een 1-bit toe
  bitCount++;
  lastBitTime = millis();
}

In de setup() worden de interrupts gekoppeld aan de Wiegand D0- en D1-pinnen:


// setup
attachInterrupt(digitalPinToInterrupt(WIEGAND_D0), ISR_D0, FALLING);
attachInterrupt(digitalPinToInterrupt(WIEGAND_D1), ISR_D1, FALLING);

In de loop() wordt gecontroleerd of er nieuwe bits zijn ontvangen. Wanneer er een volledige kaart binnen is, wordt deze verwerkt en in JSON-formaat naar de seriële monitor gestuurd.


// loop
if (bitCount > 0 && millis() - lastBitTime > 100) {
  if (currentState == STATE_IDLE) {
    currentState = STATE_BUSY;

    // Bouw ruwe bits-string op
    rawBits = "";
    for (int i = bitCount - 1; i >= 0; i--) {
      rawBits += ((cardData >> i) & 1) ? "1" : "0";
    }

    // Start JSON-uitvoer
    Serial.print("{\"bits\":");
    Serial.print(bitCount);
    Serial.print(",\"data\":\"");
    Serial.print(cardData, HEX);
    Serial.print("\",\"raw\":\"");
    Serial.print(rawBits);

    facilityCode = 0;
    cardNumber = 0;

    // Extra velden voor 36-bit Wiegand
    if (bitCount == 36) {
      facilityCode = (cardData >> 19) & 0xFFFF;
      cardNumber   = (cardData >> 3)  & 0xFFFF;

      Serial.print("\",\"facility\":");
      Serial.print(facilityCode);
      Serial.print(",\"card\":");
      Serial.print(cardNumber);
      // displayText(String(facilityCode) + " " + String(cardNumber));
    }

    Serial.println("}");

    greenLedState = OFF;
    redLedState   = BLINK_FAST;
    currentState  = STATE_WAITING;
  }

  // Reset buffer
  cardData = 0;
  bitCount = 0;
}

Dit is de basis. de eerste versie had een computer nodig voor het verwerken van de json string die via serial verzonden wordt. Hier draait extra software die de input verwerkt. Idealiter kan de scanner standalone werken (enkel wifi nodig)

In het huidige versie wordt de kaartinformatie via MQTT naar een node-red server gestuurd. Vanaf daar kunnen verschillende services de data verder verwerken en feedback teruggeven.

De ontvangen feedback kan vervolgens worden weergegeven op een 0.91 inch OLED-scherm.

Onderstaand staat een demo-PHP-pagina die de data ontvangt via een form post en vervolgens verwerkt. Dit is een eenvoudig voorbeeld, maar het belangrijkste hierin is dat het kaartnummer wordt gecontroleerd en dat er op basis daarvan feedback wordt teruggegeven. Deze dit gaat nu via een form post request omdat dit door elke server verwerkt kan worden.

<?php 
$card = $_POST["cardnumber"];
switch ($card) {
    case 1:
    case 2:
    case 3:
    case 4:
		echo "Welkom ";
	break;
    default:
		http_response_code(409);
		echo "Unknown ";
}
echo $card;
?>

naast cardnumber worden de volgende variablen ook doorgegeven
card = 123456789 #data op de kaart
raw = 000000000000000000000000000000000000 #bits gelezen
bits = 36 #aantal bits (voor onze kaart altijd 36)
facility = 0000 (groep code)
cardnumber = 00000 (uniek kaartnummer)