initial commit of working card reader
This commit is contained in:
commit
75e7e8bf99
BIN
authorized_cards.db
Normal file
BIN
authorized_cards.db
Normal file
Binary file not shown.
96
database.py
Normal file
96
database.py
Normal file
|
@ -0,0 +1,96 @@
|
|||
import sqlite3
|
||||
from sqlite3 import Error
|
||||
from datetime import datetime
|
||||
|
||||
database = 'authorized_cards.db'
|
||||
|
||||
sql_create_user_table = """ CREATE TABLE IF NOT EXISTS users (
|
||||
id integer PRIMARY KEY,
|
||||
name text NOT NULL,
|
||||
card_id integer NOT NULL,
|
||||
counter integer NOT NULL,
|
||||
first_seen date NOT NULL,
|
||||
last_seen date NOT NULL
|
||||
); """
|
||||
|
||||
|
||||
def create_connection(db_file):
|
||||
""" create a database connection to the SQLite database
|
||||
specified by the db_file
|
||||
:param db_file: database file
|
||||
:return: Connection object or None
|
||||
"""
|
||||
conn = None
|
||||
try:
|
||||
conn = sqlite3.connect(db_file)
|
||||
except Error as e:
|
||||
print(e)
|
||||
|
||||
return conn
|
||||
|
||||
|
||||
def create_table(conn, create_table_sql):
|
||||
""" create a table from the create_table_sql statement
|
||||
:param conn: Connection object
|
||||
:param create_table_sql: a CREATE TABLE statement
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
c = conn.cursor()
|
||||
c.execute(create_table_sql)
|
||||
except Error as e:
|
||||
print(e)
|
||||
|
||||
|
||||
def create_user(conn, user, card_id, counter, first_seen, last_seen):
|
||||
"""
|
||||
Create a new task
|
||||
:param conn:
|
||||
:return:
|
||||
"""
|
||||
|
||||
sql = ''' INSERT INTO users(name, card_id, counter, first_seen, last_seen)
|
||||
VALUES(?,?,?,?,?) '''
|
||||
cur = conn.cursor()
|
||||
cur.execute(sql, (user, card_id, counter, first_seen, last_seen))
|
||||
return cur.lastrowid
|
||||
|
||||
|
||||
def select_all_users(conn):
|
||||
"""
|
||||
Query all rows in the tasks table
|
||||
:param conn: the Connection object
|
||||
:return:
|
||||
"""
|
||||
cur = conn.cursor()
|
||||
cur.execute("SELECT * FROM users")
|
||||
|
||||
rows = cur.fetchall()
|
||||
|
||||
return rows
|
||||
|
||||
def increment_counter(conn, id):
|
||||
"""
|
||||
increment the authentication counter in the database for the given id
|
||||
"""
|
||||
sql = ''' UPDATE users
|
||||
SET counter = counter + 1 ,
|
||||
last_seen = ?
|
||||
WHERE id = ?'''
|
||||
cur = conn.cursor()
|
||||
cur.execute(sql, (str(datetime.utcnow()), id,))
|
||||
conn.commit()
|
||||
|
||||
|
||||
def setup_db():
|
||||
# create a database connection
|
||||
conn = create_connection(database)
|
||||
|
||||
# create tables
|
||||
if conn is not None:
|
||||
# create projects table
|
||||
create_table(conn, sql_create_user_table)
|
||||
else:
|
||||
print("Error! cannot create the database connection.")
|
||||
|
||||
return conn
|
123
main.py
Normal file
123
main.py
Normal file
|
@ -0,0 +1,123 @@
|
|||
# Setting up raspi for card reader
|
||||
# https://pimylifeup.com/raspberry-pi-rfid-rc522/
|
||||
#
|
||||
from database import *
|
||||
import time
|
||||
|
||||
import RPi.GPIO as GPIO
|
||||
from mfrc522 import SimpleMFRC522
|
||||
|
||||
class DoorLock():
|
||||
def __init__(self):
|
||||
# initialize card reader
|
||||
self.reader = SimpleMFRC522()
|
||||
|
||||
def increment(self, counter):
|
||||
# increment counter and send it to card
|
||||
counter += 1
|
||||
data_new = str(counter)
|
||||
|
||||
self.reader.write(data_new)
|
||||
|
||||
# check if counter was updated successfully
|
||||
_, text = self.reader.read()
|
||||
try:
|
||||
counter_new = int(text)
|
||||
except ValueError:
|
||||
return False
|
||||
return counter == counter_new
|
||||
|
||||
def check_authorization(self, reader_id, counter):
|
||||
# open database
|
||||
conn = create_connection(database)
|
||||
|
||||
# check if id is in the database
|
||||
with conn:
|
||||
users = select_all_users(conn)
|
||||
|
||||
for user in users:
|
||||
db_id = user[0]
|
||||
name = user[1]
|
||||
user_card_id = user[2]
|
||||
user_counter = user[3]
|
||||
if reader_id == user_card_id:
|
||||
# check if use counter on the card matches counter in the database
|
||||
# if counter is different -> assume the card has been cloned
|
||||
if counter == user_counter:
|
||||
print("user {} with card_id {} authorized".format(name, hex(reader_id)))
|
||||
return True, db_id
|
||||
else:
|
||||
print("error: counter does not match! please investigate!")
|
||||
|
||||
# if no match was found in the database: deny entry
|
||||
print("You shall not pass!")
|
||||
print("could not authorize card_id {}".format(reader_id))
|
||||
return False, None
|
||||
|
||||
|
||||
def unlock_door(self):
|
||||
# TODO send command to open door lock
|
||||
print("Unlocking door!\n\n")
|
||||
|
||||
def release_the_kraken(self):
|
||||
# TODO notify that authentication failed
|
||||
# not implemented yet
|
||||
print("Release the Kraken!")
|
||||
|
||||
def run_authorization(self):
|
||||
try:
|
||||
while True:
|
||||
print("Hold card before reader..")
|
||||
uid, data = self.reader.read()
|
||||
|
||||
print("data = ", data)
|
||||
#counter = int.from_bytes(data, byteorder='big')
|
||||
try:
|
||||
counter = int(data)
|
||||
except ValueError:
|
||||
print("error: data on the card could not be converted")
|
||||
counter = None
|
||||
|
||||
if counter is not None:
|
||||
print("card read: \n uid = {}\ncounter = {}\n".format(hex(uid), counter))
|
||||
authorized, db_id = self.check_authorization(uid, counter)
|
||||
|
||||
if authorized:
|
||||
# increment use counter on the card
|
||||
increment_status = self.increment(counter)
|
||||
|
||||
if increment_status:
|
||||
# update the counter and the time of last access in the database
|
||||
# open database
|
||||
conn = create_connection(database)
|
||||
increment_counter(conn, db_id)
|
||||
|
||||
self.unlock_door()
|
||||
else:
|
||||
# if we cannot increment the counter on the card (e.g. because the card was removed too quickly)
|
||||
# we do not let the user in even though authentication was correct -> try again
|
||||
print("increment failed!")
|
||||
else:
|
||||
print("authentication failed")
|
||||
self.release_the_kraken()
|
||||
time.sleep(1.5)
|
||||
finally:
|
||||
#GPIO.cleanup()
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# create database with some users
|
||||
# conn = setup_db()
|
||||
# with conn:
|
||||
# create_user(conn, 'Simon', 4225799947, 0, str(datetime.utcnow()), str(datetime.utcnow()))
|
||||
# create_user(conn, 'Valentin', 154921302, 0, str(datetime.utcnow()), str(datetime.utcnow()))
|
||||
# users = select_all_users(conn)
|
||||
|
||||
doors_of_durin = DoorLock()
|
||||
|
||||
data = bytearray([0]*16)
|
||||
#data = '0'
|
||||
#write_success = doors_of_durin.reader.write(data)
|
||||
doors_of_durin.run_authorization()
|
||||
pass
|
Loading…
Reference in New Issue
Block a user