{"id":1023,"date":"2021-11-28T12:53:21","date_gmt":"2021-11-28T10:53:21","guid":{"rendered":"https:\/\/www.gressly.ch\/?page_id=1023"},"modified":"2021-12-12T17:10:05","modified_gmt":"2021-12-12T15:10:05","slug":"gerate-mit-rest-api-steuern","status":"publish","type":"page","link":"https:\/\/www.gressly.ch\/index.php\/openhab\/gerate-mit-rest-api-steuern\/","title":{"rendered":"Ger\u00e4te mit REST API steuern"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">HTTP JSON lesen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Hat ein Ger\u00e4t kein Binding und kann somit nicht einfach als Thing importiert werden muss man eine andere L\u00f6sung finden. Falls das Ger\u00e4t eine HTTP Schnittstelle aufweist, kann man das mit einem <em>HTTP URL Thing<\/em> l\u00f6sen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dazu unter Einstellungen-Things auf das Pluszeichen klicken und das <strong>HTTP Binding<\/strong> w\u00e4hlen. Anschliessend Name w\u00e4hlen, URL des Ger\u00e4tes eintragen und die Refresh Time definieren.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"776\" src=\"https:\/\/www.gressly.ch\/wp-content\/uploads\/2021\/11\/image-2-1024x776.png\" alt=\"\" class=\"wp-image-1027\" srcset=\"https:\/\/www.gressly.ch\/wp-content\/uploads\/2021\/11\/image-2-1024x776.png 1024w, https:\/\/www.gressly.ch\/wp-content\/uploads\/2021\/11\/image-2-300x227.png 300w, https:\/\/www.gressly.ch\/wp-content\/uploads\/2021\/11\/image-2-768x582.png 768w, https:\/\/www.gressly.ch\/wp-content\/uploads\/2021\/11\/image-2.png 1053w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Anschliessend braucht es <strong>Channels <\/strong>die man hinzuf\u00fcgen muss. In der Registerkarte Channels auf Add Channel kreiert genau dies.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"865\" src=\"https:\/\/www.gressly.ch\/wp-content\/uploads\/2021\/11\/image-3-1024x865.png\" alt=\"\" class=\"wp-image-1031\" srcset=\"https:\/\/www.gressly.ch\/wp-content\/uploads\/2021\/11\/image-3-1024x865.png 1024w, https:\/\/www.gressly.ch\/wp-content\/uploads\/2021\/11\/image-3-300x253.png 300w, https:\/\/www.gressly.ch\/wp-content\/uploads\/2021\/11\/image-3-768x649.png 768w, https:\/\/www.gressly.ch\/wp-content\/uploads\/2021\/11\/image-3.png 1048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Hier mein Beispiel welches die Wassertemperatur von meinem Warmwasserboiler liest. Wichtig ist einerseits die <em>State URL extension<\/em>, welche der IP-Adresse vom Ger\u00e4t angef\u00fcgt wird. Dies dient dazu, dass der HTTP-Aufruf das gew\u00fcnschte Resultat zur\u00fcck liefert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bei mir ist das also <em>http:\/\/192.168.178.113\/getval.json<\/em> welches dieses Resultat liefert (vereinfacht):<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">{\t\n\t\"DATETIME\": \"Sun, 2021-11-28 12:37:07\",\n\t\"MODBUS_VAL_OPERATING_TIME\": \"313 days 17 hours 40 min.\",\n\t\"MODBUS_VAL_STATUS\": \"0\",\n\t\"MODBUS_VAL_HEATER_LOAD\": \"0\",\n\t\"MODBUS_VAL_TEMPERATURE_SENSOR0\": \"42\"\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><br>Nun muss aus der Antwort nur noch der gew\u00fcnschte Wert gelesen werden. Bei mir ist die Antwort ein JSON-String. Um einen Wert aus vielen zu extrahieren, verwendet man die <em>State Transformation<\/em>. Da wird mit <strong>JSONPATH:$.PFAD_ZUM_WERT<\/strong> automatisch der Wert aus dem JSON geholt.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">HTTP PUT mit Wert in URL<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Um einen Wert an das Ger\u00e4t zur\u00fcckzusenden muss man erst einmal den <strong>Read\/Write Mode<\/strong> auf <strong>Read\/Write<\/strong> stellen oder, falls nur schreiben erw\u00fcnscht ist nat\u00fcrlich auf <strong>Write Only<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Je nach Ger\u00e4t, das man steuern will, muss man nun die korrekte Art Informationen zu senden w\u00e4hlen. Wenn das zu steuernde Ger\u00e4t HTTP PUT mit Wert in der URL erfordert, dann geht man so vor: In der <strong>Command URL Extension<\/strong> die URL definieren, nur dass man f\u00fcr den eigentlichen Wert einen Platzhalter einf\u00fcgt. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Z.B. licht?status=%2$s<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So wird dann der Wert, den man mit dem Item verbindet, in die URL \u00fcbernommen. Dabei gibt es 2 verschiedene Platzhalter.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>%1$<\/td><td>Aktuelles Datum mit Zeit<\/td><\/tr><tr><td>%2$<\/td><td>Der gesetzte Wert des Items. Dieser ist je nach Item-Typ anders . Details dazu findet man <a rel=\"noreferrer noopener\" href=\"https:\/\/www.openhab.org\/addons\/bindings\/http\/\" target=\"_blank\">hier<\/a>.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">HTTP PUT mit JSON Payload<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Es gibt jedoch Ger\u00e4te, die man nicht wie oben beschrieben mit der URL steuert. Man muss den Wert im Payload senden, also im eigentlichen Body der Request. Nehmen wir also mal an ein Ger\u00e4t braucht ein HTTP PUT Request mit einem JSON als Inhalt. Folgendes Beispiel w\u00fcrde eine Lampe einschalten:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">{\n  LICHT=1\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Nun gibt es keine Transformation, die man analog wie oben mit Platzhaltern einsetzen kann. Man kann sich hier mit einem Trick behelfen indem man eine Map ablegt. Man erstellt also eine Datei im <strong>\/etc\/openhab\/transformations<\/strong> Verzeichnis. Z.B. <strong>licht.map<\/strong> mit diesem Inhalt:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ON: { LICHT=1 }\nOFF: { LICHT=0 }<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Dann f\u00fcgt man bei <strong>Command Transformation<\/strong> folgendes ein:<strong> MAP:licht.map<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Rule mit HTTP PUT<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Um periodisch eine HTTP PUT Request mit Payload zum Ger\u00e4t zu senden, habe ich eine <strong>Rule <\/strong>erstellt. Mein Ger\u00e4t muss diesen Befehl immer wieder erhalten, sonst wird die Steuerung wieder deaktiviert. Daher ist ein einmaliges Schreiben \u00fcber den Channel nicht wirksam. <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"732\" height=\"510\" src=\"https:\/\/www.gressly.ch\/wp-content\/uploads\/2021\/12\/image-1.png\" alt=\"\" class=\"wp-image-1075\" srcset=\"https:\/\/www.gressly.ch\/wp-content\/uploads\/2021\/12\/image-1.png 732w, https:\/\/www.gressly.ch\/wp-content\/uploads\/2021\/12\/image-1-300x209.png 300w\" sizes=\"auto, (max-width: 732px) 100vw, 732px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Der Soll-Wert den ich schreiben will, wird durch ein neues <strong>Item <\/strong>vom Typ Number dargestellt. Diesen kann ich auf einer <strong>Page <\/strong>mit einem <strong>Stepper <\/strong>oder <strong>Slider <\/strong>einfach ver\u00e4ndern. <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"753\" height=\"468\" src=\"https:\/\/www.gressly.ch\/wp-content\/uploads\/2021\/12\/image.png\" alt=\"\" class=\"wp-image-1074\" srcset=\"https:\/\/www.gressly.ch\/wp-content\/uploads\/2021\/12\/image.png 753w, https:\/\/www.gressly.ch\/wp-content\/uploads\/2021\/12\/image-300x186.png 300w\" sizes=\"auto, (max-width: 753px) 100vw, 753px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Alle 5 Sekunden, f\u00fchrt die Rule dieses <strong>DSL-Script <\/strong>aus:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">var stepWrite = HeaterStepSetter.state;\nvar json = '{ MODBUS_CMD_SET_HEATER_STEP:'+stepWrite+' }';\nHTTP.sendHttpPutRequest('http:\/\/192.168.178.113', 'application\/json', json, 1000);<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Der Wert wird im Script in ein JSON verpackt und anschliessend als Payload zum Ger\u00e4t gesendet. So wird das Ger\u00e4t entsprechend gesteuert und der gew\u00fcnschte Wert ver\u00e4ndert.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>HTTP JSON lesen Hat ein Ger\u00e4t kein Binding und kann somit nicht einfach als Thing importiert werden muss man eine andere L\u00f6sung finden. Falls das Ger\u00e4t eine HTTP Schnittstelle aufweist, kann man das mit einem HTTP URL Thing l\u00f6sen. Dazu unter Einstellungen-Things auf das Pluszeichen klicken und das HTTP Binding w\u00e4hlen. Anschliessend Name w\u00e4hlen, URL des Ger\u00e4tes eintragen und die Refresh Time definieren. Anschliessend braucht es Channels die man hinzuf\u00fcgen muss. In der Registerkarte Channels auf Add Channel kreiert genau dies. Hier mein Beispiel welches die Wassertemperatur von meinem Warmwasserboiler liest. Wichtig ist einerseits die State URL extension, welche der IP-Adresse vom Ger\u00e4t angef\u00fcgt wird. Dies dient dazu, dass der HTTP-Aufruf das gew\u00fcnschte Resultat zur\u00fcck liefert. Bei mir ist das also http:\/\/192.168.178.113\/getval.json welches dieses Resultat liefert (vereinfacht): { &#8220;DATETIME&#8221;: &#8220;Sun, 2021-11-28 12:37:07&#8221;, &#8220;MODBUS_VAL_OPERATING_TIME&#8221;: &#8220;313 days 17 hours 40 min.&#8221;, &#8220;MODBUS_VAL_STATUS&#8221;: &#8220;0&#8221;, &#8220;MODBUS_VAL_HEATER_LOAD&#8221;: &#8220;0&#8221;, &#8220;MODBUS_VAL_TEMPERATURE_SENSOR0&#8221;: &#8220;42&#8221; } Nun muss aus der Antwort nur noch der gew\u00fcnschte Wert gelesen werden. Bei mir ist die Antwort ein JSON-String. Um einen Wert aus vielen zu extrahieren, verwendet man die State Transformation. Da wird mit JSONPATH:$.PFAD_ZUM_WERT automatisch der Wert aus dem JSON geholt. HTTP PUT mit Wert in URL Um einen Wert an das Ger\u00e4t zur\u00fcckzusenden muss man erst einmal den Read\/Write Mode auf Read\/Write stellen oder, falls nur schreiben erw\u00fcnscht ist nat\u00fcrlich auf Write Only. Je nach Ger\u00e4t, das man steuern will, muss man nun die korrekte Art Informationen zu senden w\u00e4hlen. Wenn das zu steuernde Ger\u00e4t HTTP PUT mit Wert in der URL erfordert, dann geht man so vor: In der Command URL Extension die URL definieren, nur dass man f\u00fcr den eigentlichen Wert einen Platzhalter einf\u00fcgt. Z.B. licht?status=%2$s So wird dann der Wert, den man mit dem Item verbindet, in die URL \u00fcbernommen. Dabei gibt es 2 verschiedene Platzhalter. %1$ Aktuelles Datum mit Zeit %2$ Der gesetzte Wert des Items. Dieser ist je nach Item-Typ anders . Details dazu findet man hier. HTTP PUT mit JSON Payload Es gibt jedoch Ger\u00e4te, die man nicht wie oben beschrieben mit der URL steuert. Man muss den Wert im Payload senden, also im eigentlichen Body der Request. Nehmen wir also mal an ein Ger\u00e4t braucht ein HTTP PUT Request mit einem JSON als Inhalt. Folgendes Beispiel w\u00fcrde eine Lampe einschalten: { LICHT=1 } Nun gibt es keine Transformation, die man analog wie oben mit Platzhaltern einsetzen kann. Man kann sich hier mit einem Trick behelfen indem man eine Map ablegt. Man erstellt also eine Datei im \/etc\/openhab\/transformations Verzeichnis. Z.B. licht.map mit diesem Inhalt: ON: { LICHT=1 } OFF: { LICHT=0 } Dann f\u00fcgt man bei Command Transformation folgendes ein: MAP:licht.map Rule mit HTTP PUT Um periodisch eine HTTP PUT Request mit Payload zum Ger\u00e4t zu senden, habe ich eine Rule erstellt. Mein Ger\u00e4t muss diesen Befehl immer wieder erhalten, sonst wird die Steuerung wieder deaktiviert. Daher ist ein einmaliges Schreiben \u00fcber den Channel nicht wirksam. Der Soll-Wert den ich schreiben will, wird durch ein neues Item vom Typ Number dargestellt. Diesen kann ich auf einer&#46;&#46;&#46;<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":695,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1023","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.gressly.ch\/index.php\/wp-json\/wp\/v2\/pages\/1023","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gressly.ch\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.gressly.ch\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.gressly.ch\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gressly.ch\/index.php\/wp-json\/wp\/v2\/comments?post=1023"}],"version-history":[{"count":15,"href":"https:\/\/www.gressly.ch\/index.php\/wp-json\/wp\/v2\/pages\/1023\/revisions"}],"predecessor-version":[{"id":1077,"href":"https:\/\/www.gressly.ch\/index.php\/wp-json\/wp\/v2\/pages\/1023\/revisions\/1077"}],"up":[{"embeddable":true,"href":"https:\/\/www.gressly.ch\/index.php\/wp-json\/wp\/v2\/pages\/695"}],"wp:attachment":[{"href":"https:\/\/www.gressly.ch\/index.php\/wp-json\/wp\/v2\/media?parent=1023"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}