NFC/RFID mit dem Raspberry Pi

rbp_nfcBei einer Hausautomatisierung kann es durchaus von Vorteil sein, wenn das “Haus” weiß, ob man zuhause ist oder nicht. Beispielsweise können nicht genutzte Geräte automatisch ausgeschaltet werden oder eine Überwachung aktiviert werden. Bisher habe ich die Präsenz der Bewohner durch durch die Prüfung mittels WLAN und Bluetooth erkennen lassen, wie in diesem Artikel beschrieben wurde. Heute möchte ich eine Lösung zeigen, bei der sich die Bewohner mittels RFID an- und abmelden können.

 

Einleitung

Die bisherige Lösung, die die Bewohner via WLAN und Bluetooth “suchte”, war ein wenig unzuverlässig. War ein Akku eines Handys leer, saß man bereits im Dunkeln. Zudem musste immer WLAN oder Bluetooth aktiviert sein, weil sonst eine Präsenzerkennung nicht funktionierte. Auch wurde die Präsenz nur alle 5 Minuten geprüft, so dass es eine Weile dauern konnte, bis die entsprechenden Geräte eingeschaltet wurden. Also musste eine bessere Lösung her. Beim stöbern in den Weiten des Internets stieß ich auf dieses RFID-Set:

RC522

In diesem Set, welches hier günstig erhältlich ist, befindet sich:

  • eine Leseplatine
  • zwei Pinleisten zum Anlöten
  • eine RFID-Karte
  • ein RFID-Schlüsselanhänger

 

Verbindung mit dem Raspberry

Ich habe mich dazu entschieden, die Platine nebst ein paar LEDs in ein Kunststoffgehäuse zu setzen, welches wiederum nahe der Eingangstür an die Wand montiert wird. Die Verbindung der Platine gestaltet sich nach dem Anlöten der entsprechenden Pinleiste recht einfach. Bei der Pinleiste sollte man jedoch sorgfältig löten, da in meinem Fall der erste Versuch an einer kalten Lötstelle scheiterte. Wir verbinden die einzelnen Kontakte wie folgt mit der Himbeere:

Schaltung

 

Fertig verpackt sieht meine Kunststoffbox recht ansehnlich aus:

DSC00847 - Kopie

 

Installation

device-tree deaktivieren

Damit die entsprechenden und benötigten Module geladen werden können, deaktivieren wir zunächst den sog. “device-tree“. Dazu öffnen wir das Tool

raspi-config

und wählen unter “Advanced Options” den entsprechenden Menüpunkt. Nach einem Neustart der Himbeere ist der “device-tree” nun deaktiviert.

 

SPI einschalten

Zum aktivieren von SPI-Geräten, wie unser Lesegerät eines ist, editieren wir die Datei “/etc/modprobe.d/raspi-blacklist.conf” und kommentieren die Zeile mit “SPI” aus, so dass dieses Modul beim Systemstart aktiviert wird. Die Datei sollte nun in etwa so aussehen:

# blacklist spi and i2c by default (many users don’t need them)
# blacklist spi-bcm2708
blacklist i2c-bcm2708

 

BCM-Treiber installieren

Für den Betrieb des Lesegerätes benötigen wir zudem noch weitere Treiber. Diese installieren wir wie folgt:

cd /opt/
wget http://www.airspayce.com/mikem/bcm2835/bcm2835-1.48.tar.gz
tar -zxf bcm2835-1.48.tar.gz
cd bcm2835-1.48
./configure
make
make install

 

Steuerungssoftware installieren

Für den Betrieb unseres RFID-Lesers wurde bereits die passende Software für den Raspberry entwickelt, so dass wir diese nun wie folgt installieren:

cd /opt/
apt-get install subversion
svn checkout http://rpi-rc522.googlecode.com/svn/trunk/ rpi-rc522-read-only
cd rpi-rc522-read-only/rc522
gcc config.c rfid.c rc522.c main.c -o rc522_reader -lbcm2835
cp RC522.conf /etc/

 

Seriennummern der Tags auslesen

Nun ist es an der Zeit, die Seriennummer des ersten Tags in Erfahrung zu bringen. Dazu habe ich den im Lieferumfang enthaltenen Schlüsselanhänger genutzt. Wir starten die soeben installierte Software zunächst händisch im sogenannten “Debug-Modus“. So wird beim Erkennen eines RFID-Tags eine Meldung in der Konsole ausgegeben und die erkannte Seriennummer mitgeteilt. Diese brauchen wir für den weiteren Verlauf der Anleitung.

/opt/rpi-rc522-read-only/rc522/rc522_reader -d

 

Das Programm beenden wir mit der Tastenkombination “STRG+C

 

Konfiguration

Ich lasse den RC522-Daemon unter den Rechten des Nutzers “nobody” auf meinem System laufen. Daher ermitteln wir zunächst die User-ID dieses Nutzers mit:

id -u nobody

 

Die ID der Gruppe “nobody” ermitteln wir wie folgt:

cat /etc/shadow |grep nobody |cut -d ":" -f3

 

Nun editieren wir die Datei “/etc/RC522.conf” mit

nano /etc/RC522.conf

 

Dort ändern wir die Zeilen “UID” und “GID” und tragen dort die soeben ermittelten IDs des Nutzers und der Gruppe ein. Den GPIO-Port ändern wir nicht, dafür tragen wir nun am Ende der Datei für jede RFID-Tag-Seriennummer eine Zeile ein, die ein entsprechendes Script ausführt. Bei mir sehen die Zeilen beispielsweise wie folgt aus:

[3af8cz30] /scripts/rfid/rfid.sh DANIEL

 

Die Seriennummer haben wir weiter oben in dieser Anleitung in Erfahrung gebracht.

 

Das Script

In diesem Fall belassen wir die Intelligenz bei der Himbeere, an dem das Lesegerät angeschlossen ist. OpenHAB fragt hier nicht aktiv nach dem Zustand sondern das folgende Script teilt diesen automatisch bei einer Zustandsänderung mit. Wir erstellen zunächst ein “Arbeitsverzeichnis” mit

mkdir -p /scripts/rfid/stati
chmod 777 /scripts/rfid/stati/

und erstellen nun das Script “/scripts/rfid/rfid.sh” mit folgendem Inhalt:

#Pruefen, ob Suffix angegeben
if [ -z "$1" ] ;then
    echo "So geht das nicht"
    exit 1;
fi

#GPIO-Ports definieren
GPIO_D_G=3
GPIO_D_R=2
GPIO_T_G=5
GPIO_T_R=4
GPIO_G_G=22
GPIO_G_R=21

STATUSDATEI="/scripts/rfid/stati/rfid_$1.status"

if [ ! -f $STATUSDATEI ] ; then
    echo "0" > $STATUSDATEI
fi

ALTERSTATUS=$(cat $STATUSDATEI)

#Jemand kommt nach Hause
if [ $ALTERSTATUS -eq 0 ] ; then
    #Piepen
    /scripts/buzzer/2xbeep.sh

    #Meldung an openHAB
    /usr/bin/curl -s --header "Content-Type: text/plain" --request POST --data "ON" http://192.168.1.212:8080/rest/items/RFID_${1}_SWITCH

    #Statusdatei aktualisieren
    echo "1" > $STATUSDATEI

fi

#######################################################################

#Jemand geht weg
if [ $ALTERSTATUS -eq 1 ] ; then
    #Piepen
    /scripts/buzzer/1xbeep.sh

    #Meldung an openHAB
    /usr/bin/curl -s --header "Content-Type: text/plain" --request POST --data "OFF" http://192.168.1.212:8080/rest/items/RFID_${1}_SWITCH

    #Statusdatei aktualisieren
    echo "0" > $STATUSDATEI

fi


#Gruppe auslesen
GRUPPENSTATUS=0
for i in $(cat /scripts/rfid/stati/*); do
    if [ $i -eq 1 ] ; then
        GRUPPENSTATUS=1
    fi
done

#Status an openHAB petzen
if [ $GRUPPENSTATUS -eq 0 ] ; then
    /usr/local/bin/gpio write $GPIO_G_G 0
    /usr/local/bin/gpio write $GPIO_G_R 1
    /usr/bin/curl -s --header "Content-Type: text/plain" --request POST --data "OFF" http://192.168.1.212:8080/rest/items/RFID_GRUPPE_SWITCH
else
    /usr/local/bin/gpio write $GPIO_G_G 1
    /usr/local/bin/gpio write $GPIO_G_R 0
    /usr/bin/curl -s --header "Content-Type: text/plain" --request POST --data "ON" http://192.168.1.212:8080/rest/items/RFID_GRUPPE_SWITCH
fi


#LEDs setzen
/usr/local/bin/gpio write $GPIO_D_G 0
/usr/local/bin/gpio write $GPIO_D_R 0
/usr/local/bin/gpio write $GPIO_T_G 0
/usr/local/bin/gpio write $GPIO_T_R 0
/usr/local/bin/gpio write $GPIO_G_G 0
/usr/local/bin/gpio write $GPIO_G_R 0

if [ $GRUPPENSTATUS -eq 0 ] ; then
    /usr/local/bin/gpio write $GPIO_G_R 1
else
    /usr/local/bin/gpio write $GPIO_G_G 1
fi

STATUSDANIEL=$(cat /scripts/rfid/stati/rfid_DANIEL.status)
if [ $STATUSDANIEL -eq 0 ] ; then
    /usr/local/bin/gpio write $GPIO_D_R 1
else
    /usr/local/bin/gpio write $GPIO_D_G 1
fi

STATUSTINA=$(cat /scripts/rfid/stati/rfid_TINA.status)
if [ $STATUSTINA -eq 0 ] ; then
    /usr/local/bin/gpio write $GPIO_T_R 1
else
    /usr/local/bin/gpio write $GPIO_T_G 1
fi

 

In diesem Script werden gleich mehrere Dinge umgesetzt. Zunächst die Mitteilung der Stati an OpenHAB, dann werden in meinem Fall ebenfalls in das Kunststoffgehäuse untergebrachte LEDs geschaltet. Zu guter Letzt nutze ich als Rückmeldung, dass mein Tag gelesen wurde, einen Buzzer, den ich in diesem Beitrag vorgestellt habe. Wer diese Funktionen nicht benötigt, kommt auch mit dieser verkürzten Version des Scripts aus:

#Pruefen, ob Suffix angegeben
if [ -z "$1" ] ;then
    echo "So geht das nicht"
    exit 1;
fi

STATUSDATEI="/scripts/rfid/stati/rfid_$1.status"

if [ ! -f $STATUSDATEI ] ; then
    echo "0" > $STATUSDATEI
fi

ALTERSTATUS=$(cat $STATUSDATEI)

#Jemand kommt nach Hause
if [ $ALTERSTATUS -eq 0 ] ; then

    #Meldung an openHAB
    /usr/bin/curl -s --header "Content-Type: text/plain" --request POST --data "ON" http://192.168.1.212:8080/rest/items/RFID_${1}_SWITCH

    #Statusdatei aktualisieren
    echo "1" > $STATUSDATEI

fi

#######################################################################

#Jemand geht weg
if [ $ALTERSTATUS -eq 1 ] ; then
    #Meldung an openHAB
    /usr/bin/curl -s --header "Content-Type: text/plain" --request POST --data "OFF" http://192.168.1.212:8080/rest/items/RFID_${1}_SWITCH

    #Statusdatei aktualisieren
    echo "0" > $STATUSDATEI

fi


#Gruppe auslesen
GRUPPENSTATUS=0
for i in $(cat /scripts/rfid/stati/*); do
    if [ $i -eq 1 ] ; then
        GRUPPENSTATUS=1
    fi
done

#Status an openHAB petzen
if [ $GRUPPENSTATUS -eq 0 ] ; then
    /usr/bin/curl -s --header "Content-Type: text/plain" --request POST --data "OFF" http://192.168.1.212:8080/rest/items/RFID_GRUPPE_SWITCH
else
    /usr/bin/curl -s --header "Content-Type: text/plain" --request POST --data "ON" http://192.168.1.212:8080/rest/items/RFID_GRUPPE_SWITCH
fi

 

Dem Script erlauben wir die Ausführung mit

chmod 755 /scripts/rfid/rfid.sh

 

Das Script wird künftig im Kontext des Nutzers “nobody” ausgeführt. Daher müssen wir die Status-Dateien für jeden Nutzer zunächst per Hand erstellen:

touch /scripts/rfid/stati/rfid_DANIEL.status
chmod 666 /scripts/rfid/stati/rfid_DANIEL.status

touch /scripts/rfid/stati/rfid_TINA.status
chmod 666 /scripts/rfid/stati/rfid_TINA.status

 

Das Script selbst können wir testen, indem wir es wie folgt aufrufen:

/scripts/rfid/rfid.sh NUTZER

 

Automatischer Start

Damit der RC522-Daemon beim Systemstart ebenfalls aktiviert wird, tragen wir folgende Zeile in die Datei “/etc/rc.local” ein, und zwar VOR der Zeile “exit 0“:

/opt/rpi-rc522-read-only/rc522/rc522_reader &

 

Weitere RFID-Tags

Es gibt auf dem Markt eine große Anzahl an verschiedenen Tags. Hier nur eine kleine Auswahl, welche ich persönlich testen konnte:

 

 

Integration in OpenHAB

Die Integration in OpenHAB wird in diesem Artikel ausführlich beschrieben.