Raspberry Pi & NFC

Aus FHEMWiki
Zur Navigation springen Zur Suche springen

NFC (Near Field Communication) boomt zur Zeit. Wir kennen die Technik bereits von unseren Ausweiskarten, auch der neue Personalausweis hat so einen Chip.

Was die Sicherheit angeht, scheint man sich da ziemlich sicher zu sein. Das wird auch für Zahlungen per NFC-Chip auch in immer mehr Smartphones beworben.

FHEM-Aufgaben mit passiven NFC-TAGs steuern

Hier soll aufgezeigt werden, wie man relativ günstig einen kompletten NFC-Reader baut, der billige passive NFC-TAGs (ca. 2.-EUR/Stück) einliest und die NFC-ID an FHEM schickt. Auch wird gezeigt, wie FHEM diese verarbeitet. Diese NFC-TAGs gibt es als Aufkleber, Schlüsselanhänger, Ausweiskarten. Wer will kann auch sein NFC-taugliches Smartphone einsetzen.

In einer Secure-Anwendung ist eine NFC-ID nur ein Teil des Sicherheitskonzeptes. Hier wird nur die NFC-ID ausgelesen und an FHEM geschickt. Wer übrigens nur per NFC-Smartphone per Internet FHEM steuern will, der braucht nur einen eingerichteten FHEM-Server und eine App wie NFC Launcher. Alle anderen, die auch Kindern und Smartphones ohne NFC-Chip den Zugang zum NFC-System gewähren wollen, benötigen dagegen einen NFC-Reader (dann mit Aufkleber/Schlüsselanhänger).

Auch mehrere RPi-NFC-Reader sind parallel möglich.

Sicherheit

Das gesamte FS20-Konzept war sicherheitstechnisch noch nie überzeugend. Auch ein Raspberry Pi ist "nur" ein Rechner und kann auch abstürzen. Das gesamte Konzept hier mit NFC/USB/WLAN ist ebenfalls nichts, was insbesondere im professionellen Bereich eingesetzt werden sollte.

Sehr interessant und lehrreich(!) sind etliche Beiträge im FHEM-Forum von Henryk Plötz (Chaos Computer Club Berlin), der die hier eingesetzte Technik sehr ausführlich erklärt.

Definitiv ist dies hier keine Lösung, die im sicherheitskritischen Bereich heutige Sicherheitsstandards erfüllt. Aus professioneller Sicht kann man diese Lösung hier getrost als "Spielzeug" ansehen. Ob man hiermit auch seine HM Keymatic (Haustüre) oder Alarmanlage schalten will, sollte man sich gut überlegen.

Benötigte Hardware

  • Raspberry Pi (2x USB erforderlich) mit Netzteil (45 EUR)
  • optional Gehäuse (8 EUR)
  • SD-Karte (möglichst schnell, muss nicht groß sein) (10 EUR)
  • USB-NFC-Reader. SCM SCL3711 ist getestet, evtl. gehen auch andere Geräte [https://github.com/henryk/libopenkey [5]] funktioniert dieser Stick nicht.
  • NFC-TAGS. Standard-Tags mit Milfare-Classic reichen hier vollkommen aus. Einfach mal z.B. bei Amazon/Ebay "NFC TAG" eingeben. (ca. 1-2 EUR/Stück)
  • USB-Verlängerungskabel (4 EUR)
  • empfohlen: WLAN-USB-Stick EDIMAX EW-7811UN (11.-EUR)

Benötigte Software

  • ein Debian Wheezy muss auf der RPi laufen. Für die Installationsanleitung [http://elinux.org/RPi_Easy_SD_Card_Setup ist das hier] ein guter Startpunkt. Die RPi sollte so eingerichtet werden, dass man sich per ssh einloggen kann.
  • >= libnfc-1.6.0-rc1 aus dem Internet mit Bauanleitung (nicht schwer).
  • Zusatzpakete mit Abhängigkeiten wie pcscd.

libnfc

Eine sehr gute Bauanleitung mit Auflistung aller zusätzlich benötigten Pakete ist hier zu finden. Dort direkt in den Bereich Debian/Ubuntu gehen. Die anderen Bereiche sind nicht relevant.

Der pcscd wird hierbei installiert. Gemäß der Fussnote auf der Kompatiblitätsliste wird er nicht von allen Geräten benötigt und sollte wie bei dem hier verwendetem SCL SCM3711 abgeschaltet werden.

root@raspberrypi:~# /etc/init.d/pcscd stop

Um beim nächsten Booten nicht mehr aktiv zu sein:

root@raspberrypi:~# update-rc.d pcscd remove

Skripte, Einstellungen für WLAN, NFC-auslesen, FHEM-Config, Start-/Stop-Skript

WLAN

Die Angaben gelten für den WLAN-USB-Stick EDIMAX EW-7811UN und können bei anderen Geräten abweichen.

Neu angelegt: /etc/wpa.conf

network={
ssid="<SSID>"
proto=RSN
key_mgmt=WPA-PSK
pairwise=CCMP TKIP
group=CCMP TKIP
psk="<Passwort>"
}

Modifiziert: /etc/network/interfaces

auto lo 
iface lo inet loopback
iface eth0 inet dhcp
auto wlan0
iface wlan0 inet dhcp
wpa-conf /etc/wpa.conf
iface default inet dhcp

Natürlich dürfen hier nicht gleichzeitg WLAN-Stick und RJ45 (Kupfer-Kabel) eingesteckt sein.

Das Laden falscher Kernel-Module verhindern

Wenn wir jetzt einfach den NFC-Stick einstecken würden, dann würden original Kernel-Module geladen, die aber so nicht funktionieren.

Wir "blacklisten" daher einige Kernelmodule. Folgendes in die neue /etc/modprobe.d/blacklist-libnfc.conf schreiben:

blacklist pn533
blacklist nfc

WLAN und Funktionstest

So ein NFC-Reader an der Haustür kann ein wichtiges Haussteuerungsmodul werden. So hat ein Test, ob das WLAN noch vorhanden ist Sinn. Folgendes ist optional:

Datei /usr/local/bin/rpi_network_chk.sh

#!/bin/bash
 
# Restartet das Netzwerk, wenn kein Ping mehr auf die Fritzbox möglich
# Hintergrund: Raspberry PI hat das WLAN nach Fritzboxausfall nicht mehr aufgebaut
FritzBox='192.168.0.254'
LogFile="/var/log/nfc2fhem.log"
 /bin/ping -c1 $FritzBox
 pingtest=$?
 [[ $pingtest != 0 ]] &&
    {
      echo "`date`: WLAN nicht ok, restarting network" >> $LogFile
      /etc/init.d/networking restart
    }

Die Datei muss ausführbar sein:

root@raspberrypi:~# chmod +x /usr/local/bin/rpi_network_chk.sh

Dieses Skript kann z.B. alle 10 min ausgeführt werden. Eintrag in /etc/crontab:

*/10 * * * * root /usr/local/bin/rpi_network_chk.sh >>/dev/null 2>&1

Funktionstest

Wenn die folgenden Tests nicht erfolgreich sind, dann braucht man nicht weiterzumachen.

NFC-Stick-Erkennung

Wir öffnen als root die messages. Wer nicht als root unterwegs ist, muss vor allen Befehlen noch ein "sudo" davorstellen:

root@raspberrypi:~# tail -f /var/log/messages

Nun stecken wir den NFC-Stick ein. Er muss erkannt werden:

Jan 19 21:09:30 raspberrypi kernel: [88321.631101] usb 1-1.3: new full-speed USB device number 7 using dwc_otg
Jan 19 21:09:30 raspberrypi kernel: [88321.767620] usb 1-1.3: New USB device found, idVendor=04e6, idProduct=5591
Jan 19 21:09:30 raspberrypi kernel: [88321.767651] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
Jan 19 21:09:30 raspberrypi kernel: [88321.767668] usb 1-1.3: '''Product: SCL3711-NFC&RW'''Jan 19 21:09:30 raspberrypi kernel: [88321.767680] usb 1-1.3: Manufacturer: SCM Micro

Nun wird es spannend: Ein "nfc-list" sollte eine lange Liste ergeben, ein "nfc-list | grep "NFC device"" folgendes:

root@raspberrypi:~# nfc-list | grep "NFC device"
NFC device: SCM Micro / SCL3711-NFC&RW - PN533 v2.7 (0x07) opened

Wer nicht bis hier erfolgreich war, muss suchen, alles weitere baut darauf auf.

Bei einem aufgelegten NFC-Tag sollte dieser erkannt werden:

root@raspberrypi:~# nfc-list | grep NFCID
   UID (NFCID1): a2 d7 94 ee

NFCID-Daemon nfc2fhem installieren

Mehr als ein einfaches und kurzes shell-Skript wird hier nicht benötigt.

/usr/local/bin/nfc2fhem.sh

#!/bin/bash
# provided by Martin Haas 1/2013
# Skript, das die NFC-ID eines NFC-Tags ausliest und an FHEM schickt
# FHEM muss je nach fhem.cfg nicht lokal sein.
FhemIP="192.168.0.x"
LogFile="/var/log/nfc2fhem.log"
CheckIntervall=300   # wie oft [sec] soll geprüft werden ob NFC Reader noch vorhanden ist
SleepTime=0.5      # wie oft [sec] soll nach einem NFC-Tag gesucht werden
 
############################
declare -i nextcheck=$(date +"%s")+$CheckIntervall

while true
do
    NFCID="$(nfc-list | grep NFCID)"
    [[ $NFCID != '' ]] && 
    {
        NFCID="$(echo $NFCID | cut -d":" -f2 | sed 's/ //g;s/)//g;s/(//g')"
        echo "set $NFCID irgendwas" | nc -w5 $FhemIP 7072
        echo "`date`: $NFCID detected" >>$LogFile
        sleep 4
    }
    sleep $SleepTime
    #Test ob Checkintervall vorbei um nach Reader zu suchen
    aktdate=$(date +"%s") 
    [[ $aktdate > $nextcheck ]] &&
    {
        nextcheck=$aktdate+$CheckIntervall
        NFCDevice="$(nfc-list | grep "No NFC device found")"
        [[ $NFCDevice != '' ]] &&  
        {
            echo "`date`: NFC Reader unavailable" >>$LogFile
            echo "{ Log 2, \"nfc2fhem: NFC Reader unavailable\" }" | nc -w5 $FhemIP 7072
        }
    } 
done

Das Skript muss ausführbar sein

chmod +x /usr/local/bin/nfc2fhem.sh


Start-/Stop-Skript

Nach dem Booten soll nfc2fhem.sh automatisch gestartet werden:

Wir erstellen die Datei /etc/init.d/nfc2fhem

#!/bin/sh
# description: Start or stop the scan of NFC-Tags for fhem
### BEGIN INIT INFO
# Provides:       nfc2fhem.sh
# Required-Start:    $local_fs $remote_fs
# Required-Stop:    $local_fs $remote_fs
# Default-Start:    2 3 4 5
# Default-Stop:     0 1 6
# Short-Description:  NFC 2 FHEM
### END INIT INFO
set -e
cd /usr/local/bin 
case "$1" in
'start')
    echo "Starting nfc2fhem..."
    nohup ./nfc2fhem.sh&
    RETVAL=$?
    ;;
'stop')
    echo "Stopping nfc2fhem..."
    pkill nfc2fhem.sh
    RETVAL=$?
    ;;
'status')
    cnt=`ps -ef | grep "nfc2fhem" | grep -v grep | wc -l`
    if [ "$cnt" -eq "2" ]
    then
        echo "nfc2fhem is not running"
    else
        echo "nfc2fhem is running"
    fi
    ;;
*)
    echo "Usage: $0 { start | stop | status }"
    RETVAL=1
    ;;
esac
exit $RETVAL

Mit folgendem startet nfc2fhem.sh bei jedem reboot automatisch:

root@raspberrypi:# update-rc.d nfc2fhem defaults

FHEM vorbereiten

In FHEM nutzen wir das dummy-Modul. Damit können wir mit jedem TAG eine Aufgabe ausführen, mit Logiken natürlich entsprechend mehr.

Beispiel-Eintrag in fhem.cfg

#Ein an FHEM geschickter NFC-Tag sieht z.B. so aus: 02ec8ee9
#NFC-Tag Test
define 02ec8ee9 dummy
define nfcnot1 notify 02ec8ee9 set lampe toggle

Weitere Beispiele sind in der commandref.html zu finden: [6]

FHEM-Zugriff von extern

Sollte auf der RPi nicht auch FHEM laufen, so muss FHEM den Remote-Zugriff erlauben: Eintrag in fhem.cfg

define telnetPort telnet 7072 global

Hilfe/Support

Fragen werden gerne im FHEM-Forum auf http://forum.fhem.de beantwortet.