OH3 HTTP-BINDING StateTransformation for Switches

Hi,

currently I’m migrating OH 2.5 to 3.0.
Most of the things work fine, but I’m in trouble with the new HTTP-Binding.
I’m trying to connect to an ETH008, which is accessed via http://xxx.xxx.xxx.xxx/io.cgi

The call returns something like relays 10000000 representing of each relay.

I’m trying to transfer the state with the following transformation:
REGEX:relays (\d)\d*∩MAP:binarySwitch.map
(The first transfarmation extracts the right number, the second maps it to on or off)
This works fine for a string, but not for a switch. Here I got UNDEF

This is my configuration:

UID: http:url:b8943d8d7e
label: WRL02
thingTypeUID: http:url
configuration:
  authMode: BASIC
  ignoreSSLErrors: false
  baseURL: http://xxx.xxx.xxx.xxx/io.cgi
  password: "ImAPassword"
  refresh: 1
  commandMethod: POST
  timeout: 3000
  bufferSize: 2048
  username: admin
location: Arbeiten
channels:
  - id: WRL02_RelaysInfo
    channelTypeUID: http:string
    label: RelaysInfo
    description: ""
    configuration:
      mode: READONLY
  - id: WRL02_StateRelay1
    channelTypeUID: http:string
    label: StateRelay1
    description: ""
    configuration:
      mode: READONLY
      stateTransformation: REGEX:relays (\d)\d*∩MAP:binarySwitch.map
  - id: WRL02_RL02_CMD
    channelTypeUID: http:switch
    label: WRL02_RL02_CMD
    description: ""
    configuration:
      mode: READONLY
      stateTransformation: REGEX:relays (\d)\d*∩MAP:binarySwitch.map

Hope someone could help :slight_smile:

UNDEF means that the binding could find out what value the transformed value should be converted to. I don’t see the on/off-values configured, did you set these?

I thought, the ON- /OFF-Values were for the command only?

This is the corresponding entry for OpenHab 2.5:
Switch RL2 ["Switch"] { http=">[ON:POST:http://xxx.xxx.xxx.xxx/io.cgi?DOA2=0{Authorization=Basic XXXXXXXXXXX}] >[OFF:POST:http://xxx.xxx.xxx.xxx/io.cgi?DOI2=0{Authorization=Basic xxxxxxxxxxxxxx}] <[http://xxx.xxx.xxx.xxx/io.cgi{Authorization=Basic xxxxxxxxxxxxxxxxxxxx}:1:JS(binaryToOnOff_PW7.js)]" }

where binaryToOnOff_PW7.js is
(function(relayStatus) { var digit = relayStatus.substring(8,9); // var logger = Java.type("org.slf4j.LoggerFactory").getLogger("myScript"); logger.warn("status: " + digit); if (digit == '1') { return 'ON'; } else { return 'OFF'; } })(input)

What gave you that impression? I can’t find any hint the documentation that says so. The logic (also for all other channels with “special values”) is

inbound:
receive value -> stateTransformation -> lookup special value -> state

outbound:
command -> lookup special value -> commandTransformation -> send value

Ok, but how to deal with different values for command an state?

Use different transformations. You could define „on=1“ and „off=0“ (if that is what you need to send e.g. in the rL as command) and use a MAP for the incoming state to map „true=1“ and „false=0“.

Since you can concatenate transformations, you could (e.g.) use JSONPATH to extract „true/false“ and then MAP those values.

That does the trick! Thank you for your great support!
Merry Christmas btw :wink:

FTR:

Imagine you have a device that

  • a state available at https://my.url/esh/getstate.json
  • switches a device to ON with https://my.url/esh/1 and to OFF with https://my.url/esh/0

The JSON looks like { "on" : false } for “device is off” or { "on" : true } for “device is on”.

Install the HTTP binding, the JSONPATH transformation and the MAP transformation.

Create a thing with a channel as follows:

UID: http:url:0f530eeb1b
label: My Remote Device
thingTypeUID: http:url
configuration:
  authMode: BASIC
  ignoreSSLErrors: false
  baseURL: https://my.url/esh
  delay: 200
  refresh: 30
  commandMethod: GET
  timeout: 3000
  bufferSize: 2048
channels:
  - id: switch
    channelTypeUID: http:switch
    label: Powerswitch
    description: ""
    configuration:
      onValue: "1"
      offValue: "0"
      stateExtension: getstate.json
      stateTransformation: JSONPATH:$.on∩MAP:true1false0.map
      commandExtension: "%2$s"

For the command the ON/OFF from openHAB are converted to 1/0 (onValue/offValue) and appended as a String to the baseURL (commandExtension).

For the state the stateExtension is appended to the baseURL. The resulting JSON is first processed by the JSONPATH transformation and the state is extracted as true/false. This is then MAP to 1/0 (the onValue/offValue) and send as ON/OFF to the linked item.

The true1false0.map is as follows:

true=1
false=0

@Kai Any idea how to add examples like this to the binding documentation? It becomes very lengthy if we have more than one and they are more a howto/tutorial than documentation.

There is a HTML5 tag if that is what you want:

<details>
<summary>Full Example</summary>
<p>Example Text</p>
</details>
Full Example
UID: http:url:0f530eeb1b
label: My Remote Device
thingTypeUID: http:url
configuration:
  authMode: BASIC
  ignoreSSLErrors: false
  baseURL: https://my.url/esh
  delay: 200
  refresh: 30
  commandMethod: GET
  timeout: 3000
  bufferSize: 2048
channels:
  - id: switch
    channelTypeUID: http:switch
    label: Powerswitch
    description: ""
    configuration:
      onValue: "1"
      offValue: "0"
      stateExtension: getstate.json
      stateTransformation: JSONPATH:$.on∩MAP:true1false0.map
      commandExtension: "%2$s"
1 Like

I am somehow trying to migrate a similar thing from 2.5 (http v1) to 3.0

Before I used the following item to reboot my weatherstation webserver:
Switch LOCALWEATHER_observerreboot "Reboot Wetterstation" {http=">[ON:GET:http://192.168.1.5/msgreboot.htm] >[OFF:GET:http://192.168.1.5/msgreboot.htm]"}

Just firing this URL initates a reboot.
With the 3.0 http binding I would still like to keep it in a things file but struggle in migrating this.

any hints?

for anybody stumbling over this
I solved the above problem with:

Thing http:url:WeatherObserverReboot "WetterStationReboot" [ baseURL="http://192.168.1.5/", commandMethod="GET"] { 
	Channels: 
		Type switch : LOCALWEATHER_observerreboot [ commandExtension="msgreboot.htm",  onValue="ON", offValue="OFF"] 
}

Hi guys,

I am struggling here as well:
I got the http binding work to read my alarm-system’s state by using this config:

UID: http:url:AbusIP
label: HTTP Abus IP
thingTypeUID: http:url
configuration:
  authMode: BASIC_PREEMPTIVE
  ignoreSSLErrors: false
  baseURL: http://192.168.68.36:8060/
  password: xxx
  delay: 0
  refresh: 10
  commandMethod: GET
  contentType: text/plain
  timeout: 3000
  username: root
  bufferSize: 2048
channels:
  - id: AbusState
    channelTypeUID: http:switch
    label: Abus State
    description: ""
    configuration:
      onValue: Set
      stateExtension: getMode.cgi
      offValue: Unset
      stateTransformation: REGEX:Mode=(.*)

This is working fine and translates the states Set / Unset to ON / OFF.

However, the commands do not work and I tried this modified channel config:

channels:
  - id: AbusState
    channelTypeUID: http:switch
    label: Abus State
    description: ""
    configuration:
      onValue: Set
      stateExtension: getMode.cgi
      offValue: Unset
      stateTransformation: REGEX:Mode=(.*)
      commandExtension: setMode.cgi?Mode=

Because my previous OH2.5 item looked like this:

[ON:GET:http://192.168.68.36:8060/setMode.cgi?Mode=Set{Authorization=Basic xxx}[OFF:GET:http://192.168.68.36:8060/setMode.cgi?Mode=Unset{Authorization=Basic xxx}

Any suggestion?

You are not sending the value of your transformed command via the URL. Try:

commandExtension: setMode.cgi?Mode=%2$s

assuming you want to send Set or Unset after Mode=.

That’s it!
Awesome - You made my day :slight_smile:

By the way:
I love OH3 - even though the migration takes some time and causes significant effort, but the Main UI is much better and the option of merging 2 http items into one (command and state) is a great advantage (among others.

Thanks to @J-N-K for your help on the BASIC_PREEMPTIVE authentication topic

1 Like

It’s me again with an old issue.

From my Alarm-systems I get a string with \n like this:

InputCH1=OFF
InputCH2=OFF
InputCH3=OFF
InputVCH1=OFF
InputVCH2=DEACTIVATED
InputVCH3=DEACTIVATED
OutputCH1=OFF
OutputCH2=OFF
OutputWired=OFF
AlarmPowerFail=OFF
AlarmLowBattery=OFF
AlarmFault=OFF
AlarmFire=OFF
AlarmTechnical=OFF
AlarmBurglary=OFF
AlarmEntry=OFF
AlarmPanic=OFF

The first 3 lines (InputCh) are window contacts I would like to query using http.
(see also my problems with REGEX and http1 about this issue here:

So, when using AlarmPanic instead, it works just fine:

- id: Entrance
    channelTypeUID: http:contact
    label: Eingang
    description: ""
    configuration:
      stateExtension: getOverviewStatus.cgi
      stateTransformation: REGEX:.*AlarmPanic=(.*)
      openValue: ON
      closedValue: OFF

Using the right channel “InputCH1” does not (returns the intire string including the next lines.

My previous http config was this and worked just fine (even though it’s a mess):

{http="<[cacheAbusState:10000:REGEX(.*InputCH1=(.*)\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*)]"}

But using the same REGEX structure does not work.

2021-01-02 09:04:47.194 [DEBUG] [.transform.SingleValueTransformation] - Transformation ChannelStateTransformation{pattern='.*InputCH1=(.*)\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*', serviceName='REGEX'} returned empty res$
InputCH2=OFF
InputCH3=OFF
InputVCH1=OFF
InputVCH2=DEACTIVATED
InputVCH3=DEACTIVATED
OutputCH1=OFF
OutputCH2=OFF
OutputWired=OFF
AlarmPowerFail=OFF
AlarmLowBattery=OFF
AlarmFault=OFF
AlarmFire=OFF
AlarmTechnical=OFF
AlarmBurglary=OFF
AlarmEntry=OFF
AlarmPanic=OFF
.

So, obviously REGEX handling has changed (!?) and I wonder where the “.” at the end comes from?

Any suggestion how to get rid of the stuff after the next newline would be greatly appreciated.

EDIT:
I found a workaround - which is not pretty, but works:

REGEX:.*InputCH1=([A-Z]{2}).*

This will return ON / OF, which is mapped to OPEN / CLOSED.

.*InputVCH2=(.*?)\s

Should do. You need to make the group-matching-part non-greedy, that is done my appending ? to the quantifier. Otherwise .* will match everything as long as the rest can still me satisfied. Since . matches everything (including the EOL-characters), it’ll match everything until the last \n. You can test your regular expressions at Free Online Java Regular Expression Tester - FreeFormatter.com.

Another solution would be .*InputCH3=([A-Z]*).

Thanks a lot (again) for your support.

I tried this in the past (and again), but this does not work.
The \s seems to be ignored or better not even found by REGEX:

2021-01-02 10:39:17.592 [DEBUG] [.transform.SingleValueTransformation] - Transformation ChannelStateTransformation{pattern='.*InputVCH1=(.*?)\s', serviceName='REGEX'} returned empty result when applied to InputCH1=OFF
InputCH2=OFF
InputCH3=OFF
InputVCH1=OFF
InputVCH2=DEACTIVATED
InputVCH3=DEACTIVATED
OutputCH1=OFF
OutputCH2=OFF
OutputWired=OFF
AlarmPowerFail=OFF
AlarmLowBattery=OFF
AlarmFault=OFF
AlarmFire=OFF
AlarmTechnical=OFF
AlarmBurglary=OFF
AlarmEntry=OFF
AlarmPanic=OFF

.

The same with this:

2021-01-02 10:46:04.635 [DEBUG] [.transform.SingleValueTransformation] - Transformation ChannelStateTransformation{pattern='.*InputVCH1=([A-Z]*)', serviceName='REGEX'} returned empty result when applied to InputCH1=OFF
InputCH2=OFF
InputCH3=OFF
InputVCH1=OFF
InputVCH2=DEACTIVATED
InputVCH3=DEACTIVATED
OutputCH1=OFF
OutputCH2=OFF
OutputWired=OFF
AlarmPowerFail=OFF
AlarmLowBattery=OFF
AlarmFault=OFF
AlarmFire=OFF
AlarmTechnical=OFF
AlarmBurglary=OFF
AlarmEntry=OFF
AlarmPanic=OFF
.

That’s the frustrating part with REGEX in OH.
It does not work the same way like regex testers like REGEX101.com :frowning:

Well it does. But the regex needs to match the full response. REGEX:.*InputCH3=([A-Z]*).* works. .*InputVCH3=(.*?)\s.* also works. The missing .* at the end prevented the part after the matching group to match, why the regex did not match at all.

YES!
This works!
Thank you so much!

the new http 3.0 binding rocks!

Hello everyone,
I’m a beginer in OH. I’m using OH3 and I’d like to configure a http url thing to execute command and request the state to a web server, using get and post methods. I’m able to modify the php web files to test trought openhab.
I tested the get method to read and write an output at time. After this, I tried to modify the state request to read all status bits at a time to have best performance. But, when I introduce a regular expression in “State Trasformation” field, nothing changes: there is no error, but nothing is read anymore. Maybe it doesn’t match the regex.
To simplify the testing, I created a new channel of string type and configure it to read a string by get method. This example run correctly:

But when I add a regular expression, the linked point does not update. I tested a lot of regex, but always the same result.
This is a regex of the tested ones:

Where is the issue?
I forget to say that initially I’ve installed OH2 and later updated it to OH3.

If anyone wants to try it, I can upload the test_http.php page on a pubblic url.