Hey I’m trying tu use the exec in a rule to execute a jq command. I’m using 1.14 of the exec binding.
Running this command in a terminal will return the label of a TV channel. sudo -u openhab /usr/bin/curl -s http://209.0.0.0:8080/rest/items/LG_TV0_Channel | /usr/bin/jq '.stateDescription.options[] | select(.value=="3_26_20_20_230_143_1") | .label'
`"20 - DIGI Sport 1 HD"`
This is the actual rule
rule “Get Channel from rest/items”
when Item WebOS_state received update then
val newValue = executeCommandLine(“sudo -u openhab /usr/bin/curl -s http://209.0.0.0:8080/rest/items/LG_TV0_Channel | /usr/bin/jq ‘.stateDescription.options | select(.value==“3_26_20_20_230_143_1”) | .label’”, 1000)
WebOS_label.postUpdate( newValue )
end
The goal will be to replace the 3_26_20_20_230_143_1 string with the value of WebOS_state.
Can somebody help me or guide me to the proper documentation? I don’t know much about codding.
Thank you!
rule "Get Channel from rest/items"
when Item WebOS_state received update
then
myText = "sudo -u openhab /usr/bin/curl -s http://209.0.0.0:8080/rest/items/LG_TV0_Channel | /usr/bin/jq ‘.stateDescription.options[] | select(.value==\"3_26_20_20_230_143_1\") | .label’"
val newValue = executeCommandLine(myText, 1000)
logInfo("test", "exec string = " + newValue)
WebOS_label.postUpdate( newValue )
end
and I get this error: 19:46:58.799 [ERROR] [untime.internal.engine.RuleEngineImpl] - Rule 'Get Channel from rest/items': An error occurred during the script execution: Couldn't invoke 'assignValueTo' for feature JvmVoid: (eProxyURI: test.rules#|::0.2.0.2.0.0::0::/1)
Note that I used the actual string in the value parameter and not the item value.
EDIT: the error was because I was missing “val” in front of “myText”
Okay, why do you expect it not to return the entire JSON?
I presume you are using the pipe | to pass the output to something else (jq?).
That works in a shell environment (the console)
It doesn’t work if there is no shell (executeCommandLine)
What are you actually trying to achieve here? It looks like something you could do in a rule.
My bad, I was thinking that the executeCommandLine runs like any command in a linux terminal.
What I’m trying to do is to get the name of the current TV channel from the webos binding.
Actually this is my problem LGWebOS Binding (for LG WebOS TVs)
I see.
I guess the binding populates that with “discovered” data from TV.
Yup, those Item options are not directly accessible from DSL rules.
You could re-jig your idea to use HTTP Action to grab the target Items JSON, then use a JSONPATH transform to recover the text you want, all in a DSL rule.
Alternatively, there may be a way to get direct access to Item option properties via new rule engine, let’s consult @5iver on that?
from core.log import logging, LOG_PREFIX#, log_traceback
LOG = logging.getLogger("{}.TEST_3".format(LOG_PREFIX))
# get a list of all state description options for an Item
LOG.warn("stateDescription.options: '{}'".format(itemRegistry.getItem("Lock_EntranceFront").stateDescription.options))
# get the state description option that matches the current state of an Item
LOG.warn("stateDescription.options that match current state: '{}'".format([option for option in itemRegistry.getItem("Lock_EntranceFront").stateDescription.options if option.value == items["Lock_EntranceFront"].toString()][0]))
# get the label of the state description option that matches the current state of an Item
LOG.warn("label: '{}'".format([option for option in itemRegistry.getItem("Lock_EntranceFront").stateDescription.options if option.value == items["Lock_EntranceFront"].toString()][0].label))
That was the problem. After some googleing I found that passing pipe to exec is not working so I made a script: #!/bin/bash
curl -s ‘http://209.0.0.0:8080/rest/items/LG_TV0_Channel’ | jq ‘.stateDescription.options | select(.value=="’$1’") | .label’
The rule now becomes:
rule “Get Channel from rest/items”
when Item WebOS_state received update
then
logInfo(“test”, "WebOS_state received: " + WebOS_state.state.toString)
val myText = "/etc/openhab2/scripts/webOs_channel.sh " + “"” + WebOS_state.state.toString + “"”
val newValue = executeCommandLine(myText, 6000)
logInfo(“test”, "command = " + myText)
logInfo(“test”, "exec = " + newValue)
WebOS_label.postUpdate( newValue )
end
jq is notorious for problem with quote and parsing from one liners like this without a full shell. jq solves this by allowing you to define your arguments and variables before wrapping them in your query.
some examples here
you can look up the --arg and --argjson functions of jq. I’ve battled this myself in the past.
I begin to wonder if you can get hold of this info directly in DSL.
I don’t have a suitable Item to try it out on, with real stateDescription options … but try this and see what you get
var sd = LG_TV0_Channel.getStateDescription
logInfo("test", "object {}", sd)
logInfo("test", "options list {}", sd.getOptions)
I thought you were asking for an NGRE example . Here is how you could get an option using the rules DSL…
rule "Test DSL rule"
when
System started
then
logWarn("Rules", "Test: Start")
var current_label
val state_description_options = Lock_EntranceFront.stateDescription.options
state_description_options.forEach[option|
if (option.value == Lock_EntranceFront.state.toString()) {
current_label = option.label
}
]
logWarn("Rules", "current_label: '{}'", current_label)
logWarn("Rules", "Test: End")
end