如何将MFRC522 RFID与Adafruit指纹扫描Python脚本合并?
问题描述
我写了两个Python脚本,分别用于MFRC522 RFID扫描仪和Adafruit 4651指纹扫描仪:
- RFID脚本负责验证标签ID与数据,通过后执行SSH命令,还支持主标签授权新标签的功能
- 指纹脚本验证指纹通过后执行相同的SSH命令
现在想把两个脚本合并成一个,让程序自动检测是RFID标签还是指纹被触发。之前试过用指纹扫描仪的感应触发,但不行,因为它会在循环开始时检查状态,之后就一直等标签出现。
硬件信息:
- RFID模块:普通MFRC522
- 指纹传感器:Adafruit 4651
以下是原脚本:
原指纹脚本(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 pi@192.168.2.3 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脚本(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 pi@192.168.2.3 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()
解决方案
核心思路是将两个设备的检测改为非阻塞模式,在主循环中轮流检查RFID和指纹的触发状态,避免某一个设备的阻塞操作导致另一个设备无法响应。
关键改进点
- 把指纹检测从阻塞循环改为单次非阻塞检查
- 给RFID读取设置短超时,避免卡住主循环
- 统一封装重复逻辑(比如SSH解锁命令)
- 添加防重复触发的休眠机制
合并后的完整代码
import time import board import adafruit_fingerprint import serial import subprocess from mfrc522 import SimpleMFRC522 import secrets import RPi.GPIO as GPIO # 初始化指纹传感器(设置短超时实现非阻塞) uart = serial.Serial("/dev/ttyS0", baudrate=57600, timeout=0.1) finger = adafruit_fingerprint.Adafruit_Fingerprint(uart) # 初始化RFID模块 rfid_scanner = SimpleMFRC522() # 全局变量(兼容原脚本逻辑) idInList = 0 pinInList = 0 # 统一SSH解锁命令 UNLOCK_CMD = 'ssh pi@192.168.2.3 sudo python3 /home/pi/pirfid/actor.py' def unlock_via_ssh(): subprocess.call(UNLOCK_CMD, shell=True) # -------------------------- 指纹相关函数 -------------------------- def check_fingerprint(): """非阻塞检查指纹是否匹配""" # 单次尝试获取指纹图像,不循环等待 if finger.get_image() != adafruit_fingerprint.OK: return False if finger.image_2_tz(1) != adafruit_fingerprint.OK: return False if finger.finger_search() != adafruit_fingerprint.OK: return False return True # -------------------------- RFID相关函数 -------------------------- def masterPresent(file_pathUID, uid, file_pathPIN, pin): masterID = 0 masterPIN = 0 with open(file_pathUID, 'r') as fileUID: content = fileUID.readline() if str(uid) in content: masterID = 1 with open(file_pathPIN, 'r') as filePIN: content = filePIN.readline().strip() pin = pin.strip() if pin == content: masterPIN = 1 if masterID == 1 and masterPIN == 1: tagAuth(file_pathUID, file_pathPIN) def tagAuth(file_pathUID, file_pathPIN): print("----------------") print("检测到主标签") print("----------------") time.sleep(2) print("请放置待授权的标签") # 授权流程需要用户配合,这里用阻塞读取 uid, data = rfid_scanner.read() uid_str = str(uid) pin = data.strip() with open(file_pathUID, 'r') as fileUID: contentID = fileUID.read() with open(file_pathPIN, 'r') as filePIN: contentPIN = filePIN.read() if uid_str in contentID or pin in contentPIN: print("----------------") print("该标签已被授权") print("----------------") time.sleep(3) else: with open(file_pathUID, 'a+') as fileUID: fileUID.write("\n") fileUID.write(uid_str) newPIN = secrets.token_hex(16) rfid_scanner.write(newPIN) with open(file_pathPIN, 'a+') as filePIN: filePIN.write("\n") filePIN.write(newPIN) print("----------------") print("新标签授权成功") print("----------------") time.sleep(3) def searchUID(file_pathUID, uid): global idInList with open(file_pathUID, 'r') as fileUID: content = fileUID.read() idInList = 1 if str(uid) in content else 0 def searchPIN(file_pathPIN, pin): global pinInList with open(file_pathPIN, 'r') as filePIN: content = filePIN.read() pin = pin.strip() pinInList = 1 if pin in content else 0 def check_rfid_access(uid, pin): searchUID("/home/pi/pi-rfid/known_UID", uid) searchPIN("/home/pi/pi-rfid/known_PIN", pin) if idInList == 1 and pinInList == 1: print("Access granted") print("----------------") unlock_via_ssh() else: print("Access denied") print("----------------") # -------------------------- 主循环 -------------------------- try: # 初始化指纹LED finger.set_led(1,4,0,0) print("等待指纹或RFID标签...") while True: # 检查指纹 if check_fingerprint(): print("指纹验证通过") finger.set_led(2,1,200,0) unlock_via_ssh() time.sleep(2) # 防止重复触发 finger.set_led(1,4,0,0) # 检查RFID(0.1秒超时,非阻塞) start_time = time.time() rfid_detected = False uid = None pin_data = None while time.time() - start_time < 0.1: try: uid, pin_data = rfid_scanner.read() rfid_detected = True break except: pass if rfid_detected: print(f"检测到RFID标签: UID={uid}, PIN={pin_data.strip()}") masterPresent("/home/pi/pi-rfid/known_UID", uid, "/home/pi/pi-rfid/known_PIN", pin_data) check_rfid_access(uid, pin_data) time.sleep(2) # 防止重复触发 # 降低CPU占用 time.sleep(0.05) except KeyboardInterrupt: print("用户终止程序") uart.close() GPIO.cleanup() finally: uart.close() GPIO.cleanup()
使用说明
- 脚本启动后会同时监听指纹和RFID设备,任意一个触发都会执行对应验证逻辑
- 指纹验证通过或RFID授权成功后,会短暂休眠避免重复触发
- 若CPU占用过高,可适当延长主循环最后的休眠时间(比如改为0.1秒)
内容的提问来源于stack exchange,提问作者walwei88
相关产品推荐
相关产品推荐

