trueten.de

"Here's another nice mess you've gotten me into!" Oliver Hardy

RaspBerry Pi: Überallklingel 1.2

Zu Beschleunigung der Zustellung dringend erwarteter Pakete habe ich mich in der Vergangenheit aller möglichen Tricks bedient:

• Duschen.
• Auf dem Klo sitzen.
• Im Keller oder auf dem Dachboden herum lungern.
• Verschlafen.
• Am Fenster auf das gelbe Fahrzeug warten.
• ...

Klappt im Grunde alles nicht richtig. Irgendwie war doch immer eine Benachrichtigung im Briefkasten, mit dem Vorwurf, der / die ZustellerIn hätte mich oder einen anderen Vertreter meiner Sippschaft nicht angetroffen.

Daher kam das Überallklingel Projekt der c't 17/2017, S. 84 wie gerufen. Flugs einen Pi Zero W (*) herausgekramt, einen Widerstand, eine Diode und einen Optokoppler auf ein Stück Lochrasterplatine gelötet und dann beherzt an das Kabelwirrwar der heimischen Siedle HT401a-01 Telefonanlage angeschlossen. Nach der Installation der Telefonanlagensoftware Asterisk und wenigen Stunden Konfigurationsarbeit funktionierte das ganze sehr schön. Bis die Postboten ihre Taktik änderten und die Klingel ungeduldig bearbeiteten, derweil bereits etwas ältere Blogger die Treppe zur Sprechanlage hoch schnauften. Einige dieser Schlingel verstiegen sich dann wohl in die Vermutung, der Paketempfänger sei nicht zu Hause und machten sich daraufhin hurtig davon.


Damit es mal wieder so richtig wie bei Mr. Beaker in den Ohren klingelt ;-)

Klar, daß mensch dieser unvorteilhaften Situation nicht tatenlos zusehen konnte. Eine Erweiterung der Fähigkeiten der Überallklingel war vonnöten. Wenn der RaspBerry Pi(*) ein Signal (von der Klingel) empfangen und dies an die Telefone, die an der FritzBox(*) hängen weiter leiten kann, dann kann man davon ausgehen, daß er ein solches auch von diesen Telefonen aus (an den Türöffner) senden kann.

Dabei müssen zwei Probleme gelöst werden:

  • Wie kann man den Bengel dazu überreden, die 12Volt Spannnung zu vertragen?
  • Wie muss die vohandene Asterisk Installation erweitert werden, um ein Telefonsignal in eine Aktion des Türöffners zu verwandeln?

Die Suche bei einer beliebigen Internetsuchmaschine ergibt zum ersten Problem hunderte Vorschläge, die darauf hinauslaufen, selbiges mittels Relais zu lösen. Ich habe hier dann die Schaltung von xgadget sowie die Anleitung von 4hf übernommen. Die Relais gibt es über die dortigen Quellen zu erwerben oder eben auf Amazon oder in der Bucht. Ja nachdem, was man schalten will, kauft man eben bis zu 16-fach Relais, die dann jedoch ein eigenes Netzteil benötigen.

Der Relaisanbieter gibt es viele, vermutlich kommen die Bauteile jedoch aus der selben chinesischen Fabrik und werden nur entsprechend Anbieter gebrandet. Wie auch immer: Ich habe für unsere Klingel ein 2 Kanal Relais Modul(*) verwendet. Dieses ist zwar größer als das Einfach Modul, kostet meist jedoch weniger. Komisch? So ist der Kapitalismus nun mal, auch in China. (Stimmt nicht! Hier gibt es die Dinger sogar für 0,88€ plus 1€ Versandkosten!(*))

Doch genug der Ideologie, zurück zur Klingel. Die Signalseite des Relais mit den gewünschten Pins des Raspberry Pi GPIO verdrahten und dann die Lastseite parallel zum Türöffner der Sprechanlage geschaltet. Meistens fangen hier die Probleme an. Sprechanlagen aus der Steinzeit? Kein Problem. Was hatte ich mich aber über die Nachrichten des Postboten und die Anrufe von Familienmitglieder gewundert: Angeblich sei niemand zuhause gewesen. Solche Banditen! Oder sollte etwa...?

Es bleibt kompliziert.

Auch bei Sprechanlagen aus der Steinzeit besteht die Möglichkeit, daß diese nicht nur zur Kommunikation mit der Klingel an der Haustüre, sondern auch zur selbigen mit Etagentelefonen, Klingeln an der Wohnungstüre und anderen Gerätschaften vorgesehen waren. Was bei uns der Fall war und dafür sorgte, daß die Klingel zwar klingelte, wenn diese vor der Wohnungstüre betätigt wurde, jedoch nicht von der Haustüre aus. Getestet hatte ich natürlich nur von der Wohnugnstüre aus 8-)

Nachdem auch dieses nicht unerhebliche Problem gelöst war, stand erneuten Versuchen nichts im Wege. Außer Asterisk. Dies ist ja nun nicht gerade ein einfaches Telefonanlagenprogramm, sondern doch schon ein relativ mächtiges Werkzeug, mit dem durchaus auch die Kommunikation von Callcentern oder Konzernzentralen mit dazugehörigen Videoanlagen, Faxgeräten, IP-Telefonie usw. geregelt werden kann. Mit Kanonen auf Spatzen? Wenn's hilft. Zum Glück ist Asterisk skalierbar und es gibt auch eine ausgezeichnete Dokumentation, das Asterisk Buch im Netz.

Leider erfordern umfangreiche Programme etwas Einarbeitung. Deshalb gibt es auch Alternativen wie DoorPi. Im Vergleich zu Asterisk deutlich überschaubarer und auch hinsichtlich Home 4.0 sicherlich sinnvoll. Wenn nicht die Klingel schon auf der Grundlage von Asterisk funktioniert hätte und die DoorPi Lösung ebenso gut dokumentiert wäre. Nach einem kurzen Seitenblick habe ich DoorPi deshalb zur Seite gelegt.

Konzentriert

Die Überallklingel wurde über ein Python Script ausgelöst, das .call Dateien im Outbound von Asterisk anlegt, sobald ein (Klingel)Signal auf ausgewählten GPIO Pins anliegt. Asterisk reagiert auf die .call Datei und setzt deren Inhalt in Aktionen, in dem Fall in einem Anruf bei der Rundrufnummer der FritzBox um. Auf das Projekt ging Andrijan Möcker in seinem c't Artikel ein, diesen kann man auch noch als PDF Datei beziehen.

Beim Türöffner muss ein Signal an einen GPIO Pin gesendet werden, die dann an das Relais weiter geleitet werden, woraufhin der parallel geschaltete Öffner anzieht und die Türe sich öffnen lässt. Da ich des Prorgrammierens in Python nicht mächtig und obendrein zu faul bin, das für eine Klingel zu erlernen, habe ich das in Bash gemacht:

#!/bin/sh
gpio mode 12 out
gpio write 12 0
sleep 2
gpio write 12 1

Mit diesen viereinhalb Zeilen schaltet der Raspberry Pi für 2 Sekunden (so schnell muss der Postbote die Tür öffnen) das Relais über den GPIO Pin 10. Was, Pin 10? Wieso das denn, da steht doch 12? Stimmt. Bei den GPIO Pins gibt es soviele Bezeichnungen für deren Belegungen, wie andere Leute Unterhosen im Schrank haben. Alternative Fakten eben. Tatsächlich ist für die Bezeichnung die jeweilige Bibliothek, die für die Ansteuerung verwendet wird, verantwortlich. Eine gute Übersicht gibt es bei RaspBerry Guide.

Ich verwende hier wiring PI. Dieses Lib ist schnell installiert, ich verweise dazu an der Stelle auf tutorials-raspberry.de. Also. Pin 19 mit dem Signaleingang des Relais verbinden, einen GND Pin des GPIO mit dem selbigen des Relais und Schlußendlich einen 5 Volt Pin des GPIO mit dem VCC Pin des Relais verbinden. Die nebeneinander liegenden VCC und JD-VCC Pins des Relais bleiben bzw. werden im Gegensatz zur Anleitung bei xgadgets mittels eines Pin Steckers gebrückt, damit ersparen wir uns die zusätzliche Versorgung mit 3,3 Volt.

In meinem Fall musste ich die 5 Volt mittels einer Quick & Dirty Lötlösung von dem auf dem Raspberry PI verbauten ZigBee Modul(*) (dem Thema widme ich einen späteren Beitrag) von Dresden Elektronik klauen. Es gehen natürlich auch GPIO Extender(*), falls die Stromverorgungspins alle schon vergeben sind.

Ein erster Funktionstest

"Fliegender" Aufbau. Nach Ablauf diverser Tests werden alle Kabel schön sauber in ein Gehäuse gestopft.
Ein Test, ob man die richtigen Pins belegt hat, ist in jedem Fall sinnvoll. Da 5 Volt im Spiel sind - was für den Raspberry oder auch den auf dem Relais verbauten Optokoppler tödlich sein kann - rate ich in jedem Fall zur sorgfältigen Kontrolle der Schaltung. Für einen ersten Test kann man notfalls auf die Widerstände vom GPIO zum Relais verzichten, aber das ist was für faule Kerle. (Im Falle eines gegrillten RaspBerry Pi bitte ich die entsprechenden Werbelinks in diesem Beitrag zu nutzen, dann hat wenigstens einer etwas davon).

Das Relais selber muss mensch an der Stelle noch nicht an die Sprechanlage anschließen.

Ein entschlossener Aufruf des Scriptes mit dem obigen Inhalt, das vorher unter einem beliebigen Namen zum Beispiel als /usr/local/bin/oeffner.sh gespeichert und anschließend mittels:

sudo chmod a+x /usr/local/bin/oeffner.sh

ausführbar gemacht worden ist, sollte einen deutlich hörbaren Schaltvorgang des Relais zur Folge haben. Zudem sollten die auf dem Relais verbauten LEDs lustig im Schalttakt blinken.

Die halbe Miete

Nun biegen wir beinahe auf der Zielgeraden ein. Zuvor gilt es jedoch die Haarnadelkurve Asterisk zu bewältigen. Wie oben ausgeführt mit durchaus steilem Anstieg der Lernkurve, aber dafür gibt es ja diesen Beitrag hier.

Das Relais schaltet also im Ergebnis der Ausführung des Scripts oeffner.sh. Da der ganze Zweck der Übung der ist, mittels Anwahl einer bestimmten Nummernfolge auf einem der an die FritzBox angeschlossenen Telefone dieses Script auszuführen um so die Türe zu öffnen verwenden wir einen Befehl in Asterisk. Ich setze jetzt voraus, daß Asterisk läuft, sich erfolgreich bei der Fritzbox als IP Telefon angemeldet hat und Klingelsignale empfängt. Dazu habe ich in der FritzBox unter "Telefonie" das IP Telefon "622" mit dem Passwort "Sowasvongeheim" angelegt und in dem Python Script zur Generierung der .call Datei diese Daten ein eingegeben. Nicht verschlampern, die brauchen wir noch, nämlich hier, in dem etwas von mir angepassten (fett markiert) Python Script, das von c't Autor Andrijan Möcker geschrieben wurde:

import time
import shutil
import RPi.GPIO as gpio
import os
import sys
#Einstellungen
klingel_gpio = 24 #GPIO, der mit der Schaltung verbunden ist
callfilepfad = "/home/pi/klingel.call" #Dateipfad in dem das Script die .call-Datei ablegt
sipkanal = "622" #Name des SIP-Kanals (in eckigen Klammern in der SIP.conf)
sipziel = "**702" #Ziel des Anrufes (Beispiel: **702 als Anrufergruppe der Fritz!Box)
sipwartezeit = "4" #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/de/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)

Zu den von mir vorgenommenen Änderungen schreibe ich weiter unten noch ein paar Worte, das sind im wesentlichen auch die Stellen, die auf die Gegebenheiten vor Ort verändert werden müssen. An der Stelle ein Einschub, nämlich die durch dieses Script im Outbound Verzeichnis von Asterisk /var/lib/asterisk/outgoing/ erzeugte .call Datei:

Channel: SIP/622/**702
Application: Playback
WaitTime 4
Data: /var/lib/asterisk/sounds/custom/play

Asterisk fragt dieses Verzeichnis ständig ab (pollt) und führt darin enthaltenen Dateien aus. In unserem Fall: Anruf bei der FritzBox mit dem SIP Protokoll unter der Userkennung 622 an die Nummer **702, die ich in dem darüber gezeigten klingelscript.py bereits angelegt habe. Bei erfolgreichem Anruf wird für die Dauer von 4 Sekunden der Inhalt der Datei /var/lib/asterisk/sounds/custom/play ausgeführt. Diese braucht nicht zu existieren, es reicht der Impuls durch den Aufruf, um ein Klingelsignal bei der FritzBox auszulösen.

Nach eingehender Lektüre des bereits erwähnten Asterisk Buches bei dem vor allem auf die Zusammenhänge bei den Benutzerrechten geachtet werden sollte, schreiten wir zur Tat. (Das Semikolon leitet Kommentare ein, diese werden nicht ausgeführt):

;Allgemeine Einstellungen in der Asterisk Konfigurationsdatei für SIP Telefonie
; /etc/asterisk/sip.conf
; Ein paar notwendige Grundeinstellungen
;
[general]
port=5060
bindaddr=0.0.0.0
videosupport=no
dtmfmode=rfc2833
srvlookup=yes
directmedia=no
nat=no
localnet=192.168.178.0/255.255.255.0 ; Das lokale Netz sowie die Broadcast Adresse
transport=udp
callerid=KlingelPi <622> ; Diese Anruferkennung erscheint auf kompatiblen Telefonen
;
; Der Sip Provider, in unserem Fall die FritzBox
; User:Passwort:Ziel/User
register => 622:Sowasvongeheim@192.168.178.1/624
;
; Wir legen mal ein Ziel für den Türöffner an:
[624]
type=friend
secret=Sowasvongeheim
host=192.168.178.1
insecure=invite,port
;
; Virtuelles Telefon für das Python Script, das via .call Datei die Überallklingel auslöst.
[622]
type=friend
username=622
fromuser=622
secret=Sowasvongeheim
host=192.168.178.1
insecure=invite,port

Nun nützt eineM die beste sip.conf nichts, wenn es keine passenden Contexte in der /etc/asterisk/extensions.conf gibt. Wobei, das stimmt nicht ganz, das Script der c't lässt die extensions unberührt. Im Rahmen der Lektüre des Asterisk Handbuches auf der Suche nach alle, was Shell Befehle betrifft, springen einem dann 2 Möglichkeiten zur Befehlsausführung ins Gesicht: System() und TrySytem(). Dazu mal ein Vollzitat:

Führt durch die C-Funktion system() einen Befehl auf der Shell sh aus.
Diese Anwendung ist der TrySystem()-Anwendung sehr ähnlich, abgesehen davon, dass sie -1 zurückliefert, falls sie den Systembefehl nicht ausführen kann, wohingegen die TrySystem()-Anwendung stets 0 zurückliefert.

So. Ob Bash oder sh ist Wurst, wir haben damit die Möglichkeit, daß Asterisk das oeffner.sh Script ausführt. Sofern ein Context zutrifft. Da wir in der FritzBox ja ein Telefon angelegt haben, kommt über dieses mit der Kurzwahl **622 Kennung nicht nur das Signal vom Postboten an der Klingel, sondern mensch kann die **622 auch anrufen. It's Magic!

; Entweder an die bestehende /etc/asterisk/extensions.conf anhängen oder überschreiben, sofern keine anderen
; Contexte / Extensions ausgeführt werden müssen.
;
[default]
; Das Klingelscript verweist auf die Extension 622:
exten => 622,1,Answer() ; Asterisk nimmt ab
exten => 622,2,WaitExten(1) ; wartet 1 Sekunde
exten => 622,2,Hangup() ; und legt dann auf
; Mehr braucht es nicht zum Klingeln
;
; Anruf bei **622 verweist hierher:
exten => 624,1,Answer() ; Asterisk nimmt ab
exten => 624,2,System(/usr/local/bin/oeffner.sh) ; Asterisk ruft die sh Shell auf und führt darin das oeffner.sh Script aus
exten => 624,3,Hangup() ; Asterisk legt nach Abarbeitung des Scripts auf

Hier wird nun klar, warum ich bei der extensions.conf einige Zeit vertrödelt hatte und letzlich im Unterschied zur c't keinen Rundruf via **9 bei der FritzBox starte, sondern darin eine Gruppe angelegt habe, in der die anzurufenden Telefone vereint sind: Ein Rundruf bei der *9 führt nämlich dazu, daß auch der Öffner ausgelöst wird, denn die **622 ist ja die Nummer, die für die Türöffnung angerufen wird. Und eine Selbstöffnung wollen wir nun nicht wirklich einbauen, das gehört in Arztpraxen...

Ein Blick in das "sauber" von Profis verlegte Siedle HT401a-01
Die Rechnung ohne den Wirt Elektriker

Der bisherige Aufbau empfängt also Signale der Klingel, löst dadurch Anrufe auf den entsprechenden, bei der FritzBox registrierten Telefonen auf der **702 aus und wenn mensch mittels Kurzwahl **622 auf einem dieser Telefone wählt, klickt das Relais.

Das Relais betätigt den Öffner. Wenn es denn (richtig) angeschlossen ist. In unserm Fall verfluche ich jedes Mal die Elektriker, die Ende der 80er Jahre nicht daran gedacht haben, daß im Jahr 2018 jemand einen RaspBerry an ihre "Installation" anschließen will. Es hilft also kein Rezept wie : "Das blaue Kabel durchschneiden, an beide Enden das Relais anschließen, funktioniert 100%". Bestenfalls geht die Klingel nicht, schlimmstenfalls blickt mensch nicht mehr durch...

Nun denn, es hilft nichts, beim Anschluss der Klingel hat sich bei unserer Installation letztlich die gute alte Zahnstochermethode, mit der Kinder gerne Schellenbergerles² gespielt haben (Mit Zahnstocher den Klingelknopf an der Haustüre festklemmen) um die Leitungen oder Anschlüsse zu finden, die in dem Fall im Unterschied zu vorher Spannung anzeigen.

Im Falle unserer uralten Siedle HT401a-01  Anlage war das aber nicht nötig, die Schraubklemmen „7“ und „c“ im Telefon müssen für die Überallklingel abgegriffen werden, wie Moritz Cichon in seinem Blog im Beitrag "Siedle HT401a-01 Klingel austauschen: Endlich ein angenehmer Gong" ausführte.

Bei dem Anschluss des Relais ist es etwas einfacher, hier hilft es, den Öffnerknopf im Haustelefon anzusehen und welche Kontakte er im Auslösezustand schließt. Im Fall Siedle auf die Klemme "I" und den Pin "c" oben rechts auf der Platine. (Der Anschluss an "Lw" wie "Läutewerk"=Vorgabe von Siedle funktionierte bei unserem Telefon leider nicht. Notfalls Platine heraushebeln und die Schaltung an den Leiterplatten nachverfolgen. Hint: Meßgeräte helfen auch hier weiter ;-)) Daran schließen wir dann das Relais parallel an. Keinesfalls in einer Reihenschaltung, sonst löst weder der Türöffner des Haustelefons noch der Anruf bei der **622 den Türöffner aus.

An der Stelle eine Warnung: Auch wenn in Telefonanlagen in der Regel nur niedrige Ströme fließen können diese durchaus unangenehme Folgen (Kurzschluss der Klingelanlage, Stillstand Herzschrittmacher, Mega Ärger mit dem Vermieter usw.) haben. Daher: Ohne entsprechende Ausbildung bitte Fachleute zur Hilfe heranziehen. Es müssen ja nicht die sein, die bei uns die Klingelanlage verlegt haben.

In dem Sinne: Viel Erfolg beim Nachbauen!

Eigentlich fehlt jetzt noch eine Sprechfunktion. Man will ja nicht jedeN ins Haus lassen...



Blogpost enthält Werbung!

**trueten.de ist Teil des Amazon Partnerprogramm EU. Das bedeutet, wenn ihr ein Produkt über die Links kauft, welche mit einem „*“ gekennzeichnet sind (affiliate Link), erhaltet ihr diese zu den üblichen Preisen und ich bekomme eine kleine Provision. So könnt ihr unser Blog ohne extra Aufwand unterstützen! Vielen Dank!