Created
August 16, 2016 12:26
-
-
Save bitmorse/31daa3ada45a64fcdf0850f702c7941a to your computer and use it in GitHub Desktop.
hacky checkpoint with rfid card reader
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import serial | |
import sys | |
import wiringpi | |
from time import sleep | |
import Adafruit_Nokia_LCD as LCD | |
import Adafruit_GPIO.SPI as SPI | |
from simplemysql import SimpleMysql | |
from threading import Thread | |
from PIL import Image | |
from PIL import ImageDraw | |
from PIL import ImageFont | |
from slackclient import SlackClient | |
def pretty_date(time=False): | |
""" | |
Get a datetime object or a int() Epoch timestamp and return a | |
pretty string like 'an hour ago', 'Yesterday', '3 months ago', | |
'just now', etc | |
""" | |
from datetime import datetime | |
now = datetime.now() | |
if type(time) is int: | |
diff = now - datetime.fromtimestamp(time) | |
elif isinstance(time,datetime): | |
diff = now - time | |
elif not time: | |
diff = now - now | |
second_diff = diff.seconds | |
day_diff = diff.days | |
if day_diff < 0: | |
return '' | |
if day_diff == 0: | |
if second_diff < 10: | |
return "just now" | |
if second_diff < 60: | |
return str(second_diff) + " seconds ago" | |
if second_diff < 120: | |
return "a minute ago" | |
if second_diff < 3600: | |
return str(second_diff / 60) + " minutes ago" | |
if second_diff < 7200: | |
return "an hour ago" | |
if second_diff < 86400: | |
return str(second_diff / 3600) + " hours ago" | |
if day_diff == 1: | |
return "Yesterday" | |
if day_diff < 7: | |
return str(day_diff) + " days ago" | |
if day_diff < 31: | |
return str(day_diff / 7) + " weeks ago" | |
if day_diff < 365: | |
return str(day_diff / 30) + " months ago" | |
return str(day_diff / 365) + " years ago" | |
def notify_octanis_slack(name): | |
token = "xoxp-..." # found at https://api.slack.com/web#authentication | |
sc = SlackClient(token) | |
print sc.api_call( | |
"chat.postMessage", channel='#random', text="Somebody checked in at Hackuarium. ", | |
username='Hackuarium Checkpoint', icon_emoji=':key:' | |
) | |
def notify_hackuarium_slack(name): | |
token = "xoxp-..." # found at https://api.slack.com/web#authentication | |
sc = SlackClient(token) | |
print sc.api_call( | |
"chat.postMessage", channel='#_random', text="Somebody arrived at Hackuarium!", | |
username='Hackuarium Checkpoint', icon_emoji=':wave:' | |
) | |
def reset_rfid_reader(): | |
wiringpi.digitalWrite(18, 0) | |
sleep(0.1) | |
wiringpi.digitalWrite(18, 1) | |
def setup_display(disp): | |
# Clear display. | |
disp.clear() | |
disp.display() | |
# Create blank image for drawing. | |
# Make sure to create image with mode '1' for 1-bit color. | |
image = Image.new('1', (LCD.LCDWIDTH, LCD.LCDHEIGHT)) | |
# Get drawing object to draw on image. | |
draw = ImageDraw.Draw(image) | |
draw.rectangle((0,0,LCD.LCDWIDTH,LCD.LCDHEIGHT),outline=255,fill=255) | |
return draw,image | |
def render(disp,image): | |
# Display image. | |
disp.image(image) | |
disp.display() | |
def welcome_msg(disp,font): | |
draw,image = setup_display(disp) | |
draw.text((10,5), 'Welcome to', font=font) | |
draw.text((8,15), 'Hackuarium!', font=font) | |
draw.text((0,32), 'Check in here.', font=font) | |
render(disp,image) | |
def success_msg(disp, name, font): | |
draw,image = setup_display(disp) | |
draw.text((0,5), 'Welcome back,', font=font) | |
draw.text((0,30), name + " <3", font=font) | |
render(disp,image) | |
def failure_msg(disp, id, font): | |
draw,image = setup_display(disp) | |
draw.text((0,5), 'Whooooooo', font=font) | |
draw.text((0,12), 'are you?', font=font) | |
draw.text((0,19), 'Who, who,', font=font) | |
draw.text((0,28), 'who, who?', font=font) | |
render(disp,image) | |
def log_swipe(db,mifare_card_id,authorised): | |
db.insert("logs", {"mifare_card_id": mifare_card_id, "authorised":authorised}) | |
db.commit() | |
def is_card_authorised(db, id): | |
user = db.getOne("users", ["name","groups"], ("mifare_card_id LIKE %s",[id])) | |
if user: | |
print("Found user:"+ user.name) | |
return 1,user | |
else: | |
return 0,None | |
def cycle_checkins_today(db,disp,font): | |
#query db for checkins today | |
logs = db.getAll("logs",["mifare_card_id", "timestamp"],("timestamp >= DATE_ADD(NOW(), INTERVAL -12 HOUR)",[])) | |
if logs: | |
i=0 | |
previous_id=None | |
while(i<len(logs)): | |
id = logs[i].mifare_card_id | |
if previous_id != id: | |
timestamp = logs[i].timestamp | |
authorised, user = is_card_authorised(db,id) | |
if authorised: | |
draw,image = setup_display(disp) | |
draw.text((0,5), user.name, font=font) | |
draw.text((0,14), 'checked in', font=font) | |
draw.text((0,22), pretty_date(timestamp), font=font) | |
render(disp,image) | |
sleep(10) | |
previous_id = id | |
i+=1 | |
authorised=0 | |
def rfid_reader(db, ser, disp, font): | |
#rfid reader requires a reset after every card read *rolls eyes* | |
reset_rfid_reader() | |
welcome_msg(disp,font) | |
line = "" | |
while True: | |
for c in ser.read(): | |
line += c | |
if c == '\n': | |
if "Series Number:" in line: | |
id = line.split(':', 1)[1].rstrip() | |
authorised,user = is_card_authorised(db,id) | |
if(authorised): | |
success_msg(disp, user.name, font) | |
if("octanis" in user.groups): | |
notify_octanis_slack(user.name) | |
if("hackuarium" in user.groups): | |
notify_hackuarium_slack(user.name) | |
print("Authorised id:"+id) | |
else: | |
failure_msg(disp, id,font) | |
print("Unauthorised id:"+id) | |
log_swipe(db,id,authorised) | |
ser.reset_input_buffer() | |
reset_rfid_reader() | |
line = "" | |
break | |
db.close() | |
ser.close() | |
def slideshow(db, disp, font): | |
while(1): | |
welcome_msg(disp,font) | |
sleep(6) | |
cycle_checkins_today(db,disp,font) | |
# MAIN DEFINITIONS | |
# Raspberry Pi software SPI config: | |
SCLK = 11 | |
DIN = 10 | |
DC = 23 | |
RST = 24 | |
CS = 8 | |
RFID_RESET = 18 | |
DISPLAY_CONTRAST=60 | |
def main(): | |
#setup reset pin | |
wiringpi.wiringPiSetupGpio() | |
wiringpi.pinMode(RFID_RESET, 1) | |
# Software SPI usage (defaults to bit-bang SPI interface): | |
disp = LCD.PCD8544(DC, RST, SCLK, DIN, CS) | |
disp.begin(contrast=DISPLAY_CONTRAST) | |
#mysql setup | |
db = SimpleMysql( | |
host=" ", | |
db=" ", | |
user=" ", | |
passwd=" ", | |
keep_alive=False # try and reconnect timedout mysql connections? | |
) | |
#rfid serial port setup | |
ser = serial.Serial( | |
port='/dev/ttyAMA0',\ | |
baudrate=115200,\ | |
parity=serial.PARITY_NONE,\ | |
stopbits=serial.STOPBITS_ONE,\ | |
bytesize=serial.EIGHTBITS,\ | |
timeout=None) | |
#display font | |
font = ImageFont.truetype(sys.path[0]+'/PixelOperator8.ttf',8) | |
print("connected to: " + ser.portstr) | |
#start threads | |
t1 = Thread(target=rfid_reader, args=(db,ser,disp,font)) | |
t1.start() | |
sleep(3) | |
t2 = Thread(target=slideshow, args=(db,disp,font)) | |
t2.start() | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment