Ein Denkmal für Burak BektaÅŸ
Zur Fotoseite beim Umbruch Bildarchiv
Weitere Informationen:
burak.blogsport.de/
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 Wohnungstü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
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-Funktionsystem()
einen Befehl auf der Shellsh
aus.Diese Anwendung ist derTrySystem()
-Anwendung sehr ähnlich, abgesehen davon, dass sie -1 zurückliefert, falls sie den Systembefehl nicht ausführen kann, wohingegen dieTrySystem()
-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...