HTTP Binding Data-Binary

  • Platform information:
    • Hardware: X86/8GB/SSD
    • OS: Ubuntu
    • Java Runtime Environment:
    • openHAB version: 2
  • Issue of the topic: I have a device in my network which I can launch a CURL command against and it will return a JSON file which I want to pull apart and show in OpenHAB. I prefer to do this with the HTTP binding.

The curl command is:

curl ‘http://10.0.0.2/dyn/getAllOnlValues.json?sid=7Y-18GWyxTBylEWF’ --data-binary ‘{“destDev”:[]}’

The --data-binary option is mandatory, if I delete it, the server returns a 404 error.

The JSON is quite big and via JSON-path statements I succeeded in getting the right values (tested this with http://jsonpath.com/, it returns the value I want between square brackets

This is my items file:

Number http_number_PowerA “Vermogen A [%.1f]” { http="<[http://10.0.0.2/dyn/getAllOnlValues.json?sid=7Y-18GWyxTBylEWF’:JSONPATH($.result.0123-76AD1234.5432_40251E00.1.0.val)]" }

And I have created an entry in sitemap:

Text item=http_number_PowerA

However, the item stays empty… How do I pass the --data-binary option in the HTTP binding?

I do not believe you can. I think you will have to continue to use curl and use the Exec binding or executeCommandLine to access this data.

Okay, trying to get that working now:

exec.items file:

String SMAJSON "[%s]" (All) {channel="exec:command:smajson"}

exec.things file:

Thing exec:command:smajson [command="curl 'http://192.168.4.129/dyn/getAllOnlValues.json?sid=yBak0jS7r0F7TjSX' --data '{"destDev":[]}'", interval=15, timeout=5]

But logging is saying some strange things:

2018-03-15 13:39:36.017 [ERROR] [el.item.internal.GenericItemProvider] - Binding configuration of type 'channel' of item 'SMAJSON' could not be parsed correctly.
org.eclipse.smarthome.model.item.BindingConfigParseException: UID must have at least 4 segments.
        at org.eclipse.smarthome.model.thing.internal.GenericItemChannelLinkProvider.createItemChannelLink(GenericItemChannelLinkProvider.java:82)[133:org.eclipse.smarthome.model.thing:0.9.0.b4]
        at org.eclipse.smarthome.model.thing.internal.GenericItemChannelLinkProvider.processBindingConfiguration(GenericItemChannelLinkProvider.java:72)[133:org.eclipse.smarthome.model.thing:0.9.0.b4]
        at org.eclipse.smarthome.model.item.internal.GenericItemProvider.internalDispatchBindings(GenericItemProvider.java:312)[123:org.eclipse.smarthome.model.item:0.9.0.b4]
        at org.eclipse.smarthome.model.item.internal.GenericItemProvider.internalDispatchBindings(GenericItemProvider.java:284)[123:org.eclipse.smarthome.model.item:0.9.0.b4]
        at org.eclipse.smarthome.model.item.internal.GenericItemProvider.processBindingConfigsFromModel(GenericItemProvider.java:167)[123:org.eclipse.smarthome.model.item:0.9.0.b4]
        at org.eclipse.smarthome.model.item.internal.GenericItemProvider.modelChanged(GenericItemProvider.java:347)[123:org.eclipse.smarthome.model.item:0.9.0.b4]
        at org.eclipse.smarthome.model.core.internal.ModelRepositoryImpl.notifyListeners(ModelRepositoryImpl.java:207)[122:org.eclipse.smarthome.model.core:0.9.0.b4]
        at org.eclipse.smarthome.model.core.internal.ModelRepositoryImpl.addOrRefreshModel(ModelRepositoryImpl.java:120)[122:org.eclipse.smarthome.model.core:0.9.0.b4]
        at org.eclipse.smarthome.model.core.internal.folder.FolderObserver.checkFile(FolderObserver.java:272)[122:org.eclipse.smarthome.model.core:0.9.0.b4]
        at org.eclipse.smarthome.model.core.internal.folder.FolderObserver.access$1(FolderObserver.java:265)[122:org.eclipse.smarthome.model.core:0.9.0.b4]
        at org.eclipse.smarthome.model.core.internal.folder.FolderObserver$WatchQueueReader.processWatchEvent(FolderObserver.java:146)[122:org.eclipse.smarthome.model.core:0.9.0.b4]
        at org.eclipse.smarthome.core.service.AbstractWatchQueueReader.run(AbstractWatchQueueReader.java:122)[98:org.eclipse.smarthome.core:0.9.0.b4]
        at java.lang.Thread.run(Thread.java:745)[:1.8.0_121]

You pass --data instead of --data-binary?

Yes, that works too. But doesn’t matter because afaics (?) the regular --data option isn’t supported either in the HTTP binding, so that’s why I diverted to exec binding.

Open for any suggestion though!

Maybe need to escape the " in ..{"destDev":[]}'".
I hate this too, it’s to hard to find out the correct syntax… while you know it should be possible…

You could create a shell script that includes the curl call, to avoid the need for the special chars in the exec command text.

ah, just learned about this 2.0 way of using the Exec binding. You miss the Channel name in the Item.
{channel="exec:command:smajson:output"} (append :output)

VSCode does wonders for stuff like this.

In this case, you can see just by looking at the way the forum did syntax highlighting that this is the problem. The command needs to be a single String.

image

The fact that destDev is highlighted in black instead of red like the rest of the String shows you that it isn’t being seen as a single string. Escape the double quotes and it will not treat the " as the end of the string but as part of the string.

'{\"destDev\":[]}'"

This would have been a problem in exec 1.x, HTTP, in Rules or anywhere else.

1 Like

I think we’re getting somewhere:

2018-03-15 15:45:04.524 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'exec.things'
2018-03-15 15:45:04.543 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'exec.things'
2018-03-15 15:45:04.557 [ERROR] [hab.binding.exec.handler.ExecHandler] - An exception occurred while waiting for the process ('curl 'http://192.168.4.129/dyn/getAllOnlValues.json?sid=yBak0jS7r0F7TjSX' --data '{"destDev":[]}'') to finish : 'null'
2018-03-15 15:45:04.558 [WARN ] [hab.binding.exec.handler.ExecHandler] - Forcibly termininating the process ('curl 'http://192.168.4.129/dyn/getAllOnlValues.json?sid=yBak0jS7r0F7TjSX' --data '{"destDev":[]}'') after a timeout of 15000 ms

This is my file now:
exec.things

Thing exec:command:smajson:output [command="curl 'http://192.168.4.129/dyn/getAllOnlValues.json?sid=yBak0jS7r0F7TjSX' --data '{\"destDev\":[]}'"", interval=15, timeout=5]

exec.items

String SMAJSON "[%s]" (All) {channel="exec:command:smajson:output"}

I don’t think the Thing should have the :output in it’s definition. The Item should.

1 Like

Okay, we’re getting something now.

Item is updated to:

curl: (1) Protocol “'http” not supported or disabled in libcurl curl: (1) Protocol “'http” not supported or disabled in libcurl

This is my exec.things file now:

Thing exec:command:smajson [command="curl 'http://192.168.4.129/dyn/getAllOnlValues.json?sid=yBak0jS7r0F7TjSX' --data '{\"destDev\":[]}'", interval=15, timeout=5]
curl: (1) Protocol “'http” not supported or disabled in libcurl curl

Your URL needs to:
a) Come after the options
b) be either not quoted or wrapped in double quotes, not single quotes

After which options? Like this then?

Thing exec:command:smajson [command=“curl --data ‘{“destDev”:[]}’ http://192.168.4.129/dyn/getAllOnlValues.json?sid=yBak0jS7r0F7TjSX”, interval=15, timeout=5]

After deleting the single quotes around the URL I’m getting a 404 now, which means the data option is not getting passed through or something is going wrong there.

In your OP you used --data-binary but in these later posts you are using --data

Good thinking Rich, but unfortunately that’s not the issue, I tested that before I changed the option and --data was okay too.

Tested it in the exec.things file with --data-binary to no avail…

Probably still a quoting issue there somewhere, then. You could grab a debug log to try to figure out what the binding thinks it’s executing…

@namraccr @rlkoshak @jwveldhuis

Ding Ding :smile:

After doing some TCP dumps I saw the difference and the solution was deleting the single qutoes around the curly brackets.

The item gets populated with the JSON now but that brings up a new question:

Can you process an item and split it in different new items without using rules? I was thinking of creating a JSONSMA-item and make “sub-items” which point to the “main” item and process that main item with JSONPATH so the sub-items get populated…?

You could use the JSONPATH transform in the thing but that gives you only one item
unfortunately you can’t do that without a rule

see:

rule "jsonpath"
when
    Item SMAJSON changed
then
    val jsonString = SMAJSON.state.toString
    Item1.postUpdate(transform("JSONPATH",".$.path.path1", jsonString))
    Item2.postUpdate(transform("JSONPATH",".$.path.path2", jsonString))
    Item3.postUpdate(transform("JSONPATH",".$.path.path3", jsonString))
end

Thanks for the quick reply, it confirmed my fears I should start writing a rule again.

Continuing with this story, I implemented your rule (changed the variables names to match my naming convention)

rule "Process JSON from SMA Inverter"
when
    Item JSON_SMA changed
then
    logInfo("RULE", "JSON from SMA inverter changed!")

    logInfo("RULE", "---------------------------------------------------------------------------------")
    logInfo("RULE", "-----------------------------WRITING THE ITEM TO LOG-----------------------------")
    logInfo("RULE", "---------------------------------------------------------------------------------")
    logInfo("RULE", JSON_SMA.state.toString)


    val jsonString = JSON_SMA.state.toString

    logInfo("RULE", "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-")
    logInfo("RULE", "++++++++++++++++++++++++++++WRITING THE STRING TO LOG++++++++++++++++++++++++++++")
    logInfo("RULE", "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-")
    logInfo("RULE", jsonString)

    

    number_SMA_DCVermogenA.postUpdate(transform("JSONPATH","$.result.XXXX-XXXXXXXX.XXXX_XXXXXXXX.1.0.val", jsonString))
    
    

However, the logging shows:

2018-03-18 00:37:24.078 [ERROR] [.script.engine.ScriptExecutionThread] - Rule ‘Process JSON from SMA Inverter’: The argument ‘state’ must not be null or empty

So I checked if it really was empty or null, which it isn’t. I’m outputting both the item defined in the items file to the log and the jsonString val object and they both return the JSON in the log file…

If I comment out the number_SMA… transform rule, the error disappears in the logging. Additional strange thing is that I have multiple of these code-lines (vermogen means power in Dutch, so I have power,amperage,voltage etc) but I’m seeing the error only once though I would expect to see it the amount of times I have defined a statement to process a value…

add an if condition to test is the string is null
It will be on the first execution of the rule after saving the file and should be fine thereafter

if (jsonString != null) {
    number_SMA_DCVermogenA.postUpdate(transform("JSONPATH","$.result.XXXX-XXXXXXXX.XXXX_XXXXXXXX.1.0.val", jsonString))
}