Telegram Bot (Babble / Rivescript) mit dem SmartHome einrichten

Babble Telegram Chat

Wie richte ich einen Telegram Bot (Babble) mit FHEM ein?

  1. Einrichtung eines neuen Bots mit /newbot
  2. Definition des Telebots in FHEM
  3. Einrichten Eures Kontaktes in FHEM
  4. Rivescript installieren
  5. 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>&lt;----- 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
define_telebot

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
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
attr teleBot pollingTimeout 120

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
set teleBot message Hello World

und auf Eurem Smartphone erscheint „Hello World“.

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;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.

Babble Menu

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

Sprachkommando Stehlampe

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.

TelegramChat