Atm tracking issue
Posted: Tue May 28, 2019 6:08 pm
Hello, I am trying to make an Atm where you scan an RFID card and then you type in a pin number and it opens the atm. Right now I have it where the ATM will scan a card and enter the pin code and everything works. The only issue I am have is that if you scan a RFID card then scan a second one before the first one times out then the program will freeze up. Below I have posted my code. I did my best to try to solve the issue on my own here is what I did. I created a tracking variable (see line 12). Then on all my resets and forgets I made sure the tracker variable will be returned to equal 0 (see line 68,79,83...etc). After that I tired to make it where if the tracker was equal to 0 (Meaning that somewhere the code has been reset) then let the RFID scan correctly and open the next panel. On line 161 i made it set tracker to 1 so that mean a rfid was scanned and should not allow another card to be scanned. The main issue is im not sure where and how i need to place the if statement to allow this to work. If anyone can help me it would be greatly appreciated. If you have more question just reply below and ill respond asap. Thanks again
Code: Select all
#!/usr/bin/env python3
import sys
import MySQLdb
from threading import Thread
import threading
import time
import RPi.GPIO as GPIO
import json
from random import randint
from evdev import InputDevice
from select import select
tracker = 0;
#from twilio.rest import Client
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(13,GPIO.OUT)
try:
# python 2
import Tkinter as tk
import ttk
except ImportError:
# python 3
import tkinter as tk
from tkinter import ttk
class Fullscreen_Window:
global dbHost
global dbName
global dbUser
global dbPass
dbHost = 'localhost'
dbName = 'door_lock'
dbUser = 'admin'
dbPass = 'Starwars1460'
def __init__(self):
self.tk = tk.Tk()
self.tk.title("Three-Factor Authentication Security Door Lock")
self.frame = tk.Frame(self.tk)
self.frame.grid()
self.tk.columnconfigure(1, weight=1)
self.tk.attributes('-zoomed', True)
self.tk.attributes('-fullscreen', True)
self.state = True
self.tk.bind("<F11>", self.toggle_fullscreen)
self.tk.bind("<Escape>", self.end_fullscreen)
self.tk.config(cursor="none")
self.show_idle()
t = Thread(target=self.listen_rfid)
t.daemon = True
t.start()
def show_idle(self):
self.welcomeLabel = ttk.Label(self.tk, text="WELCOME TO\nBANK OF ESCAPE KEMAH\nPLEASE INSERT CARD")
self.welcomeLabel.config(font='size, 30 bold', justify='center', anchor='center',foreground="white", background="royalblue3")
self.welcomeLabel.grid(column=1, sticky=tk.W+tk.E, pady=170)
def pin_entry_forget(self):
tracker = 0
self.validUser.grid_forget()
self.photoLabel.grid_forget()
self.enterPINlabel.grid_forget()
self.row4bg.grid_forget()
count = 0
while (count < 12):
self.btn[count].grid_forget()
count += 1
def openAtm_forget(self):
tracker = 0
self.openAtm.grid_forget()
def closeAtm_forget(self):
tracker = 0
self.closeAtm.grid_forget()
def returnToIdle_fromPINentry(self):
tracker = 0
self.pin_entry_forget()
self.show_idle()
def returnToIdle_fromopenAtm(self):
tracker = 0
self.openAtm_forget()
self.show_idle()
def returnToIdle_fromcloseAtm(self):
tracker = 0
self.closeAtm_forget()
self.show_idle()
def returnToIdle_fromPINentered(self):
tracker = 0
self.PINresultLabel.grid_forget()
self.show_idle()
#def returnToIdle_fromAccessGranted(self):
#GPIO.output(13,GPIO.LOW)
#self.SMSresultLabel.grid_forget()
#self.show_idle()
#def returnToIdle_fromSMSentry(self):
#self.PINresultLabel.grid_forget()
#self.smsDigitsLabel.grid_forget()
#count = 0
#while (count < 12):
#self.btn[count].grid_forget()
#count += 1
#self.show_idle()
#def returnToIdle_fromSMSentered(self):
#self.SMSresultLabel.grid_forget()
#self.show_idle()
def toggle_fullscreen(self, event=None):
self.state = not self.state # Just toggling the boolean
self.tk.attributes("-fullscreen", self.state)
return "break"
def end_fullscreen(self, event=None):
self.state = False
self.tk.attributes("-fullscreen", False)
return "break"
def listen_rfid(self):
global pin
global accessLogId
keys = "X^1234567890XXXXqwertzuiopXXXXasdfghjklXXXXXyxcvbnmXXXXXXXXXXXXXXXXXXXXXXX"
dev = InputDevice('/dev/input/event3')
rfid_presented = ""
while True:
r,w,x = select([dev], [], [])
for event in dev.read():
if event.type==1 and event.value==1:
if event.code==28:
dbConnection = MySQLdb.connect(host=dbHost, user=dbUser, passwd=dbPass, db=dbName)
cur = dbConnection.cursor(MySQLdb.cursors.DictCursor)
cur.execute("SELECT * FROM access_list WHERE rfid_code = '%s'" % (rfid_presented))
if cur.rowcount != 1:
self.welcomeLabel.config(text="ACCESS DENIED")
# Log access attempt
cur.execute("INSERT INTO access_log SET rfid_presented = '%s', rfid_presented_datetime = NOW(), rfid_granted = 0" % (rfid_presented))
dbConnection.commit()
time.sleep(3)
self.welcomeLabel.grid_forget()
self.show_idle()
else:
tracker = 1
user_info = cur.fetchone()
userPin = user_info['pin']
self.welcomeLabel.grid_forget()
self.validUser = ttk.Label(self.tk, text="Welcome\n %s!" % (user_info['name']), font='size, 18', justify='center', anchor='center',foreground="white", background="royalblue3")
self.validUser.grid(column=1,columnspan=1, sticky=tk.N+tk.S+tk.E+tk.W)
self.image = tk.PhotoImage(file=user_info['image'] + ".gif")
self.photoLabel = ttk.Label(self.tk, image=self.image, background="royalblue3", justify="center", anchor="center")
self.photoLabel.grid(column=1, columnspan=1,sticky=tk.N+tk.S+tk.E+tk.W)
self.enterPINlabel = ttk.Label(self.tk, text="Please enter your PIN:", font='size, 16', justify='center', anchor='center', foreground="white",background="royalblue3")
self.enterPINlabel.grid(column=1, columnspan=1, sticky=tk.N+tk.S+tk.E+tk.W)
self.row4bg = ttk.Label(self.tk, background="royalblue3")
self.row4bg.grid(column=1, columnspan=1,sticky=tk.N+tk.S+tk.E+tk.W)
pin = ''
keypad = [
'1', '2', '3',
'4', '5', '6',
'7', '8', '9',
'*', '0', '#',
]
# create and position all buttons with a for-loop
# r, c used for row, column grid values
r = 1
c = 8
n = 0
# list(range()) needed for Python3
self.btn = list(range(len(keypad)))
for label in keypad:
# partial takes care of function and argument
#cmd = partial(click, label)
# create the button
self.btn[n] = tk.Button(self.tk, text=label, font='size, 18',foreground="white",background="royalblue3", width=4, height=1, command=lambda digitPressed=label:self.codeInput(digitPressed, userPin, user_info['sms_number']))
# position the button
self.btn[n].grid(row=r, column=c, ipadx=10, ipady=20, pady=20)
# increment button index
n += 1
# update row/column position
c += 1
if c > 10:
c = 8
r += 1
# Log access attempt
cur.execute("INSERT INTO access_log SET rfid_presented = '%s', rfid_presented_datetime = NOW(), rfid_granted = 1" % (rfid_presented))
dbConnection.commit()
accessLogId = cur.lastrowid
self.PINentrytimeout = threading.Timer(10, self.returnToIdle_fromPINentry)
self.PINentrytimeout.start()
self.PINenteredtimeout = threading.Timer(5, self.returnToIdle_fromPINentered)
rfid_presented = ""
dbConnection.close()
else:
rfid_presented += keys[ event.code ]
def codeInput(self, value, userPin, mobileNumber):
global accessLogId
global pin
global smsCodeEntered
pin += value
pinLength = len(pin)
self.enterPINlabel.config(text="Digits Entered: %d" % pinLength)
if pinLength == 4:
self.PINentrytimeout.cancel()
self.pin_entry_forget()
if pin == userPin:
self.pin_entry_forget()
self.openAtm = ttk.Label(self.tk, text="ACCESS GRANTED\nUNLOCKING ATM")
self.openAtm.config(font='size, 30 bold', justify='center', anchor='center',foreground="white", background="green")
self.openAtm.grid(column=1, sticky=tk.W+tk.E, pady=170)
self.openAtmtimeout = threading.Timer(5, self.returnToIdle_fromopenAtm)
self.openAtmtimeout.start()
else:
self.pin_entry_forget()
self.closeAtm = ttk.Label(self.tk, text="ACCESS DENIED\nLOCKING ATM")
self.closeAtm.config(font='size, 30 bold', justify='center', anchor='center',foreground="white", background="firebrick")
self.closeAtm.grid(column=1, sticky=tk.W+tk.E, pady=170)
self.closeAtmtimeout = threading.Timer(3, self.returnToIdle_fromcloseAtm)
self.closeAtmtimeout.start()
# Log access attempt
dbConnection = MySQLdb.connect(host=dbHost, user=dbUser, passwd=dbPass, db=dbName)
cur = dbConnection.cursor()
cur.execute("UPDATE access_log SET pin_entered = '%s', pin_entered_datetime = NOW(), pin_granted = %s, mobile_number = '%s' WHERE access_id = %s" % (pin, pin_granted, mobileNumber, accessLogId))
dbConnection.commit()
#if pin == userPin:
#self.PINresultLabel = ttk.Label(self.tk, text="Thank You, Now\nPlease Enter Code\nfrom SMS\n")
#self.PINresultLabel.config(font='size, 20', justify='center', anchor='center')
#self.PINresultLabel.grid(columnspan=3, sticky=tk.W+tk.E, pady=20)
#self.smsDigitsLabel = ttk.Label(self.tk, text="Digits Entered: 0", font='size, 18', justify='center', anchor='center')
#self.smsDigitsLabel.grid(columnspan=3, sticky=tk.W+tk.E)
#smsCode = self.sendSMScode(mobileNumber)
#smsCodeEntered = ''
#keypad = [
# '1', '2', '3',
# '4', '5', '6',
# '7', '8', '9',
# '', '0', '',
#]
# create and position all buttons with a for-loop
# r, c used for row, column grid values
#r = 4
#c = 0
#n = 0
# list(range()) needed for Python3
#self.btn = list(range(len(keypad)))
#for label in keypad:
# partial takes care of function and argument
#cmd = partial(click, label)
# create the button
#self.btn[n] = tk.Button(self.tk, text=label, font='size, 18', width=4, height=1, command=lambda digitPressed=label:self.smsCodeEnteredInput(digitPressed, smsCode))
# position the button
#self.btn[n].grid(row=r, column=c, ipadx=10, ipady=10)
# increment button index
#n += 1
# update row/column position
#c += 1
#if c > 2:
# c = 0
# r += 1
#self.SMSentrytimeout = threading.Timer(60, self.returnToIdle_fromSMSentry)
#self.SMSentrytimeout.start()
#else:
#self.PINresultLabel = ttk.Label(self.tk, text="Incorrect PIN\nEntered!")
#self.PINresultLabel.config(foreground="white", background="firebrick",font='size, 30 bold', justify='center', anchor='center')
#self.PINresultLabel.grid(column=1,sticky=tk.W+tk.E, pady=170)
#self.PINenteredtimeout.start()
#def smsCodeEnteredInput(self, value, smsCode):
#global smsCodeEntered
#global accessLogId
#smsCodeEntered += value
#smsCodeEnteredLength = len(smsCodeEntered)
#
#self.smsDigitsLabel.config(text="Digits Entered: %d" % smsCodeEnteredLength)
#if smsCodeEnteredLength == 6:
#self.SMSentrytimeout.cancel()
#self.pin_entry_forget()
#if smsCodeEntered == smsCode:
#smscode_granted = 1
#else:
#smscode_granted = 0
# Log access attempt
#dbConnection = MySQLdb.connect(host=dbHost, user=dbUser, passwd=dbPass, db=dbName)
# cur = dbConnection.cursor()
#cur.execute("UPDATE access_log SET smscode_entered = '%s', smscode_entered_datetime = NOW(), smscode_granted = %s WHERE access_id = %s" % (smsCodeEntered, smscode_granted, accessLogId))
#dbConnection.commit()
#if smsCodeEntered == smsCode:
#self.SMSresultLabel = ttk.Label(self.tk, text="Thank You,\nAccess Granted")
#self.SMSresultLabel.config(font='size, 20', justify='center', anchor='center')
#self.SMSresultLabel.grid(columnspan=3, sticky=tk.W+tk.E, pady=210)
#self.PINresultLabel.grid_forget()
#self.smsDigitsLabel.grid_forget()
#GPIO.output(13,GPIO.HIGH)
#self.doorOpenTimeout = threading.Timer(10, self.returnToIdle_fromAccessGranted)
#self.doorOpenTimeout.start()
#else:
#self.PINresultLabel.grid_forget()
#self.smsDigitsLabel.grid_forget()
#self.SMSresultLabel = ttk.Label(self.tk, text="Incorrect SMS\nCode Entered!")
#self.SMSresultLabel.config(font='size, 20', justify='center', anchor='center')
#self.SMSresultLabel.grid(sticky=tk.W+tk.E, pady=210)
#self.SMSenteredtimeout = threading.Timer(10, self.returnToIdle_fromSMSentered)
#self.SMSenteredtimeout.start()
#def sendSMScode(self, mobileNumber):
# Retreive our Twilio access credentials and "from" number
#dbConnection = MySQLdb.connect(host=dbHost, user=dbUser, passwd=dbPass, db=dbName)
#cur = dbConnection.cursor(MySQLdb.cursors.DictCursor)
#cur.execute("SELECT account_sid, auth_token, twilio_sms_number FROM twilio_api_credentials WHERE id = 1")
#credentials = cur.fetchone()
#account_sid = credentials['account_sid']
#auth_token = credentials['auth_token']
#twilio_sms_number = credentials['twilio_sms_number']
#dbConnection.close()
#smsCode = str(randint(100000, 999999))
#messageText = "Your access code is %s. Please enter this on the touchscreen to continue." % smsCode
#client = Client(account_sid, auth_token)
#message = client.messages.create(
#to=mobileNumber,
#from_=twilio_sms_number,
#body=messageText)
#return smsCode
if __name__ == '__main__':
w = Fullscreen_Window()
w.tk.mainloop()