Wie richte ich einen Telegram Bot (Babble) mit FHEM ein?
- Einrichtung eines neuen Bots mit /newbot
- Definition des Telebots in FHEM
- Einrichten Eures Kontaktes in FHEM
- Rivescript installieren
- Testen & Absichern
Setup des Telegram Bots
In diesem Blog möchte ich Euch zeigen, wie Ihr einen Telegram Bot (Chatbot) mit dem Raspberry SmartHome (FHEM) einrichtet. In einem zweiten Schritt kann man sogar über Google Home Mini mit FHEM sprechen. Dazu später mehr, zunächst zu Telegram.
Dazu startet ihr Telegram und einen Chat mit dem User BotFather. Dann gebt ihr /newbot ein. Es ergibt sich ein Dialog:
<strong>/newbot</strong> ---------------- BotFather: Alright, a new bot. How are we going to call it? Please choose a name for your bot. ---------------- Client: <strong>MeinFHEMBot</strong> ---------------- BotFather: Good. Now let's choose a username for your bot. It must end in `bot`. Like this, for example: TetrisBot or tetris_bot. ---------------- Client: <strong>my_fhem_bot</strong> <em><----- ersetzen durch Euren erdachten Namen</em> ---------------- BotFather: Done! Congratulations on your new bot. You will find it at telegram.me/my_fhem_bot. You can now add a description, about section and profile picture for your bot, see /help for a list of commands. ---------------- Use this token to access the HTTP API: 1234567890:abcdefghijklmnopqrst-uvwxyz
Eine Beschreibung des Bot APIs könnt ihr hier einsehen https://core.telegram.org/bots/api


Definition des Telebots in FHEM
Wir kopieren uns das persönliche Token 1234567890:abcdefghijklmnopqrst-uvwxyz
in die Zwischenablage. Wir starten FHEM und geben in das Kommandofeld von FHEM folgendes ein:
define teleBot TelegramBot 1234567890:abcdefghijklmnopqrst-uvwxyz

wobei wir 1234567890:abcdefghijklmnopqrst-uvwxyz durch den Token aus unserer Zwischenablage ersetzen. Jetzt sorgen wir noch dafür, daß der FHEM den Bot auch abfragt:
attr teleBot pollingTimeout 120

Einrichten Eures Kontaktes in FHEM
Wenn wir jetzt aus dem Smartphone an @my_fhem_bot (also Euren erdachten Namen des Bots) eine Nachricht senden, werdet ihr als Chat-User bei FHEM aufgenommen. Wenn ihr alle User die Nachrichten senden dürfen aufgenommen habt, solltet Ihr verhindern, daß weitere die Erlaubnis erhalten:
attr teleBot allowUnknownContacts 0

Damit ist FHEM technisch mit Telegram verbunden.
Testen des Telegram Bots
Die Kommunikation kann folgendermaßen getestet werden: wenn ihr an den Chatbot aus Eurem Smartphone schreibt, sollte die Nachricht im Logfile von FHEM auftauchen. Die andere Richtung könnt ihr im Kommandofeld von FHEM austesten mit
set teleBot message Hello World

und auf Eurem Smartphone erscheint „Hello World“.

Reaktion auf Text und Sprache (Rivescript & Babble)
Zur Reaktion auf Text und Sprache (Spracheingabe Google) verwende ich Talk2Fhem oder Babble. Im weiteren Verlauf gehe ich auf Nutzung von Babble ein. Zunächst installieren wir Rivescript ein Chatbot. Dazu loggen wir uns auf unserem Raspberry Pi ein und geben in der Bash
cpan RiveScript
und
cd /opt/fhem mkdir rivescript cd rivescript wget https://svn.fhem.de/trac/export/HEAD/trunk/fhem/contrib/Babble/begin.rive wget https://svn.fhem.de/trac/export/HEAD/trunk/fhem/contrib/Babble/general.rive
ein. Zum weiteren Setup geben wir in das Kommandofeld von FHEM
define Babble Babble
ein. Dann stellen wir noch die Sprache auf Deutsch und sorgen dafür, daß Umlaute richtig ankommen
attr global language DE attr teleBot utf8Special 1
Nun definieren wir noch eine User Function um den Chatbot mit FHEM zu verbinden und ein InlineKeyboard zu senden.
############################################################################# # # TelegramInlineKeyboard # ############################################################################# sub telegramRecognition($){ my ($event) = @_; my $querypeer = ReadingsVal("teleBot", "queryPeer", 0); my $msgpeer = ReadingsVal("teleBot", "msgPeer", 0); my $queryReplyMsgId= ReadingsVal("teleBot", "queryReplyMsgId", 0); my $MsgId = ReadingsVal("teleBot", "MsgId", 0); my $menuMsgId = ReadingsVal("teleBot", "menuMsgId", $queryReplyMsgId); my $calldata = ReadingsVal("teleBot", "callData", ""); my $tg; my $dp; my $dm; my $res; my $cmd; my $click; my ($cb1,$cb2,$cb1raw); #-- Hier kann man - ggf. für jeden $querypeer anders ! - einstellen, welcher Bestätigungstext vom Bot # gesendet wird, und ob es eine nicht-klickbare Liste (linke Spalte oben) oder eine klickbare Liste # (rechte Spalte oben) sein soll if( $querypeer eq "Marc_Boettinger"){ fhem("attr teleBot queryAnswerText Gerne zu Diensten, Meister !"); $click=1; }elsif( $querypeer eq "Ramona_Boettinger"){ fhem("attr teleBot queryAnswerText Gerne zu Diensten, Ramona !"); $click=0; }else{ fhem("attr teleBot queryAnswerText Gerne zu Diensten!"); $click=0; } #-- receiving reply from bot to telegram if( $event =~ /botreply\:\s(.*)/ ){ $cb1 = $1; fhem("set teleBot msg \@$msgpeer $cb1"); fhem("setreading teleBot prevCmd ChatBot $cb1"); #-- click event from inline keyboard }elsif( $event =~ /queryData\:\s(.*)/ ){ ($cb1,$cb2) = split(/ /,$1,2); #Log 1,"[telegramRecognition] queryData $cb1"; #-- Level 0/1 =&amp;amp;amp;gt; new menuMsgId after start of Bot if( $cb1 =~ /(Steuerung)|(ChatBot)/ ){ $menuMsgId = $queryReplyMsgId; fhem("setreading teleBot menuMsgId $menuMsgId"); fhem("setreading teleBot prevCmd $cb1"); } } if( $event =~ /menuData\:\s*(.*)\s*(.*)/ ){ my $cb1 = $1; my $cb2 = $2; if( $cb1 eq "Hauptmenü"){ if( $msgpeer eq "Marc_Boettinger"){ fhem("set teleBot queryInline \@$msgpeer (ChatBot) Hauptmenü"); }elsif( $msgpeer eq "Ramona_Boettinger"){ fhem("set teleBot queryInline \@$msgpeer (ChatBot) Hauptmenü"); }else{ fhem("set teleBot queryInline \@$msgpeer (ChatBot) Hauptmenü"); } } #-- Process line from forced reply }elsif( $event =~ /msgReplyMsgId\:\s+(\d*)/ ){ my $mn = $1; my $mo = ReadingsVal("teleBot", "prevMsgId", 0)+1; my $prev = ReadingsVal("teleBot","prevCmd","none"); #-- ChatBot if( $prev =~ /ChatBot/ ){ my $text = ReadingsVal("teleBot","msgText",""); if( $text =~ /(s|S)top.*/ ){ fhem("setreading teleBot prevCmd 0"); InternalTimer(gettimeofday()+1, "telegramRecognition","queryData: Hauptmenü",0); }else{ fhem("{Babble_DoIt('Babble','".$text."','teleBot')}"); } } } }
eingeben. Um die Funktion zu triggern definieren wir das folgende Notify
define n_telbot notify teleBot:((queryData)|(msgReplyMsgId)).* {telegramRecognition("$EVENT")}
Allen Geräten, die wir über ein Sprachkommando / Telegram steuern möchten, weisen wir das Attribut babbleDevice mit dem Namen, den wir nennen wollen um es zu schalten. ZB für unsere Stehlampe:
attr Switch_Hallway babbleDevice Stehlampe_2
Sofern wir mehrere Stehlampen haben, können wir ein „_1“, „_2“ … „_n“ anhängen. Nun klicken wir im Hauptmenu auf Babble um Sprachkommandos zu definieren.

Es erscheint eine komfortable Eingabemaske. Exemplarisch kann man das Sprachkommando für die Stehlampe wie folgt definieren

Wir fügen den Ort hinzu, in dem die Stehlampe aufgestellt ist. Dann wählen wir unter Stehlampe den Ort aus und das Verb, mit dem wir das Objekt schalten möchten und den Zustand. In das Feld ganz rechts fügen wir das FHEM Kommando ein. Wir können noch angeben, ob wir eine Bestätigung der Ausführung erhalten möchten.
Nun können wir Telegram starten und
/start
eingeben. Wir erhalten ein Menu, auf dem wir den Chatbot starten können. Ich habe die Interaktion mittels Telegram einmal in einem Video festgehalten.
