Python Forum

Full Version: ATM Tracking Issue
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
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

#!/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()
The following tutorial might be able to help you with the locking up.
https://python-forum.io/Thread-Tkinter-H...ng-the-gui