WebHook aus Modul dynamisch erstellen

Hallo,

ich schreibe zur Zeit ja an der Anbindung der Homebridge über WebHooks an IPS. (Apple HomeKit über IP-Symcon WebHook)

Nun habe ich folgendes vor, da man zur Zeit den WebHook immer per Hand anpassen musse, würde ich gerne ein kleines PHP Modul dafür schreiben, welches genau diese Aufgabe übernimmt, ob das so möglich ist weiß ich nicht, daher hier mal meine Überlegung…

Der WebHook wird so aufgebaut:

<?

switch ($_GET["action"]) {
    case "get":
        switch ($_GET["device"]) {
            case "TVBuero":
              echo GetValue(39504 /*[zwave-Module\WG\Stecker Büro (031)\Status]*/);
              break;
            case "Flur Temperatur":
              echo GetValue(47209 /*[zwave-Module\Rauchmelder\Z-Wave Rauch Flur (NodeID 045)\Wert\Temperature]*/);
              break;
            case "Sterne":
              echo GetValue(45652 /*[zwave-Module\WG\Z-Wave Dimmer (NodeID 043)\Status]*/);
              if($_GET["brightness"] == "1")   {
                echo GetValue(36873 /*[zwave-Module\WG\Z-Wave Dimmer (NodeID 043)\Intensität]*/);
              }
              break;
            case "Wohnzimmer Decke":
              echo GetValue(31296 /*[zwave-Module\WG\UP Wohn(035)\Status]*/);
              break;
            case "Luftfeuchtigkeit Badezimmer":
              echo GetValue(23228 /*[LCN-Module\022-ix Boden Bad\Values (0, 22)\03 Feuchte]*/);
              break;
      			case "Thermostat Balkon":
      			  if (isset($_GET["CurrentHeatingCoolingState"])) {
      			  	echo GetValue(34095 /*[zwave-Module\WG\Z-Wave Thermostat Wohn (NodeID 051)\Modus]*/);
      			  }
      			  if (isset($_GET["TargetHeatingCoolingState"])) {
      			  	echo GetValue(34095 /*[zwave-Module\WG\Z-Wave Thermostat Wohn (NodeID 051)\Modus]*/);
      			  }
      			  if (isset($_GET["CurrentTemperature"])) {
      			  	echo GetValue(19317 /*[zwave-Module\WG\Z-Wave Thermostat Wohn (NodeID 051)\Wert\Temperature]*/);
      			  }
      			  if (isset($_GET["TargetTemperature"])) {
      			  	echo GetValue(56056 /*[zwave-Module\WG\Z-Wave Thermostat Wohn (NodeID 051)\SetPoint (Heating)]*/);
      			  }
      			  break;
        }
        break;
    case "setOn":
        switch ($_GET["device"]) {
          case "TVBuero":
            ZW_SwitchMode(50077 /*[zwave-Module\WG\Stecker Büro (031)]*/, true);
            echo GetValue(39504 /*[zwave-Module\WG\Stecker Büro (031)\Status]*/);
            break;
          case "Wohnzimmer Decke":
            ZW_SwitchMode(13588 /*[zwave-Module\WG\UP Wohn(035)]*/, true);
            echo GetValue(31296 /*[zwave-Module\WG\UP Wohn(035)\Status]*/);
            break;
          case "Sterne":
            ZW_SwitchMode(54766 /*[zwave-Module\WG\Z-Wave Dimmer (NodeID 043)]*/,true);
            break;
        }
        break;
    case "setOff":
        switch ($_GET["device"]) {
          case "TVBuero":
            ZW_SwitchMode(50077 /*[zwave-Module\WG\Stecker Büro (031)]*/, false);
            echo GetValue(39504 /*[zwave-Module\WG\Stecker Büro (031)\Status]*/);
            break;
          case "Wohnzimmer Decke":
            ZW_SwitchMode(13588 /*[zwave-Module\WG\UP Wohn(035)]*/, false);
            echo GetValue(31296 /*[zwave-Module\WG\UP Wohn(035)\Status]*/);
            break;
          case "Sterne":
            ZW_SwitchMode(54766 /*[zwave-Module\WG\Z-Wave Dimmer (NodeID 043)]*/, false);
            echo GetValue(45652 /*[zwave-Module\WG\Z-Wave Dimmer (NodeID 043)\Status]*/);
            break;
        }
    case "setBrightness":
      switch ($_GET["device"]) {
        case "Sterne":
          ZW_DimSet(54766 /*[zwave-Module\WG\Z-Wave Dimmer (NodeID 043)]*/,$_GET["Intensity"]);
		  break;
        }
    case "setThermostat":
      switch ($_GET["device"]) {
        case "Thermostat Balkon":                                                 
          if (isset($_GET["State"])) {
		  	       ZW_ThermostatModeSet(46464 /*[zwave-Module\WG\Z-Wave Thermostat Wohn (NodeID 051)]*/, $_GET["State"]);
		      }
		      if (isset($_GET["TargetTemperature"])) {
		  	       ZW_ThermostatSetPointSet(46464 /*[zwave-Module\WG\Z-Wave Thermostat Wohn (NodeID 051)]*/, 1, $_GET["TargetTemperature"]);
		      }
      }  
  } 

?>

Ich würde gerne ein Modul schreiben, wo ich in einer Form alle Geräte auswählen kann, die in den WebHook intergriert werden sollen.

Also wenn ich zum Beispiel einen Thermostaten im Modul auswähle müsste folgendes im WebHook angelegt werden:

Unter dem case „get“:

      			case "Thermostat Balkon":
      			  if (isset($_GET["CurrentHeatingCoolingState"])) {
      			  	echo GetValue(34095 /*[zwave-Module\WG\Z-Wave Thermostat Wohn (NodeID 051)\Modus]*/);
      			  }
      			  if (isset($_GET["TargetHeatingCoolingState"])) {
      			  	echo GetValue(34095 /*[zwave-Module\WG\Z-Wave Thermostat Wohn (NodeID 051)\Modus]*/);
      			  }
      			  if (isset($_GET["CurrentTemperature"])) {
      			  	echo GetValue(19317 /*[zwave-Module\WG\Z-Wave Thermostat Wohn (NodeID 051)\Wert\Temperature]*/);
      			  }
      			  if (isset($_GET["TargetTemperature"])) {
      			  	echo GetValue(56056 /*[zwave-Module\WG\Z-Wave Thermostat Wohn (NodeID 051)\SetPoint (Heating)]*/);
      			  }
      			  break;

Und unter dem case „setThermostat“:

    case "setThermostat":
      switch ($_GET["device"]) {
        case "Thermostat Balkon":                                                 
          if (isset($_GET["State"])) {
		  	       ZW_ThermostatModeSet(46464 /*[zwave-Module\WG\Z-Wave Thermostat Wohn (NodeID 051)]*/, $_GET["State"]);
		      }
		      if (isset($_GET["TargetTemperature"])) {
		  	       ZW_ThermostatSetPointSet(46464 /*[zwave-Module\WG\Z-Wave Thermostat Wohn (NodeID 051)]*/, 1, $_GET["TargetTemperature"]);
		      }
      } 

Ist sowas möglich? Wenn ja hat evtl. jemand einen Ansatz für mich, wie ich anfangen müsste?

Grüße,
Kai

Hallo Kai,

im Detail kann ich Dir das so schnell auch nicht sagen, aber hier mal meine ersten Gedanken:

  • das PHP-Modul legt bei der Initialisierung einen Webhook an, dieses ist dann die Schnittstelle zur Homebridge
  • grundsätzliche Auswertung erfolgt im Modul
  • die Zielvariablen sollten nicht über das Konfigurationsformular abgebildet werden (da 1:n), sondern über die definierte Ablage von Links z.B. unterhalb der Modul-Instanz (wird so z.B. beim Alexa-Modul gemacht)
  • die Verbindung zwischen dem Gesprochenem und der Variablen muss dann (wohl) über den Namen der Variablen erfolgen

Joachim

Hierfür bietet sich dann die Listen an :slight_smile:
Die Links würde ich dann gar nicht mehr nutzen.

Draft für Listen in PHP-Modulen

Michael

Hallo,

danke für eure Antworten.
Ich verstehe eure Ansätze, weiß aber noch gar nicht damit umzugehen.
Für mich besteht noch folgendes Problem:

Woher weiß IPS dann welche Funktion genommen werden muss um das Gerät zu schalten?

Beispiel:

Ein Z-Wave Gerät wird mit einer Funktion ZW_XXX( id,„wert“) als Beispiel geschaltet, ein LCN Modul wird hier wiederum mit einer ganz anderen Funktion geschaltet. :confused:

Und wie kann ich auf die Geräte zugreifen, die dann Beispielsweise unter meiner Instanz verlinkt sind? :confused:

Vielleicht kann mir dazu ja einer von euch noch was erklären.

@Michael, die Liste gibt es ja noch gar nicht. :stuck_out_tongue:

Vielen Dank, das Ihr euch immer den Kopf zerbrecht, wenn ich wieder mit meinen komischen Fragen um die Ecke komme. :smiley:

Grüße,
Kai

…das Schreiben von Modulen hat so seine Herausforderungen![emoji6]
Da muss man fragen (dürfen)!

Was für Aktionen erforderlich sind könnte man ggf. über die GUID der Instanz managen…
Joachim

Ja, aber sie kommen :slight_smile:
Der einfachste Weg ein Gerät unbekannten Typs anzusteuern, sollte per IPS_RequestAction gehen.
Alternativ die Instanz abfragen und ermitteln um welchen Typ es sich handelt (siehe z.b. Script für ShutterControl in der Doku) und den dazugehörigen Befehl ausführen.
Michael

Ich würde für so was den Draft der Listen ausprobieren ist zumindest übersichtlicher als alles andere oder ein dynamisches Konfigurationsformular. Am besten Du ließt die verfügbaren Instanzen über die GUID aus und bestimmst dann noch anhand der Variablen der Instanz und deren Ident um was es sich genau handelt z.B. Shutter oder Lampe. Die ganzen Daten legst Du dann in einem Array ab mit Namen, Typ und ObjektID. Den Namen kannst Du ja aus dem Namen der Instanz übernehmen. Im Webhook lässt Du dann den Devicenamen übergeben und suchst dann im Array nach dem Typ und der ObjektID. Abhängig von Typ rufst Du dann die passende Funktion auf die über die ObjektId das Gerät schaltet.

Wie würde denn deiner Meinung nach dann so ein dynamisches Formular aussehen?

Meinst du da sowas mit:

Dann könnte ich da doch auch zum Beispiel das komplette Z-Wave Gerät verlinken oder nicht? Dann muss ich doch nicht die ganzen Variablen einzeln verlinken. Oder sehe ich das falsch?

Für denn Hook habe ich jetzt sowas angedacht:

Diese Funktion habe ich im Modul:

public function getSiriValue($device) {
      //hier die abfrage der werte für siri
    return $value; // zurückgegen der werte an den hook
}

Und so baue ich den Hook auf:

  $sid = $this->RegisterScript("SiriTest", "SiriTest", '<? //Do not delete or modify.
      switch ($_GET["action"]) {
        case "get":
        switch ($_GET["device"]) {
          case "TVBuero":
      echo IPSHomebridge_getSiriValue(' . $this->InstanceID . ',"wert für die funktion im modul");
        break;
        }
      }
      ', -8);
      IPS_SetHidden($sid, true);
      $this->RegisterHook('/hook/siriTest', $sid);

Grüße,
Kai

Schau Dir mal den Kodi Konfiguartor an oder Flow
Microsoft Flow Modul
Sieht im ersten Moment aus wie jedes andere Formular auch, nur mit dem Unterschied das nur das angezeigt wird was Du für notwendig erachtest, und sich die Anzeige je nachdem was auswählt wurde ändert. Trotz alledem wird ein dynamisches Konfiguartionsformular bei der Masse an Geräten schnell unübersichtlich bzw. man muss ewig scrollen, in sofern würde ich wirklich mal ein Blick auf die Listen werfen das ist in dem Fall wohl wirklich übersichtlicher. Ich habe damit aber auch noch nichts gemacht ist ja auch erst ein Draft.

Ja so was in der Art oben wählt man die Anzahl der Geräte aus und dann wird die passende Anzahl an Auswahlfeldern eingeblendet. Wobei ich das in dem Fall nicht so lösen würde. Du brauchst eher einen Button in der Testumgebung der zunächst mal die Geräte einliest. Dann generierst Du aus dem Ergebnis das Formular. Die Geräte sind dann also schon überall eingetragen. Dann machst Du vor jedem Gerät noch einen Haken für den User ob dies auch für Siri genutzt werden soll und ein Textfeld zur Eingabe des Siri Namens, den Du initial einfach mit dem Instanz Namen befüllst. Dann muss der User im Zweifelsfall nur noch Haken setzten bzw. die Namen ändern wenn er das Braucht aber nicht umständlich anfangen die Geräte einzeln ins Konfigurationsformular einzutragen.

Hallo,

die Listen kann man ja leider noch nicht verwenden, sonst hätte ich mir das schon angeschaut.

Grüße,
Kai

Dann würde die Form ja völlig explodieren, es gibt sicherlich Anlagen, die nen paar Hundert bis Tausend Geräte besitzen.

Ein Skript braucht Du ab 4.1 nicht mehr der Hook wird intern im Modul aufgerufen über die Funktion ProcessHookData


/**
 * This function will be called by the hook control. Visibility should be protected!
 */
		
protected function ProcessHookData()

Registrieren tust Du den Webhook für das Modul mit


private function RegisterHook($WebHook)
		{
  			$ids = IPS_GetInstanceListByModuleID("{015A6EB8-D6E5-4B93-B496-0D3F77AE9FE1}");
  			if(sizeof($ids) > 0)
				{
  				$hooks = json_decode(IPS_GetProperty($ids[0], "Hooks"), true);
  				$found = false;
  				foreach($hooks as $index => $hook)
					{
					if($hook['Hook'] == $WebHook)
						{
						if($hook['TargetID'] == $this->InstanceID)
  							return;
						$hooks[$index]['TargetID'] = $this->InstanceID;
  						$found = true;
						}
					}
  				if(!$found)
					{
 					$hooks[] = Array("Hook" => $WebHook, "TargetID" => $this->InstanceID);
					}
  				IPS_SetProperty($ids[0], "Hooks", json_encode($hooks));
  				IPS_ApplyChanges($ids[0]);
				}
  		}

…letzteres würde ich erst einmal ausschließen…

Es liest sich so, als ob auch Du gerade erst mit Modulen anfängst. Daher würde ich erst einmal sehen, dass Du die Kernfunktion implementierst, ggf. erst einmal ohne viel Dynamik. Die Details kommen dann später - viele Projekte scheitern an zu hohen Zielen![emoji6]

Joachim

Richtig und deshalb macht eine Liste sinn wie z.B. beim Homematic Konfigurator sonst wird das unübersichtlich wie gesagt.

Gerade selber erst das TreppenhausLicht-Modul von Symcon angesehen, dort wird das tatsächlich universell gelöst :smiley:
Manchmal sollte man erst beim Entwickler abschauen :rolleyes:

Michael

Hallo,

so vielen Dank für eure ganzen Antworten.
Das Hook Script habe ich rausgeworfen und nutze jetzt ProcessHookData(). :slight_smile:
Danke für den Einwand ist wesentlich schicker. :slight_smile:

Jetzt stellt sich mir nur noch die Frage, wenn ich das über die dynamische Form machen, so wie ich es auf dem Screenshot dargestellt habe, also einen Link auf das komplette Gerät. Wie kann ich dann anhand des Link ggf. Status oder andere Variablen abfragen? Geht das überhaupt über einen Link?

Grüße,
Kai

PS: Danke für euch Geduld. :slight_smile:

Ich versteh die Frage nicht ganz. Wenn Du in einem Konfigurationsformular eine Instanzfeld einbaust hast Du doch die die ObjektID der Instanz als Eigenschaft dann kannst Du doch mit allen Funktionen arbeiten, oder was war jetzt genau Dein Anliegen?

Hallo,
ich war einfach noch verwirrt bzgl. der verschiedenen Funktionen von z-Wave, LCN und co.
Aber ich kann ja die IPS_RequestAction nutzen, wenn ich weiß welche Variable ich ändern muss.

Da habe ich mir überlegt, ich lasse in der Konfigurationsform, sobald eine Instanz ausgewählt ist weitere Auswahlfelder anzeigen, mit den Variablen der Instanz. Da kann ich dann auswählen welche für zum Beispiel State bei einem Switch geändert werden muss, richtig?

Grüße,
Kai

Gesendet von iPhone mit Tapatalk