Einbindung eines Fingerabdrucklesers des Typs ZFM-20 (auch bekannt als "Arduino fingerprint sensor") zur Öffnung der Türe

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    Da in jedem Forum ein paar Regeln eingehalten werden müssen, möchte ich diese auch vorher hier festlegen und niederschreiben. Die grundsätzliche Netiquette setze ich bei Jedem voraus. Darüber hinaus möchte ich nur spezielle Regeln ansprechen:
    - Unterlasse FullQuote sondern nutze Alternativen wie Inline-Quoting
    -> siehe auch https://de.wikipedia.org/wiki/Fullquote vs. https://de.wikipedia.org/wiki/TOFU#Alternativen_zu_TOFU
    - Unterlasse nichtssagende Antworten wie "Danke" oder "werde ich mal testen" oder ähnliches, sofern Du nicht der Threadersteller bist und einen Lösungsvorschlag angeboten bekommen hast.
    - Vermeide Doppel-Posts (zwei Beiträge von Dir hintereinander) sondern editiere wenn möglich Deine Posts.

    Danke...

    • Einbindung eines Fingerabdrucklesers des Typs ZFM-20 (auch bekannt als "Arduino fingerprint sensor") zur Öffnung der Türe

      Ich habe meinen Fingarabdruckleser des Typs ZFM-20 (auch bekannt als "Arduino fingerprint sensor") an mein DoorPi geklemmt. da es dafür (noch) kein Keyboard gibt, habe ich mir das "virtuelle Keyboard" zu Nutze gemacht um die Freigabe des Fingerabdrucklesers zu implementieren.

      Was es Braucht:
      • Funktionierendes DoorPi, vorkonfiguriert auf Raspberry Pi B+ oder 3 (bei mir ist der 3-er im Einsatz)
      • Fingerabdruckleser des Typs ZFM-20 (ebay, AliExpress...)
      • USB-TTL-Konverter (z.B. mit dem CP2102-Chip) oder einen Arduino Nano mit gebrücktem GND-Rst, so kann dieser als USB-TTL fungieren.
      • wahlweise zwei LED's (grün / rot oder Dual-LED)
      • Kabel, Lötkolben, Widerstände...


      Vorbereitung der Hardware:
      • Fingerabdruckleser in entsprechend sinnvolles Gehäuse packen
      • Ich habe für die initialisierung des Lesevorganges einen Taster auf das Gehäuse gepackt. (zukünftig will ich den Leser anderweitig einbauen und die Auslösung dann über eine Lichtschranke realisieren.)
      • ebenfalls fanden die beiden LED's darauf platz (diese signalisieren den Lesvorgang erfolgreich / fehlerhaft)
      • PiFace Board ist von Vorteil, würde aber auch über GPIO mit entsprechenden Widerständen und Relais-Board funktionieren (war mir aber zu Umständlich)
      • Wie man den Fingerabdruckleser genau anschliesst und wie die Library dafür installiert wird, könnt ihr Bastian Raschke's Webseite entnehmen, da spare ich mir das Wiederkäuen.
      • Anschliessend Fingerleser gemäss Bastian's Anleitung testen.



      Vorbereitung der Software:
      • Die Python-Library für den Fingerabdruckleser hat ebenfalls einige Beispiele mitgeliefert:
      • Mit dem Beispiel "example_enroll.py" können die Finger entsprechend eingelesen werden
      • Das "example_search.py" habe ich entsprechend erweitert, damit das erfolgreiche Lesen eine Aktion in DoorPi auslöst
      • Ich habe das Script abgeändert und in "finger.py" umbenannt. Anschliessend habe ich es unter "/usr/local/etc/DoorPi/scripts/" abgelegt (ausführbar machen nicht vergessen, aber das wisst ihr sicher)
      Der CODE muss an diversen Stellen noch am jeweiligen System angepasst werden. Dies habe ich im Code kommentiert:

      Source Code: finger.py

      1. #!/usr/bin/env python
      2. # -*- coding: utf-8 -*-
      3. """
      4. PyFingerprint
      5. Copyright (C) 2015 Bastian Raschke <bastian.raschke@posteo.de>
      6. All rights reserved.
      7. @author: Bastian Raschke <bastian.raschke@posteo.de>
      8. @revisioned <a class="call-via-3cx" href="tcxcallto:<a class="call-via-3cx" href="tcxcallto:@@d9b1463e4362a27d0d3759c7fc4d37e4bca338b5@@">@@ddab7559119bf4f9550208ae088f8690aa7a735a@@</a>"><a class="call-via-3cx" href="tcxcallto:@@4ba43bf30e5a91b1c8670c24b7e420d52b24c8a2@@">@@f8f444cb62eef8b80e21229cec94092d42cd7d98@@</a></a> by Sven Gächter (sven@familiegaechter.ch) to interact with DoorPi to unlock Doors
      9. """
      10. import hashlib
      11. from pyfingerprint.pyfingerprint import PyFingerprint
      12. import time , requests
      13. import os
      14. os.environ['http_proxy']=''
      15. import urllib2
      16. #Timeout for Reader unread
      17. t_end = time.time() + 10
      18. #print(time.time())
      19. #print(t_end)
      20. ## Search for a finger
      21. ## Tries to initialize the sensor
      22. try:
      23. f = PyFingerprint('/dev/ttyUSB0', 57600, 0xFFFFFFFF, 0x00000000)
      24. if ( f.verifyPassword() == False ):
      25. raise ValueError('The given fingerprint sensor password is wrong!')
      26. except Exception as e:
      27. print('The fingerprint sensor could not be initialized!')
      28. print('Exception message: ' + str(e))
      29. exit(1)
      30. ## Gets some sensor information
      31. print('Currently stored templates: ' + str(f.getTemplateCount()))
      32. ## Tries to search the finger and calculate hash
      33. try:
      34. print('Waiting for finger...')
      35. ## Wait that finger is read
      36. while time.time() < t_end and ( f.readImage() == False ):
      37. pass
      38. ## Converts read image to characteristics and stores it in charbuffer 1
      39. f.convertImage(0x01)
      40. ## Searchs template
      41. result = f.searchTemplate()
      42. positionNumber = result[0]
      43. accuracyScore = result[1]
      44. if ( positionNumber == -1 ):
      45. print('No match found!')
      46. # Transaction to DoorPi: No Finger listed or too long- Timeout. // Please modify URL below with your credentials e.g: http://door:pi@doorpi:8080
      47. r = requests.get('http://username:password@doorpi-url:port/control/trigger_event?event_name=OnKeyPressed_webservice.redled&event_source=doorpi.keyboard.from_filesystem')
      48. r.json()
      49. exit(0)
      50. else:
      51. print('Found template at position #' + str(positionNumber))
      52. print('The accuracy score is: ' + str(accuracyScore))
      53. # Transaction to DoorPi: Door Release OK. // Please modify URL below with your credentials e.g: http://door:pi@doorpi:8080
      54. r = requests.get('http://username:password@doorpi-url:port/control/trigger_event?event_name=OnKeyPressed_webservice.dooropen&event_source=doorpi.keyboard.from_filesystem')
      55. r.json()
      56. ## OPTIONAL stuff to secure the Transaction (future revisions)
      57. ##
      58. ## Loads the found template to charbuffer 1
      59. f.loadTemplate(positionNumber, 0x01)
      60. ## Downloads the characteristics of template loaded in charbuffer 1
      61. characterics = str(f.downloadCharacteristics(0x01))
      62. ## Hashes characteristics of template
      63. print('SHA-2 hash of template: ' + hashlib.sha256(characterics).hexdigest())
      64. except Exception as e:
      65. print('Operation failed!')
      66. print('Exception message: ' + str(e))
      67. exit(1)
      Display All

      Damit die Events von DoorPi verarbeitet werden können habe ich das "virtuelle Keyboard" aktiviert und mir folgende virtuelle Inputs erstellt (Kommentare mit "//" bitte bei allen folgenden Code's rauslöschen):

      Source Code: doorpi.ini

      1. [keyboards]
      2. onboardpins = piface
      3. webservice = filesystem
      4. [onboardpins_InputPins]
      5. 0 = call:11 // 1 und 2 sind die Türglocken
      6. 1 = call:12
      7. 3 = sleep:0 // Taster für den Start des Lesevorganges
      8. 4 = sleep:0 // Sabotagekontakt
      9. [onboardpins_OutputPins]
      10. 0 = Tueroeffner // Hier hängt der öffner
      11. 5 = greenled // Wie der Name schon sagt..
      12. 6 = redled // Dito.
      13. [webservice_InputPins] // Virtuele Inputs für die Anbindung des Fingerlesers (ohne weitere Funktion)
      14. dooropen = sleep:0
      15. redled = sleep:0
      16. [webservice_keyboard]
      17. base_path_input = /var/DoorPI/keyboard/inputs/
      18. base_path_output = /var/DoorPI/keyboard/outputs/
      19. bouncetime = 2000
      20. polarity = 0
      21. pressed_on_keydown = True
      22. reset_input = True
      Display All

      Die virtuellen Inputs lösen die folgenden Events aus:



      Source Code: doorpi.ini

      1. [EVENT_OnKeyPressed_onboardpins.3]
      2. 10 = os_execute:/usr/local/etc/DoorPi/scripts/finger.py
      3. [EVENT_OnKeyPressed_onboardpins.4]
      4. 10 = os_execute:/usr/local/etc/DoorPi/scripts/sabotage.sh
      5. 11 = break
      6. [EVENT_OnKeyPressed_webservice.dooropen]
      7. 10 = out:Tueroeffner,1,0,3
      8. 20 = out:greenled,1,0,3
      9. [EVENT_OnKeyPressed_webservice.redled]
      10. 10 = out:redled,1,0,1
      11. 15 = sleep:1
      12. 20 = out:redled,1,0,1
      Display All
      EVENT_OnKeyPressed_onboardpins.3:
      • Dieser Event wird vom Input 3 getriggert. Hier hängt der Taster zum starten des Fingerlesevorgangs dran


      EVENT_OnKeyPressed_onboardpins.4
      • Minimale Sicherheit: Wenn jemand das Lesergehäuse vor der Haustür öffnet, werde ich über das Script "sabotage.sh" via Telegram informiert, anschliessend stoppt DoorPi und nichts geht mehr (Vorsicht, In diesem Fall braucht's noch einen Schlüssel oder einen ssh-Zugang auf die DoorPi um neu zu starten).


      EVENT_OnKeyPressed_webservice.dooropen:
      • Dieser Event wird von "finger.py" angestossen, wenn der Lesevorgang erfolgreich war
      • Zugleich wird die grüne LED für 3s. eingeschaltet (zeigt den erfolgreichen Lesevorgang an)


      EVENT_OnKeyPressed_webservice.redled:
      • Dieser Event schaltet die rote LED, wenn der Lesevorgang zu lange kein Ergebnis bringt (der Vorgang bricht nach 10s ab), oder der vorgehaltene Finger nicht verzeichnet ist.


      Wenn dann alles aufgebaut ist, kann mittels Knopfdruck der Lesevorgang gestartet werden: Ist der Finger korrekt, wird die Türe freigegeben.


      Das System hat noch einige leaks, so sind teilweise Wartezeiten zwischen Knopfdruck und Lesevorgang (der Leser wird zuerst initialisiert) sowie nach Abschluss des Lesevorgangs bis zum öffnen der Tür in Kauf zu nehmen.
      • Das hat mit dem Verarbeiten der Events zu tun. Je nach dem was DoorPi sonst noch treibt, geht's schneller.
      • Dieser Tatsache könnte mit einem DoorPi-Keyboard sicher abgeholfen werden - Leider reichen meine Python-Kenntnisse dafür (noch) nicht aus


      Zum Thema Sicherheit ist vorweg zu nehmen, dies ist ein Experimental aufbau! Bitte nicht bei der nächsten Sparkasse verbauen :)
      • Tauscht jemand den Leser mit einem baugleichen Modell mit vorgespeicherten Fingern, kann die Tür problemlos geöffnet werden. Deshalb habe ich den Sabotagekontakt vorgesehen.
      • Hier würde das Speichern und Abgleichen des Hash's, welcher die Library anbietet, entgegenwirken. Da hänge ich mich dann mal dran.


      Kritik und Verbesserungsvorschläge sind willkommen. :)
      Files
      • finger.zip

        (1.36 kB, downloaded 134 times, last: )
    • Einbindung eines Fingerabdrucklesers des Typs ZFM-20 (auch bekannt als "Arduino fingerprint sensor") zur Öffnung der Türe

      Hi,
      dein Projekt klingt interessant. Hast du schon weitere Fortschritte machen können?
      Ich überlege mir damit meine Garagentür öffnen zu lassen. Eine Codeeingabe finde ich hierfür zu aufwendig, wenn jedesmal die Türe zufliegt
    • gonzo0815 wrote:

      Hallo,

      konnte das Projekt soweit umsetzten.
      Was mir nur nicht so recht gefällt das man das script finger.py immer mit einem Befehl starten muss.
      Gibt es keine Möglichkeit das der Fingerprint die ganze zeit aktiv ist?

      Gruß Bernd
      Hallo Bernd,
      ich aktiviere den Sensor mit einen Bewegungsmelder. Funktioniert im derzeitigem Testaufbau auch gut
    • gonzo0815 wrote:

      Hallo,

      konnte das Projekt soweit umsetzten.
      Was mir nur nicht so recht gefällt das man das script finger.py immer mit einem Befehl starten muss.
      Gibt es keine Möglichkeit das der Fingerprint die ganze zeit aktiv ist?

      Gruß Bernd
      Hallo Bernd.

      Ja, du kannst den Leser die ganze Zeit an lassen, sofern dich das ständige Geflacker des Lesers nicht stört.

      Starte das Sceipt bwim Start von Doorpi oder bau' dir einen Service,
      Packe den gesamten Code des Scripts “finger.pi“ ab
      “## Tries to search the finger and calculate hash“
      in eine “while True:“ Schleife und entferne die While-Schleife “while time.time() > t_end and“ und lass den Rest stehen. Schon macht der Leser was du willst.

      Ich bastle noch immer am entsprechenden Keyboard, doch bin ich noch nicht so weit, wie ich sein möchte...
      Gruss Sven

      Gesendet von meinem BAH-W09 mit Tapatalk

      The post was edited 1 time, last by sgaechter ().

    • New

      Hallo Gonzo.
      Wie gewünscht, das Script mit while True- Schleife

      Python Source Code

      1. #!/usr/bin/env python
      2. # -*- coding: utf-8 -*-
      3. """
      4. PyFingerprint
      5. Copyright (C) 2015 Bastian Raschke <bastian.raschke@posteo.de>
      6. All rights reserved.
      7. @author: Bastian Raschke <bastian.raschke@posteo.de>
      8. @revisioned by Sven Gächter (sven@familiegaechter.ch) to interact with DoorPi to unlock Doors
      9. This Version will fire the Fingerscanner forever
      10. """
      11. import hashlib
      12. from pyfingerprint.pyfingerprint import PyFingerprint
      13. import time , requests
      14. import os
      15. os.environ['http_proxy']=''
      16. import urllib2
      17. #Timeout for Reader unread
      18. t_end = time.time() + 10
      19. #print(time.time())
      20. #print(t_end)
      21. ## Search for a finger
      22. ## Tries to initialize the sensor
      23. try:
      24. f = PyFingerprint('/dev/ttyUSB0', 57600, 0xFFFFFFFF, 0x00000000)
      25. if ( f.verifyPassword() == False ):
      26. raise ValueError('The given fingerprint sensor password is wrong!')
      27. except Exception as e:
      28. print('The fingerprint sensor could not be initialized!')
      29. print('Exception message: ' + str(e))
      30. exit(1)
      31. ## Gets some sensor information
      32. print('Currently stored templates: ' + str(f.getTemplateCount()))
      33. ## Tries to search the finger and calculate hash
      34. while True:
      35. try:
      36. print('Waiting for finger...')
      37. ## Wait that finger is read
      38. while ( f.readImage() == False ):
      39. pass
      40. ## Converts read image to characteristics and stores it in charbuffer 1
      41. f.convertImage(0x01)
      42. ## Searchs template
      43. result = f.searchTemplate()
      44. positionNumber = result[0]
      45. accuracyScore = result[1]
      46. hashkey = hashlib.sha256(characterics).hexdigest()
      47. f.loadTemplate(positionNumber, 0x01)
      48. characterics = str(f.downloadCharacteristics(0x01))
      49. if (positionNumber == -1 ) or accuracyScore < 70: ## Sicherheit erhöht: Der Erfassungswert des Fingers muss über 70 sein
      50. print('No match found!')
      51. # Transaction to DoorPi: No Finger listed or too long- Timeout. // Please modify URL below with your credentials e.g: http://door:pi@doorpi:8080
      52. r = requests.get('http://username:password@doorpi-url:port/control/trigger_event?event_name=OnKeyPressed_webservice.redled&event_source=doorpi.keyboard.from_filesystem')
      53. r.json()
      54. #exit(0)
      55. else:
      56. print(('found Finger with Key: %s on position %s, with accuracy of: %s',str(fingerkey),str(positionNumber),str(accuracyScore))
      57. print('SHA-2 hash of Finger: %s',str(hashkey))
      58. # Transaction to DoorPi: Door Release OK. // Please modify URL below with your credentials e.g: http://door:pi@doorpi:8080
      59. r = requests.get('http://username:password@doorpi-url:port/control/trigger_event?event_name=OnKeyPressed_webservice.dooropen&event_source=doorpi.keyboard.from_filesystem')
      60. r.json()
      61. except Exception as e:
      62. print('Operation failed!')
      63. print('Exception message: ' + str(e))
      64. #exit(1)
      Display All
      Ungetestet, aber sollte klappen.

      Habe auf Zeile 66 noch die Sicherheit etwas erhöht. Nun muss ein Finger einen Übereinstimmungs-Score von 70 haben, dass die Türe auf geht. Kann natürlich auch wieder angepasst werden. :)

      Gruss
      Sven