Hallo,
nachdem ich gefragt wurde wie ich das mit dem auslesen eines Wiegandreaders gemacht habe folgt hier eine kurze, unvollständige, Anleitung.
Da ich ersteinmal der Meinung bin das ein Codeschloss nicht direkt eine Kernfunktion des DoorPi ist bringe ich es unter "offtopic", verschieben könnt ihr es ja immer noch.
Meine Ausgangssituation war ein Schliesssystem für eine WG mit hoher Fluktuation. Ständig waren die hochwertigen Schlüssel (meist mit WG Bewohner) spurlos verschwunden, ein einfaches Schloss sollte es aufgrund der unkontrollierten Nachmachbarkeit der Schlüssel aber auch nicht sein.
Es fand sich noch ein Abus CFA 1000 (ja, ich weiss ...) und weil es wenigstens ein bischen Sicherheit sein sollte wurde als Codeschloss ein "sTouch-standalone-W-w Mifare" bei i-keys gekauft und ausschliesslich Desfire EV1 RFID Tags ausgegeben (oder nur Pincode).
Wenn man die beiden Begriffe "sTouch-standalone-W-w" und "Abus" in die Suchmaschine haut, dann kommt man auf einen recht lehrreichen Blog von Stefan Thesen der da was mit einem Arduino verbastelt hat.
Wir wollten da aber was mit
- einer Datenbank dahinter (wurde mySql)
- zeitgesteuerten Zwangsschliessungen (realisiert über cronjobs)
- langem logging über Zutritte
- Erweiterbarkeit durch "Beweisfotos" (letzlich realisiert über Snapshotabgriff einer IP-Cam und versand per Telegram)
und was uns sonst noch einfallen würde, daher sollte es eine Raspberry Lösung werden.
Weil das Rad nicht neu erfunden werden sollte habe ich nach längerer Suche folgende Lib gefunden die in Zusammenarbeit mit pigpio wunderbar funktionierte (ausser dem Parity Kram, aber der wurde schlussendlich ignoriert)
https://github.com/joan2937/pi…n/WIEGAND_CODE/wiegand.py
Ich hänge euch jetzt hier mal das Kerngerüst des kleines Scripts an, habe einiges rausgenommen das zu spezifisch wäre und an einigen Stellen einfach nur geschrieben was dort implementiert werden müßte.
Die genaue Beschaltung des Rasp habe ich jetzt nicht mehr im Kopf und bin auch gerade weit weg vom Gerät, aber ich denke das bekommt jeder selbst zusammen.
Vom Raspberry zum Wiegandreader verlaufen 5 Leitungen, D0 und D1 für die Daten, Ground und 2 Leitungen von denen eine die LED am Reader steuert und die andere einen Beeper.
Da gehören natürlich an den richtigen Stellen noch ein paar Widerstände und Zenerdioden rein um die Pegel anzupassen und die Eingänge in definierten Zustand zu bringen.
Der verwendete Reader ist zum Glück gut dokumentiert: https://www.i-keys.de/download…sKey-Anleitung-Mifare.pdf
Konfiguriert wurde der Reader als Wiegandreader auf 34bit und "4-6 Ziffern werden als Transponder ID gesendet".
Der Pseudocode 0000 wurde verwendet um von aussen die Türe abschliessen zu können.
(Teile des Codes stammen glaube ich von hier: https://m.reddit.com/r/AskElectronics/comments/10llyy/ ) Evtl. mit Copyright aufpassen.
Vieleicht kann das ja jemand schöner bauen, ist nie über einen Prototypen der einfach live ging drüber hinausgekommen
Jochen
#!/usr/bin/python -u
#coding: utf-8
import time
import pigpio
import wiegand
import MySQLdb
import os
import urllib
def bitCount(int_type):
count = 0
while(int_type):
int_type &= int_type - 1
count += 1
return(count)
def close_door():
pi.write(24, 0) # green LED an
pi.write(26, 1) # tuer zu an
pi.write(27, 0)
time.sleep(0.2) # kleiner beep
pi.write(27, 1)
pi.write(26, 0) # tuer zu aus
time.sleep(0.2)
pi.write(26, 1) # tuer zu an
time.sleep(3.7)
pi.write(26, 0) # tuer zu aus
pi.write(24, 1) # green LED aus
def open_door():
pi.write(27, 0)
time.sleep(0.1) # kleiner beep
pi.write(27, 1)
pi.write(24, 0) # green LED an
# kurzer Impuls um fernsteuerung aufzuwecken
pi.write(19, 1) # tuer auf an
pi.write(27, 0)
time.sleep(0.2) # kleiner beep
pi.write(27, 1)
pi.write(19, 0) # tuer auf aus
time.sleep(0.2)
# Tuere auf
pi.write(19, 1) # tuer auf an
time.sleep(3.7)
pi.write(19, 0) # tuer auf aus
pi.write(24, 1) # green LED aus
def callback(bits, value):
print("bits={} value={}".format(bits, value))
FAC_PAR_MASK = 0
FACILITY_MASK = 0
CARD_MASK = 0
CARD_PAR_MASK = 1
card = 0
fascility = 0
if ((bits != 34) and (bits != 18)):
# lehne ersteinmal alles ab was nicht 34 bit oder 18 bit hat
print time.asctime(),": FEHLER --> unbekanntes Datenformat "
return
if (bits ==18):
print time.asctime(),": Tuergong"
text = "Ding Dong!"
# sende türsignal mit Foto ueber Telegram
return
if (bits == 4):
# 4 bit keycode
facility = 0
card = value
fac_par_ok = True
card_par_ok = True
if (bits == 18):
# 18 bit sebury ring code
facility = 0
card = (value) >> 1
fac_par_ok = True
card_par_ok = True
if (bits == 26):
FAC_PAR_MASK = 0b10000000000000000000000000
FACILITY_MASK = 0b01111111100000000000000000
CARD_MASK = 0b00000000011111111111111110
CARD_PAR_MASK = 1;
facility = (value & FACILITY_MASK) >> 17
card = (value & CARD_MASK) >> 1
fac_par = (value & FAC_PAR_MASK) >> 25
# even parity
fac_par_ok = (bitCount(facility) + fac_par) % 2 == 0
card_par = value & CARD_PAR_MASK
# odd parity
card_par_ok = (bitCount(card) + card_par) % 2 == 1
if (bits == 34):
FAC_PAR_MASK = 0b1000000000000000000000000000000000
FACILITY_MASK = 0b0111111111111000000000000000000000
CARD_MASK = 0b0000000000000111111111111111111110
# FACILITY_MASK = 0b0111111111111111100000000000000000
# CARD_MASK = 0b0000000000000000011111111111111110
CARD_PAR_MASK = 0b0000000000000000000000000000000001
facility = (value & FACILITY_MASK) >> 22
card = (value & CARD_MASK) >> 1
fac_par = (value & FAC_PAR_MASK) >> 33
# even parity
fac_par_ok = (bitCount(facility) + fac_par) % 2 == 0
card_par = value & CARD_PAR_MASK
# odd parity
card_par_ok = (bitCount(card) + card_par) % 2 == 1
# Ignore the parity because sometimes it's wrong
if fac_par_ok and card_par_ok:
print("Both parity bits ok, successful read.")
print("Facility:", facility)
print("Card:", card)
else:
if not fac_par_ok:
print("Facility parity check failed!")
if not card_par_ok:
print("Card parity check failed!")
print("Facility:", facility)
print("Card:", card)
if (card == 0):
print time.asctime(),": schliesse tuer "
text = "Schliesse Tuer"
# Hier telegram nachricht das Tuer geschlossen wurde + logging
close_door()
else:
db = MySQLdb.connect(...)
cursor = db.cursor()
anz = cursor.execute("select Zugangscode.Aktiv as code_ok, Zugangscode.Art as code_art, Benutzer.ID as benutzer_id, Benutzer.Name as benutzer_name, Benutzer.Aktiv as benutzer_aktiv from Zugangscode,Benutzer where Zugangscode.Benu
tzer = Benutzer.ID and Zugangscode.Code = '%s'",(card, ) )
#Fehlerfall
if (anz != 1):
print time.asctime(),": FEHLER --> unbekannte PIN : ",card
text = "FEHLER --> unbekannte PIN : ",card
# hier telegram nachricht ueber falsche Pin eingabe + logging
time.sleep(0.2)
pi.write(27, 0)
time.sleep(1)
pi.write(27, 1)
time.sleep(0.2)
pi.write(27, 0)
time.sleep(1)
pi.write(27, 1)
time.sleep(0.2)
pi.write(27, 0)
time.sleep(1)
pi.write(27, 1)
if (anz == 1):
data = cursor.fetchone();
if ((data[0]==1) and (data[4] == 1)):
# Pin ist okay, tuer aufmachen
print time.asctime(),": oeffne tuer : ", data[2],":",data[3]," ",data[1],":",card
text = "Tuere geoeffnet durch " + data[3]
# hier telegram nachricht ueber türöffnung + logging
open_door()
else:
# pin oder benutzer nicht aktiv
print time.asctime(),": FEHLER --> nicht aktiv : ", data[2],":",data[3]," ",data[1],":",card,"Benutzer aktiv:",data[4]," PIN aktiv:",data[0]
text = "FEHLER --> nicht aktiv : ", data[2],":",data[3]," ",data[1],":",card,"Benutzer aktiv:",data[4]," PIN aktiv:",data[0]
# hier telegram nachricht über oeffnungsversuch duch deaktivierten user
pi.write(27, 0)
time.sleep(1)
pi.write(27, 1)
time.sleep(0.2)
pi.write(27, 0)
time.sleep(1)
pi.write(27, 1)
time.sleep(0.2)
pi.write(27, 0)
time.sleep(1)
pi.write(27, 1)
db.close
###### main ###################
while 1 == 1:
print time.asctime(),": Initialisiere Keypad"
pi = pigpio.pi()
# init senderports
pi.set_mode(19, pigpio.OUTPUT)
pi.set_mode(26, pigpio.OUTPUT)
pi.set_pull_up_down(19, pigpio.PUD_DOWN) # setze pullup wiederstaende down
pi.set_pull_up_down(26, pigpio.PUD_DOWN) # setze pullup wiederstaende down
# init buzzer port
pi.set_mode(27, pigpio.OUTPUT)
pi.set_pull_up_down(27, pigpio.PUD_UP)
pi.write(27, 1)
# init LED port
pi.set_mode(24, pigpio.OUTPUT)
pi.set_pull_up_down(24, pigpio.PUD_UP)
pi.write(24, 1)
w = wiegand.decoder(pi, 17, 18, callback)
time.sleep(300)
w.cancel()
pi.stop()
Alles anzeigen