From 32528f7a11aa4aefb05ff5b551e85c1ff470c48e Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Sun, 26 Jun 2022 16:58:56 -0600 Subject: [PATCH] Add original code --- old.py | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 old.py diff --git a/old.py b/old.py new file mode 100644 index 0000000..9f420b7 --- /dev/null +++ b/old.py @@ -0,0 +1,193 @@ +import os +import sys +import RPi.GPIO as GPIO +import serial +import sqlite3 +import atexit +import time +import logging +import pygame +import threading +import urllib + +def dict_factory(cursor, row): + d = {} + for idx, col in enumerate(cursor.description): + d[col[0]] = row[idx] + return d + +class DaemonApp(object): + def __init__(self): + self.stdin_path = '/dev/null' + self.stdout_path = '/dev/null' + self.stderr_path = '/dev/null' + self.pidfile_path = '/var/run/door.pid' + self.pidfile_timeout = 5 + + self.running = True + self.log = logging.getLogger("daemon") + + def __halt(self): + self.running = False + + def run(self): + atexit.register(self.__halt) + + self.setup() + while self.running: + try: + self.loop() + except KeyboardInterrupt: + break + except Exception as ex: + self.log.exception(ex) + break + + self.stop() + + def setup(self): + pass + + def stop(self): + pass + + def loop(self): + pass + +class App(DaemonApp): + def __init__(self, serial, db_file): + super(App, self).__init__(); + + self.serial = serial + self.db_file = db_file + + self.recent = {} + + def setup(self): + self.log.info("starting") + + GPIO.setwarnings(False) + GPIO.setmode(GPIO.BCM) + GPIO.setup(17, GPIO.OUT) + # The 110 Door fails secure, + # drive low to close the NO relay and unlock the door + # leave HIGH otherwise. + # The 108 Door fails secure, + # but needs to be driven HIGH to close the normally open relay and unlock the door + GPIO.output(17, GPIO.LOW) + + def loop(self): + card = self.serial.readline() + if not card: + return + + card = card.strip() + if len(card) != 10: + return + + now = time.time() + if card in self.recent: + if now - self.recent[card] < 5.0: + self.recent[card] = now + return + + self.recent[card] = now + + self.handle_card_read(card) + + def stop(self): + self.log.info("stopping") + + def handle_card_read(self, card): + db = sqlite3.connect(self.db_file) + db.row_factory = dict_factory + baseurl = "http://my.protospace.ca/locks/door/108A/" + + self.unify_serial_numbers(db, card) + + # TODO flag duplicates + cards = self.query_cards(db, card) + if cards: + card = cards.pop(0) + + # TODO merge duplicate values + for temp in cards: + pass + + self.update_timestamp(db, card['serial']) + if not card['active']: + self.log.warn("%s[%s] denied access" % (card["owner"], card['serial'])) + urlaction = "DENIED" + rfid = "%s" % card['serial'] + + else: + self.log.info("%s[%s] entered the space" % (card["owner"], card['serial'])) + urlaction = "ALLOWED" + rfid = "%s" % card['serial'] + + threading.Thread(target=self.unlock_door, kwargs={"duration": 5.0}).start() + + else: + self.log.info("Card read: %s" % (card,)) + rfid = "%s" % (card,) + urlaction = "NOT IN DB" + + url = baseurl + rfid + "/" + urlaction + + try: + response = urllib.urlopen(url).read() + self.log.info("Web log response was %s" % (response)) + except: + self.log.warn("A generic error occurred on the web call.") + + db.close() + + def unify_serial_numbers(self, db, card): + q = "UPDATE cards SET serial='%s' WHERE serial='%s'" % (card, card[::-1]) + db.execute(q) + + def update_scan_log(self, db, card): + q = "INSERT INTO scan_logs" + + def update_timestamp(self, db, card): + q = "UPDATE cards SET first_seen = datetime('now') WHERE serial = '%s' AND first_seen IS NULL" % (card) + db.execute(q) + + q = "UPDATE cards SET last_seen = datetime('now') WHERE serial = '%s'" % (card) + db.execute(q) + + db.commit() + + def unlock_door(self, duration): + #108 Door needs HIGH to unlock + #110 Door needs LOW to unlock + GPIO.output(17, GPIO.HIGH) + time.sleep(duration) + GPIO.output(17, GPIO.LOW) + + def play_sound(self, path): + if not (path and os.path.exists(path)): + return + + if not pygame.mixer.music.get_busy(): + try: + pygame.mixer.music.load(path) + pygame.mixer.music.play() + except: + self.log.warn("Failed to play sound '%s'" % (path)) + + def query_cards(self, db, card): + cur = db.cursor() + query = "SELECT * FROM cards WHERE serial='%s' ORDER BY id ASC" % card + cur.execute(query) + + cards = [] + + row = cur.fetchone() + while row: + cards.append(row) + row = cur.fetchone() + + self.log.debug(cards) + + return cards