Issue
I wrote two separate scripts for the RFID and fingerprint scanner which check for ID and data on the tag or a positive answer from the fingerprint scannner and execute a ssh command. I would like to merge them into one script with the script detecting wether a RFID tag or a finger is presented.
I thought about using the inductive trigger on the fingerprint scanner but this won’t work as it checks the state at the beginning of the loop and then waits for a tag to be presented.
The RFID is a run-of-the-mill MFRC522. Fingerprint sensor: https://www.adafruit.com/product/4651
Any ideas on how to achieve this?
finger.py
import time
import board
import adafruit_fingerprint
import serial
import subprocess
uart = serial.Serial("/dev/ttyS0", baudrate=57600, timeout=1)
finger = adafruit_fingerprint.Adafruit_Fingerprint(uart)
def get_fingerprint():
while finger.get_image() != adafruit_fingerprint.OK:
pass
if finger.image_2_tz(1) != adafruit_fingerprint.OK:
return False
if finger.finger_search() != adafruit_fingerprint.OK:
return False
return True
try:
finger.set_led(1,4,0,0)
while True:
finger.set_led(1,4,0,0)
if get_fingerprint():
finger.set_led(2,1,200,0)
subprocess.call('ssh [email protected] sudo python3 /home/pi/pirfid/actor.py',shell=True)
else:
finger.set_led(1,2,10,5)
time.sleep(1)
finger.set_led(1,2,10,5)
time.sleep(1)
finger.set_led(1,2,10,5)
time.sleep(1)
except KeyboardInterrupt:
print("Aborted by User")
uart.close()
finally:
uart.close()
rfid.py
from mfrc522 import SimpleMFRC522
from time import sleep
import subprocess
import os
import secrets
#Create object for RFID module
scan = SimpleMFRC522()
#Master Tag present
def masterPresent(file_pathUID,id,file_pathPIN,pin):
with open(file_pathUID, 'r') as fileUID:
content = fileUID.readline()
if str(id) in content:
masterID = 1
else:
masterID = 0
with open(file_pathPIN, 'r') as filePIN:
content = filePIN.readline()
pin = pin.strip()
content = content.strip()
if pin in content:
masterPIN = 1
else:
masterPIN = 0
if masterID == 1 and masterPIN == 1:
tagAuth("/home/pi/pi-rfid/known_UID","/home/pi/pi-rfid/known_PIN")
else:
pass
#Authorise new Tag
def tagAuth(file_pathUID,file_pathPIN):
# Read Tag UID and write to file
print("----------------")
print("Master Tag detected")
print("----------------")
sleep(2)
print("Place Tag to authorise")
id,data = scan.read()
id = str(id)
pin = data.strip()
with open(file_pathUID, 'r') as fileUID:
contentID = fileUID.read()
with open(file_pathPIN, 'r') as filePIN:
contentPIN = filePIN.read()
if id in contentID or pin in contentPIN:
print("----------------")
print("Tag already in use")
print("----------------")
sleep(3)
else:
with open (file_pathUID,'a+') as fileUID:
fileUID.write("\n")
fileUID.write(id)
#Create random hex sring and write to tag and file
newPIN = secrets.token_hex(16)
scan.write(newPIN)
with open (file_pathPIN,'a+') as filePIN:
filePIN.write("\n")
filePIN.write(newPIN)
print("----------------")
print("New Tag sucessfully authorised")
print("----------------")
sleep (3)
#Search UID in file
def searchUID(file_pathUID,id):
global idInList
with open(file_pathUID, 'r') as fileUID:
content = fileUID.read()
if id in content:
idInList = 1
else:
idInList = 0
#Search PIN in file
def searchPIN(file_pathPIN,pin):
global pinInList
with open(file_pathPIN, 'r') as filePIN:
content = filePIN.read()
pin = pin.strip()
if pin in content:
pinInList = 1
else:
pinInList = 0
#Unlock over SSH
def unlockSSH():
subprocess.call('ssh [email protected] sudo python3 /home/pi/pirfid/actor.py',shell=True)
#Check for Access
def checkAccess():
global pinMatch,idInLiist
if idInList == 1 and pinInList == 1:
print("Access granted")
print("----------------")
unlockSSH()
else:
print("Access denied")
print("----------------")
#Loop
try:
while True:
print("Place your Tag")
id,data = scan.read()
printData()
masterPresent("/home/pi/pi-rfid/known_UID",id,"/home/pi/pi-rfid/known_PIN",data)
searchUID("/home/pi/pi-rfid/known_UID",str(id))
searchPIN("/home/pi/pi-rfid/known_PIN",data)
checkAccess()
except KeyboardInterrupt:
print("Aborted by User")
GPIO.cleanup()
finally:
GPIO.cleanup()
Solution
You could use threads to run both tasks in parallel. Something like this for example:
def rfid_task():
# run RFID loop here
try:
while True:
...
def finger_task():
# run fingerprint loop here
try:
finger.set_led(1,4,0,0)
while True:
...
# this is the main entry point
if __name__ == "__main__":
# create a threads that will run both loops in parallel
rfid_thread = threading.Thread(target=rfid_task)
finger_thread = threading.Thread(target=finger_task)
# wait until both threads finish
rfid_thread.join()
finger_thread.join()
I don't see any problems with your code, but keep in mind that threading can introduce race conditions (because different parts of your code can run at the same time). It could indeed cause problems with the hardware libraries, maybe it is neccessary to allocate the resources from within the threads.
Also I would consider re-starting the loops on failure (e.g. by wrapping them in another while True:
, probably with some timeout). Otherwise I would implement some kind of mechanism that stop the remaining thread if the other one fails.
Answered By - Dominik Berse Answer Checked By - Dawn Plyler (WPSolving Volunteer)