Concatenate inside exec command

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.

You could set up Jython and the helper libraries manually…

https://openhab-scripters.github.io/openhab-helper-libraries/index.html

… or copy an add-on to your $OPENHAB_HOME/addons/ directory…

If you have any questions, just ask!

1 Like

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 :slightly_smiling_face:. 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
1 Like

It’s also possible to run it in a shell if you pass the command to a shell. For example:

    val myText = "bash -c 'sudo -u openhab /usr/bin/curl... | /usr/bin/jq \..."

Though I would still recommend using a shell script like you have done already. As mentioned, getting the quotes right and all the escaping becomes challenging. But I wanted to mention that it is possible to run commands in a shell so you can get pipes and redirects and such.

NOTE: There is no reason to sudo -u openhab, it’ll already be running as user openhab.

I don’t know how to use your example.
I tried

rule "Test DSL rule"
when
    System started
then
    logWarn("Rules", "Test: Start")

    var current_label
    val state_description_options = WebOS.stateDescription.options

    state_description_options.forEach[option|
        if (option.value == WebOS_state.state.toString()) {
            current_label = option.label
        }
    ]
    logWarn("Rules", "current_label: '{}'", current_label)

    logWarn("Rules", "Test: End")
end

where WebOS is like this, but with a lot more value/ label lines

{
  "link": "http://209.0.0.0:8080/rest/items/LG_TV0_Channel",
  "state": "3_24_57_57_212_321_1",
  "stateDescription": {
    "pattern": "%s",
    "readOnly": false,
    "options": [
      {
        "value": "3_14_56_56_103_320_1",
        "label": "56 - Travel"
      },
      {
        "value": "3_24_57_57_212_321_1",
        "label": "57 - Travel Channel HD"
      }
    ]
  },
  "commandDescription": {
    "commandOptions": [
      {
        "command": "3_14_56_56_103_320_1",
        "label": "56 - Travel"
      },
      {
        "command": "3_24_57_57_212_321_1",
        "label": "57 - Travel Channel HD"
      }
    ]
  },
  "editable": false,
  "type": "String",
  "name": "LG_TV0_Channel",
  "label": "Channel",
  "tags": [
  ],
  "groupNames": [ 
  ]
}

And WebOS_state is 3_24_57_57_212_321_1 so the output should be “57 - Travel Channel HD”

log says
14:20:14.218 [INFO ] [smarthome.event.ItemStateChangedEvent] - WebOS_state changed from 3_12_95_95_101_412_1 to 3_24_57_57_212_321_1
14:20:15.020 [WARN ] [.eclipse.smarthome.model.script.Rules] - Test: Start
14:20:15.023 [INFO ] [g.eclipse.smarthome.model.script.test] - WebOS_state received: 3_24_57_57_212_321_1
14:20:15.072 [WARN ] [.eclipse.smarthome.model.script.Rules] - current_label: '{}'
14:20:15.082 [WARN ] [.eclipse.smarthome.model.script.Rules] - Test: End

How about this?

rule "Test DSL rule"
when
    Item WebOS_state changed
then
    logWarn("Rules", "Test: Start")
    logWarn("Rules", "WebOS_state changed: {}", WebOS_state.state)

    var current_label
    val state_description_options = WebOS_state.stateDescription.options

    state_description_options.forEach[option|
        if (option.value == WebOS_state.state.toString()) {
            current_label = option.label
        }
    ]
    logWarn("Rules", "current_label: '{}'", current_label)

    logWarn("Rules", "Test: End")
end

Still not working

16:38:57.942 [WARN ] [.eclipse.smarthome.model.script.Rules] - Test: Start
16:38:57.965 [WARN ] [.eclipse.smarthome.model.script.Rules] - WebOS_state changed: 3_3_22_22_233_153_1
16:38:57.982 [WARN ] [.eclipse.smarthome.model.script.Rules] - current_label: '{}'
16:38:57.994 [WARN ] [.eclipse.smarthome.model.script.Rules] - Test: End

I don’t think you want the quotes around the curly braces in the logInfo

I have removed the quotes
logWarn("Rules", "current_label: {}", current_label)

log is the same
17:37:38.854 [WARN ] [.eclipse.smarthome.model.script.Rules] - current_label: {}

Try some more logging…

rule "Test DSL rule"
when
    Item WebOS_state changed
then
    logWarn("Rules", "Test: Start")
    logWarn("Rules", "WebOS_state changed: {}", WebOS_state.state)

    var current_label
    val state_description_options = WebOS_state.stateDescription.options
    logWarn("Rules", "state_description_options: {}", state_description_options)

    state_description_options.forEach[option|
        logWarn("Rules", "option: {}", option)
        if (option.value == WebOS_state.state.toString()) {
            current_label = option.label
        }
    ]
    logWarn("Rules", "current_label: {}", current_label)

    logWarn("Rules", "Test: End")
end

That’s a bit curious; in a logInfo() curly braces get replaced with the object following. Importantly, the curly braces do not themselves appear in the output.
Looks like that doesn’t work with logWarn.

Let’s spell it out
logInfo(“test”, "result " + current_label.toString)

This…

logWarn("Rules", "'{}'", null)

… logs…

2020-10-06 11:06:55.079 [WARN ] [org.eclipse.smarthome.model.script.Rules] - '{}'

And this…

logWarn("Rules", "'{}'", "test")

… logs this…

2020-10-06 11:10:23.548 [WARN ] [org.eclipse.smarthome.model.script.Rules] - 'test'

There is no issue using single quotes around your curly brackets, but when your logging null, it looks odd.

18:20:16.979 [WARN ] [.eclipse.smarthome.model.script.Rules] - state_description_options: []
18:20:17.358 [INFO ] [smarthome.event.ItemStateChangedEvent] - WebOS_state changed from 3_12_92_92_101_390_1 to 3_3_93_93_233_401_1
18:20:17.359 [WARN ] [.eclipse.smarthome.model.script.Rules] - current_label: {}
18:20:17.379 [WARN ] [.eclipse.smarthome.model.script.Rules] - Test: End

That’s missing one of the logs… maybe two

What Channel is WebOS_state linked to? Maybe provide all of your Harmony Hub Item definitions?

Never mind… I just scrolled up. It looks like this rule shoujld be using the LG_TV0_Channel Item instead of WebOS_state.

This is the item definition

String LG_TV0_Channel "Channel [%s]"         { channel="lgwebos:WebOSTV:tv1:channel" }
Number LG_TV0_ChannelDummy "ChannelUpDown"

String LG_TV0_Application "Application [%s]" { channel="lgwebos:WebOSTV:tv1:appLauncher"}
String LG_TV0_Application_Name "Application [%s]"

String WebOS        "JSON [%s]"     {http="<[WebOS:1000:JSONPATH($..*)]"}
String WebOS_state  "State [%s]"    {http="<[WebOS:1000:JSONPATH($.state)]"}
String WebOS_label  "Channel [%s]"

And this is the log

18:37:34.919 [WARN ] [.eclipse.smarthome.model.script.Rules] - Test: Start
18:37:34.916 [INFO ] [smarthome.event.ItemStateChangedEvent] - WebOS changed from ["http://209.12.145.41:8080/rest/items/LG_TV0_Channel", "3_17_94_94_202_410_1", "{pattern=%s, readOnly=false, options=[{"value":"0_2_1_0_2_0_0","label":"1 - S 02"},{"value":"0_4_3_0_4_0_0","label":"3 - S 03"},{"value":"0_6_5_0_6_0_0","label":"5 - S 04"},{"value":"0_8_7_0_8_0_0","label":"7 - S 05"},{"value":"0_10_9_0_10_0_0","label":"9 - S 06"},{"value":"0_12_11_0_12_0_0","label":"11 - S 08"},{"value":"0_14_13_0_14_0_0","label":"13 - S 09"},..........................and more lines
18:37:34.942 [WARN ] [.eclipse.smarthome.model.script.Rules] - WebOS_state changed: 3_3_93_93_233_401_1
18:37:35.346 [WARN ] [.eclipse.smarthome.model.script.Rules] - state_description_options: []
18:37:35.372 [WARN ] [.eclipse.smarthome.model.script.Rules] - current_label: {}
18:37:35.388 [WARN ] [.eclipse.smarthome.model.script.Rules] - Test: End

Maybe this helps
openhab> smarthome:status LG_TV0_Channel
3_3_93_93_233_401_1

openhab> smarthome:status WebOS_state
3_3_93_93_233_401_1

openhab> smarthome:status WebOS
["http://209.12.145.41:8080/rest/items/LG_TV0_Channel", "3_3_93_93_233_401_1", "{pattern=%s, readOnly=false, options=[{"value":"0_2_1_0_2_0_0","label":"1 - S 02"},{"value":"0_4_3_0_4_0_0","label":"3 - S 03"},{"value":"0_6_5_0_6_0_0","label":"5 - S 04"},{"value":"0_8_7_0_8_0_0","label":"7 - S 05"},{"value":"0_10_9_0_10_0_0","label":"9 - S 06"},{"value":"0_12_11_0_12_0_0","label":"11 - S 08"},{"value":"0_14_13_0_14_0_0","label":"13 - S 09"},{"value":"0_16_15_0_16_0_0","label":"15 - S 10"}......................

WebOS_state and LG_TV0_Channel output the same string. I will stop using WebOS_state item because is confusing

It worked!
Thanks Scott!

I changed the rule like this:

rule "Test DSL rule"
when
    Item LG_TV0_Channel changed
then
    logWarn("Rules", "Test: Start")
    logWarn("Rules", "LG_TV0_Channel changed: {}", LG_TV0_Channel.state)
    var current_label
    val state_description_options = LG_TV0_Channel.stateDescription.options
    logWarn("Rules", "state_description_options: {}", state_description_options)
    state_description_options.forEach[option|
        logWarn("Rules", "option: {}", option)
        if (option.value == LG_TV0_Channel.state.toString()) {
            current_label = option.label
        }
    ]
    logWarn("Rules", "current_label: {}", current_label)
    logWarn("Rules", "Test: End")
end

and the log is:

19:07:07.596 [WARN ] [.eclipse.smarthome.model.script.Rules] - Test: Start
19:07:07.615 [WARN ] [.eclipse.smarthome.model.script.Rules] - LG_TV0_Channel changed: 3_3_22_22_233_153_1
19:07:07.683 [WARN ] [.eclipse.smarthome.model.script.Rules] - state_description_options: [StateOption [value=0_2_1_0_2_0_0, label=1 - S 02], StateOption [value=0_4_3_0_4_0_0, label=3 - S 03]..............................................
19:07:07.720 [WARN ] [.eclipse.smarthome.model.script.Rules] - option: StateOption [value=0_2_1_0_2_0_0, label=1 - S 02]
19:07:07.735 [WARN ] [.eclipse.smarthome.model.script.Rules] - option: StateOption [value=0_4_3_0_4_0_0, label=3 - S 03]
19:07:07.749 [WARN ] [.eclipse.smarthome.model.script.Rules] - option: StateOption [value=0_6_5_0_6_0_0, label=5 - S 04]

it iterates all the values

19:07:10.187 [WARN ] [.eclipse.smarthome.model.script.Rules] - option: StateOption [value=3_8_17398_1014_238_2518_1, label=1014 - Realitatea FM]
19:07:10.195 [WARN ] [.eclipse.smarthome.model.script.Rules] - option: StateOption [value=3_11_17399_1015_251_2510_1, label=1015 - Radio Maria Ro]
19:07:10.203 [WARN ] [.eclipse.smarthome.model.script.Rules] - current_label: 22 - DIGI Sport 2 HD
19:07:10.209 [WARN ] [.eclipse.smarthome.model.script.Rules] - Test: End

1 Like

One more question how do I post the result to an item?

I tried
WebOS_label.postUpdate( current_label )

and I get an error
19:23:34.562 [ERROR] [untime.internal.engine.RuleEngineImpl] - Rule 'Test DSL rule': An error occurred during the script execution: Could not invoke method: org.eclipse.smarthome.model.script.actions.BusEvent.postUpdate(org.eclipse.smarthome.core.items.Item,org.eclipse.smarthome.core.types.State) on instance: null

Also when savind the rule there is a validation message
19:24:45.829 [INFO ] [del.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model '(7)_webos.rules', using it anyway:
Type cannot be derived

Make the label a string

1 Like