Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
executable file 404 lines (361 sloc) 12.9 KB
#!/usr/bin/python
# -*- coding: utf-8 -*-
# neuer Versuch
# cleaner
# anzeige MUSS mit lock gemacht werden da sonst evtl idle anzeige unterbrochen wird im schreibvorgang,
# und dann die auswertung mit ihrer anzeige nicht mehr auf /ram/temp.bmp zugreifen kann -> aufgehängt
# Python Imports
import os
import sys
import subprocess
import threading
import pygame
import time
import math
import socket
import MySQLdb
import serial
import signal
import locale
import RPi.GPIO as GPIO
import ConfigParser
# log program launch
print "-------START--------"
print "started at" + time.strftime("%D -- %H:%M:%S", time.localtime())
# GPIO Setup
GPIO.setmode(GPIO.BCM)
GPIO.setup(19, GPIO.OUT)
GPIO.setup(20, GPIO.IN)
GPIO.setup(21, GPIO.IN)
GPIO.output(19, GPIO.LOW)
# Wochentag in Deutsch
locale.setlocale(locale.LC_ALL, 'de_DE.UTF-8')
# Datenbank Verbindung
#get from ini file
config = ConfigParser.ConfigParser()
config.read('db.ini')
database = dict(config.items('db'))
print "loaded database connection parameters from file"
# init vars
lock = threading.Lock()
texttime = None
dienstgangstatus = False
saldostatus = False
queue = []
network = False
offline = False
stuck = False
DEVNULL = open(os.devnull, "wb")
# setup pygame
pygame.init()
# setup display resolution should match
# dont forget to adjust layout aswell
# if running in an X environment, fullscreen and no cursor should be enabled
window = pygame.display.set_mode((320,240))
#pygame.display.toggle_fullscreen()
#pygame.mouse.set_visible(0)
minerva = pygame.image.load("minerva.png")
font0 = pygame.font.SysFont("droidsans", 21)
font1 = pygame.font.SysFont("droidsans", 83)
font2 = pygame.font.SysFont("droidsans", 33)
font3 = pygame.font.SysFont("droidsans", 30)
font2.set_italic(1)
font2.set_bold(1)
label0 = font0.render("Fritz-Haber-Institut Berlin", 1, (255,255,255))
offlinelabel = font0.render("offline", 1, (232,12,122))
label3 = font0.render(socket.gethostname(), 1, (255,255,255))
label4 = font3.render("Dienstgang >>", 1, (255,255,255))
label5 = font3.render("Saldo abrufen >>", 1, (255,255,255))
rect2 = pygame.Rect(5, 125, 310, 5)
def anzeige(name, status, banner):
window.fill([0,0,0])
window.blit(minerva, (0,0))
label4_hpos = (315 - label4.get_width())
label5_hpos = (315 - label5.get_width())
window.blit(label4, (label4_hpos,30))
window.blit(label5, (label5_hpos,180))
if banner == "kommt":
color = (161,255,24)
if banner == "geht":
color = (255,0,0)
if banner == "minerva":
color = (45,232,225)
label1 = font1.render(status, 1, (255,255,255))
label2 = font2.render(name, 1, (255,255,255))
label1_hpos = (320 - label1.get_width()) / 2
label2_hpos = (320 - label2.get_width()) / 2
pygame.draw.rect(window, color, rect2)
window.blit(label0, (0,225))
window.blit(label1, (label1_hpos,65))
window.blit(label2, (label2_hpos,135))
window.blit(label3, (260,225))
global offline
try:
subprocess.check_call(['timeout', '0.2s', 'ping', '-c1', database['host']], stdout=DEVNULL, stderr=DEVNULL)
if offline:
print status + ": back online!"
offline = False
except:
window.blit(offlinelabel, (0,0))
if not offline:
print status + ": went offline!"
offline = True
# this is for the C-Berry Display
pygame.image.save(window, "/ram/temp.bmp")
os.system("./tft_bmp /ram/temp.bmp")
# this is for X environment
#pygame.display.flip()
def idle():
global texttime
while True:
while not lock.locked():
oldtime = texttime
lt = time.localtime()
texttime = time.strftime("%H:%M:%S", lt)
if dienstgangstatus and not saldostatus:
name = "Dienstgang?"
elif saldostatus and not dienstgangstatus:
name = "Saldo?"
elif not saldostatus and not dienstgangstatus:
name = time.strftime("%a %d.%m.%Y -- KW: %V", lt)
if oldtime != texttime or GPIO.input(20) == 0 or GPIO.input(21) == 0 :
lock.acquire()
anzeige(name, texttime, "minerva")
lock.release()
time.sleep(0.01)
time.sleep(0.01)
def serialRead():
serialData = serial.Serial(port='/dev/ttyAMA0',baudrate=9600)
ID = ''
ID2 = ''
while True:
while not lock.locked():
if serialData.read() == '\x02' and ID == '':
ID = serialData.read(12)
serialData.flushInput()
if serialData.read() == '\x02' and ID != '':
ID2 = serialData.read(12)
print "ID: " + ID + " -- ID2: " + ID2
if ID == ID2:
ID = ID.replace('\x00', '0')
auswertung(ID, None, False)
serialData.flushInput()
ID = ''
ID2 = ''
time.sleep(0.01)
time.sleep(0.01)
def knopf():
global dienstgangstatus
global saldostatus
while True:
while not lock.locked():
if GPIO.input(20) == 0 and not saldostatus:
print "pressed dienstgang button"
dienstgangstatus = not dienstgangstatus
time.sleep(0.3)
if GPIO.input(21) == 0 and not dienstgangstatus:
print "pressed saldo button"
saldostatus = not saldostatus
time.sleep(0.3)
time.sleep(0.01)
time.sleep(0.01)
def auswertung(ID, zeit, silent):
global db
global dienstgangstatus
global saldostatus
global queue
lock.acquire()
lt = time.localtime()
print "auswertung started!"
if not zeit:
jetzt = time.strftime("%Y-%m-%d %H:%M:%S", lt)
else:
print "custom time!"
jetzt = zeit
print(jetzt)
try:
subprocess.check_call(['timeout', '0.2s', 'ping', '-c1', database['host']], stdout=DEVNULL, stderr=DEVNULL)
network = True
except:
network = False
if network:
db = MySQLdb.connect(host=database["host"],
user=database["user"],
passwd=database["passwd"],
db=database["db"])
dbc = db.cursor()
#alt:
#dbc.execute("select rfid, t.maID, concat(nachname, ', ', vorname) as name from Transponder t join Mitarbeiter m on t.maID = m.maID where t.rfid = %s;", [ID])
dbc.execute("select rfid, t.maID, concat(nachname, ', ', vorname) as name from transponder t join mitarbeiter m on t.maID = m.maID where t.rfid = %s;", [ID])
ma = dbc.fetchone()
else:
ma = None
if ma != None and network:
maID = ma[1]
name = ma[2]
print "MA is: " + name
print "ID is: " + ID
if saldostatus:
# neue DB: saldo direkt aus DB lesen
dbc.execute("select sum(saldomin) from saldo where maID = %s;", [maID])
saldo = dbc.fetchone()
#alt:
#sshline = "ssh saldoread@chronos.rz-berlin.mpg.de /var/www/timerec/saldo_akt.php " + str(maID)
#status = subprocess.check_output(["ssh", "saldoread@chronos.rz-berlin.mpg.de", "/var/www/timerec/saldo_akt.php", str(maID)])[:-1]
if saldo[0] < 0:
banner = "geht"
vorzeichen = "-"
else:
banner = "kommt"
vorzeichen = "+"
saldostd = int(math.floor(abs(saldo[0]/60)))
saldomin = abs(saldo[0]%60)
if saldostd < 10:
saldostd = "0" + str(saldostd)
if saldomin < 10:
saldomin = "0" + str(saldomin)
status = vorzeichen + str(saldostd) + ":" + str(saldomin)
print "saldo is: " + status
saldostatus = False
else:
#alt:
#dbc.execute("select status from MA_Zeit where maID = %s and datumzeit <= %s order by datumzeit desc, mz_ID desc limit 1;", (maID, jetzt))
dbc.execute("select status from zeit where maID = %s and datumzeit <= %s and date(datumzeit) = %s and status != 'Dienst' order by datumzeit desc, zeit_ID desc limit 1;", (maID, jetzt, jetzt[:-9]))
status = dbc.fetchone()
print "status is: "
print(status)
if status != None:
status = status[0]
if status == "geht" or status == None:
status = "kommt"
anwesend = 1
elif status == "kommt":
status = "geht"
anwesend = 0
print "status after if is: " + status
if dienstgangstatus:
# Dienstgang wird statt "kommt" oder "geht" eingesetzt. so nimmt dies keinen Einfluss auf den Saldo oder andere Aktivitäten, der Dienstgang wird aber dennoch registriert.
status = 'Dienst'
dienstgangstatus = False
banner = "minerva"
else:
banner = status
#alt:
#dbc.execute("update Mitarbeiter set anwesend=%s, statusa=%s where maID = %s;", (anwesend, status, maID)) # für alte uhren und alte DB
#dbc.execute("insert into MA_Zeit (maID, datumzeit, status, zt_ID, userid) values (%s, %s, %s, %s, %s);", (maID, jetzt, status, "0", socket.gethostname()))
dbc.execute("insert into zeit (maID, datumzeit, status, userid) values (%s, %s, %s, %s);", (maID, jetzt, status, socket.gethostname()))
#alt:
#if dienstgangstatus:
# dbc.execute("select last_insert_id();")
# last_insert = dbc.fetchone()[0]
# dbc.execute("update MA_Zeit set mz_bem = '#A' where mz_ID = %s", [last_insert])
# dienstgangstatus = False
#banner = status
db.commit()
dbc.close()
db.close()
elif ma == None and network:
name = ID
status = "N/A"
banner = "minerva"
print "mailing unknown ID " + ID
sendmail = "./mailscript.sh "+ID
sendmail = sendmail.replace('\x00', '')
os.system(sendmail)
else:
name = "wird nachgereicht"
status = "OK"
banner = "minerva"
print "currently offline. saving results."
queue.append((jetzt, ID))
print "now in queue:"
print(queue)
if not silent:
print "display data!"
anzeige(name, status.upper(), banner)
GPIO.output(19, GPIO.HIGH)
time.sleep(0.3)
GPIO.output(19, GPIO.LOW)
time.sleep(1.2)
print "auswertung finished!"
lock.release()
def offlinesubmit():
global queue
while True:
try:
subprocess.check_call(['timeout', '0.2s', 'ping', '-c1', database['host']], stdout=DEVNULL, stderr=DEVNULL)
if len(queue) >= 1:
print "submitting offline counts..."
for zeit in queue:
print "current item: " + zeit[1] + " @ " + zeit[0]
auswertung(zeit[1], zeit[0], True)
queue = []
except:
continue
time.sleep(1)
def unstuck():
global stuck
oldtime = None
while True:
if oldtime == texttime and not oldtime == None:
print "we're stuck!"
stuck = True
oldtime = texttime
time.sleep(3)
def timeout():
global saldostatus
global dienstgangstatus
while True:
if saldostatus or dienstgangstatus:
time.sleep(10)
if saldostatus or dienstgangstatus:
saldostatus = False
dienstgangstatus = False
print "10 secs passed, resetting buttons to none..."
time.sleep(0.1)
def signalhandler(signum, frame):
global stuck
stuck = True
signal.signal(signal.SIGTERM, signalhandler)
try:
# C-Berry Display init
os.system("./tft_init")
os.system("./tft_clear")
os.system("./tft_pwm 255")
print "init display done ..."
# init functions as threads
idlethread = threading.Thread(target=idle)
serialthread = threading.Thread(target=serialRead)
knopfthread = threading.Thread(target=knopf)
offlinethread = threading.Thread(target=offlinesubmit)
unstuckthread = threading.Thread(target=unstuck)
timeoutthread = threading.Thread(target=timeout)
# make them independent
idlethread.daemon = True
serialthread.daemon = True
knopfthread.daemon = True
offlinethread.daemon = True
unstuckthread.daemon = True
timeoutthread.daemon = True
# finally launch threads
idlethread.start()
serialthread.start()
knopfthread.start()
offlinethread.start()
unstuckthread.start()
timeoutthread.start()
print "started all threads"
# catch exit in main thread
while not stuck:
try:
time.sleep(0.2)
except:
print "we appear to be stuck, quitting application."
pygame.quit()
sys.exit(0)
except:
print "something bad happend, quitting!"
GPIO.cleanup()
db.close()
pygame.quit()
sys.exit(0)