Android App IPSymconVoice

Hallo Michael,

war mir so nicht bewusst. Hatte aber auch meine Instanzvariablen noch nie umbenannt sondern immer nur verlinkt. :wink:
Ist aber ein guter Einwand und ich habe das Script entsprechend geändert.

Die Funktion ist ein sehr guter Ansatz. Werde ich mal versuchen bei mir auch so zu verwenden und das Script anzupassen. Dann kann man ja die Funktion weiter ausbauen bzgl. verschiedener Hardware. Ich mache es nämlich derzeit auch über die Hilfsvariablen.
Gerade im Script ist noch viel Potential drinnen. zB: habe ich gerade auch überlegt wenn der Befehl UND vorkommt entsprechend einen Split zu machen und in einer Schleife dann mehrmal zu durchlaufen. Dann würde zB: auch folgender Satz funktionieren: „Schließe im Büro den Rollladen und schalte das Licht ein“ und sonst gibt es im Script noch ein paar Dinge zu lösen wie bereits angesprochen zB: Heizkörperthemostate Temperatur setzen usw…

Bzgl. SSL Support habe ich schlechte Nachrichten. Das unterstützt der „MIT App Inventor 2“ nicht mit dem ich derzeit die Android App Entwicklungen gemacht habe.
appinventor-sources/Web.java at master · mit-cml/appinventor-sources · GitHub und einem Posting das ich noch gefunden habe per Google Suche
Ich will aber mittelfristig auf das Android Studio umsteigen bzgl. App Entwicklung (Winterprojekt), als Feature die Steuerung per QR-Code Scan realisierbar machen und langfristig schwebt mir als Zusatzfeature AndroidWear vor. Stichwort Smartwatch Sprachsteuerung und zusätzlich noch NFC Funktion in Verbindung mit Smartwatch für „NFC Schalter“, denn das ist momentan doch umständlich immer Handy raus holen, entsperren, App starten, NFC Lese-Button drücken und dann erst hinhalten zu können damit NFC gelesen wird und der Befehl ausgeführt wird.

LG
Thiemo

Hi Thiemo. Habe mir auch deine App installiert und dein Script im Einsatz. Daumen hoch und ein fettes Danke dafür. Genau das angesprochene in deinem letzten Post wollte ich grade als Featurerequest anfragen: ist es möglich den Button NFC lesen als default zu programmieren? Denn die App wird ja schon mal automatisch gestartet beim dranhalten. Dann würde zumindest die Punkte … App starten und Button drücken wegfallen :slight_smile:

Gesendet von meinem GT-I9505 mit Tapatalk

Also bei mir klappt SSL mit Deiner App wenn ich die SSL CheckBox setze. :confused:

Ich erlaube auch nur HTTPS Traffic von Extern in mein Heimnetz. Wichtig ist allerdings ein korrekt konfiguriertes SSL Zertifikat. Dies muss vom Android Gerät als gültig angesehen werden. Ansonsten verweigern die internen SSL Bibliotheken die Verbindung.

Hallo Thiemo,

danke für Deine Arbeit :slight_smile:

Die Einrichtung hat problemlos funktioniert - der Sprachbefehl landet in der Variablen.

Aber kannst bitte den zweiten Schritt näher beschreiben:

Array aufbauen mit Euren Konfigurationen.

u.a. „Script „LED_Kueche_schalten“ (Homematic Schalter)“

Was genau passiert der Aktor-ID, STAUS-ID oder Skript-ID?

MST

Hallo,

da ich es ursprünglich umgehen wollte im Script direkt Befehle für das Schalten einzubauen (hier wäre es ja hilfreich wenn es eine IP-Symcon Funktion von haus aus geben würde der ich einfach die Instanzvariable mitgebe als Schaltbefehl und die im Hintergrund dann automatisch zB: ENO_SwitchMode, MXC_SwitchMode, HM_WriteValueBoolean, etc… aufruft oder eine globale IP-Symcon Funktion mit welche der Status abgefragt werden kann), dachte ich es wäre einfacher beim Schalten von Aktoren immer nicht direkt die Instanz anzusprechen, sondern eine Boolean Variable hinter der ein Script stehen muss welches als auslösendes Ereignis eine Veränderung der Boolean Variable hat und im ausgelagerten Script dann der Schaltbefehl durchgeführt wird je nachdem welche Hardware verbaut ist.

Ich hoffe der Absatz oben ist verständlich :slight_smile:

Die Idee mit dem SetValueUniversal hier im Thread gefällt mir allerdings sehr gut. Leider werde ich wahrscheinlich erst am Sonntag dazu kommen mich bei mir mit dieser Funktion näher zu befassen um mein Script dann auch umzubauen und bei mir zu testen und dann hier die neue Script Version zu posten.

LG
Thiemo

Ok cool :slight_smile: Kannst Du mir nähere Infos bzgl. dem Zertifikat zukommen lassen. Hatte das nämlich auch ursprünglich in Verdacht da ich beim Android Browser auch die Ausnahme bzgl. Zertifikat bestätigen muss um überhaupt das Webfront zu bekommen. Hatte dann versucht das Webfront Zertifikat von IP-Symcon unter Android zu installieren. Bin aber daran gescheitert weil es anscheinend bei mir als Selbst-Zertifiziertes nicht installiert wurde. (Mein Handy ist nicht gerootet, habe SSL aber noch nicht auf meinem alten Handy probiert das gerootet ist und ein Custom-ROM drauf hat) … Muss ich gleich mal testen ob das die Lösung ist … Nein ist es nicht, wahrscheinlich kapiere ich das Thema Zertifikate nicht richtig

:confused:

Also wenn ich sage „Schalte das Licht im Büro ein“ tut sich im IPS-Headquarter nichts.

Ich habe mein Array schon alles alles reinpackt.

MST

Hi,

ich habe das Auswerteskript für die Spracherkennung mit einem anderen Ansatz umgeschrieben. Ich denke, dass man hiermit alle Freiheiten bei der Gestaltung der Sprachsteuerung hat.

Das Prinzip ist gleich geblieben: Ich habe einen Eingangsstring mit dem Kommando, welcher von Thiemos App oder einer anderen SpeechToText Engine geliefert wurde. Eine Aktualisierung dieser Variable triggert das Erkennungsscript, welches den Satz analysiert, die Befehle ausführt und eine Ergebnisantwort als String zurück liefert, welche dann angezeigt oder vorgelesen wird.

Die ganze Konfigurationslogik steckt in einem verketteten $config Array. Wie ich es aufbaue erkläre ich in einem Beispiel:

Ich möchte fürs erste folgende Kommandos unterstützen:

Das Licht im Wohnzimmer einschalten.
Das Licht im Wohnzimmer ausschalten.

Welche Temperatur ist im Bad.
Setze die Temperatur im Bad auf 20.5 Grad.

In den Sätzen habe einen Ort und ein Gewerk welches den zugehörigen Sensor/Aktor beschreibt. (Wohnzimmer Licht), (Bad Temperatur).
Damit selektiere ich mein Gerät. Mit dem Gerät kann ich meistens unterschiedliche Aktionen durchführen. (einschalten, ausschalten, Abfragen, Werte setzen usw.)

Für das Wohnzimmer Licht Beispiel suche im Satz die Wörter Licht und Wohnzimmer als Filter und einschalten bzw. ausschalten als Aktion. Der Satz
„Wenn ich auf einschalten drücke geht das Licht im Wohnzimmer an“ wäre kein Unterschied zu
„einschalten Licht Wohnzimmer“

Mit dem Parameter „REGEX1“ – REGEX99 gebe ich die Filterkriterien an. Die Einträge werden als Reguläre Ausdrücke ohne Beachtung der Gross/Kleinschreibung interpretiert. Wenn ich exakt nach Wohnzimmer suche will, sollte ich vor und nach dem Wort ein Leerzeichen setzen, ansonsten sind Wohnzimmerteppich oder Hundewohnzimmer auch gültig.

Ein Element des Config Arrays für die Sprachsteuerung Licht-Wohnzimmer sieht wie folgt aus:


    array(
        'REGEX1' => ' Wohnzimmer ',
        'REGEX2' => ' Licht | Lampe ',
            'COMMAND1' => array(
              'REGEX' => ' an | ein | einschalten ',
              'CODE' => '
                  HM_WriteValueBoolean(13859, "STATE", true);
              ',
              'SAY' => 'Ich habe im Wohnzimmer das Licht eingeschaltet'
          ),
            'COMMAND2' => array(
              'REGEX' => ' aus | ausschalten ',
              'CODE' => '
                  $resultcode = HM_WriteValueBoolean(13859, "STATE", false);
              ',
              'SAY' => 'Ich habe im Wohnzimmer das Licht ausgeschaltet'
      )


'REGEX1' => ' Wohnzimmer ',  

ist der erste Filter. Nun brauche ich noch zusätzlich ‚Licht‘‚ welches ich als REGEX2 eintrage.
Da ich statt Licht auch Lampe sagen möchte kann ich beide Wörter mit ODER verknüpft eintragen.
In Regulären Ausdrücken sieht das so aus:


'REGEX2' => ' Licht | Lampe ',

Jetzt kommt die Aktion „einschalten“ welche in einem neuen Array Namens COMMAND1 konfiguriert wird.
Ich muss zuerst das Aktionswort wieder als Regulärer Ausdruck konfigurieren. Ich nutze hierfür


'REGEX' => ' an | ein | einschalten ',

Wenn also die Filterkriterien Wörter von vorhin UND das COMMAND Wort vorhanden sind wird der PHP- Code unter CODE ausgeführt.
Hier können beliebige PHP Befehle eingetragen werden. Diese müssen natürlich auch mit ; getrennt werden und es dürfen keine (’) einfachen Hochkommata verwendet werden, da dies die Begrenzung für den Code ist. Doppelte (") sind aber möglich. Mit diesen PHP Code schalte ich dann z.B. meinen Aktor oder frage den Wert einer Variablen mit den bekannten IPS Kommandos ab.
Falls ich bei den Befehlen umfangreicheren Code schreiben muss, macht es evt. Sinn, diese in eine Funktion auszulagern und in CODE den Funktionsnamen aufzurufen. Später folgt dazu noch ein Beispiel. Hier schaltet der Code einen Homematic Schalter ohne Abfrage ob es geklappt hat.


'CODE' => '
                  HM_WriteValueBoolean(13859, "STATE", true);
                 ',

Der Eintrag unter SAY beinhaltet die Anwort auf die Aktion. Ich kann hier nicht nur statischen Text eingeben sondern auch Variablen verwenden. Diese Variablen können z.B. im CODE Bereich definiert worden sein. Im resultierenden Antworttext wird dann der Inhalt der Variablen eingefügt. Ein Beispiel folgt auch später.

Falls die Aktion im Array COMMAND1 mit ‚REGEX‘ => ’ an | ein | einschalten ', nicht gefunden wurde, wird das nächste Array COMMAND2 geprüft usw.
Falls es in allen COMMAND Aktionen keine Übereinstimmungen mit REGEX gibt, wird das nächste Filter/Actions Array verarbeitet.

Wenn sich in den verbleibenden Array auch keine Filter/Aktions Übereinstimmungen findet, konnte das Kommando nicht erkannt werden. In diesem Fall wird als Antwort der Klassiker „‚Nein Dave, das kann ich nicht tun!‘ zurück geliefert. :smiley:

Weiter geht es mit der Config des Bad Temperatur Beispiels.


    array(
        'REGEX1' => ' Bad ',
        'REGEX2' => ' Temperatur ',
            'COMMAND1' => array(
              'REGEX' => ' Status | welche ',
              'CODE' => '
                    $result = GetValue(21154);
                    $result = number_format($result, 1, ".", "");
              ',
              'SAY' => 'Im Bad beträgt die Temperatur $result Grad'
          ),
            'COMMAND2' => array(
               'REGEX' => ' setzen | einstellen ',
               'CODE' => '
                  $resultcode = HM_WriteValueFloat(52815, "SET_TEMPERATURE", $numbers[0]);
               ',
               'SAY' => 'Ich habe im Bad die Temperatur auf $numbers[0] Grad gestellt'
      )

Am Anfang befindet sich der bekannte Filter aus REGEX(Nr)


        'REGEX1' => ' Bad ',
        'REGEX2' => ' Temperatur ',

Wenn ich z.B. zwei Badezimmer habe, könnte ich zur Unterscheidung ‚REGEX3‘ => ’ Keller ', noch einfügen.
Die COMMAND Sequenz zur Abfrage der Temperatur ist wie folgt:


                'REGEX' => ' Status | welche ',
                'CODE' => '
                  $result = GetValue(21154);
                  $result = number_format($result, 1, ".", "");
                 ',
                'SAY' => 'Im Bad beträgt die Temperatur $result Grad'

Mein Aktionswort ist " Status " oder " Welche " (Welche Temperatur ist im Bad) oder Kurzform (Status Temperatur Bad)
Unter CODE ist ein simpler Zweiteiler. Der Variablen $result wird der Wert der IPS Temperatursensor Variablen zugewiesen. Anschliessend wird diese Float Variable nach String gewandelt mit einer Nachkommastelle, „.“ als Dezimalstelle und keinem Tausender Zeichen. Diese Variable wird dann in SAY genutzt.
Im Bad beträgt die Temperatur 23.7 Grad

Das Setzen eines Temperaturwertes (z:B. Homematic Thermostat) sieht im COMMAND Teil wie folgt aus:


            'COMMAND2' => array(
               'REGEX' => ' setzen | einstellen ',
               'CODE' => '
                  $resultcode = HM_WriteValueFloat(52815, "SET_TEMPERATURE", $numbers[0]);
               ',
               'SAY' => 'Ich habe im Bad die Temperatur auf $numbers[0] Grad gestellt'

Hier steht nicht neues ausser dem $numbers[] Array. Das $numbers Array beinhaltet alle Zahlen aus dem Kommandostring.
Wenn ich zum Beispiel den Satz:
„Wenn die Aussentemperatur unter -20,5 Grad fällt setze die Vorlauftemperatur auf 75 Grad“
finde ich in $numbers[0]=-20.5 und in $numbers[1]=75 als Float Werte. Diese kann ich dann weiter verwenden.

Der komplette Code ist hier. Er beinhaltet auch noch ein Beispiel für einen Funktionsaufruf für „Alle Lichter aus“


<?

$SpeechInputID = 59626 /*[Status\Sprachsteuerung\AndroidReceive]*/;
$SpeechOutputID = 31363 /*[Status\Sprachsteuerung\AndroidSend]*/;

$config = array(
	array(
		'REGEX1' => 'wie spät ist es',
			'COMMAND1' => array(
	   		'REGEX' => 'wie spät ist es',
	   		'CODE' => '$result = date("H")." Uhr ".date("i");',
	   		'SAY' => 'Die aktuelle Uhrzeit ist $result'
			)
	),

	array(
    	'REGEX1' => ' Wohnzimmer ',
    	'REGEX2' => ' Licht | Lampe ',
    		'COMMAND1' => array(
      		'REGEX' => ' an | ein | einschalten ',
        		'CODE' => '
         	 	HM_WriteValueBoolean(13859, "STATE", true);
         	',
        		'SAY' => 'Ich habe im Wohnzimmer das Licht eingeschaltet'
      	),
    		'COMMAND2' => array(
      		'REGEX' => ' aus | ausschalten ',
        		'CODE' => '
         	 	$resultcode = HM_WriteValueBoolean(13859, "STATE", false);
         	',
        		'SAY' => 'Ich habe im Wohnzimmer das Licht ausgeschaltet'
      	)
   ),
	array(
    	'REGEX1' => ' Bad ',
    	'REGEX2' => ' Temperatur ',
    		'COMMAND1' => array(
      		'REGEX' => ' Status | welche ',
        		'CODE' => '
         	 	$result = GetValue(21154);
         	 	$result = number_format($result, 1, ".", "");
         	',
        		'SAY' => 'Im Bad beträgt die Temperatur $result Grad'
      	),
    		'COMMAND2' => array(
      		'REGEX' => ' setzen | einstellen ',
        		'CODE' => '
         	 	$resultcode = HM_WriteValueFloat(52815, "SET_TEMPERATURE", $numbers[0]);
         	',
        		'SAY' => 'Ich habe im Bad die Temperatur auf $numbers[0] Grad gestellt'
      	)
   ),
	array(
    	'REGEX1' => ' Alle ',
    	'REGEX2' => ' Lichter ',
    		'COMMAND1' => array(
      		'REGEX' => ' aus | ausschalten ',
        		'CODE' => '
         	 	$result = MyFunctionAllLightsOff();
          	',
        		'SAY' => '$result'
      	)
   )
);

// BEGIN der eigenen Hilfsfunktionen

function MyFunctionAllLightsOff() {
	// hier schalte ich per Script alle Lichter aus
	// und liefere einen String mit der Antwort
	return "Ich habe alle Lichter ausgeschaltet";
	
	// Falls es ein Problem gab oder ich etwas anderes sagen will
	// liefere ich in Anhängigkeit einfach einen anderen String zurück.
	return "Ich habe das Licht im Klo nicht ausgeschaltet da dort jemand sitzt";
}

// ENDE der eigenen Hilfsfunktionen


// Ab hier nichts mehr ändern. (Version 1.11)

$SpeechInput = GetValueString($SpeechInputID);
SetValueString($SpeechOutputID, "");  // lösche Outputstring um bei Timingproblemen keine alten Antworten zu erhalten
IPS_LogMessage("Sprachsteuerung", 'SpeechInput=" '.$SpeechInput.' "');

// Alle Nummern aus dem InputString ermitteln. Liefert ein Array $numbers
// mit allen gefundenen Zahlen als Float-Werte oder false.
$minusspeech = array(" Minus ", " minus ", "- ");
preg_match_all("/-?\d+(,|\.)?\d*/", str_replace($minusspeech, "-",$SpeechInput), $numbers);
if(isset($numbers[0][0])) {
	$numbers = $numbers[0];
   for ($i = 0; $i < count($numbers); $i++) {
   	$numbers[$i] = floatval(str_replace(',', '.' , $numbers[$i]));
   	IPS_LogMessage("Sprachsteuerung", '  $numbers['.$i.']='.$numbers[$i]);
	}
}else {
	$numbers = false;
  	IPS_LogMessage("Sprachsteuerung", '  $numbers=false');
}

// Alle Einträge des $config Arrays werden auf Übereinstimmung mit dem Speech-Satz geprüft
$config_count = 0;
foreach ($config as $element) {
	$config_count++;
	$check_command = true;
	$answer = "";
	IPS_LogMessage("Sprachsteuerung", 'CONFIG'.$config_count);
   // Prüfe REGEX1 - REGEXxx auf Übereinstimmung
   for ($i = 1; $i < 100; $i++) {
		@$RegEx = $element['REGEX'.$i];
      if(empty($RegEx)) {
			break; // Abbruch da REGEXx Eintrag nicht vorhanden ist
		} else {
		   if(preg_match('/'.$RegEx.'/i', ' '.$SpeechInput.' ')) {
				IPS_LogMessage("Sprachsteuerung", '  REGEX'.$i.'['.$RegEx.']=true');
			} else {
				IPS_LogMessage("Sprachsteuerung", '  REGEX'.$i.'['.$RegEx.']=false');
            // Ein REGEXx Eintrag wurde nicht gefunden. Prüfung auf COMMAND wird nicht durchgeführt
				$check_command = false;
			}
      }
	}

	if($check_command == true) {
		// Alle REGEX wurden gefunden, suche jetzt nach den COMMAND Ausdrücken
      for ($i = 1; $i < 100; $i++) {
			@$RegEx = $element['COMMAND'.$i]['REGEX'];
			if(empty($RegEx)) {
				break; // Abbruch da COMMANDx Eintrag nicht vorhanden
			} else {
				if(preg_match('/'.$RegEx.'/i', ' '.$SpeechInput.' ')) {
					IPS_LogMessage("Sprachsteuerung", '    COMMAND'.$i.' REGEX['.$RegEx.']=true');
					$code = $element['COMMAND'.$i]['CODE'];
					$say = $element['COMMAND'.$i]['SAY'];
					IPS_LogMessage("Sprachsteuerung", '      Execute CODE :'.$code);
               // Script in CODE ausführen...
               eval($code);
               // Variablen in SAY auflösen...
					eval("\$say = \"$say\";");
					IPS_LogMessage("Sprachsteuerung", '      SAY : '.$say);
					$answer = $say;
				} else {
					IPS_LogMessage("Sprachsteuerung", '    COMMAND'.$i.' REGEX['.$RegEx.']=false');
				}
         }
		}
	}
	if($answer != "") break; // Abbruch da passendes Element aus Config gefunden wurde
}
// Leerer Anwortstring bedeutet nichts passendes gefunden.
if($answer == "") $answer = 'Nein Dave, das kann ich nicht tun!';
IPS_LogMessage("Sprachsteuerung", 'SpeechOutput="'.$answer.'"');
SetValueString($SpeechOutputID, $answer);

?>

Viel Spass bei der Sprachsteuerung. Ich bin mit Thiemos Android App über die Sprachsteuerung wesentlich schneller in der Bedienung von IPS als über die Menüs. Und es macht richtig Spass!

** Neue Version 1.1 **

  • Bugfix der fehlerhaften Erkennung von Zahlen.
  • Erkannte Zahlen in $numbers werden gelogged.
    ** Version 1.11 **
  • löscht Outputstring um bei Timingproblemen keine alten Antworten zu erhalten

Sprachauswertung.ips.zip (1.83 KB)

Sprachauswertung_1.1.ips.zip (1.93 KB)

Wenn ich Wert auf nette Umgangsformen (auch mit meiner Haussteuerung) lege, ist das Wort „Bitte“ bestimmt nicht fehl am Platz.

Mach bitte im Wohnzimmer das Licht an. ist dann immer gerne gehört.

Mit dem folgenden Eintrag an erster Stelle des $config Arrays reagiert IPS sehr empfindlich auf schnöde Befehle!


	array(
		'REGEX1' => '^((?!bitte).)*$',
		'COMMAND1' => array(
	   		'REGEX' => '^((?!bitte).)*$',
	   		'CODE' => ' ',
	   		'SAY' => 'Geht das auch etwas freundlicher! Wie lautet denn das Zauberwort?'
		)
	),


Und für die Trekkies ist Computer im Satz sehr wichtig!
Wie spät ist es → keine Antwort…
Computer wie spät ist es


$config = array(
	array(
		'REGEX1' => '^((?!Computer).)*$',
		'COMMAND1' => array(
	   		'REGEX' => '^((?!Computer).)*$',
	   		'CODE' => ' ',
	   		'SAY' => '  '
		)
	),
	array(
		'REGEX1' => 'wie spät ist es',
		'COMMAND1' => array(
	   		'REGEX' => 'wie spät ist es',
	   		'CODE' => '$result = date("H")." Uhr ".date("i");',
	   		'SAY' => 'Die aktuelle Sternzeit ist $result'
		)
	),

Ich sage nur…
Sehr geil :smiley:
Da eh jeder seiner Kommandos definieren muss, ist es auch sinnvoll hier einfach gleich dir Geräte direkt anzusprechen.
Das mit dem Universalschalt-Script wäre z.B. bei 1-Wire eh nicht gegangen und jeder hätte dafür individuelle Lösungen gebaut.
Michael

So, das klappt jetzt. :smiley:

Allerdings scheitere ich jetzt an SSL. Ausschalten mag ich es nicht dauerhaft und die Zertifikat-Geschichte ist nach ersten Recherchen arg umständlich (signieren lassen oder „fälschen“).

Grüße
galleto

Sprachkommando: Schalte das Licht im Wohnzimmer ein

Antwort (wenn Licht aus war): Das Licht im Wohnzimmer wurde eingeschaltet
Antwort (wenn Licht bereits an ist): Das Licht im Wohnzimmer ist bereits an
Antwort (bei Problemen mit HM): Das Licht im Wohnzimmer konnte wegen eines technischen Problems nicht geschaltet werden

Beim Ausschalten soll das Verhalten natürlich analog sein.

Folgende $config Array Konfiguration ist notwendig. Die VariablenID ist die Status-Variable z.B. STATE des Homematic Aktors welche bei „Licht an“ true und bei „Licht aus“ false ist.


	array(
    	'REGEX1' => ' Wohnzimmer ',
    	'REGEX2' => ' Licht | Lampe ',
    		'COMMAND1' => array(
      		'REGEX' => ' an | ein | einschalten ',
        		'CODE' => '
         	 	$return = HM_SetValueBoolean(29192, true);
         	',
        		'SAY' => 'Das Licht im Wohnzimmer $return'
      	),
    		'COMMAND2' => array(
      		'REGEX' => ' aus | ausschalten ',
        		'CODE' => '
         	 	$return = HM_SetValueBoolean(29192, false);
         	',
        		'SAY' => 'Das Licht im Wohnzimmer $return'
      	)
   ),

Die untere Funktion muss in das Erkennungsscript eingefügt werden.



function HM_SetValueBoolean($VariableID, $BoolValue) {
	// Suche übergeordnete Instanz zum Beschreiben
	$ParentID = IPS_GetObject($VariableID)['ParentID'];
	// Den Namen des Ident der Variablen z.B. STATE
	$ObjectIdent = IPS_GetObject($VariableID)['ObjectIdent'];
	// Prüfe aktuellen Status und vergleiche mit Zielstatus
	$CurrentState = GetValueBoolean($VariableID);
	$answer = "";
	if($CurrentState == $BoolValue) {
		// Der aktuelle Status ist gleich dem Zielstatus -> Schalten ist unnötig
		$BoolValue ? $answer = "ist bereits an" : $answer = "ist bereits aus";
		} else {
			// Schalte Instanzvariable
			if(@HM_WriteValueBoolean($ParentID, $ObjectIdent, $BoolValue)) {
				// Das Schalten war erfolgreich HM_WriteValueBoolean lieferte true
				$BoolValue ? $answer = "wurde angeschaltet" : $answer = "wurde ausgeschaltet";
			} else {
				// Homematic ist gerade unpässlich...
				$answer = "konnte wegen eines technischen Problems nicht geschaltet werden.";
			}
	}
	return $answer;
}


Das Prinzip kann natürlich für andere Hardware angepasst werden.

Super Arbeit ihr beiden, Thiemo und Heimgeist!

Ich habe das ganze soweit auch schon bei mir miteingebaut und habe aktuell noch eine Frage an Heimgeist.
Du hast in deinem letzten Post dein „Erkennungsskript“ vorgestellt anhand es Beispiels einer Lampe.

Ich bin gerade dabei das für einen Rollo zu realisieren.
Ich habe bereits anpassungn vorgenommen, da ich eine Rolladen habe prüfe ich nicht wie bei dir, ob ein Boolean-Variable true oder fals ist, sondern ob eine Integer-Variable einen bestimmten Wert hat.

Soweit eigentlich kein Problem, ich wollte nur gerade diese Zeilen umschreiben:

            if(@HM_WriteValueBoolean($ParentID, $ObjectIdent, $BoolValue)) {
                // Das Schalten war erfolgreich HM_WriteValueBoolean lieferte true
                $BoolValue ? $answer = "wurde angeschaltet" : $answer = "wurde ausgeschaltet";

Was macht den das @ vor dem „HM_WriteValue…“ genau?

Und was passiert ind er dritten Zeile genau?
Das dürfte eine verkürzte Schreibweiße auf „true“ oder „false“ mit anschiender Zuweisung sein.
Wie mache ich das am besten mit einem Integer Wert, da habe ich nicht nur „true“ und „fals“ sondern 100 für komplettt geschlossen, 0 für komplett geöffnet und zwischendrin noch verschiedenen Zwischenstellungen.

Mal eine Nacht drübergeschlafen habe ich weiter gemacht:

Ausschnitt des eigentlichen Skripts, mit den Betreffenden Stellen:


//Eltern, Rollo Wohnzimmer
	array(
    	'REGEX1' => ' Wohnzimmer ',
    	'REGEX2' => ' Rollo | Rolladen ',
    		'COMMAND1' => array(
      		'REGEX' => ' hochfahren | hoch fahren | öffnen ',
        		'CODE' => '
         	 	$return=ZW_DimSet_Integer(59922,0);
         	',
        		'SAY' => 'Der Rollo im Wohnzimmer $return'
      	),
    		'COMMAND2' => array(
      		'REGEX' => ' lamelle | lamellen stellung ',
        		'CODE' => '
         	 	$return=ZW_DimSet_Integer(59922,84);
         	',
        		'SAY' => 'Der Rollo im Wohnzimmer $return'
      	),
    		'COMMAND3' => array(
      		'REGEX' => ' runterfahren | schließen | herunter',
        		'CODE' => '
         	 	$return=ZW_DimSet_Integer(59922,100);
         	',
        		'SAY' => 'Der Rollo im Wohnzimmer $return'
      	)
   ),
	array(
    	'REGEX1' => ' Bad ',
    	'REGEX2' => ' Temperatur ',
    		'COMMAND1' => array(
      		'REGEX' => ' Status | welche ',
        		'CODE' => '
         	 	$result = GetValue(23771 /*[Objekt #23771 existiert nicht]*/);
         	 	$result = number_format($result, 1, ".", "");
         	',
        		'SAY' => 'Im Bad beträgt die Temperatur $result Grad'
      	),
    		'COMMAND2' => array(
      		'REGEX' => ' setzen | einstellen ',
        		'CODE' => '
         	 	$resultcode = HM_WriteValueFloat(52815 /*[Objekt #52815 existiert nicht]*/, "SET_TEMPERATURE", $numbers[0]);
         	',
        		'SAY' => 'Ich habe im Bad die Temperatur auf $numbers[0] Grad gestellt'
      	)
   ),
	array(
    	'REGEX1' => ' Alle ',
    	'REGEX2' => ' Lichter ',
    		'COMMAND1' => array(
      		'REGEX' => ' aus | ausschalten ',
        		'CODE' => '
         	 	$result = MyFunctionAllLightsOff();
          	',
        		'SAY' => '$result'
      	)
   )
);

Aktuell sieht das Erkennungssrkript wie folgt aus: (Anstatte Boolean mit Integer und Rollosteuerung)

//Auswertung des Status
function ZW_DimSet_Integer($VariableID, $BoolValue) {
    // Suche übergeordnete Instanz zum Beschreiben
    $ParentID = IPS_GetObject($VariableID)['ParentID'];
    // Den Namen des Ident der Variablen z.B. STATE
    $ObjectIdent = IPS_GetObject($VariableID)['ObjectIdent'];
    // Prüfe aktuellen Status und vergleiche mit Zielstatus
    $CurrentState = GetValueInteger($VariableID);
    $answer = "";
    if($CurrentState == $BoolValue) {
        // Der aktuelle Status ist gleich dem Zielstatus -> Schalten ist unnötig
        $answer = "ist bereits in dieser Stellung.";
        } else {
            // Schalte Instanzvariable
            if($CurrentState != $BoolValue) {
                // Das Schalten war erfolgreich
                switch($BoolValue) {
                
                  case 0: //Öffnen
                  ZW_DimSet(25186 /*[Fibaro Rollo Eltern Wohnzimmer]*/,0);
       				$answer = "öffnet.";
                  break;
                  
                  case 84: //Lamelle
                  ZW_DimSet(25186 /*[Fibaro Rollo Eltern Wohnzimmer]*/,84);
       				$answer = "fährt auf Lamellenstellung.";
                  break;
                  
                  case 100: //Schließen
                  ZW_DimSet(25186 /*[Fibaro Rollo Eltern Wohnzimmer]*/,100);
       				$answer = "schließt.";
                  break;
					}
                
            
            } else {
                // Das Schalten war nicht erfogreich
                $answer = "konnte wegen eines technischen Problems nicht geschaltet werden.";
            }
    }
    return $answer;
}

Soweit läuft es super, Rollo fährt je nachdem was man sagt, aber ein Problem hab ich immernoch:
(Hatte ich schon gestern)

Wenn der Rollo jetzt z.B auf Geschlossen steht (100%) und ich dann Sage „Rollo Wohnzimmer Lamelle“, dann fährt der Rollo zwar auf Lammelenstellung (84%) aber die Sprachausgabe sagt „ist bereits in dieser Stellung“, obwohl er es davor nicht war.

Das klingt meiner Meinung nach auf den ersten Blick nach einem Timingproblem, aber ich konnte keinen Fehler im Skript / in meinem Abgewandelten Modell feststellen.

an Thiemo !

Du hast mir den verregneten Sonntag sowas von gerettet :wink:

Ich kann mich Allen nur anschließen - einfach nur geil !!!

Vielen Dank für die German Design Award-verdächtige-APP

LG Tom
jetzt fehlt nur noch etwas so hochkarätiges für’s iPhone … :smiley:

Ich hätte noch einen Wunsch bezüglich der Einstellungen in der APP.
Mein IPS ist per SSL und ReverseProxy angebunden.
Darum ist die URL etwas anders z.b. sslsubdomain.domain.tdl/ips/api/
Ich hatte versucht das irgendwie in die Einstellungen zu bekommen, aber leider haut er auch ohne Port immer den Doppelpunkt in die URL.
Dann kommt das raus, was natürlich nicht geht: sslsubdomain.domain.tdl/ips:/api/
Michael

@Daste,

die meisten Fragen hast Du vermutlich schon selber beantwortet.
„@“ vor einem Befehl unterdrückt Fehlermeldungen und hat ansonsten keinen Einfluss auf die Funktion.


$BoolValue ? $answer = "wurde angeschaltet" : $answer = "wurde ausgeschaltet";

// ist die Kurzform von:

if($BoolValue == true) {
   $answer = "wurde angeschaltet";
} else {
   $answer = "wurde ausgeschaltet";
}

Da ich kein Z-Wave habe kann ich Dein Problem leider nicht nachstellen. Füge doch einfach mal ein paar IPS_LogMessage(„Sprachsteuerung“, „$CurrentState=“.$CurrentState); oder andere Variablen in Dein Script ein und versuche den Fehler durch Anzeige der Variablen Werte einzugrenzen.

Evtl. kann es aber auch sein, dass Dein Script OK ist aber Du die vorherige Antwort als aktuelle Antwort bekommst.
Das kannst Du auch in der „Meldungen“ Konsole überprüfen, welche Antwort als String gesetzt ist.

Ich habe das Problem mit den falschen (alten) Antworten auch schon mal beobachtet und daher bei der Übernahme des Inputstring den Outputstring auf leer „“ gestetzt.


// Ab hier nichts mehr ändern.

$SpeechInput = GetValueString($SpeechInputID);
SetValueString($SpeechOutputID, "");

Bei Homematic nutze ich übrigens folgendes Array und Script für die Rollosteuerung.


   array(
    	'REGEX1' => ' Bad ',
    	'REGEX2' => ' Rollo | Rolladen ',
    		'COMMAND1' => array(
      		'REGEX' => ' auf | öffnen | hoch ',
        		'CODE' => '
         	 	$return = HM_SetValueFloat(42694, 1.0);
         	',
        		'SAY' => 'Das Rollo im Bad $return'
      	),
    		'COMMAND2' => array(
      		'REGEX' => ' zu | schließen | runter ',
        		'CODE' => '
         	 	$return = HM_SetValueFloat(42694, 0.0);
         	',
        		'SAY' => 'Das Rollo im Bad $return'
      	),
      	'COMMAND3' => array(
      		'REGEX' => ' Beschatten | Schatten | Lamellenstellung ',
        		'CODE' => '
         	 	$return = HM_SetValueFloat(42694, 0.1);
         	',
        		'SAY' => 'Das Rollo im Bad $return'
      	)
   ),


function HM_SetValueFloat($VariableID, $FloatValue) {
	// Suche übergeordnete Instanz zum Beschreiben
	$ParentID = IPS_GetObject($VariableID)['ParentID'];
	// Den Namen des Ident der Variablen z.B. STATE
	$ObjectIdent = IPS_GetObject($VariableID)['ObjectIdent'];
	// Prüfe aktuellen Status und vergleiche mit Zielstatus
	$CurrentState = GetValue($VariableID);
	IPS_LogMessage("Sprachsteuerung", "Debug = ".$CurrentState);
	$answer = "";
	if($CurrentState == $FloatValue) {
		// Der aktuelle Status ist gleich dem Zielstatus -> Schalten ist unnötig
		$answer = "ist bereits in dieser Stellung";
	} else {
	   // Setze Instanzvariable auf $FloatValue Wert
	   if(@HM_WriteValueFloat($ParentID, $ObjectIdent, $FloatValue)) {
	      // Das Setzen des Wertes war erfolgreich HM_WriteValueFloat lieferte true
			// Liefere eine Antwort in Anhängigkeit des gesetzten FloatValue Wertes
			if($FloatValue == 0.0) $answer = "wurde geschlossen";
			if($FloatValue > 0.0 AND $FloatValue < 1.0) $answer = "wurde auf Beschattung gefahren";
			if($FloatValue == 1.0) $answer = "wurde geöffnet";
		} else {
			// Homematic ist gerade unpässlich...
			$answer = "konnte wegen eines technischen Problems nicht gesteuert werden.";
		}
	}
	return $answer;
}

Man ist das cool :).

Super Projekt. Vielen Dank an Thiemo für die tolle App. Ist wirklich hitverdächtig.
Als php-Script nehme ich aber, Thiemo Du magst mir verzeihen, das von Heimgeist ;). Ich denke es hat mehr potential, ist sehr gut strukturiert. Vielleicht könnte man es auch mit in die IPSLibrary integrieren.

Ich bin noch am Anfang und versuche so nach und nach meine Rollläden und Lichter einzubinden. Was ich aber auch lästig finde ist das öffnen der App und das klicken auf den Button. Ist auch in einem vorherigen Beitrag schon mal angeklungen. Bei mir soll das System auf einem in die Wand eingebautes Tablett laufen. Da ist es lästig immer erst hin zu rennen und die App zu starten.

Ich stelle mir folgendes Szenario vor:
Im Haus liegen ein oder mehrer BT-Mikrofone welche mit dem Tablett gekoppelt sind. Beim drücken auf die Sprechtaste wird Timos App gestartet und es kann der Befehl gegeben werden. Denkt Ihr sowas ist möglich. Was würde man dazu noch für Hardware oder Software (APP) benötigen. Google spuckt bei der Suche nach BT-Microfon fast nur Headsets aus. Es sollte aber schon was größeres sein.
Ich habe seit kurzem die Amazon Fire-TV. Bei der kann man direkt in die Fernbedienung sprechen. So was wäre das Richtige. Vielleicht kennt jemand von Euch entsprechende Hardware.

Danke für das Feedback. Diese Woche habe ich Zeit die App noch zu verbessern und das Script das ich verwende noch zu erweitern. Da habe ich wohl einen Fehler in der App wenn der Port leer ist dann darf natürlich kein : kommen.

Noch zur Verständis (bei mir lautet der Aufruf im Browser so):
http://10.0.0.88:82/api/
bei Dir wäre es dann so mit Bezug eines Ports?
http://sslsubdomain.domain.tdl:82/ips/api/

Dann müsste ich eigentlich noch in den Einstellungen zusätzlich eine Option mit einbauen die das /api/ enthalten hat und bei Bedarf verändert werden kann auf zB: /ips/api/ damit Du auch mit Port arbeiten kannst bei Bedarf.

Danke
LG
Thiemo