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.
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.
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