Raspi, Python-Script, Türklingel

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Exxter
Beiträge: 385
Registriert: 10.01.2003 00:15:15
Lizenz eigener Beiträge: GNU General Public License

Raspi, Python-Script, Türklingel

Beitrag von Exxter » 30.12.2022 17:14:08

Hallo,

in der c't war mal ein HowTo "Die Überallklingel", in dem beschrieben wird, wie man eine normale Türklingel mit einem Raspi verbinden kann um zB. ein an der Fritzbox angeschlossenes Telefon klingeln zu lassen, wenn jemand die Türklingel drückt. Das funktioniert ganz wunderbar. Folgendes Python-Script liegt im Autostart des Raspis und wird ausgeführt, wenn zwei GPIO's gebrückt werden (also die Klingel an der Haustür gedrückt wird):

Code: Alles auswählen

import time
import shutil
import RPi.GPIO as gpio
import os
import sys

#Einstellungen
klingel_gpio = 3 #GPIO, der mit der Schaltung verbunden ist (Standard 4)
callfilepfad = "/root/klingel/anruf.call" #Dateipfad in dem das Script die .call-Datei ablegt
sipkanal = "620" #Name des SIP-Kanals (in eckigen Klammern in der SIP.conf)
sipziel = "**9" #Ziel des Anrufes (Beispiel: **9 als Rundruf der Fritz!Box)
sipwartezeit = "20" #Wartezeit bevor wieder aufgelegt wird

###
#Hier wird die .call-Datei zusammengebaut und abgespeichert
callfile = "Channel: SIP/" + sipkanal + "/" + sipziel + "\nApplication: Playback\nWaitTime:" + sipwartezeit + "\nData: /var/lib/asterisk/sounds/custom/play"

cf = open(callfilepfad, "w")
cf.write(callfile)
cf.close()
###

gpio.setmode(gpio.BCM)
gpio.setup(klingel_gpio, gpio.IN, pull_up_down=gpio.PUD_UP)

def voip():
        try:
                shutil.copyfile(callfilepfad,'/var/spool/asterisk/outgoing/anruf.call')
                print(text)
        except Exception:
                pass

while True:
        time.sleep(0.01)
        if not gpio.input(klingel_gpio):
                time.sleep(0.1)
                if not gpio.input(klingel_gpio):
                        voip()
                        time.sleep(5)
Die Frage ist, kann man das Script so erweitern, dass zusätzlich auch ein Bash-Script gestartet wird?

JTH
Moderator
Beiträge: 3077
Registriert: 13.08.2008 17:01:41
Wohnort: Berlin

Re: Raspi, Python-Script, Türklingel

Beitrag von JTH » 30.12.2022 17:26:23

Exxter hat geschrieben: ↑ zum Beitrag ↑
30.12.2022 17:14:08
Die Frage ist, kann man das Script so erweitern, dass zusätzlich auch ein Bash-Script gestartet wird?
Klar. Die simpelste Variante, ein externes Kommando auszuführen, wäre subprocess.run().
Manchmal bekannt als Just (another) Terminal Hacker.

Exxter
Beiträge: 385
Registriert: 10.01.2003 00:15:15
Lizenz eigener Beiträge: GNU General Public License

Re: Raspi, Python-Script, Türklingel

Beitrag von Exxter » 30.12.2022 17:39:03

Ich habe es jetzt so versucht, das klappt noch nicht:

Code: Alles auswählen

gpio.setmode(gpio.BCM)
gpio.setup(klingel_gpio, gpio.IN, pull_up_down=gpio.PUD_UP)

def voip():
        try:
                shutil.copyfile(callfilepfad,'/var/spool/asterisk/outgoing/anruf.call')
                subprocess.run(["/root/klingel/test.sh",])
                print(text)
        except Exception:
                pass

while True:
        time.sleep(0.01)
        if not gpio.input(klingel_gpio):
                time.sleep(0.1)
                if not gpio.input(klingel_gpio):
                        voip()
                        time.sleep(5)

Wo baut man das am besten ein? Die test.sh ist ausführbar, manuell ausgeführt klappt sie. In ihr steht:

Code: Alles auswählen

#!/bin/bash

echo 'es klingelt' >> /var/log/klingel.log

exit 0

JTH
Moderator
Beiträge: 3077
Registriert: 13.08.2008 17:01:41
Wohnort: Berlin

Re: Raspi, Python-Script, Türklingel

Beitrag von JTH » 30.12.2022 17:47:56

Erstmal brauchst du ganz am Anfang bei den Imports noch ein

Code: Alles auswählen

import subprocess

Der run()-Aufruf sieht sonst schon richtig aus. Ich würde ihn, von der Benennung der voip()-Funktion her, aber eher zwischen die vorletzte und letzte Zeile, die mit dem voip() und sleep(5), verschieben. An der Stelle würde nämlich ein Fehler auch nicht untergehen (das noch fehlende import). In der voip()-Funktion werden alle Fehler ohne Ausgabe verschluckt und fallen nicht auf.
Manchmal bekannt als Just (another) Terminal Hacker.

Exxter
Beiträge: 385
Registriert: 10.01.2003 00:15:15
Lizenz eigener Beiträge: GNU General Public License

Re: Raspi, Python-Script, Türklingel

Beitrag von Exxter » 30.12.2022 18:02:48

OK, sieht jetzt so aus:

Code: Alles auswählen

import time
import shutil
import RPi.GPIO as gpio
import os
import sys
import subprocess

#Einstellungen
klingel_gpio = 3 #GPIO, der mit der Schaltung verbunden ist (Standard 4)
callfilepfad = "/root/klingel/anruf.call" #Dateipfad in dem das Script die .call-Datei ablegt
sipkanal = "620" #Name des SIP-Kanals (in eckigen Klammern in der SIP.conf)
sipziel = "**9" #Ziel des Anrufes (Beispiel: **9 als Rundruf der Fritz!Box)
sipwartezeit = "20" #Wartezeit bevor wieder aufgelegt wird

###
#Hier wird die .call-Datei zusammengebaut und abgespeichert
callfile = "Channel: SIP/" + sipkanal + "/" + sipziel + "\nApplication: Playback\nWaitTime:" + sipwartezeit + "\nData: /var/lib/asterisk/sounds/custom/play"

cf = open(callfilepfad, "w")
cf.write(callfile)
cf.close()
###

gpio.setmode(gpio.BCM)
gpio.setup(klingel_gpio, gpio.IN, pull_up_down=gpio.PUD_UP)

def voip():
        try:
                shutil.copyfile(callfilepfad,'/var/spool/asterisk/outgoing/anruf.call')
                print(text)
        except Exception:
                pass

while True:
        time.sleep(0.01)
        if not gpio.input(klingel_gpio):
                time.sleep(0.1)
                if not gpio.input(klingel_gpio):
                        voip()
                        subprocess.run(["/root/klingel/test.sh",])
                        time.sleep(5)
Wenn ich jetzt klingele kommt:

Code: Alles auswählen

root@pi3:~/klingel$ python mailklingel.py
mailklingel.py:25: RuntimeWarning: A physical pull up resistor is fitted on this channel!
  gpio.setup(klingel_gpio, gpio.IN, pull_up_down=gpio.PUD_UP)
Traceback (most recent call last):
  File "mailklingel.py", line 40, in <module>
    subprocess.run(["/root/klingel/test.sh",])
AttributeError: 'module' object has no attribute 'run'
root@pi3:~/klingel$
Wenn ich
subprocess.run(["bash", "/root/klingel/test.sh"])
Kommt die gleiche Fehlermeldung.

Könnte an der Python Version 2.7.16 (Raspbian GNU/Linux 10 (buster)) liegen? Aber wenn ich es mit python3 aufrufe kommt:

Code: Alles auswählen

root@pi3:~/klingel$ python3 mailklingel.py
  File "mailklingel.py", line 30
    print(text)
              ^
TabError: inconsistent use of tabs and spaces in indentation
root@pi3:~/klingel$


JTH
Moderator
Beiträge: 3077
Registriert: 13.08.2008 17:01:41
Wohnort: Berlin

Re: Raspi, Python-Script, Türklingel

Beitrag von JTH » 30.12.2022 18:09:03

Ach Gottchen, das ist Python 2?! 8O Da hieß die Funktion anscheinend noch call(), nicht run(). Also einfach ersetzen.

https://docs.python.org/2.7/library/sub ... ocess.call

Oder, das ist wohl zukunftssicherer, das ganze mit python3 aufrufen und zukünftig als Python 3 erweitern.

Die Zeile mit print(text) kannst du übrigens ersatzlos entfernen, die Variable text gibt es eh nicht. Die Zeile macht daher nichts, außer einen Fehler zu schmeißen, der allerdings unterdrückt wird.
Manchmal bekannt als Just (another) Terminal Hacker.

Exxter
Beiträge: 385
Registriert: 10.01.2003 00:15:15
Lizenz eigener Beiträge: GNU General Public License

Re: Raspi, Python-Script, Türklingel

Beitrag von Exxter » 30.12.2022 18:22:15

Haa, funktioniert mit call! Danke! :D

Hmm, ich würde natürlich lieber Python3 nutzen, aber ich vermute da müsste man das Scrypt komplett umschreiben, oder? Keine Ahnung ob es Python2 noch in Rasbian 11 bzw 12 gibt.

Die Zeile print(text) lösche ich raus.
Zeile rausgelöscht, wieder zurück zu "run" und es kommt mit python3:

Code: Alles auswählen

root@pi3:~/klingel$ python3 mailklingel.py
  File "mailklingel.py", line 40
    time.sleep(5)
                ^
TabError: inconsistent use of tabs and spaces in indentation
root@pi3:~/klingel$
Edit: aah, seltsam. bei der angeprangerten Zeile waren 3 Tabs davor. Ich habe sie in Vim entfernt, neu davorgesetzt, gleiche Ausgabe. Dann fiel mir auf, dass ich mit dem Cursor nicht vor den ersten Tab in der Zeile kam und habe statt Tabs Leerzeichen genommen, damit läuft das Script jetzt auch mit Python3 :mrgreen:

Vielen herzlichen Dank JTH! :THX:

JTH
Moderator
Beiträge: 3077
Registriert: 13.08.2008 17:01:41
Wohnort: Berlin

Re: Raspi, Python-Script, Türklingel

Beitrag von JTH » 30.12.2022 18:46:07

Ja, Python ist eine einheitliche Einrückung wichtig (mir auch ;) ).

Das Skript benutzt, soweit ich das am Handy überflogen hab, keine Konstrukte, bei denen es Unterschiede zwischen Python 2 und 3 gäbe. Es lief ja nun auch mit dem python3-Interpreter.

Freut mich, wenn's wie gewünscht funktioniert ;) Zugfahrt erfolgreich genutzt.
Manchmal bekannt als Just (another) Terminal Hacker.

Antworten