Need a little help with HTTP Binding

Hi guys,
one again I am stuck :wink:

I have here a device which controls the floor heaters and gets the room temperatures. Its easy reachable via a local IP adress. No authentification required.
I hope i am right so far: I opened the adress in chrome and also opened this chrome sidebar which shows all the code. I was able to find the little box in the code, which holds the value of the room temperature. See below:

So, i right-clicked on the code and copied the JS-path. Dont know if this was rigth :wink:
It looks like this:

document.querySelector("#ControllerTActual1")

Added a thing in OH via the HTTP Binding. Added a number channel and number item. Item shows UNDEF.
Here come the config of the thing and channels:

UID: http:url:fa6bc5a33f
label: Test HTTP
thingTypeUID: http:url
configuration:
  authMode: BASIC
  ignoreSSLErrors: false
  baseURL: http://192.168.178.20/indexdesktop.html
  delay: 0
  stateMethod: GET
  refresh: 30
  commandMethod: GET
  contentType: text/html
  timeout: 3000
  bufferSize: 2048
channels:
  - id: TestTemp
    channelTypeUID: http:number
    label: TestTemp
    description: ""
    configuration:
      mode: READONLY
      stateTransformation: document.querySelector("#ControllerTActual1")

Can you help me? Thank you :wink:

stateTransformation is to be used with one of the openHAB Transformation Services. You can’t just use any old JavaScript!

You may want to check out the XPATH Transformation Service.

@hafniumzinc i see, thank you for the hint.

Anyway, i am not able to figure this out by myself. Is there any basic tutorial on how i can “extract” values from a web-page via XPATH into the HTTP-Binding? Tried to understand the documentation, no chance :wink: I need more basic step-by-step instructions.

So, for now i installed the XPATH binding. But i dont get, how to work with it. Ofc i found the “copy Xpath” and “copy full Xpath” option in chrome browser. They look like this:

/html/body/div[2]/div/div/div[4]/div[2]/div/div/div[2]/div[1]/table/tbody/tr[3]/td[2]
//*[@id="ControllerTActual1"]

I tried to paste both of them into the state transformation line. Still no changes, item shows UNDEF.

The “stateTransformation” field requires the type of transformation you want to perform on the input.

Try this:

XPATH://*[@id="ControllerTActual1"]

The reason is: XPATH is not the only kind of transformation available in openHAB. There is also JSONPATH, MAP, JS, …
See Transformations | openHAB and Add-ons | openHAB (section “Data Transformation”)

An additional hint, totally unrelated to your question: Since you are dealing with temperatures here, you can check the “Show advanced” checkmark (above the “State Transformation” field) and enter “°C” in the “Unit” field. this makes the result a “temperature” instead of just a unit-less number.

@Fleck
okay, done. Sadly no change, still showing UNDEF on the item.
Does the HTTP-Binding need something else it can read from? Or does it read from the actual page (see photo above)?

Here my config:


UID: http:url:fa6bc5a33f
label: Test HTTP
thingTypeUID: http:url
configuration:
  authMode: BASIC
  ignoreSSLErrors: false
  baseURL: http://192.168.178.20/indexdesktop.html
  delay: 0
  stateMethod: GET
  refresh: 30
  commandMethod: GET
  contentType: text/xml
  timeout: 3000
  bufferSize: 2048
channels:
  - id: TestTemp
    channelTypeUID: http:number
    label: TestTemp
    description: ""
    configuration:
      mode: READONLY
      stateTransformation: XPATH://*[@id="ControllerTActual1"]
      unit: °C

Your thing config appears to be correct. I just created a test-thing and test-item, which worked and looked identical to yours.

Try disabling and re-enabling the thing and see if it makes a difference.

Or, the problem could be in the webpage: Perhaps indexdesktop.html loads the temperatures with a Javascript? Can you try to just load indexdesktop.html without a browser? E.g. curl -o http://192.168.178.20/indexdesktop.html | grep ControllerTActual1 from a Linux terminal or $html=Invoke-WebRequest http://192.168.178.20/indexdesktop.html; $html.ParsedHtml.getElementsByClassName("colA")[0].getAttribute("outerHTML") (you might have to try [1] or higher number before .getAttribute) in Windows Powershell.
Or, perhaps simpler, create a second channel of type string, with the same URL but no stateTransformation, link it to a string item and check the result.
If the temperature is present in the raw html I don’t know what could be wrong.

@Fleck

Hi Jens, back on it :wink:
I just tested what you supposed with the new channel. However, i found out something new: The device (Heizungssteuerung) has got a XML-API (german: XML-Schnittstelle). So now i can reach another page http://192.168.178.20/data/static.xml
I created a new string channel with this adress and indeed, i can see a lot of text, including the temperature for i.e. Schlafzimmer.

Now, in the browser i opened this side-menu and searched for i.e. the line with the temperature i need. I can click directly on the value (22.0) → copy XPATH. I pasted it into another channel. Sadly it shows “UNDEF.”
I think i am very close :wink: Must be something wrong with the XPATH.

UID: http:url:fa6a4ec433
label: HTTP URL Thing
thingTypeUID: http:url
configuration:
  authMode: BASIC
  ignoreSSLErrors: false
  baseURL: http://192.168.178.20/data/static.xml
  delay: 0
  stateMethod: GET
  refresh: 30
  commandMethod: GET
  contentType: text/xml
  timeout: 3000
  bufferSize: 2048
channels:
  - id: Test1
    channelTypeUID: http:string
    label: Test1
    description: ""
    configuration: {}
  - id: Test2
    channelTypeUID: http:number
    label: Test2
    description: ""
    configuration:
      mode: READONLY
      stateTransformation: XPATH://*[@id="folder18"]/div[2]/div[3]/span[2]
      unit: °C

The left side and the right side of the screenshot show different things. The right-hand side is probably what the browser made of the xml. Assuming the left screenshot is the actual text retrieved from data/static.xml try this xpath:

XPATH://HEATAREA[@nr="1"]/T_ACTUAL/text()

If it still does not work, try linking a string item to your Test1 channel. This should show the entire xml. You can then copy this text and try the xpath expression in an online XPath tester .

This way you can find out if the problem is in the stateTransformation or if there is a problem even earlier with retrieving the entire xml.

1 Like

@Fleck
Whooooot! :wink:
It works now!

How exactly did you come up with this line? So i am able to reproduce it :wink:
At least, i am able to read out the values now, which is very nice.

Do you have any suggestions on how i could write values into the xml?

Thank you so much!

How exactly did you come up with this line

By writing an xml string similar to your screenshot in the input field of some random online xpath tool and then thinking about how to identify the desired node. The rest was trial and error :slight_smile:

In the case of xml, the items are sorted in a „tree“. The data we are looking for (22) is the text of the node „T_ACTUAL“, which in turn is part of the node „HEATAREA“. Since HEATAREA might appear more than once (I don‘t know the entire xml) we use the attribute „nr=1“ to identify this exact HEATAREA. The tricky part was only the two slashes at the start, which mean „look in any subnode“ (not just in the „root“ of the xml tree) and the brackets after HEATAREA which are a condition, meaning „HEATAREA where the attribute „nr“ has the value „1“. Simple as that :slight_smile:

1 Like

@Fleck

New device, same problem… :wink:
I am trying forever to find out the correct XPATH. Would you mind helping me again?
This is really hard for noobs like me, sigh.
This one is a litte tricky, i guess. Its from my inverter (Photovoltaik). At night (like just right now) these lines at “measurement” sometimes disappear. I Would like to read out the values for i.e. voltage or power (which right now is not visible, because its zero).

Here the .xml xode

<root>
<Device Name="StecaGrid 3600" Type="Inverter" Serial="748613ZB005303130026" BusAddress="1" NetBiosName="INV005303130026" IpAddress="192.168.178.30" DateTime="2022-05-28T23:36:45">
<Measurements>
<Measurement Value="240.299" Unit="V" Type="AC_Voltage"/>
<Measurement Value="50.020" Unit="Hz" Type="AC_Frequency"/>
<Measurement Value="1.200" Unit="V" Type="DC_Voltage"/>
</Measurements>
</Device>
</root>

Try this:

XPATH:string(//Measurement[@Type= "AC_Voltage"]/@Value)

The difference to the previous xpath expression is:

  1. We do not want the text contents of an xml node (<nodename>text content</nodename>) but an attribute: This results in /@Value for the last part of the expression.
  2. We want just the value of the attribute („240.123“) instead of the entire attribute (value=„240.123“), this requires enclosing the entire expression the the string() function.

The expression was tested at https://codebeautify.org/Xpath-Tester

1 Like

@Fleck

This is working perfectly now, thank you so much!
Still, i don´t understand how to get correct XPATHs but i swear, i will learn someday :wink: