Skriptaufruf passiert zwei Mal | RPi 3 | GPIO.add_event_detect
Verfasst: Dienstag 5. Mai 2020, 12:58
Hallo zusammen!
Ich bin Python technisch noch relativ am Anfang bzw. google mich durch sämtliche Probleme, die ich so habe. Bisher konnte ich alles recht gut damit lösen!
Kurz zu meinem Projekt: ich habe mit einem RPi 3 ein System gebastelt, welches SMS empfängt, die SMS nach einem bestimmten Codewort durchsucht und wenn jenes gefunden wird, den SMS Inhalt auf einem 16x4 LCD anzeigt und dazu einen Audiovisuellen Alarm mit Buzzer und LEDs ausgibt. Das funktioniert eigentlich alles gut.
Des weiteren habe ich zwei physische Taster an meinem Gerät. Mit dem einen kann ich die letzte empfangene SMS nochmals anzeigen lassen und mit dem anderen kann der Audiovisuelle Alarm abgebrochen werden. Die Software Basis bildet hierbei ein ständig laufender Hintergrundprozess, der beim Booten mitstartet. Dieser Prozess wartet auf die Eingabe vom Taster mit der letzten SMS Anzeige mittels dem Befehl
Die Funktion sms_recall sieht so aus:
Das Problem hierbei ist jedoch, dass das dort aufgerufene Skript call_last_sms.py immer zweimal (nicht mehr und nicht weniger) aufgerufen wird! In diesem Skript sind keinerlei Schleifen oder ähnliches eingebaut, ein einfacher Code, der einmal durchlaufen werden soll. Das Eigenartige: kommentiere ich den Befehl os.system("... aus und ersetze ihn z.B. mit einem einfachen print, dann wird die Funktion nur einmal ausgeführt und die Ausgabe wird auch wirklich nur so oft ausgegeben, wie ich den Taster drücke. Der Taster ist auch Hardwaretechnisch zusätzlich zum bouncetime = 500 entprellt. Und das bestätigt sich ja auch dadurch, dass eine print Ausgabe nur einmal je Tastendruck erscheint. Ich habe auch schon versucht, mit einer globalen Variable und einer if-Abfrage das mehrfache ausführen zu verhindern. Das ginge grundsätzlich, allerdings möchte ich ja, dass bei einem erneuten Tastendruck die SMS wieder angezeigt wird. Wenn ich das mit einer Abfrage blockiere, geht das natürlich nicht.
Die Frage lautet also: wieso wird der Befehl os.system("... zwei mal ausgeführt?!
Ich weiß, ich gehe mit diesem Befehl über das OS und bleibe nicht in Python, aber anders habe ich es noch nicht geschafft, das Skript aufzurufen. Ich wollte auch schon den kompletten Inhalt des Skripts call_last_sms.py in die Funktion packen. Leider hakt es dort gewaltig in Bezug auf den Import von datetime. Kann mir jemand sagen, was hier schieflauft?
Der Code ist bestimmt nicht der schönste und einiges könnte man vermutlich noch effektiver gestalten, aber mehr Wissen hab ich im Moment nicht und es funktioniert. Hier also nochmal der gesamte der Code:
Hintergrundprozess "lcd_startup_init.py":
Aufruf der letzten SMS "call_last_sms.py":
Ich bin Python technisch noch relativ am Anfang bzw. google mich durch sämtliche Probleme, die ich so habe. Bisher konnte ich alles recht gut damit lösen!
Kurz zu meinem Projekt: ich habe mit einem RPi 3 ein System gebastelt, welches SMS empfängt, die SMS nach einem bestimmten Codewort durchsucht und wenn jenes gefunden wird, den SMS Inhalt auf einem 16x4 LCD anzeigt und dazu einen Audiovisuellen Alarm mit Buzzer und LEDs ausgibt. Das funktioniert eigentlich alles gut.
Des weiteren habe ich zwei physische Taster an meinem Gerät. Mit dem einen kann ich die letzte empfangene SMS nochmals anzeigen lassen und mit dem anderen kann der Audiovisuelle Alarm abgebrochen werden. Die Software Basis bildet hierbei ein ständig laufender Hintergrundprozess, der beim Booten mitstartet. Dieser Prozess wartet auf die Eingabe vom Taster mit der letzten SMS Anzeige mittels dem Befehl
Code: Alles auswählen
GPIO.add_event_detect(gpio_button, GPIO.FALLING, callback=sms_recall, bouncetime = 500)
Die Funktion sms_recall sieht so aus:
Code: Alles auswählen
def sms_recall(gpio_button):
os.system("sudo python /home/pi/scripts/call_last_sms.py")
return
Die Frage lautet also: wieso wird der Befehl os.system("... zwei mal ausgeführt?!
Ich weiß, ich gehe mit diesem Befehl über das OS und bleibe nicht in Python, aber anders habe ich es noch nicht geschafft, das Skript aufzurufen. Ich wollte auch schon den kompletten Inhalt des Skripts call_last_sms.py in die Funktion packen. Leider hakt es dort gewaltig in Bezug auf den Import von datetime. Kann mir jemand sagen, was hier schieflauft?
Der Code ist bestimmt nicht der schönste und einiges könnte man vermutlich noch effektiver gestalten, aber mehr Wissen hab ich im Moment nicht und es funktioniert. Hier also nochmal der gesamte der Code:
Hintergrundprozess "lcd_startup_init.py":
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Script 4
#
# Description:
# + Show time and alarm status at startup for 5 minutes after RPi startup
# + Monitor GPIO Input for calling last SEG SMS
from __future__ import print_function, division, absolute_import, unicode_literals
import os
import glob
import sys
from time import sleep, strftime
from time import *
import time
import datetime
from RPLCD.i2c import CharLCD
import RPi.GPIO as GPIO
import codecs
from itertools import islice
lcd = CharLCD(i2c_expander="PCF8574", address=0x27,port=1,cols=20,rows=4,
dotsize=8,charmap="A02",auto_linebreaks=True,backlight_enabled=False)
gpio_button = 26
GPIO.setmode(GPIO.BCM) # BCM = use logic numbering of pins (not physical)
GPIO.setup(gpio_button, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
display_minutes = 0
displaytime = 1
line1 = 1
line2 = 2
lcd.backlight_enabled = True
def sms_recall(gpio_button):
os.system("sudo python /home/pi/scripts/call_last_sms.py")
return
# interrupt this code immediately (anytime) when button is pressed:
GPIO.add_event_detect(gpio_button, GPIO.FALLING, callback=sms_recall, bouncetime = 500)
sleep(0.5) # sleep to give CPU time to react on event
while True:
lcd.clear()
lcd.cursor_pos = (line1,0)
lcd.write_string(" Kein Alarm")
lcd.cursor_pos = (line2,0)
lcd.write_string(datetime.datetime.now().strftime(" %H:%M"))
sleep(60)
display_minutes += 1
if display_minutes == displaytime: # turn backlight off after set number of minutes
lcd.backlight_enabled = False
lcd.clear()
# swap lines to prevent possible LCD burn-in effect:
if display_minutes % 2 != 0:
line1 = 2
line2 = 1
else:
line1 = 1
line2 = 2
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
###############################
# Script 1
#
# Description:
# Read last incoming SMS again and show it on the LCD
# multiple times
#
# Created on: 09.03.2020
# Changed: 05.05.2020
#
###############################
from __future__ import print_function, division, absolute_import, unicode_literals
from time import *
from RPLCD.i2c import CharLCD
from itertools import islice
import os
import glob
import sys
import time
import datetime
import textwrap
import codecs
import RPi.GPIO as GPIO
from datetime import datetime
###############################
# Define Counters and Variables
linecount = 0
###############################
lcd = CharLCD(i2c_expander="PCF8574", address=0x27,port=1,cols=20,rows=4,
dotsize=8,charmap="A00",auto_linebreaks=True,backlight_enabled=True)
# open files with codecs. method to show german umlaute like ü ä ö
with codecs.open("/home/pi/processed_sms/processed_sms.txt","r","utf-8") as processed_file_read:
for line in processed_file_read:
linecount += 1
# show last SEG SMS on LCD:
timestamp = os.path.getmtime("/home/pi/processed_sms/processed_sms.txt")
date_time = datetime.fromtimestamp(timestamp)
datum = date_time.strftime("%d.%m.%Y")
zeit = date_time.strftime("%H:%M")
lcd.cursor_pos = (0,0)
lcd.write_string(" Letzte SEG SMS:")
lcd.cursor_pos = (1,0)
lcd.write_string("--------------------")
lcd.cursor_pos = (2,0)
lcd.write_string("Datum:")
lcd.cursor_pos = (2,7)
lcd.write_string(datum)
lcd.cursor_pos = (3,0)
lcd.write_string("Uhrzeit:")
lcd.cursor_pos = (3,9)
lcd.write_string(zeit)
sleep(5)
times_to_display = 1
display_count = 1
# show SMS text x times on LCD
#while display_count <= times_to_display:
# set current file position in text file with seek() in order to "jump around"
processed_file_read.seek(0)
# read lines 0 to 4 of file
new_data_0_4 = processed_file_read.readlines()[0:4]
lcd.clear()
lcd.write_string("".join(new_data_0_4))
sleep(3)
if linecount > 4:
# set new current file position in text file
processed_file_read.seek(1)
# read next lines 4 to number of lines
new_data_5_8 = processed_file_read.readlines()[4:8]
lcd.clear()
lcd.write_string("".join(new_data_5_8))
sleep(3)
if linecount > 8:
processed_file_read.seek(2)
# read lines 4 to number of lines
new_data_max = processed_file_read.readlines()[8:(linecount)]
lcd.clear()
lcd.write_string("".join(new_data_max))
sleep(3)
lcd.clear()
lcd.cursor_pos = (1,0)
lcd.write_string(" Bitte warten....")