Exec 2 Binding: how to execute a script and use the execution result?

Hi all,
I have a question regarding the usage of Exec 2 Binding. Suppose I have a script that receives a command (“ON” or “OFF”), controls a device (turns it on or off) and returns the execution result - the actual state of the device (again “ON” or “OFF”). The device can go offline or some errors could occur, so the command may fail and after receiving an “ON” command the script could actually return an “OFF” value and vice versa. It would be great if I could create an openHAB configuration where:

  • a Switch changes it’s state when the user clicks on it;
  • the script gets called and the state of the Switch is passed to it as an argument (“ON” or “OFF”) (Exec input channel is used);
  • the script tries to turn on or off the the device and returns the result (“ON” or “OFF”) (I suppose Exec output channel must be used);
  • the state of the Switch is updated according to the state returned from the script.

So basically the user clicks/taps on a Switch an if an error occurs the state of the Switch will not change. If everything is fine the Switch will change it’s state and the user can be sure the command succeeded.
I know that periodic polling of the actual device state could be used but that is not desired for many reasons.

Any help would be greatly appreciated.

You will want to use Rules and Design Pattern: Proxy Item.

  • Create a proxy Item that represents your Light switch’s state to OH

  • Continue to use the Exec binding or use executeCommandLine in a rule to call your script, I’ll assume you continue to use the Exec binding

  • Rules that get triggered when the Proxy Item receives a command and when the Item linked to the output channel receives an update

rule "Proxy Item received command"
when
    Item MySwitchProxy received command
then
    MySwitchInput.sendCommand(receivedCommand) // set the argument to the script, I think this kicks off the script if not
    MySwitch.sendCommand(ON) // trigger the script to run
end

rule "Process result from script"
when
    Item MySwitchOutput received update
then
    if(MySwitchOutput.state != MySwitchProxy.state) MySwitchProxy.postUpdate(MySwitchOutput.state)
end

If you use executeCommandLine you can do it all in one Rule

rule "Proxy Item received command"
when
    Item MySwitchProxy received command
then
    val result = executeCommandLine("/path/to/script " + receivedCommand, 1000)
    if(result != MySwitchProxy.state.toString) MySwitchProxy.postUpdate(result)
end
1 Like

I have tried this solution and it works great! Thank you, rlkoshak.
I see that Rules support in openHAB makes it really flexible.

Have you ever considered that adding such functionality to Exec 2 Binding would be very useful? I mean something like an input_output Channel. It could accept a command from an Item and return the result that could be applied back to the Item.

I think that such usage scenario is typical for scripts and command-line apps: provide input data, execute, receive and use output data.

The binding is designed to provide the result in a separate channel on purpose. It would be very difficult to provide a solution that would be generic because most of the time what the script returns is not compatible with the Switch Item that triggered the script to run in the first place.

Of course the solution must be generic. It could be something like this:

Thing exec:command:thing_1 [command="my_script"]
Switch item_1 {channel="exec:command:thing_1:input_output:input"}
String item_2 {channel="exec:command:thing_1:input_output:output"}

Here both item_1 and item_2 use the same input_output channel. item_1 provides input parameters to the command (script) and item_2 uses the output of the command (script).

And using the same item for input/ouput could possibly be done like this:

Switch item_1 {channel="exec:command:thing_1:input_output"}