Skip to content

Instantly share code, notes, and snippets.

@bitmorse
Created August 16, 2016 12:26
Show Gist options
  • Select an option

  • Save bitmorse/31daa3ada45a64fcdf0850f702c7941a to your computer and use it in GitHub Desktop.

Select an option

Save bitmorse/31daa3ada45a64fcdf0850f702c7941a to your computer and use it in GitHub Desktop.

Revisions

  1. bitmorse created this gist Aug 16, 2016.
    263 changes: 263 additions & 0 deletions rfid_reader.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,263 @@
    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()