Moin moin zusammen
Ich bin neu hier und habe sehr wenig Python Erfahrungen, bin aber auh kein Programmierneuling.
Nun bräuchte ich einmal Hilfe oder Anregungen zu folgendem Sachverhalt:
Auf einem Raspi habe ich ein kleines Python Skript, welches bei bestimmten Ereignissen eine Statusmeldung in ein Logfile schreibt oder eine SMS versenden soll. Der SMS Fall wird wahrscheinlich nie eintreffen und die Logdatei täglich zu überprüfen ist unsinnig.
Dazu möchte ich eine Art Überwachung für das Programm einbauen. Wenn es ausfällt soll einfach ein Ausgang am Pi angesprochen werden, den ich dann abgreife und mit einer kleinen Sirene verbinde.
Ich bin mir nun nicht sicher, ob man die Abfrage in das Programm selber implementieren soll, oder ob es eine Linux Status Abfrage wird.
Das Script wird auch mit systemd bei jedem boot gestartet.
Für Tipps und Anregungen wäre ich sehr dankbar.
Programmfehler erkennen und melden.
In Systemd Units kann man über die Option "OnFailure" andere Units angeben, die gestartet werden, wenn der Prozess fehlschlägt. Damit kann man so eine Logik, wie du sie beschreibst, umsetzen. Dein eigentliches Skript wird über die primäre Service-Unit gestartet, das "Nofallskript" über eine sekundäre Service-Unit (z. B. vom Typ "oneshot"), die du in der ersten als "OnFailure" hinterlegst.Stevo hat geschrieben: Ich bin mir nun nicht sicher, ob man die Abfrage in das Programm selber implementieren soll, oder ob es eine Linux Status Abfrage wird.
Das Script wird auch mit systemd bei jedem boot gestartet.
Ich kenne dein Skript nicht, allgemein würde ich statt einer externen Lösung eher dazu neigen, den Code so zu strukturieren, dass Skript nicht einfach so "ausfällt", sondern Exceptions angemessen behandelt werden und diese Notfallfunktion ggf. integriert ist.
@nezzcarth
Danke für den Vorschlag, dass ist eine gute Idee
Der Vollständigkeit halber möchte ich einmal genauer erläutern, worum es geht.
Ich habe zu Hause eine Alarmanlage, welche bisher lediglich einen lokalen Alarm ausgibt. Diese möchte ich um eine selbstgebaute Übertragungseinrichtung erweitern. Die Events Störung sowie Scharf/Unscharf sollen lediglich in einer Log Datei gespeichert werden, echte Alarme zusätzlich per SMS an mich und weitere Personen versand werden. Da ich mir nicht täglich eine Routine SMS zusenden möchte, suche ich nach einem Weg, dieses Skript ausfallsicher zu machen bzw. eine Benachrichtigung zu erhalten, wenn das System nicht mehr läuft.
Im folgendem Skript habe ich dazu einfach einen Ausgang in die Schleife gebaut. Diesen will ich abgreifen und auf ein frei programmierbares Relais der Alarmanlage legen. Wenn das Programm ausfällt ändert sich der Zustand des Kontaktes und die eigentliche Alarmanlage soll ein Störungsalarm senden.
Ich bin mir nur nicht sicher, wie valide dieses Verfahren ist.
Hier ist das vorläufige Skript. Für Verbesserungsvorschläge im Code bin ich auch sehr dankbar
Danke für den Vorschlag, dass ist eine gute Idee
Der Vollständigkeit halber möchte ich einmal genauer erläutern, worum es geht.
Ich habe zu Hause eine Alarmanlage, welche bisher lediglich einen lokalen Alarm ausgibt. Diese möchte ich um eine selbstgebaute Übertragungseinrichtung erweitern. Die Events Störung sowie Scharf/Unscharf sollen lediglich in einer Log Datei gespeichert werden, echte Alarme zusätzlich per SMS an mich und weitere Personen versand werden. Da ich mir nicht täglich eine Routine SMS zusenden möchte, suche ich nach einem Weg, dieses Skript ausfallsicher zu machen bzw. eine Benachrichtigung zu erhalten, wenn das System nicht mehr läuft.
Im folgendem Skript habe ich dazu einfach einen Ausgang in die Schleife gebaut. Diesen will ich abgreifen und auf ein frei programmierbares Relais der Alarmanlage legen. Wenn das Programm ausfällt ändert sich der Zustand des Kontaktes und die eigentliche Alarmanlage soll ein Störungsalarm senden.
Ich bin mir nur nicht sicher, wie valide dieses Verfahren ist.
Hier ist das vorläufige Skript. Für Verbesserungsvorschläge im Code bin ich auch sehr dankbar
Code: Alles auswählen
#!/usr/bin/python3
import os
import RPi.GPIO as IO
import time
TelephonNumbers = open("telephonnumbers.txt","r")
IO.setmode(IO.BCM)
AlarmPin = 22
ArmPin = 5
ErrorPin = 17
SystemStatus = 26
IO.setup(SystemStatus, IO.OUT)
IO.setup(AlarmPin, IO.IN, pull_up_down=IO.PUD_DOWN)
IO.setup(ArmPin, IO.IN, pull_up_down=IO.PUD_DOWN)
IO.setup(ErrorPin, IO.IN, pull_up_down=IO.PUD_DOWN)
def ArmUnarm(channel):
if IO.input(ArmPin) == 0:
os.system('echo `date` Scharf >> /home/pi/Alarm/alarm-system-dialer/log.txt')
else:
os.system('echo `date` Unscharf >> /home/pi/Alarm/alarm-system-dialer/log.txt')
def Error(channel):
if IO.input(ErrorPin) == 0:
os.system('echo `date` Stoerung >> /home/pi/Alarm/alarm-system-dialer/log.txt')
else:
os.system('echo `date` Stoerung zurueckgesetzt >> /home/pi/Alarm/alarm-system-dialer/log.txt')
def AlarmDetection(channel):
if IO.input(AlarmPin) == 0:
os.system('echo `date` Alarm >> /home/pi/Alarm/alarm-system-dialer/log.txt')
# for number in TelephonNumbers.readlines():
# os.system('echo Alarmanlage meldet: Einbruch! | sudo gammu-smsd-inject TEXT %s' %(number))
else:
os.system('echo `date` Alarm zurueckgesetzt >> /home/pi/Alarm/alarm-system-dialer/log.txt')
# os.system('echo Alarmanlage meldet: Alarm zurueckgesetzt | sudo gammu-smsd-inject TEXT %s' %(number))
IO.add_event_detect(AlarmPin, IO.BOTH, callback = AlarmDetection, bouncetime = 100)
IO.add_event_detect(ArmPin, IO.BOTH, callback = ArmUnarm, bouncetime = 100)
IO.add_event_detect(ErrorPin, IO.BOTH, callback = Error, bouncetime = 100)
try:
while True:
time.sleep(0.1)
IO.output(SystemStatus, IO.LOW)
except KeyboardInterrupt:
IO.cleanup()
@Stevo: aus welchem Grund soll das Programm abbrechen? Und wenn Du sowieso systemd benutzt, wird ein abgebrochenes Programm eh neu gestartet. Der Fall, dass das Programm nicht mehr läuft, ist damit so gut wie ausgeschlossen.
Zeile 6: eine Datei die man öffnet, sollte man auch wieder schließen. Global irgendwelche Dateien aufzumachen, ist daher seltsam.
Zeile 36: wenn man einmal die Datei gelesen hat, ist der Dateizeiger am Ende und weitere Leseversuche enden mit leerem Ergebnis.
Statt os.system sollte man eine passende Methode aus `subprocess` benutzen. Hier aber, um eine Datei zu schreiben, benutzt man direkt Python-Routinen:
Besser noch, das schreiben in ein Logfile als eigene Funktion definieren, oder gleich `logging´ benutzen. Statt an 5 Stellen jeweils den selben Dateinamen zu schreiben, definiert man eine Konstante am Anfang des Programms.
Zur Schreibweise: Variablen und Funktionen schreibt man komplett klein_mit_unterstrich und Konstanten GROSS_MIT_UNTERSTRICH (ALARM_PIN).
Zeile 6: eine Datei die man öffnet, sollte man auch wieder schließen. Global irgendwelche Dateien aufzumachen, ist daher seltsam.
Zeile 36: wenn man einmal die Datei gelesen hat, ist der Dateizeiger am Ende und weitere Leseversuche enden mit leerem Ergebnis.
Statt os.system sollte man eine passende Methode aus `subprocess` benutzen. Hier aber, um eine Datei zu schreiben, benutzt man direkt Python-Routinen:
Code: Alles auswählen
def arm_unarm(_):
msg = "Scharf" if IO.input(ArmPin) == 0 else "Unscharf"
with open(LOGFILE, "a") as log:
log.write('{} {}\n'.format(datetime.datetime.now(), msg)
Zur Schreibweise: Variablen und Funktionen schreibt man komplett klein_mit_unterstrich und Konstanten GROSS_MIT_UNTERSTRICH (ALARM_PIN).