Skip to content

Instantly share code, notes, and snippets.

@bitmorse
Created August 16, 2016 12:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bitmorse/31daa3ada45a64fcdf0850f702c7941a to your computer and use it in GitHub Desktop.
Save bitmorse/31daa3ada45a64fcdf0850f702c7941a to your computer and use it in GitHub Desktop.
hacky checkpoint with rfid card reader
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