Anleitung IP-Symcon Android Sprachsteuerung

Hi,

hier eine Anleitung zur Realisierung einer Sprachsteuerung für IP-Symcon mit Android, Raspberry, Asterisk

Hier ein kleines Demo Video:
[video=youtube_share;QfiRIS-OvX4]http://youtu.be/QfiRIS-OvX4[/video]

Vorweg ein paar Infos:

[ul]
[li]Spracherkennung über GoogleTTS (Internetverbindung notwendig!)[/li][li]Sprachmusterauswertung für Befehlssteuerung über php script in IP Symcon[/li][li]Asterisk auf Raspberry als VOIP Server[/li][li]SIP Client auf Android Device[/li][li]Server Socket als Perl Script auf Raspberry[/li][li]Server und Client-Socket eingerichtet in IP Symcon[/li][li]Ausbaufähig noch mit Handshakes, Asterisk konfigurieren um außerhalb WLAN zu erreichen, phpAGI Nutzung, offline TTS für Asterisk verwenden, usw…[/li][li]Spracherkennung nicht 100% zufriedenstellend[/li][/ul]

Server für IP-Symcon in meiner Beschreibung ist 10.0.0.88 und Raspberry ist 10.0.0.92

Asterisk auf Raspberry PI installieren

sudo apt-get install asterisk

Während Installation folgendes eingeben:
ITU-T-Telefon-Code: 43 (für Österreich) bzw. 49 (für Deutschland) usw…

Asterisk auf Raspberry PI starten

sudo /etc/init.d/asterisk start

Comannd Line Tool auf Raspberry PI testen

sudo asterisk -vvvr

Aussteigen mit Exit, Hilfe mit Help

Konfigurieren der Geräte in der sip.conf Datei auf Raspberry PI
Diese können sich anschließend am Asterik-Server anmelden.

sudo vi /etc/asterisk/sip.conf

Ich schreibe nur jene Einträge die ich modifiziert habe durch zurücknehmen des „;“ und teilweise ändern von den Werten oder komplett hinzufügen von Zeilen. Ich habe die Defaultports gelassen:
port 5060 for UDP and TCP, 5061 for TLS

[general]
allowguest=no
disable=all
allow=alaw
allow=ulaw
videosupport=yes
localnet=10.0.0.0/255.255.255.0
directmedia=no
nat=yes

und ganz zum Schluss beim File noch folgendes ergänzt:

[1000]
permit=10.0.0.0/255.255.255.0
type=friend
context=phones
host=dynamic
secret=PASSWORT
call-limit=3
contactdeny=0.0.0.0/0.0.0.0
contactpermit=10.0.0.0/255.255.0.0

[2000]
permit=10.0.0.0/255.255.255.0
type=friend
context=phones
host=dynamic
secret=PASSWORT
call-limit=3
contactdeny=0.0.0.0/0.0.0.0
contactpermit=10.0.0.0/255.255.0.0

Im Bereich „[general]“ befinden sich allgemeingültige Einstellungen für SIP mit unserer Asterisk-Installation. Dort wird z.B. der Port des Asterisk SIP-Servers angegeben, aus Sicherheitsgründen das lokale Netz und dass es sich hinter einem NAT-Router befindet. Würde man die Werte in „[general]“ raus nehmen, würde es hier trotzdem funktionieren.
Die Bereiche „[1000]“ markieren die Rufnummern und SIP-Anschlüsse. Wäre z.B. die gewünschte Rufnummer des Anschlusses nicht 1000, 2000 oder 3000 sondern 4711, dann kann man den Bereich auch mit [4711] beginnen. Die Einstellung „permit“ legt fest aus welchem Netzwerkbereich sich dieser Anschluss anmelden darf. Meine Anschlüsse dürfen sich also nur aus dem lokalen Netzwerk anmelden. Die Einstellung „type“ legt fest, was der Anschluss darf. „friend“ darf angerufen werden und selbst anrufen. „user“ darf nur anrufen, kann aber nicht angerufen werden. „peer“ kann angerufen werden, darf selbst aber keine Anrufe initiieren. Context legt eine Art Gruppe fest und wird in der extensions.conf wiederverwendet - dazu komme ich dann in einer der nächsten Abschnitte. „host=dynamic“ legt fest, dass der Anschluss sich von unterschiedlichen IP Adresse aus anmelden darf. Zu guter Letzt ist „secret“ noch das Passwort, welches der Anschluss bei der Anmeldung verwenden soll.

Erstellen eines Anrufbeantworters

sudo vi /etc/asterisk/voicemail.conf

Folgenden Inhalt abändern:

[general]
format = wav

[default]
1000 => 1001,Hans Mustermann,hansi@company.de
2000 => 2001,Ute Beispiel,ute.beispiel@company.de
;1001 und 2001 ist das Passwort wenn die Mailbox mit Anwahl Rufnummer 2999 vom Android Device abgefragt wird

Erstellen des Wählplans (Dialplan) in der extensions.conf
Damit die Geräte untereinander kommunizieren können.

sudo vi /etc/asterisk/extensions.conf

Im Default Bereich einen „;“ davor setzen um keine demo auf 1000 zu haben und auf internal zu verweisen:

[default]
;include => demo
include => internal

Ganz unten folgendes ergänzen:

[internal]
exten => _X.,1,Answer()
exten => _X.,2,Verbose(D E F A U L T ==> ${CALLERID(num)} kam um ${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)} in DEFAULT an als er versuchte die Nummer ${EXTEN} anzurufen.)
exten => _X.,3,Playback(hello-world)
exten => _X.,4,Hangup()

exten => 1001,1,Answer()
exten => 1001,2,Playback(hello-world)
exten => 1001,3,Hangup()

;;Speech recognition demo:
exten => 1236,1,Answer()
exten => 1236,n,agi(googletts.agi,"Sag nach dem Pieps Ton etwas auf Deutsch und drücke anschließend die # Taste",de)
exten => 1236,n(record),agi(speech-recog.agi,de-DE)
exten => 1236,n,Verbose(1,Script returned: ${status} , ${id} , ${confidence} , ${utterance})
;Check the probability of a successful recognition:
exten => 1236,n(success),GotoIf($["${confidence}" > "0.6"]?playback:retry)
;Playback the text:
exten => 1236,n(playback),agi(googletts.agi,"Der Text den ich erkannt habe war...",de)
exten => 1236,n,agi(googletts.agi,"${utterance}",de)
exten => 1236,n,System(echo '${utterance}' | nc -w 1 10.0.0.88 4099)
exten => 1236,n,goto(end)
;Retry in case speech recognition wasn't successful:
exten => 1236,n(retry),agi(googletts.agi,"Bitte deutlicher sprechen",de)
exten => 1236,n,goto(record)
exten => 1236,n(fail),agi(googletts.agi,"Ich konnte den Text nicht verstehen",de)
exten => 1236,n(end),Hangup()

exten => 1000,1,Dial(SIP/1000,20)
exten => 1000,2,VoiceMail(1000,u)

exten => 2000,1,Dial(SIP/2000,20)
exten => 2000,2,VoiceMail(2000,u)

exten => 2999,1,VoiceMailMain(${CALLERID(num)},s)

exten => 9999,1,Answer()
exten => 9999,n,agi(googletts.agi,"Hier spricht dein IP-Symcon. Bitte gib mir einen Befehl nach dem Pieps Ton. Bei starkem Hintergrundgeräusch drücke anschließend das #",de)
exten => 9999,n(record),agi(speech-recog.agi,de-DE)
exten => 9999,n,System(yes | rm /home/pi/asterisk.txt)
exten => 9999,n,Verbose(1,Script returned: ${status} , ${id} , ${confidence} , ${utterance})
;Check the probability of a successful recognition (quality > 0.55)
exten => 9999,n(success),GotoIf($["${confidence}" > "0.53"]?playback:retry)
;Playback the text, send to IP Sycmon, get response from IP Sycmon, check response, check ENDE
exten => 9999,n(playback),GotoIf($["${utterance}" = "auflegen" | "${utterance}" = "Auflegen"]?ende:continue)
;exten => 9999,n(continue),agi(googletts.agi,"Folgenden Befehl werde ich umsetzen",de)
;exten => 9999,n,agi(googletts.agi,"${utterance}",de)
exten => 9999,n(playback),System(echo '${utterance}' | sed -e 'ß' 'ss' -e s/ä/ae/g -e s/ö/oe/g -e s/ü/ue/g | nc -w 1 10.0.0.88 4099)
exten => 9999,n,Set(zaehler=0)
;exten => 9999,n,Wait(1)
exten => 9999,n,Set(filestatus=${SHELL(find '/home/pi/asterisk.txt' 2>/dev/null | grep -q /home/pi/asterisk.txt && echo 1 || echo 0)})
exten => 9999,n,While($[${filestatus} < 1])
exten => 9999,n,Wait(1)
exten => 9999,n,Set(zaehler=$[${zaehler} + 1])
exten => 9999,n,Set(filestatus=${SHELL(find '/home/pi/asterisk.txt' 2>/dev/null | grep -q /home/pi/asterisk.txt && echo 1 || echo 0)})
exten => 9999,n,ExecIf($["${zaehler}" > 60 ]?ExitWhile:ContinueWhile())
exten => 9999,n,EndWhile()
exten => 9999,n,Set(utterance=${SHELL(cat /home/pi/asterisk.txt | tr -d '
\r')})
exten => 9999,n,GotoIf($["${utterance}" = "" | "${utterance}" = "0"]?no_file:neu)
exten => 9999,n,goto(neu)
;Retry in case speech recognition wasn't successful:
exten => 9999,n(retry),agi(googletts.agi,"Bitte deutlicher sprechen",de)
exten => 9999,n,goto(record)
exten => 9999,n(neu),agi(googletts.agi,"${utterance}",de)
exten => 9999,n,agi(googletts.agi,"Bitte gib mir einen neuen Befehl. Zum Beenden sage einfach auflegen",de)
exten => 9999,n,goto(record)
exten => 9999,n(no_file),agi(googletts.agi,"Ich habe keine Antwort von mir selbst in /home/pi/asterisk.txt erhalten. Wiederhole deinen Befehl bitte",de)
exten => 9999,n,goto(record)
exten => 9999,n(fail),agi(googletts.agi,"Ich konnte den Text nicht verstehen",de)
exten => 9999,n,goto(ende)
exten => 9999,n(ende),agi(googletts.agi,"Vielen Dank für das nette Gespräch. Bis zum nächsten Mal. Tschüss",de)
exten => 9999,n,Wait(1)
exten => 9999,n,Hangup()

[AnrufundSprachausgabe]
exten => s,1,Answer()
exten => s,n,Wait(1)
exten => s,n,Set(utterance=${SHELL(cat /home/pi/asterisk.txt | tr -d '
\r')})
exten => s,n,GotoIf($["${utterance}" = "" | "${utterance}" = "0"]?no_file,1)
exten => s,n,agi(googletts.agi,"${utterance}",de)
exten => s,n,System(yes | rm /home/pi/asterisk.txt)
exten => s,n,Wait(1)
exten => s,n,Hangup()
exten => no_file,1,agi(googletts.agi,"Datei /home/pi/asterisk.txt existiert nicht oder der Inhalt ist leer",de)
exten => no_file,n,Wait(1)
exten => no_file,n,Hangup()

[phones]
include => internal

Darin zu sehen sind jetzt wieder die bekannten Abschnitte wie „[globals]“ für globale Variablen und „[general]“ für generelle Einstellungen. Interessant wird es bei „[internal]“, welches der Kontext für die internen Telefonate ist. Der Abschitt ganz unten ist der Kontext unserer Telefone, der ja „[phones]“ heißt. Mit „include => internal“ schließt der „phones“-Kontext schließt den Kontext „internal“ mit ein. In „[internal]“ befindet sich der eigentliche Wählplan, der hier nur ein Einzeiler ist und besagt, dass alle vierstelligen Nummern, die von unseren Anschlüssen angewählt werden dazu führen sollen, dass diese Rufnummer über SIP intern angerufen wird.
Wählpläne in Asterisk sind sehr umfangreich und bieten eine enorme Vielzahl an Möglichkeiten. Es bedarf jedoch auch eine sehr große Zeit, sich in diese einzuarbeiten.

Erstellen der Remote Telnet Möglichkeit (Optional)

ACHTUNG: Viele Rechte und Unsicheres Protokoll!!!

sudo vi /etc/asterisk/manager.conf

Einfügen von:

[general]
enabled = yes
port = 5038
; IP-Adresse Asterisk Server
bindaddr = 10.0.0.92

; No access is allowed by default.
; To set a password, create a file in /etc/asterisk/manager.d
; use creative permission games to allow other serivces to create their own
; files
include "manager.d/*.conf"
sudo vi /etc/asterisk/manager.d/REMOTE.conf

Folgender Inhalt

[admin]
secret = TESTPASSWORT
deny = 0.0.0.0/0.0.0.0
permit = 10.0.0.0/255.255.255.0
read = all,system,call,log,verbose,command,agent,user,config
write = all,system,call,log,verbose,command,agent,user,config

Reload der Configs

sudo asterisk -vvvr

Und danach folgende Befehle nacheinander:

sip reload
dialplan reload
manager reload

Danach mit Exit aussteigen

Änderung /etc/group und Gruppenschreibrecht auf /home/pi Benutzer

sudo chmod g+w /home/pi
sudo vi /etc/group

Alt:

pi:x:1000

Neu:

pi:x:1000:asterisk

Konfigurieren der Android Geräte für Asterisk

[ul]
[li]Download von CSipSimple vom Playstore und Grundeinstellung setzen bzgl. Erreichbarkeit (zB: nur WLAN)[/li][li]- Neues Konto hinzufügen und dann Auswahl von Basic und Eingabe von Kontoname (beliebig wählbar), Benutzername 1000 (Telefonnummer für erstes Device), SIP Server (IP Adresse des Raspberry), Passwort (Passwort aus sip.conf Datei) danach sollte der Eintrag auf Grün gehen und kurz mit SIP registriert auftauchen[/li][/ul]

Testen Android Geräte für Asterisk
zB: von Android Handy (1000) auf Android Tablet (2000) einfach die 2000 wählen und schon kann man Mal untereinander telefonieren. Also erster Schritt mit der Haus Telefonanlage funktioniert. Beim Anwählen von zB: 1001 sollte ein Hello World erfolgen.

Installieren verschiedener Spracherkennungsmodule auf Raspberry

wget https://github.com/downloads/zaf/asterisk-speech-recog/asterisk-speech-recog-0.5.tar.gz
wget https://github.com/downloads/zaf/asterisk-googletranslate/asterisk-googletranslate-0.2.tar.gz
wget https://github.com/downloads/zaf/asterisk-googletts/asterisk-googletts-0.6.tar.gz 
gunzip asterisk-speech-recog-0.5.tar.gz
gunzip asterisk-googletranslate-0.2.tar.gz
gunzip asterisk-googletts-0.6.tar.gz
tar -xvf asterisk-speech-recog-0.5.tar
tar -xvf asterisk-googletranslate-0.2.tar
tar -xvf asterisk-googletts-0.6.tar
sudo cp asterisk-speech-recog-0.5/speech-recog.agi /usr/share/asterisk/agi-bin/.
sudo cp asterisk-googletranslate-0.2/googletranslate.agi /usr/share/asterisk/agi-bin/.
sudo cp asterisk-googletts-0.6/googletts.agi /usr/share/asterisk/agi-bin/.
sudo apt-get install perl libwww-perl flac sox mpg123 libjson-perl libio-socket-ssl-perl build-essential tofrodos

Testen Android Geräte für Asterisk Teil2
Wenn man jetzt vom Handy aus 1236 wählt, dann sollte der erste Test möglich sein mit Google Spracherkennung und Feedback des erkannten gesprochenen über die Google API :slight_smile:

Einbinden in IP Symcon per ServerSocket
a.) Neue Instanz als Server Socket hinzufügen
grafik1.jpg
WICHTIG: „Alle Module anzeigen“ auswählen und dann Server Socket wählen
Name „AsteriskSprachsteuerungInput“ und Port 4099. Sollte danach so aussehen
grafik2.jpg

b.) Neue String Variable unter dieser Instanz anlegen mit dem Namen „receiveSprachsteuerung“

c.) Neues Script unter dieser Instanz anlegen mit folgendem Namen „receiveNCdata“ und folgendem Inhalt (die ID der Variable am Anfang mit Eurer ersetzen)

<?

$ID_ReceiveText = 50029 /*[AsteriskSprachsteuerungInput\receiveSpracherkennung]*/;

// wenn das Skript von einer RegisterVariable-Instanz aus aufgerufen worden ist
if ($_IPS['SENDER'] == "RegisterVariable")
{
    // bereits im Puffer der Instanz vorhandene Daten in $data kopieren
    $data  = RegVar_GetBuffer($_IPS['INSTANCE']);
    // neu empfangene Daten an $data anhängen
    $data .= $_IPS['VALUE'];

	 // Inhalt von $data in eine Variable schreiben
    SetValueString($ID_ReceiveText,$data);
    
    // Lerren Inhalt im Puffer der RegisterVariable-Instanz speichern
    RegVar_SetBuffer($_IPS['INSTANCE'], '');
}

?>

d.) Neue Instanz als Registered Variable hinzufügen mit Namen „receiveNC“

grafik3.jpg

Danach diese Variable receiveNC noch per Doppelklick eine übergeordnete Instanz zuweisen

grafik4.jpg

Port 4099 gegeben falls in Windows Firewall freischalten notwendig für eingehende Verbindungen!!!

Erster Test ob das gesprochene auch in IP Symcon ankommt
Auf dem Raspberry folgendes Kommando aufrufen um das Log zu sehen:

sudo asterisk -vvvr

Am Android Handy die 1236 wählen und als Test Befehl „Das ist ein Test sprechen“ und nachsehen ob es so ankommt wie unten ersichtlich.

grafik5.jpg

Jetzt geht es richtig ins eingemachte mit einem Callback in Form eines Client Sockets für den Raspberry

Auf Raspberry:

sudo vi autobahn.pl

und folgenden Inhalt einfügen:

#!/usr/bin/perl
#autobahn.pl

use IO::Socket::INET;
use Encode qw(encode decode);
use utf8;

# flush after every write
$| = 1;

my ($socket,$client_socket);
my ($peeraddress,$peerport);

# creating object interface of IO::Socket::INET modules which internally does
# socket creation, binding and listening at the specified port address.
$socket = new IO::Socket::INET (
LocalHost => '10.0.0.92',
LocalPort => '9001',
Proto => 'tcp',
Listen => 5,
Reuse => 1
) or die "ERROR in Socket Creation : $!
";

#print "SERVER Waiting for client connection on port 9001";

while(1)
{
# waiting for new client connection.
$client_socket = $socket->accept();

# get the host and port number of newly connected client.
$peer_address = $client_socket->peerhost();
$peer_port = $client_socket->peerport();

#print "Accepted New Client Connection From : $peeraddress, $peerport
 ";

# write operation on the newly accepted client.
#$data = "DATA from Server";
#print $client_socket "$data
";
# we can also send the data through IO::Socket::INET module,
# $client_socket->send($data);

# read operation on the newly accepted client
#$data = <$client_socket>;
# we can also read from socket through recv()  in IO::Socket::INET
$client_socket->recv($data,1024);
utf8::decode($data);
$data =~ s/ä/ä/g;
$data =~ s/ö/ö/g;
$data =~ s/ü/ü/g;
$data =~ s/Ä/Ä/g;
$data =~ s/Ö/Ö/g;
$data =~ s/Ãœ/Ü/g;
$data =~ s/ß/ß/g;
utf8::encode($data);
#print "Received from Client : $data
";
#if $data begin with Text: write it to /home/pi/asterisk.txt
if ($data =~ /^Text:/)
{
  @arraytext = split(/:/, $data);
  open(ASTERISK, ">/home/pi/asterisk.txt");
  print ASTERISK "$arraytext[1]
";
  close(ASTERISK);
  $cnt = chmod 0777, "/home/pi/asterisk.txt";
  $cnt = chown pi, pi, "/home/pi/asterisk.txt";
}

#if $data begin with Receiver: write it to /var/spool/asterisk/outgoing/call.call
#split the data by ; and write it with following format example
#Channel: SIP/2000
#MaxRetries: 0
#WaitTime: 30
#Context: AnrufundSprachausgabe
#Priority: 1
#Extension: 2000
if ($data =~ /^Receiver:/)
{
  @arrayreceiver = split(/:/, $data);
  @arraydata = split(/;/, $arrayreceiver[1]);
  open(CALL, ">/var/spool/asterisk/outgoing/call.call");
  print CALL "Channel: $arraydata[0]
";
  print CALL "MaxRetries: $arraydata[1]
";
  print CALL "WaitTime: $arraydata[2]
";
  print CALL "Context: $arraydata[3]
";
  print CALL "Priority: $arraydata[4]
";
  print CALL "Extension: $arraydata[5]
";
  close(CALL);
}

#close the client socket
$client_socket->close();
}

#close the server socket (with endless while this will never happen)
$socket->close();

Starten mit folgendem Kommando im Hintergrund für erste Testzwecke.

sudo perl autobahn.pl &

Eventuell ist es wieder notwendig entsprechend die Firewall auf dem IP Symcon Server bzw. die iptables auf dem Raspberry anzupassen wenn man damit arbeitet!

Client Socket in IP Symcon einrichten
a.) Neue Instanz als Client Socket hinzufügen (zu finden im gleichen Baum wie der Server Socket)
Name „AsteriskSprachsteuerungOutput“ und IP des Raspberry und Port 9001. Sollte danach so aussehen
grafik6.jpg

Ich habe nicht meine richtige IP für die Screenshots verwendet. Nicht wundern weil er bei mir nicht grün ist
b.) Neue String Variable anlegen mit dem Namen „BufferSendAutobahn“
Neue Integer Variable anlegen mit dem Namen „errorCountAutobahn“

c.) Neues Script unter dieser Instanz anlegen mit dem Namen „sendAutobahndata“ und folgendem Inhalt

<?

// Change Configuration parameters if needed
//$maxRetry = 5;  // retries until buffer is cleared
$socketReadyDelay = 2; //delay between retries if socket not ready
$msgDelay = 2;  // delay in sec until timeout and command re-send command

//-------------------------------------------------------------------------------------------
// Nothing to configure below this line

$Id_ClientSocket = IPS_GetParent($_IPS['SELF']);
$IDRegVar = @IPS_GetObjectIDByName("sendAutobahn", $Id_ClientSocket);
$IDBuffer = IPS_GetVariableIDByName("BufferSendAutobahn", $Id_ClientSocket);
$IDerrorCount = IPS_GetVariableIDByName("errorCountAutobahn", $Id_ClientSocket);

print_r($_IPS['SENDER']);

Switch ($_IPS['SENDER'])
{
    Case "RunScript":
	    if (IPS_GetInstance($Id_ClientSocket)['InstanceStatus'] != 102) {// Check if Socket is Active
	       CSCK_SetOpen($Id_ClientSocket,true);
	       IPS_ApplyChanges($Id_ClientSocket);
	       //if (IPS_GetInstance($Id_ClientSocket)['InstanceStatus'] != 102) {
	       //       IPS_SetScriptTimer($IPS_SELF, $socketReadyDelay);  //arm Timer for retry
	       //      echo "Keine Verbindung zu ".IPS_GetName($Id_ClientSocket);
	       //     Return;  // Stop in case Socket Open fail
	       //     }
	    }
	    $buffer=GetValueString($IDBuffer);                  //re-read in case modified meanwhile
	    RegVar_SendText($IDRegVar, $buffer);
       //IPS_SetScriptTimer($IPS_SELF, $msgDelay);          //arm Timer for retry if Fail
	    break;
	    
//    Case "TimerEvent":
//       IPS_SetScriptTimer($IPS_SELF, 0);                          //stop Timer
//       $errorCount=GetValue($IDerrorCount);
//       $errorCount=$errorCount+1;
//       if ($errorCount < $maxRetry) {
//         SetValue($IDerrorCount,$errorCount);
//         IPS_RunScript($_IPS['SELF']);                            // Run next try
//       }
//       else {
//        SetValue($IDerrorCount,0);
//        SetValueString($IDBuffer,"nothing to send");
//        // todo: add additional error processing there
//       }
//      break;
	    
    Default:                                                                   // send Hash ti initiate handshake
       print_r($_IPS['SENDER']);
		 //$data .= ":";
       //$hash = md5($data);
       //$hash .= "
";
       //RegVar_SendText($IDRegVar, $hash);
       //Break;
}

?>

d.) Registered Variable anlegen mit Namen „sendAutobahn“ und mit der Instanz „AsteriskSprachsteuerungOutput“ und dem Script „sendAutobahndata“ verknüpfen
Das ganze sollte jetzt in etwa so aussehen mit IP 10.0.0.92
grafik7.jpg

Include Script in IP Symcon anlegen

Neues Script erstellen mit Namen „SendToAutobahn_include“ irgendwo in Eurem Bereich und folgenden Inhalt einfügen.

<?

function SendtoAutobahn($Id_ClientSocket,$new) {
	$IDBuffer = @IPS_GetObjectIDByName("BufferSendAutobahn", $Id_ClientSocket);
	$IDSendScript = @IPS_GetObjectIDByName("sendAutobahndata", $Id_ClientSocket);
	SetValue($IDBuffer,$new);
	IPS_RunScript($IDSendScript);
}

function tsay($Id_ClientSocket,$msg) {
	$tsay = "Text: " . $msg;
   SendtoAutobahn($Id_ClientSocket,$tsay);
}

function tcall($Id_ClientSocket,$itelnr) {
	$trecv = "Receiver: SIP/" . $itelnr . ";0;30;AnrufundSprachausgabe;1;" . $itelnr;
   SendtoAutobahn($Id_ClientSocket,$trecv);
}

?>

Anschließend auf Script doppelklicken und im Menü Umbennen Button klicken um von zB: 21190.ips.php den physischen Scriptnamen umzubennen auf SendToAutobahn_include.ips.php
grafik8.jpg

Einrichten damit Perl Socket Server in Zukunft über Autostart am Raspberry lauft

sudo vi /etc/init.d/autobahn

Mit folgendem Inhalt

#! /bin/sh
# /etc/init.d/autobahn
perl /home/pi/autobahn.pl &

Danach:

sudo chmod 755 /etc/init.d/autobahn
sudo update-rc.d autobahn defaults

IP Symcon Beispiel Script für Anruf und Sprachausgabe einer Meldung
Manuell testen auf Raspberry indem 2 Dateien angelegt werden

sudo vi /home/pi/asterisk.txt

Inhalt:

Das ist ein manueller Test Alarm

Danach folgende Kommandos:

sudo chmod 777 /home/pi/asterisk.txt
sudo chown pi:pi /home/pi/asterisk.txt
sudo vi /var/spool/asterisk/outgoing/call.call

Mit folgendem Inhalt:

Channel: SIP/2000
MaxRetries: 0
WaitTime: 30
Context: AnrufundSprachausgabe
Priority: 1
Extension: 2000

Die 2te Datei wird nach dem erfolgten Anruf automatisch wieder gelöscht von Asterisk. Hier lasse ich mich auf dem Tablet testweise anrufen.

Jetzt das IP Symcon Script der über den Client Socket geht und einen Anruf tätigt mit Namen „Beispiel_Tabletanrufen_Textausgeben„ anlegen und folgendem Inhalt

<?

include_once "SendToAutobahn_include.ips.php";
// this library provides SendtoAutobahn() function;

// here we need our client socket (for example the websocket autobahn python script on Raspberry
// where also the asterisk virtual VOIP server is running)
$Autobahn = 40934 /*[AsteriskSprachsteuerungOutput]*/;

// at first for output to fill on Raspberry server the /home/pi/asterisk.txt file
// we need first the text
tsay($Autobahn,"Hier spricht dein IP-Symcon. Soeben wurde Hochwasseralarm ausgelöst!");
sleep(1);
// and then we need our Asterisk Receiver in following format
// Channel; Max Retries; Waittime; Context; Priority; Callerid
// example for internal telephone number 2000:
// SIP/2000;0;30;AnrufundSprachausgabe;1;2000
// with this information a file /var/spool/asterisk/outgoing/call.call will be created on your client socket
// (for example Raspberry with installed Asterisk virtual VOIP server)
// a simple example to only specify the internal telephone number (waittime, max retries and so on automatically filled
tcall($Autobahn,"2000");
// another way to specify all parameter
//SendtoAutobahn($Autobahn,"Receiver: SIP/2000;0;30;AnrufundSprachausgabe;1;2000");

?> 

Danach das Script ausführen und Ihr solltet einen Anruf erhalten mit der Textansage :smiley:

IP Symcon Shutter Control Script einrichten und Instanzen erstellen und einmessen
http://www.ip-symcon.de/service/dokumentation/modulreferenz/shutter-control
(ich habe zB: Möller Eaton XComfort)

IP Symcon Beispiel Script für Haussteuerung Rollladen

Jetzt ein Script anlegen mit folgendem Namen: „Beispiel_Rollladen_Temperatur“

<?

include_once "SendToAutobahn_include.ips.php";
// this library provides SendtoAutobahn() function;

// here we need our client socket (for example the websocket autobahn python script on Raspberry
// where also the asterisk virtual VOIP server is running)
$Autobahn = 40934 /*[AsteriskSprachsteuerungOutput]*/;
$input = GetValueString(50029 /*[AsteriskSprachsteuerungInput\receiveSpracherkennung]*/);

//hier in einem Array jetzt alle möglichen Variablen oder Geräteinstanzen etc... reinpacken
//(abgekupfert die Logik und ein klein wenig erweitert)
global $tg_info_devices;
$tg_info_devices = array(
"Büro1" => array("Typ" => "Licht", "Variable" => 12345, "Aussprache" => "Im Büro ist das Licht" ),
"Büro2" => array("Typ" => "Rollladen", "Variable" => 41402, "Aussprache" => "Im Büro ist der Rollladen" ),
"Schlafzimmer1" => array("Typ" => "Licht", "Variable" => 12346, "Aussprache" => "Im Schlafzimmer ist das Licht" ),
"Schlafzimmer2" => array("Typ" => "Temperatur", "Variable" => 36426, "Aussprache" => "Im Schlafzimmer beträgt die Temperatur" ),
"Schlafzimmer3" => array("Typ" => "Luftfeuchtigkeit", "Variable" => 39357, "Aussprache" => "Im Schlafzimmer beträgt die Luftfeuchtigkeit" ),
"Schlafzimmer4" => array("Typ" => "Rollladen", "Variable" => 52336, "Aussprache" => "Im Schlafzimmer ist der Rollladen" ),
"aussen1" => array("Typ" => "Windaktuell", "Variable" => 56046, "Aussprache" => "Draussen gibt es einen Wind von" ),
"aussen2" => array("Typ" => "Windböen", "Variable" => 40250, "Aussprache" => "Draussen existieren Windböen mit" ),
"aussen3" => array("Typ" => "Temperatur", "Variable" => 32134, "Aussprache" => "Draussen hat die Temperatur" ),
"aussen4" => array("Typ" => "Luftfeuchtigkeit", "Variable" => 40108, "Aussprache" => "Draussen hat es eine Luftfeuchtigkeit von" ),
"aussen5" => array("Typ" => "Regen", "Variable" => 59347, "Aussprache" => "Draussen regnet es" ),
"Wohnzimmer1" => array("Typ" => "Rollladen", "Variable" => 41403, "Art" => "Tür", "Aussprache" => "Im Wohnzimmer ist das Raffstore der Tür" ),
"Wohnzimmer2" => array("Typ" => "Rollladen", "Variable" => 41404, "Art" => "Fenster", "Aussprache" => "Im Wohnzimmer ist das Raffstore des Fensters" ),
"Wohnzimmer3" => array("Typ" => "Temperatur", "Variable" => 15013, "Aussprache" => "Im Wohnzimmer beträgt die Temperatur" ),
"Wohnzimmer4" => array("Typ" => "Luftfeuchtigkeit", "Variable" => 43371, "Aussprache" => "Im Wohnzimmer beträgt die Luftfeuchtigkeit" ),
"Bad1" => array("Typ" => "Temperatur", "Variable" => 42086, "Aussprache" => "Im Bad beträgt die Temperatur" ),
"Bad2" => array("Typ" => "Luftfeuchtigkeit", "Variable" => 10945, "Aussprache" => "Im Bad beträgt die Luftfeuchtigkeit" )
);

// a.) Suche nach Zahl, Aktion, Raum im Kommando (ansonsten wenn Aktion nicht gefunden mit Meldung aussteigen)
$zahl = 0;
$detail = "";
$tsay = "";

switch (true) {
	 // Suche nach erster Zahl im Kommando
	 case (preg_match("([1-9]+)", $input, $matches)) :
        $zahl = $matches[0];
	 case (preg_match("/Rol|Store/i", $input) ? true : false) :
		  $typ = "Rollladen";
		  break;
    case (preg_match("/Licht|Beleuchtung|Lampe|Led/i", $input) ? true : false) :
		  $typ = "Licht";
		  break;
    case (preg_match("/grad|temperatur/i", $input) ? true : false ) :
		  $typ = "Temperatur";
		  break;
	 case (preg_match("/luft|feucht/i", $input) ? true : false ) :
		  $typ = "Luftfeuchtigkeit";
		  break;
    case (preg_match("/boeen|spitze/i", $input) ? true : false ) :
		  $typ = "Windböen";
		  break;
	 case (preg_match("/kmh|wind|geschwindigkeit/i", $input) ? true : false ) :
		  $typ = "Windaktuell";
		  break;
    case (preg_match("/regen|niederschlag/i", $input) ? true : false ) :
		  $typ = "Regen";
		  break;
}

switch (true) {
    case (preg_match("/schliesse|zu|runter|unten/i", $input) ? true : false) :
        $aktion = "runter";
        break;
    case (preg_match("/oeffne|auf|hoch|oben/i", $input) ? true : false ) :
		  $aktion = "rauf";
        break;
    case (preg_match("/an|ein|on/i", $input) ? true : false ) :
		  $aktion = "ein";
		  break;
    case (preg_match("/aus|off/i", $input) ? true : false ) :
		  $aktion = "aus";
		  break;
	 case (preg_match("/wer|wie|was|wo|warum|weshalb|wann|welche|wieviel|sage|antworte/i", $input) ? true : false ) :
		  $aktion = "frage";
		  break;
	 default :
		  $aktion = "frage";
		  break;
}

switch (true) {
	 case (preg_match("/sekunde/i", $input) ? true : false ) :
		  $detail = "Sekunden";
		  break;
}

switch (true) {
	 case (preg_match("/tuer/i", $input) ? true : false ) :
		  $art = "Tür";
		  break;
    case (preg_match("/fenster/i", $input) ? true : false ) :
		  $art = "Fenster";
		  break;
	 case (preg_match("/nord/i", $input) ? true : false ) :
		  $art = "Norden";
		  break;
    case (preg_match("/sued/i", $input) ? true : false ) :
		  $art = "Süden";
		  break;
    case (preg_match("/west/i", $input) ? true : false ) :
		  $art = "Westen";
		  break;
    case (preg_match("/ost/i", $input) ? true : false ) :
		  $art = "Osten";
		  break;
	 case (preg_match("/decke/i", $input) ? true : false ) :
		  $art = "Decke";
		  break;
    case (preg_match("/wand/i", $input) ? true : false ) :
        $art = "Wand";
        break;
}

switch (true) {
    case (preg_match("/buero/i", $input) ? true : false ) :
		  $raum = "Büro";
		  break;
    case (preg_match("/wohn/i", $input) ? true : false ) :
		  $raum = "Wohnzimmer";
		  break;
    case (preg_match("/schlaf/i", $input)) :
        $raum = "Schlafzimmer";
		  break;
    case (preg_match("/kueche/i", $input) ? true : false ) :
		  $raum = "Küche";
		  break;
    case (preg_match("/bad/i", $input) ? true : false ) :
		  $raum = "Bad";
		  break;
    case (preg_match("/ess/i", $input) ? true : false ) :
		  $raum = "Essplatz";
		  break;
    case (preg_match("/klo|wc/i", $input) ? true : false ) :
		  $raum = "WC";
		  break;
    case (preg_match("/gaeste|kinder/i", $input) ? true : false ) :
		  $raum = "Gästezimmer";
		  break;
    case (preg_match("/party|feier/i", $input) ? true : false ) :
		  $raum = "Partyraum";
		  break;
    case (preg_match("/garage/i", $input) ? true : false ) :
		  $raum = "Garage";
		  break;
	 case (preg_match("/alle/i", $input) ? true : false ) :
		  $raum = "alle";
		  break;
    case (preg_match("/aussen/i", $input) ? true : false ) :
		  $raum = "Aussen";
		  break;
}

if ($zahl == 0) {
   $zahl = 1 ;
}
//print_r($typ);
//print_r($raum);
//print_r($aktion);
//print_r($zahl);

// b.) Auswerten ob $raum gesetzt
if (ISSET($raum) == FALSE ) {
   tsay($Autobahn,"Du hast vergessen eine Örtlichkeit bzw. einen Raum mit zu geben! Mit diesem Befehl kann ich so nichts anfangen!");
   exit(0);
}

// c.) Auswerten ob $aktion gesetzt
if (ISSET($aktion) == FALSE ) {
   tsay($Autobahn,"Du hast vergessen eine Aktion mit zu geben! Mit diesem Befehl kann ich so nichts anfangen!");
	exit(0);
}

// d.) Auswerten ob $typ gesetzt
if (ISSET($typ) == FALSE ) {
   tsay($Autobahn,"Du hast vergessen einen Typ mit zu geben! Mit diesem Befehl kann ich so nichts anfangen!");
	exit(0);
}

// e.) Steuern der Aktionen
// lese zuerst alle Typen die übereinstimmen aus dem Array
foreach( $tg_info_devices as $rauma => $value ) {
	 foreach( $value as $wert => $inhalt ) {
		  if ($wert == "Typ" & preg_match("/$typ/i", $inhalt) == true ) {
			  //jetzt brauchen wir auch die nächsten beiden
			  $leseweiter = TRUE;
		  }
		  if ($wert == "Typ" & preg_match("/$typ/i", $inhalt) == false) {
			  $leseweiter = FALSE;
		  }
		  if ($leseweiter == TRUE & $wert == "Variable" ) {
			  $variablea = $inhalt;
		  }
		  if ($leseweiter == TRUE & $wert == "Art" ) {
			  $arta = $inhalt;
		  }
		  if ($leseweiter == TRUE & $wert == "Aussprache" ) {
			  $aussprache = $inhalt;
			  //hier jetzt die Aktion durchführen wenn auch Raum übereinstimmt!
			  $leseweiter = FALSE;
			  if ( preg_match("/$raum/i", $rauma) == true | $raum == "alle" ) {
				  //zuerst noch Art abfragen wenn man zB: 2 Fenster, Lichter etc. in einem Raum hat
				  //ob Match gegeben ist
				  $continue = 0;
				  if (ISSET($art) == TRUE ) {
					  if ($art == $arta) {
						  $continue = 1;
					  }
				  }
				  else {
					  $continue = 1;
				  }
				  if ($continue == 1) {
				     switch ($typ) {
					  case "Rollladen" :
						  if ($aktion == "runter") {
							  if ($detail == "Sekunden") {
								  $zahlms = $zahl * 1000;
								  SC_MoveDown($variablea,$zahlms);
								  $tsay .= " $aussprache $zahl Sekunden nach unten bewegt worden!";
							  } else {
                          SC_MoveDown($variablea,0);
                          $tsay .= " $aussprache jetzt unten";
							  }
						  }
						  if ($aktion == "rauf") {
							  if ($detail == "Sekunden") {
								  $zahlms = $zahl * 1000;
								  SC_MoveUp($variablea,$zahlms);
                          $tsay .= " $aussprache $zahl Sekunden nach oben bewegt worden!";
							  } else {
                          SC_MoveUp($variablea,0);
                          $tsay .= " $aussprache jetzt oben";
							  }
						  }
						  break;
						  
					  case "Licht" :
						  if ($aktion == "ein") {
							  //offen wie zu implementieren
						  }
						  if ($aktion == "aus") {
							  //offen wie zu implementieren
						  }
						  break;
						  
					  case "Temperatur" :
						  $temperatur = GetValueFloat($variablea);
						  $tsay .= " $aussprache $temperatur Grad";
						  break;
						  
					  case (preg_match("/Wind/i", $typ) ? true : false ) :
						  $wind = GetValueFloat($variablea);
						  $tsay .= " $aussprache $wind Kilometer pro Stunde";
						  break;
						  
					  case "Luftfeuchtigkeit" :
						  $luftfeuchtigkeit = GetValueInteger($variablea);
						  $tsay .= " $aussprache $luftfeuchtigkeit Prozent";
						  break;
						  
					  case "Regen" :
						  $regen = GetValueFloat($variablea);
						  $tsay .= " $aussprache $regen Millimeter";
						  break;
				     }
				  }
			  }
        }
    }
}

if ($tsay == "") {
	$tsay = "Der Befehl konnte von mir nicht ausgewertet werden. Bitte sei präziser";
}

//Ausgabe aller gesammelten Nachrichten an Asterisk
tsay($Autobahn,"$tsay");

//f.) Offene Themen
//f1.) Prozent Angaben für öffnen /schließen usw.. aus IPSShadowing Logik?
//f2.) Wie bekommt IPSShadowing den veränderten Status mit bei Rollladen schließen über Shutter Modul???
//f3.) Licht RGB und dimmen wie implementieren in dieser Logik???

//g.) Ansätze für Lösungen
//???

//h.) Text zurücksenden an Asterisk
//tsay($Autobahn,"Der Rollladen im $RAUM wurde auf $PROZENT Prozent bewegt!");
//tsay($Autobahn,"Der Rolladen im $RAUM wurde auf $PROZENT Prozent bewegt!");
//tsay($Autobahn,"Der Rolladen im $RAUM wurde komplett geöffnet!");
//tsay($Autobahn,"Der Rolladen im $RAUM wurde komplett geschlossen!");
//tsay($Autobahn,"Der Rolladen im $RAUM wurde $PROZENT Prozent geöffnet");
//tsay($Autobahn,"Der Rolladen im $RAUM wurde $PROZENT Prozent geschlossen");
//tsay($Autobahn,"Die Temperatur $RAUM beträgt $GRAD Grad Celsius.");
//tsay($Autobahn,"Die Luftfeuchtigkeit $RAUM beträgt $PROZENT Prozent.");
//tsay($Autobahnn,"Das Licht $RAUM ist jetzt $STATUS");
//tsay($Autobahn,"Der Regen $ZEITRAUM betägt $LITER Liter pro Quadratmeter");
//tsay($Autobahn,"Die Windspitze $ZEITRAUM war $KMH Kilometer pro Stunde");

?>

Danach bei diesem Script ein Ereignis ergänzen. Und zwar ein auslösendes mit Variable AsteriskSprachsteuerungInput\receiveSpracherkennung und Status „bei Variablenaktualisierung“

Jetzt die Telefonnummer 9999 anrufen und genießen!!! :cool:

Weiterführende Links:
http://www.asterisk.org
http://www.kammerath.net/asterisk-virtuelle-telefonanlage.html
http://zaf.github.io/asterisk-googletts/
http://das-asterisk-buch.de/1.6/
http://phpagi.sourceforge.net/
http://das-asterisk-buch.de/1.6/applications.html

Reserviert für weitere Infos

Hallo Thiemo,

auch wenn ich mir nicht sicher bin ob ich das jemals testen werde…

…Hammeranleitung. Vielen Dank dafür.

'N Abend … erstmal danke für die ausführliche Anleitung. Nur komme ich leider nicht über den ersten Test hinaus. Meine Android Geräte melden mir, egal welche Nummern ich wähle, 404/not found. Ne Idee wo ich schauen kann?!

EDIT: hat sich erledigt. Habe den letzten Teil der extensions.conf noch mal kopiert, danach hat es funktioniert.

c.) Neues Script unter dieser Instanz anlegen mit dem Namen „sendAutobahndata“ und folgendem Inhalt

welcher Inhalt!?

Sorry. Hatte ich nicht mit drinnen.

Hier der Inhalt von sendautobahndata (werde es oben noch ergänzen)

<?

// Change Configuration parameters if needed
//$maxRetry = 5;  // retries until buffer is cleared
$socketReadyDelay = 2; //delay between retries if socket not ready
$msgDelay = 2;  // delay in sec until timeout and command re-send command

//-------------------------------------------------------------------------------------------
// Nothing to configure below this line

$Id_ClientSocket = IPS_GetParent($_IPS['SELF']);
$IDRegVar = @IPS_GetObjectIDByName("sendAutobahn", $Id_ClientSocket);
$IDBuffer = IPS_GetVariableIDByName("BufferSendAutobahn", $Id_ClientSocket);
$IDerrorCount = IPS_GetVariableIDByName("errorCountAutobahn", $Id_ClientSocket);

print_r($_IPS['SENDER']);

Switch ($_IPS['SENDER'])
{
    Case "RunScript":
	    if (IPS_GetInstance($Id_ClientSocket)['InstanceStatus'] != 102) {// Check if Socket is Active
	       CSCK_SetOpen($Id_ClientSocket,true);
	       IPS_ApplyChanges($Id_ClientSocket);
	       //if (IPS_GetInstance($Id_ClientSocket)['InstanceStatus'] != 102) {
	       //       IPS_SetScriptTimer($IPS_SELF, $socketReadyDelay);  //arm Timer for retry
	       //      echo "Keine Verbindung zu ".IPS_GetName($Id_ClientSocket);
	       //     Return;  // Stop in case Socket Open fail
	       //     }
	    }
	    $buffer=GetValueString($IDBuffer);                  //re-read in case modified meanwhile
	    RegVar_SendText($IDRegVar, $buffer);
       //IPS_SetScriptTimer($IPS_SELF, $msgDelay);          //arm Timer for retry if Fail
	    break;
	    
//    Case "TimerEvent":
//       IPS_SetScriptTimer($IPS_SELF, 0);                          //stop Timer
//       $errorCount=GetValue($IDerrorCount);
//       $errorCount=$errorCount+1;
//       if ($errorCount < $maxRetry) {
//         SetValue($IDerrorCount,$errorCount);
//         IPS_RunScript($_IPS['SELF']);                            // Run next try
//       }
//       else {
//        SetValue($IDerrorCount,0);
//        SetValueString($IDBuffer,"nothing to send");
//        // todo: add additional error processing there
//       }
//      break;
	    
    Default:                                                                   // send Hash ti initiate handshake
       print_r($_IPS['SENDER']);
		 //$data .= ":";
       //$hash = md5($data);
       //$hash .= "
";
       //RegVar_SendText($IDRegVar, $hash);
       //Break;
}

?>

Hallo Thiemo!

Erst mal ein großes Lob und vielen Dank für die tolle, ausführliche Anleitung.

Wie sieht bei Dir der Asterisk Kontext „AnrufundSprachausgabe“ aus?

Der Punkt, wo der von IPS ausgelöste Anruf in der extentions.conf aufschlägt, wird
leider nicht aufgeführt.

Beste Grüße

Michael

Hier der Inhalt:
[AnrufundSprachausgabe]
exten => s,1,Answer()
exten => s,n,Wait(1)
exten => s,n,Set(utterance=${SHELL(cat /home/pi/asterisk.txt | tr -d ’
\r’)})
exten => s,n,GotoIf($["${utterance}" = „“ | „${utterance}“ = „0“]?no_file,1)
exten => s,n,agi(googletts.agi,"${utterance}",de)
exten => s,n,System(yes | rm /home/pi/asterisk.txt)
exten => s,n,Wait(1)
exten => s,n,Hangup()
exten => no_file,1,agi(googletts.agi,„Datei /home/pi/asterisk.txt existiert nicht oder der Inhalt ist leer“,de)
exten => no_file,n,Wait(1)
exten => no_file,n,Hangup()

Habe ich oben jetzt auch noch ergänzt

Vielen Dank!

Ich habe die Sprachausgabe realisiert bekommen.

Klappt gut. :slight_smile:

Hallo,

ich habe das Script installiert, scheint auch grundsätzlich zu funktionieren.
Mein einziges Problem, meine Spracheingabe wird nicht von google umgesetzt.
Es kommt immer in der ${confidence} -1 etc. . . zurück.
Vorzulesende Texte, setzt google aber um.:confused:

Woran kann das liegen ??

Gruß Achim

Nachdem es mittlerweile eine neuere Version gibt habe ich folgendes gemacht. Bei mir kommt aber auch -1 zurück. Vor diesem Schritt und jetzt auch. Hatte es schon länger nicht mehr im Einsatz


wget https://github.com/zaf/asterisk-speech-recog/archive/master.zip
unzip master.zip
rm master.zip
sudo cp asterisk-speech-recog-master/speech-recog.agi /usr/share/asterisk/agi-bin/.
wget https://github.com/zaf/asterisk-googletranslate/archive/master.zip
unzip master.zip
rm master.zip
sudo cp asterisk-googletranslate-master/googletranslate.agi /usr/share/asterisk/agi-bin/.
wget https://github.com/zaf/asterisk-googletts/archive/master.zip
unzip master.zip
sudo cp asterisk-googletts-master/googletts.agi /usr/share/asterisk/agi-bin/.
sudo apt-get install perl libwww-perl flac sox mpg123 libjson-perl libio-socket-ssl-perl build-essential tofrodos

Bin auf folgendes gestoßen, mir ist aber noch nicht klar wie man es abändern müsste mit den Aufrufen damit er dann den eigenen API Key verwendet den man so generieren muss. Schade dass Google hier was geändert hat.



Hi Zaf and everybody,

I'm here just to give my little contribution info about the new Speech Recognition Script for Asterisk (using the Google Speech Recognition API v2) and to record this info for everybody.

Since some days ago my Speech Recognition Script for Asterisk stoped to work.
Following the instructions on README of the new script package everything got back work. But there are some tricks that should be in attention:

You need a Key from Google's API Console (https://console.developers.google.com) to make this work. This needs to be a "Speech API" key.
Follow this instructions: https://developers.google.com/console/help/new/#generatingdevkeys
But on the first time at Google's API Console you will not see the "Speech API" option. For this, you need to enter (register) for chromium google group (https://groups.google.com/a/chromium.org/forum/#!forum/chromium-dev)
When you go back to Google's API Console, now you can see the "Speech API" option and just turn it On.
After you need to go to the left menu at "APIs & auth", "Credentials". And click on the "Create New Key" below the "Public API access" title and choose "Server key" type.
On the "Accept requests from these server IP addresses" field, you need to put the IP address or network that your server is located, AND you need to put the IP "127.0.0.1" too (without this IP, It did not work for me).
Copy and paste the generated API key inside the new speech-recog.agi script, on the key User defined parameter.
Adjust the dialplan to the variables reported from script ("utterance" and "confidence") and you are good go !
PS.: There is a usage limit for this Google API: 1.0 requests/second/user and 50 requests per day.
Regards.

Hallo Thiemo,

unter welchen Link hast Du die Info gefunden?

Es scheint so, dass es einige ein wenig übertrieben haben. War ja auch sehr scharmant.
Für den Alltagsgebrauch max. 50 Nutzungen !?! Bin mir nicht sicher ob es dann noch wirklich brauchbar ist.

Gruß Achim

Hallo Achim,

hier ist es beschrieben:
https://github.com/zaf/asterisk-speech-recog/issues/9

Ja das mit 50 Nutzungen ist für den Alltag wenn man alles so steuern will und Status abfragen nicht ausreichend. Ich habe es die letzten Monate kaum noch selbst verwendet da es einfach zu inperformant war bzgl. Antwortzeiten und auch die Erkennungsrate teilweise nicht akzeptabel war. Eine direkte Sprachsteuerung am Andoid Handy ist da um einiges besser wenn ich mir zum Beispiel Google Now (Google Suche) ansehe das sofort Wort für Wort erkennt oder SVoice.
Ich hoffe ja es kommt irgendwann mal eine Sprachsteuerung in der IP Symcon App mit diversen Konfigurationsmöglichkeiten bzw. Integration der IPSLibrary

Gruß
Thiemo