Hi,
Ich brauche Hilfe.
Ein endlos laufendes Python-Skript wird über einen Alias-Befehl vom Terminal aus gestartet.
Der Alias-Befehl lautet: pidon und funktioniert einwandfrei.
Hier der Inhalt von .bash_alisaes
pi@pi3solar:~ $ cat .bash_aliases
alias pidon='sudo python3 /home/pi/aPy/test_scripts/GPIO/PID_EMAIL_3.py &'
alias pidoff='ps -elf | grep /home/pi/aPy/test_scripts/GPIO/PID_EMAIL_3.py | awk '{print $4}' | xargs sudo kill'
Der Alias-Befehl "pidoff" hingegen, funktioniert nicht, keine Reaktion!
Wenn die den Alias-Befehl representierende Komandozeile im Terminal Fenster
ausgeführt wird, dann stop das Script.
Hier ist das Python Script: (Ver.3.5.3)
#!/usr/bin/env python3
import RPi.GPIO as GPIO
from time import sleep, perf_counter
from datetime import datetime
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM) # is the GPIO-name, NOT the Pin
SW_GPIO = 12 # pin32 & pin30 is GND
GPIO.setup(SW_GPIO, GPIO.IN, pull_up_down=GPIO.PUD_UP)
def email():
import smtplib
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.ehlo()
server.login("k10101305dak@gmail.com","vwkpeqgdwbarvjsg")
SUBJECT = "Warnung des Bewegungsmelders"
TEXT = "Achtung !! der Bewegungsmelder hat eine Bewegung erkannt."
msg = 'Subject: {}\n\n{}'.format(SUBJECT, TEXT)
#server.sendmail("k10101305dak@gmail.com","wallieschen@gmail.com", msg)
#server.sendmail("k10101305dak@gmail.com","wasserpop@gmx.de", msg)
server.quit()
print(' Email has been send:',datetime.now())
movement = 0
active = 0
wait = 180 #__in seconds when sleep < 1 sec__
start = perf_counter() - wait
loop = True
print(' Go -> ')
if __name__ == '__main__':
try:
while loop:
movement = GPIO.input(SW_GPIO)
#print('PIR',movement)
if movement == 1 and active == 0:
actual = perf_counter()
print(' movement',movement)
if actual - start > wait:
email()
active = 1
start = perf_counter()
elif movement == 0 and active == 1:
print(' PIR free')
active = 0
elif movement == 1 and active == 1:
print(' PIR blocked')
actual = perf_counter()
if actual - start > wait:
active = 0
sleep(0.3)
except KeyboardInterrupt:
loop = False
print('\n Bye')
GPIO.cleanup()
Hat jemand eine Idee warum, gibt es Alternativen?
Grüsse
Alias-Befehl im .bash_aliases zeigt keine Reaktion, Raspberry 3B Stretch
- DeaD_EyE
- User
- Beiträge: 1257
- Registriert: Sonntag 19. September 2010, 13:45
- Wohnort: Hagen
- Kontaktdaten:
Bitte Code-Tags verwenden, damit die Einrückung erhalten bleibt.
Ich würde das ganz anders machen. Systemd kann man so konfigurieren, dass normale Benutzer auch Dienste mit den Rechten des aktuellen Benutzers starten können.
Soweit ich weiß, muss man es bei Raspberry Pi OS aktivieren: https://wiki.archlinux.org/title/System ... _instances
Dann schreibst du eine Unit-File:
~/.config/systemd/user/email.service
Der Optionsschalter -u deaktiviert den Puffer für sdtout und stderr.
Dann sieht man Ausgaben durch print und Tracebacks sofort. Ohne den Optionsschalter muss man warten bis der Puffer voll ist und wenn man Pech hat, gibt das Programm so wenig aus, dass nie etwas angezeigt wird.
Dann muss man einmal den Daemon neu laden. Das sollte man als normaler user machen können:
Starten kannst du den Dienst dann so:
Stoppen:
Das kannst du dir dann als Alias anlegen und falls du möchtest, kannst du auch mit Timer arbeiten. Wenn der Dienst z.B. nur zwischen 8 unr 16 Uhr laufen soll.
Ich würde das ganz anders machen. Systemd kann man so konfigurieren, dass normale Benutzer auch Dienste mit den Rechten des aktuellen Benutzers starten können.
Soweit ich weiß, muss man es bei Raspberry Pi OS aktivieren: https://wiki.archlinux.org/title/System ... _instances
Dann schreibst du eine Unit-File:
~/.config/systemd/user/email.service
Code: Alles auswählen
[Unit]
Description=PID EMAIL 3
[Service]
ExecStart=/usr/bin/python3 -u /home/pi/aPy/test_scripts/GPIO/PID_EMAIL_3.py
[Install]
WantedBy=default.target
Dann sieht man Ausgaben durch print und Tracebacks sofort. Ohne den Optionsschalter muss man warten bis der Puffer voll ist und wenn man Pech hat, gibt das Programm so wenig aus, dass nie etwas angezeigt wird.
Dann muss man einmal den Daemon neu laden. Das sollte man als normaler user machen können:
Code: Alles auswählen
systemctl --user daemon-reload
Code: Alles auswählen
systemctl --user start email
Code: Alles auswählen
systemctl --user stop email
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
- __blackjack__
- User
- Beiträge: 14132
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@JoPi: Du hast bei ``pidoff`` einfache Anführungszeichen *in* einer Zeichenkette die in einfache Anführungszeichen eingefasst ist. Das geht so nicht. Hier mal ein Beispiel wie man das machen kann:
Alternativ könnte man das in doppelte Anführungszeichen einfassen und das ``$``-Zeichen escapen.
Die von DeaD_EyE vorgeschlagene Lösung ist aber besser.
Anmerkungen zum Python-Quelltext:
``as`` beim Importieren ist zum umbenennen, GPIO wird aber gar nicht umbenannt.
Importe und Konstanten gehören an den Anfang des Moduls, nicht in Funktionen.
Warnungen sollte man nicht ignorieren, sondern die Ursache beseitigen.
Die Einrückung sollte einheitlich 4 Leerzeichen pro Ebene sein.
Das *gesamte* Hauptprogramm sollte durch den ``if __name__ == …``-Guard geschützt sein *und* in einer Funktion stehen, damit nicht alles mögliche Modulglobal definiert wird.
Der ``try``-Block wo im ``finally`` die GPIOs aufgeräumt werden, sollte grösser sein, denn zwischen GPIOs aufsetzen und ``try`` steht Code der Ausnahmen auslösen könnte und dann wird nicht aufgeräumt. `GPIO.cleanup()` darf man immer aufrufen, der Benutzer könnte immer Strg+C drücken, also kann man auch einfach das gesamte Hauptprogramm in den ``try``-Block setzen.
Python hat einen eigenen Datentyp für Wahrheitswerte, den sollte man auch benutzen und nicht 0 und 1 dafür missbrauchen. Bei `loop` wird das ja gemacht. Man vergleicht dann auch nicht mit den literalen Wahrheitswerten, sondern benutzt entweder den Wert selbst, oder seine Negation.
`loop` ist unsinnig. Das in der Schleife niemals verändert und an der Stelle wo `False` zugewiesen wird, ist die Schleife schon längst verlassen.
`actual` ist ziemlich sicher der falsche Name. Das heisst auf Deutsch nicht „aktuell“ sondern „tatsächlich“.
Insgesamt ist das „busy waiting“ sehr unschön. Man kann sich auch über steigende und fallende Flanken informieren lassen ohne da selbst drauf warten zu müssen. `gpiozero` statt `RPi.GPIO` wäre noch besser.
`SMTP_SSL`-Objekte sind Kontextmanager, die sollte man mit der ``with``-Anweisung verwenden.
Namen sollten nicht kryptisch abgekürzt werden. Wenn man `message` meint, sollte man nicht nur `msg` schreiben.
`format()` braucht man nur, wenn die Vorlage variabel ist. Sonst kann man das einfach als f-Zeichenkettenliteral schreiben.
Zwischenstand (ungetestet):
Code: Alles auswählen
echo 'O'\''Reilly'
Die von DeaD_EyE vorgeschlagene Lösung ist aber besser.
Anmerkungen zum Python-Quelltext:
``as`` beim Importieren ist zum umbenennen, GPIO wird aber gar nicht umbenannt.
Importe und Konstanten gehören an den Anfang des Moduls, nicht in Funktionen.
Warnungen sollte man nicht ignorieren, sondern die Ursache beseitigen.
Die Einrückung sollte einheitlich 4 Leerzeichen pro Ebene sein.
Das *gesamte* Hauptprogramm sollte durch den ``if __name__ == …``-Guard geschützt sein *und* in einer Funktion stehen, damit nicht alles mögliche Modulglobal definiert wird.
Der ``try``-Block wo im ``finally`` die GPIOs aufgeräumt werden, sollte grösser sein, denn zwischen GPIOs aufsetzen und ``try`` steht Code der Ausnahmen auslösen könnte und dann wird nicht aufgeräumt. `GPIO.cleanup()` darf man immer aufrufen, der Benutzer könnte immer Strg+C drücken, also kann man auch einfach das gesamte Hauptprogramm in den ``try``-Block setzen.
Python hat einen eigenen Datentyp für Wahrheitswerte, den sollte man auch benutzen und nicht 0 und 1 dafür missbrauchen. Bei `loop` wird das ja gemacht. Man vergleicht dann auch nicht mit den literalen Wahrheitswerten, sondern benutzt entweder den Wert selbst, oder seine Negation.
`loop` ist unsinnig. Das in der Schleife niemals verändert und an der Stelle wo `False` zugewiesen wird, ist die Schleife schon längst verlassen.
`actual` ist ziemlich sicher der falsche Name. Das heisst auf Deutsch nicht „aktuell“ sondern „tatsächlich“.
Insgesamt ist das „busy waiting“ sehr unschön. Man kann sich auch über steigende und fallende Flanken informieren lassen ohne da selbst drauf warten zu müssen. `gpiozero` statt `RPi.GPIO` wäre noch besser.
`SMTP_SSL`-Objekte sind Kontextmanager, die sollte man mit der ``with``-Anweisung verwenden.
Namen sollten nicht kryptisch abgekürzt werden. Wenn man `message` meint, sollte man nicht nur `msg` schreiben.
`format()` braucht man nur, wenn die Vorlage variabel ist. Sonst kann man das einfach als f-Zeichenkettenliteral schreiben.
Zwischenstand (ungetestet):
Code: Alles auswählen
#!/usr/bin/env python3
import smtplib
from datetime import datetime as DateTime
from time import perf_counter, sleep
from RPi import GPIO
SW_GPIO = 12 # pin32 & pin30 is GND
SUBJECT = "Warnung des Bewegungsmelders"
TEXT = "Achtung !! der Bewegungsmelder hat eine Bewegung erkannt."
SMTP_HOST = "smtp.gmail.com"
SMTP_USER = SENDER_EMAIL = "k10101305dak@gmail.com"
def email():
with smtplib.SMTP_SSL(SMTP_HOST, 465) as server:
server.ehlo()
server.login(SMTP_USER, "vwkpeqgdwbarvjsg")
message = f"Subject: {SUBJECT}\n\n{TEXT}"
# server.sendmail(SENDER_EMAIL, "wallieschen@gmail.com", message)
# server.sendmail(SENDER_EMAIL, "wasserpop@gmx.de", message)
print(" Email has been send:", DateTime.now())
def main():
try:
GPIO.setmode(GPIO.BCM) # is the GPIO-name, NOT the Pin
GPIO.setup(SW_GPIO, GPIO.IN, pull_up_down=GPIO.PUD_UP)
movement = False
active = False
wait_time = 180 # in seconds when sleep < 1 sec
start_timestamp = perf_counter() - wait_time
print(" Go ->")
while True:
movement = GPIO.input(SW_GPIO)
# print('PIR',movement)
if movement and not active:
current_timestamp = perf_counter()
print(" movement", movement)
if current_timestamp - start_timestamp > wait_time:
email()
active = True
start_timestamp = perf_counter()
elif not movement and active:
print(" PIR free")
active = False
elif movement and active:
print(" PIR blocked")
current_timestamp = perf_counter()
if current_timestamp - start_timestamp > wait_time:
active = False
sleep(0.3)
except KeyboardInterrupt:
GPIO.cleanup()
print("\n Bye")
if __name__ == "__main__":
main()
“It is easier to change the specification to fit the program than vice versa.” — Alan J. Perlis