HTTP binding - openHAB 3 version

Hi

Great binding. I just have one issue.
I can read the values for 3 channels via GET method, but I need also a GET Method to set a switch item to ON & OFF.

here is the output when I set it via curl:

# curl -i -H "Accept: application/json" -H "Content-Type: application/json" -H "Token:SECRET" 'http://10.0.1.27/relay?state=1'
HTTP/1.1 200 OK
Pragma: no-cache
Cache-Control: no-store, no-cache
Content-Type: text/plain
Content-Length: 0
Connection: close

In the old binding, I defined the item that way:
ON:GET:http://10.0.1.27/relay?state=1{Token=SECRET}
OFF:GET:http://10.0.1.27/relay?state=0{Token=SECRET}

When I configure the channel that way, I get an exception in openhab.log.

2020-07-22 16:26:43.165 [ERROR] [nal.common.AbstractInvocationHandler] - An error occurred while calling method 'ThingHandler.thingUpdated()' on 'org.openhab.binding.http.internal.HttpThingHandler@1ad26566': String index out of range: 0
java.lang.StringIndexOutOfBoundsException: String index out of range: 0
	at java.lang.String.charAt(String.java:658) ~[?:1.8.0_252]
	at org.openhab.binding.http.internal.HttpThingHandler.concatenateUrlParts(HttpThingHandler.java:308) ~[?:?]
	at org.openhab.binding.http.internal.HttpThingHandler.createChannel(HttpThingHandler.java:191) ~[?:?]
	at java.util.ArrayList.forEach(ArrayList.java:1257) ~[?:1.8.0_252]
	at java.util.Collections$UnmodifiableCollection.forEach(Collections.java:1082) ~[?:1.8.0_252]
	at org.openhab.binding.http.internal.HttpThingHandler.initialize(HttpThingHandler.java:161) ~[?:?]
	at org.eclipse.smarthome.core.thing.binding.BaseThingHandler.thingUpdated(BaseThingHandler.java:166) ~[?:?]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_252]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_252]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_252]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_252]
	at org.eclipse.smarthome.core.internal.common.AbstractInvocationHandler.invokeDirect(AbstractInvocationHandler.java:152) [bundleFile:?]
	at org.eclipse.smarthome.core.internal.common.Invocation.call(Invocation.java:52) [bundleFile:?]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_252]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_252]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_252]
	at java.lang.Thread.run(Thread.java:748) [?:1.8.0_252]

regards
Remo

@HaKuNa

I would also try MAP transformation with e.g. onoff.map

Content of onoff.map:

1=on
0=off

.
And your URL Definition should be:
.

This was the right direction, thanks.

my map file:

true=1
false=0

and the channel definition:

Thanks for your snapshot. The missing part actually was that I need to use %2$s for the state argument. @J-N-K if I didn’t overlook it that’s not documented ?

It in documentation at the bottom. See here.

https://github.com/J-N-K/openhab-addons/tree/http/bundles/org.openhab.binding.http#url-formatting

That doesn’t seem to work properly yet.
On my last example (to read and write the channel), State URL Extension was ignored.
And when I’ve set it to empty (but readwrite mode), I got an exception on saving saying

2020-07-22 22:31:15.968 [ERROR] [nal.common.AbstractInvocationHandler] - An error occurred while calling method 'ThingHandler.thingUpdated()' on 'org.openhab.binding.http.internal.HttpThingHandler@163344': String index out of range: 0
java.lang.StringIndexOutOfBoundsException: String index out of range: 0
        at java.lang.StringLatin1.charAt(StringLatin1.java:47) ~[?:?]
        at java.lang.String.charAt(String.java:693) ~[?:?]
        at org.openhab.binding.http.internal.HttpThingHandler.concatenateUrlParts(HttpThingHandler.java:308) ~[?:?]
        at org.openhab.binding.http.internal.HttpThingHandler.createChannel(HttpThingHandler.java:191) ~[?:?]

With another thing which has no Command Extension, State Extension is working, but apparently not together with Command Extensions.

Actually those docs say %2$ but I had to use %2$s like in @Celaeno1’s example.

[quote=“mstormi, post:67, topic:101851, full:true”]

Well, that‘s not exactly true.

l. 101 states that the „format needs to be appended „ and l. 106 shows exactly %2$s. But probably this needs to be reworded to be more clear.

I took the string from your README.md (as most people will simply do rather than read java docs) so please fix it there

That‘s in the readme. Anyway, it should be made more clear.

just to mention where I found the information:
→ It is explained under “URL Formatting” here https://github.com/J-N-K/openhab-addons/tree/http/bundles/org.openhab.binding.http

http://www.domain.org/home/lights/23871/?status=%2$s&date=%1$tY-%1$tm-%1$td

There’s 2 occurences. The one in the URL you refer to is correct.
But there’s another one 4 lines up which is bad which is what I took.

Did you see about the state extension not being honored ? (6 posts up)

It’s here:
After the parameter reference the format needs to be appended

I guess @mstormi means this sentence in documentation:

After concatenation of the baseURL and the commandExtension (if provided) the URL is formatted using the java.util.Formatter.

.
It better should be:
.

After concatenation of the baseURL and the commandExtension or the stateExtension (if provided) the URL is formatted using the java.util.Formatter.

I have fixed the exception and made the documentation a little bit more explicit.The link above is updated. Be careful if you drop the .jar in your addons folder: It’s now 2.5.8 instead of 2.5.7, so the old version will not be overwritten.

Thanks, it’s working as expected now. Here’s my promised complex example for your docs:

My ‘Dreambox’ TV receiver has an HTTP API. The hostname is dm900.
On requesting /web/powerstate, it returns an XML

<e2powerstate>
<e2instandby>false</e2instandby>
</e2powerstate>

meaning it is currently not in standby thus ON. A POST request /web/powerstate?newstate=5 will instruct it to switch OFF and newstate=4 means to switch ON.


The state transformation REGEX fully reads REGEX:.*?<e2instandby>(.*?)</e2instandby>.* and returns what is between <e2instandby> and </e2instandby>, i.e. false or true.
dreambox.map for the command transformation is

true=5
false=4
NULL=no data
-=no data

Very unlike the HTTPv1 binding, the item definition is only a very simple channel reference
Switch Dreambox "Dreambox [%s]" { channel="http:url:<thing ID>:<channel ID>" }

:smiley: That’s exactly my suggestion I made here:

In the readme it says:

`mode` `READWRITE` Mode this channel is allowed to operate. `READ` means receive state, `WRITE` means send commands.

In the code it is actually:

<option value="READWRITE">Read/Write</option>
<option value="READONLY">Read Only</option>
<option value="WRITEONLY">Write Only</option>

Exellent work!!
This will be the binding to integrate all those proprietary smart/cloud devices.
But I’m stuck with authentication on my Air-Heatpump.
Does the method for URL need to be Post?
Cause REGEX can’t find matches, because it’s only loading the loginpage.

If your device requires authentication, you need to define this on the thing (user/pwd or token in the http header). This depends on the device you want to connect.