Hallo zusammen,
ich habe ein Pythonscript, welches Serielle Schnittstellen einließt und GPIOs schaltet. Die Funktion des Scripts ist einwandfrei, allerdings geht der Langzeittest mächtig in die Hose. Mein Pi sitzt in einer Türsteuerung, welche fest im Haus eingebaut ist, deswegen muss das Script unbedingt stabil laufen.
Ich habe versucht die Ausgabe des Scripts in eine Textdatei umzuleiten, die Textdatei blieb aber immer leer. (Ausgabe im Terminal funktioniert einwandfrei) Ich brauche irgend eine verlässliche Loggingmethode, die mir alle Fehler die auftreten mit Timestamp oder ähnlichem ausgibt, damit ich weiß warum das Script zu welchem Zeitpunkt abstürzt.
Wenn ich den Pi starte, startet der Autostart das Script automatisch mit:
python /home/pi/read.py /dev/USB1 /dev/USB2 /dev/USB3
Dabei sind die /dev/USB1 etc. die Schnittstellen die ich dem Script übergebe. Das sind eingesteckte TTL->USB Wandler, an denen eine RFID Spule hängt. Somit lade ich die alle rein und bei Datenstrom wird das Script durchlaufen und wartet auf die nächsten Daten.
Nach dem Start läuft das Script eine unbestimmte Zeit ohne Probleme, am kommenden Tag (über Nacht irgendwann), kommt allerdings keine Reaktion mehr. Eben auch nicht, dass der Chip irgendwie falsch gelesen wurde, also gehe ich davon aus, dass das Script komplett gecrasht ist. (Kann ich nicht feststellen ohne Fehlerlog etc. was da los ist..)
Wunsch:
- Ausgabe in eine Datei oder ähnliches, aufjedenfall so, dass ich die Fehler auch mitbekomme wenn das abstürzt.
- Die Datei sollte im Fehlerfall gesichert sein, ansonsten beim Reboot überschrieben werden. (/tmp)
- Exceptions abfangen. Wenn ein Fehler auftritt, soll der Process gekillt werden falls er noch läuft und automatisch neugestartet werden. Wenn es schwer ist den Prozess zu detektieren oder ähnliches, könnte bei einer Exception auch ein Reboot ausgeführt werden. Im dem Fall soll die Logdatei natürlich erstmal gesichert werden.
Natürlich will ich vorrangig den Fehler finden, da der täglich / nach paar Stunden auftritt und beheben, dafür wie gesagt brauche ich einen Log. Da der Pi quasi 24/7 läuft wollte ich auch eine Sicherung + Reboot jeden Tag bzw. 1x die Woche ausführen. Ich denke je Woche sollte ausreichend sein, weil die Arbeit für den Pi ja sehr gering ist..
So nun, wer kann sowas? Meine Pythonkenntnisse sind wirklich beschissen und nachdem meigrafd an dem Script rumgewerkelt hat (Danke nochmal!), ist es noch etwas undurchsichtiger für mich geworden. Möchte mir da jemand helfen (gerne auch im IRC oder sonstwo, damit man das zusammen machen kann, sonst einfach hier). Dann muss ich mit den Sachen an das Haus fahren und das vor Ort einbinden und hoffen den Fehler so zu bekommen...
Script:
import os
import sys
import serial
import select
import signal
import time
import datetime
from functools import partial
import MySQLdb
import RPi.GPIO as GPIO
from Queue import Queue
queue = Queue()
GPIO.setmode(GPIO.BOARD)
GPIO.setup(29, GPIO.OUT) #LED1 BCM5
GPIO.setup(31, GPIO.OUT) #LED2 BCM6
GPIO.setup(37, GPIO.OUT) #LED3 BCM26
GPIO.setup(16, GPIO.OUT) #RELAIS1 BCM23
GPIO.setup(18, GPIO.OUT) #RELAIS2 BCM24
GPIO.setup(36, GPIO.OUT) #RELAIS3 BCM16
# Alle GPIOs auf 0 setzen
GPIO.output(29, GPIO.LOW) #LED1
GPIO.output(31, GPIO.LOW) #LED2
GPIO.output(37, GPIO.LOW) #LED3
GPIO.output(16, GPIO.LOW) #RELAIS1
GPIO.output(18, GPIO.LOW) #RELAIS2
GPIO.output(36, GPIO.LOW) #RELAIS3
db = MySQLdb.connect(host="localhost", # your host, usually localhost
user="root", # your username
passwd="raspberry", # your password
db="rfid") # name of the data base
# RFID
ID = ""
Zeichen = 0
decuid = ""
Checksumme = 0
Tag = 0
Startflag = "\x02"
Endflag = "\x03"
class SelectLoop(object):
def __init__(self, *a, **k):
super(SelectLoop, self).__init__(*a, **k)
self._input_mapping = {}
def add_file(self, fileobject, callback):
self._input_mapping[fileobject] = callback
def mainloop(self):
while True:
#print self._input_mapping.keys()
read_fds, _, _ = select.select(
self._input_mapping.keys(),
[],
[],
)
for fd in read_fds:
self._input_mapping[fd](fd)
def read_file(filename, fileobject):
#Einzelwerte Ausgeben
#print filename, fileobject.read()
if fileobject.read() == Startflag:
doppelausloeser = 0
Checksumme = 0
Checksumme_Tag = 0
ID = ""
# ID zusammen setzen
for Counter in range(13):
Zeichen = fileobject.read()
ID = ID + str(Zeichen)
# Endflag aus dem String loeschen
ID = ID.replace(Endflag, "" );
# Checksumme berechnen
for I in range(0, 9, 2):
Checksumme = Checksumme ^ (((int(ID[I], 16)) << 4) + int(ID[I+1], 16))
Checksumme = hex(Checksumme)
# Tag herausfiltern
Tag = ((int(ID[1], 16)) << 8) + ((int(ID[2], 16)) << 4) + ((int(ID[3], 16)) << 0)
Tag = hex(Tag)
# Ausgabe der Daten
#print "------------------------------------------"
#print "HEX-UID: ", ID[4:10]
decuid = int(ID[4:10],16)
while 10-len(str(decuid)) > 0:
decuid = "0" + str(decuid)
# Doppelausloeser vermeiden
while not queue.empty():
timestamp, UID = queue.get()
if (decuid == UID) and ((time.time() - timestamp) <= 10):
doppelausloeser = 1
queue.put( (time.time(), decuid) ) # tuple of unix-timestamp and UID
print filename, decuid
print doppelausloeser
if doppelausloeser == 1:
print "Doppelausloeser! ID %s wurde in den letzten 10 Sekunden schon mal eingelesen!" % decuid
else:
# Zutritt auf 0 setzen
zutritt = 0
# Datenbankverarbeitung
cur = db.cursor()
try:
cur.execute("SELECT * FROM tags_known WHERE uid = (%s)", (decuid))
rows = cur.fetchall()
if rows:
for row in rows:
timefrom = str(row[4])
timeto = str(row[5])
datefrom = str(row[6])
dateto = str(row[7])
print "UID gefunden!"
# Zeitumrechnung in Sekunden
zeitfrom_db = int(timefrom.split(':',3)[0])*3600 + int(timefrom.split(':',3)[1])*60 + int(timefrom.split(':',3)[2])
zeitto_db = int(timeto.split(':',3)[0])*3600 + int(timeto.split(':',3)[1])*60 + int(timeto.split(':',3)[2])
zeitjetzt = int(time.strftime("%H"))*3600 + int(time.strftime("%M"))*60 + int(time.strftime("%S"))
#Zeitzutritt
if zeitfrom_db < zeitjetzt and zeitto_db > zeitjetzt:
zutritt = 1
elif zeitto_db < zeitfrom_db:
if zeitfrom_db < zeitjetzt+86400 and zeitto_db+86400 > zeitjetzt+86400:
zutritt = 1
elif zeitfrom_db == 0 and zeitto_db == 0:
zutritt = 1
else:
zutritt = 0
#Datumszutritt
if zutritt != 0:
if datefrom == "None" or dateto == "None":
zutritt = 1
else:
# Datumsumrechnung
jahrfrom = datefrom.split('-',3)[0]
monatfrom = datefrom.split('-',3)[1]
tagfrom = datefrom.split('-',3)[2]
jahrto = dateto.split('-',3)[0]
monatto = dateto.split('-',3)[1]
tagto = dateto.split('-',3)[2]
if datetime.date.today() >= datetime.date(int(jahrfrom), int(monatfrom), int(tagfrom)) and datetime.date.today() <= datetime.date(int(jahrto), int(monatto), int(tagto)):
zutritt = 1
else:
zutritt = 0
if zutritt != 0:
print "Zutritt Akzeptiert!"
if filename == "/dev/USB1":
GPIO.output(29, GPIO.HIGH) #LED1
GPIO.output(16, GPIO.HIGH) #RELAIS1
time.sleep(1)
GPIO.output(29, GPIO.LOW) #LED21
GPIO.output(16, GPIO.LOW) #RELAIS1
elif filename == "/dev/USB2":
GPIO.output(31, GPIO.HIGH) #LED2
GPIO.output(18, GPIO.HIGH) #RELAIS2
time.sleep(1)
GPIO.output(31, GPIO.LOW) #LED2
GPIO.output(18, GPIO.LOW) #RELAIS2
elif filename == "/dev/USB3":
GPIO.output(37, GPIO.HIGH) #LED3
GPIO.output(36, GPIO.HIGH) #RELAIS3
time.sleep(1)
GPIO.output(37, GPIO.LOW) #LED3
GPIO.output(36, GPIO.LOW) #RELAIS3
#Access_Log
try:
cur.execute("INSERT INTO access_log(uid, reader, access) values (%s, %s, '1')", (decuid, filename[-1]))
print "Zutrittslog erfolgreich geschrieben!"
db.commit()
except:
print "Datenbankfehler!"
db.rollback()
else:
print "Zutritt abgelehnt!"
db.rollback()
if filename == "/dev/USB1":
GPIO.output(29, GPIO.HIGH) #LED1
time.sleep(0.2)
GPIO.output(29, GPIO.LOW) #LED1
time.sleep(0.1)
GPIO.output(29, GPIO.HIGH) #LED1
time.sleep(0.2)
GPIO.output(29, GPIO.LOW) #LED1
time.sleep(0.1)
GPIO.output(29, GPIO.HIGH) #LED1
time.sleep(0.2)
GPIO.output(29, GPIO.LOW) #LED1
elif filename == "/dev/USB2":
GPIO.output(31, GPIO.HIGH) #LED1
time.sleep(0.2)
GPIO.output(31, GPIO.LOW) #LED1
time.sleep(0.1)
GPIO.output(31, GPIO.HIGH) #LED1
time.sleep(0.2)
GPIO.output(31, GPIO.LOW) #LED1
time.sleep(0.1)
GPIO.output(31, GPIO.HIGH) #LED1
time.sleep(0.2)
GPIO.output(31, GPIO.LOW) #LED1
elif filename == "/dev/USB3":
GPIO.output(37, GPIO.HIGH) #LED1
time.sleep(0.2)
GPIO.output(37, GPIO.LOW) #LED1
time.sleep(0.1)
GPIO.output(37, GPIO.HIGH) #LED1
time.sleep(0.2)
GPIO.output(37, GPIO.LOW) #LED1
time.sleep(0.1)
GPIO.output(37, GPIO.HIGH) #LED1
time.sleep(0.2)
GPIO.output(37, GPIO.LOW) #LED1
else:
if filename == "/dev/USB1":
GPIO.output(29, GPIO.HIGH) #LED1
time.sleep(0.2)
GPIO.output(29, GPIO.LOW) #LED1
time.sleep(0.1)
GPIO.output(29, GPIO.HIGH) #LED1
time.sleep(0.2)
GPIO.output(29, GPIO.LOW) #LED1
time.sleep(0.1)
GPIO.output(29, GPIO.HIGH) #LED1
time.sleep(0.2)
GPIO.output(29, GPIO.LOW) #LED1
elif filename == "/dev/USB2":
GPIO.output(31, GPIO.HIGH) #LED1
time.sleep(0.2)
GPIO.output(31, GPIO.LOW) #LED1
time.sleep(0.1)
GPIO.output(31, GPIO.HIGH) #LED1
time.sleep(0.2)
GPIO.output(31, GPIO.LOW) #LED1
time.sleep(0.1)
GPIO.output(31, GPIO.HIGH) #LED1
time.sleep(0.2)
GPIO.output(31, GPIO.LOW) #LED1
elif filename == "/dev/USB3":
GPIO.output(37, GPIO.HIGH) #LED1
time.sleep(0.2)
GPIO.output(37, GPIO.LOW) #LED1
time.sleep(0.1)
GPIO.output(37, GPIO.HIGH) #LED1
time.sleep(0.2)
GPIO.output(37, GPIO.LOW) #LED1
time.sleep(0.1)
GPIO.output(37, GPIO.HIGH) #LED1
time.sleep(0.2)
GPIO.output(37, GPIO.LOW) #LED1
# Unbekannte UID in Datenbank schreiben
try:
cur.execute("SELECT * FROM tags_new WHERE uid = (%s)", (decuid))
row = cur.fetchone()
if row == None:
cur.execute("INSERT INTO tags_new(uid) values (%s)", (decuid))
print "Unbekannte UID "+decuid+" erfolgreich in die Datenbank geschrieben"
else:
print "Unbekannte UID "+decuid+" bereits vorhanden!"
db.commit()
except:
print "Datenbankfehler!"
db.rollback()
try:
cur.execute("INSERT INTO access_log(uid, reader, access) values (%s, %s, '0')", (decuid, filename[-1]))
print "Zutrittslog erfolgreich geschrieben!"
db.commit()
except:
print "Datenbankfehler!"
db.rollback()
except:
print "Datenbankfehler!"
db.rollback()
cur.close()
def main():
loop = SelectLoop()
for fname in sys.argv[1:]:
ser = serial.Serial()
ser.port = fname
ser.baudrate = 9600
try:
ser.open()
except Exception, e:
print "Error open serial port: " + str(e)
continue
if ser.isOpen():
try:
ser.flushInput() #flush input buffer, discarding all its contents
ser.flushOutput() #flush output buffer, aborting current output and discard all that is in buffer
loop.add_file(ser, partial(read_file, fname))
except Exception, e:
print "Error...: " + str(e)
loop.mainloop()
if __name__ == '__main__':
main()
Alles anzeigen
Gruß
JumpY