Variable extensions, GET, PUT and POST in one HTTP binding?

I have a question about the possibilities for very flexible use cases of the HTTP binding.
Background:
I have a HTTP binding for Rademacher Homepilot in the style of this discussion thread. The general Thing config is:

Thing http:url:HomePilot "HomePilot" [
    baseURL="http://<HomePilotIP>", 
    authMode="BASIC",
    ignoreSSLErrors="true",
    refresh=5,
    commandMethod="PUT",
    stateMethod="GET",
    contentType="application/json",
    timeout=3000,
    bufferSize=2048,
    delay=
] 

and with this, the channels are working very well; reading values and statuses with GET and commanding actuators / changing setpoints with PUT - all as JSON / REST API - is fine with far above 200 channels.

Now, I found something new (with Wireshark and some intuition :wink: ): How to trigger scenes in the HomePilot. Works fine with this example:

var HTTP = Java.type("org.openhab.core.model.script.actions.HTTP");
var url = "http://<HomePilotIP>/scenes/<mySID>/actions";
var content = "application/json";
var cmd = "{\"request_type\":\"EXECUTESCENE\", \"trigger_event\":\"TRIGGER_SCENE_MANUALLY_EVT\"}"
var result = HTTP.sendHttpPostRequest(url, content, cmd, 10*1000);

The SID (Scene ID) and the corresponding full name strings of the scenes can be found in a big JSON when requesting just http://<HomePilotIP>/scenes.

Yeah, well noted:

  • This command needs a POST method. Not GET or PUT as all of the other channels.
  • Scenes are stateless. Nothing to read there, not even an address.
  • The command to be sent is always the same. The SID to identify the scene is part of the URL only.

Okay. Nothing is blocked, but not really nice. In a rainbow-color-unicorn-farm ideal world, I would imagine this solution:

  • One write-only String channel “Activate Scene” is added to the Thing configuration.
  • A sendCommand with the full string-name of the scene triggers reading http://<HomePilotIP>/scenes (only once per command!), the resulting JSON is searched for this string
  • The SID found corresponding to this string is used to dynamically build the commandExtension, and the command mentioned above is being POSTed to this address (although all other channels use GET and PUT).

Less ideal, say only pony-farm ideal world, but still nice would be at least:

  • defining a global function, callable from all scripts and rules
  • it takes the scene name (or maybe only the SID) as argument
  • the rest (HomePilot IP, command definition etc.) is defined at only one place and does the trick independent from the Thing.

These are some ideas to sketch what would please me from the clean code / reusable code / ease of use point of view. I have read quite a few forum pages which make me think that it’s very probable that dynamic commandExtensions, POST method in a GET / PUT configuration, by-demand-polling of the scene list, global functions and passing outside arguments to scripts may at least be very difficult.

I would be very interested to know and discuss how close we could get to these ideas. :slight_smile:

The unicorn case isn’t going to happen without rules. But using a String Item that triggers a rule, you can implement all of the rest in the rule no problem using the sendHttpPutRequest Action.

The pony case is also realizable with some restrictions depending on the rules language:

  • Rules DSL: Scripts call with the callScript Action cannot return anything
  • Blockly: You have to be reasonably advanced to create a Blockly Library, knowledgeable in both Blockly and JS Scripting
  • jRuby, JS Scripting (either variety), Groovy and Java Rule both support standard libraries
1 Like

:smiley: quote=“rlkoshak, post:2, topic:150353”]
The unicorn case isn’t going to happen without rules. But using a String Item that triggers a rule, you can implement all of the rest in the rule no problem using the sendHttpPutRequest Action.
[/quote]

Wow, nice idea! :+1:So it’s just one general rule and this is triggered by the string Item being updated… theoretically even another item for a return value, if any required, would be possible.

It’ll take some time, but as soon as I have something like this working, I’ll share it at this place! :slight_smile:

UPDATE

Weeeell… that went way better than expected. I just wanted to gite it a quick try. It’s working.:smiley:

val HomePilotIP = "192.168.1.5";
val timeout = 3000;
var sceneName = HomePilot_Scene_Trigger.state.toString;
var searchString = "$.scenes[?(@.name==\"" + sceneName + "\")].sid";
var JsonSceneMap = sendHttpGetRequest("http://" + HomePilotIP + "/v4/scenes", timeout);
var SID = transform("JSONPATH", searchString, JsonSceneMap);
var url = "http://" + HomePilotIP + "/scenes/" + SID + "/actions";
var cmd = "{\"request_type\":\"EXECUTESCENE\", \"trigger_event\":\"TRIGGER_SCENE_MANUALLY_EVT\"}"
var result = sendHttpPostRequest(url, "application/json", cmd, timeout);

With this in a rule which triggers on any update on HomePilot_Scene_Trigger, a String item, it actually triggers the scene by its written clear name in the HomePilot. Very, very cool. Thanks a lot!!!