OH3 XPath

That looks interesting - I’ll have a look tomorrow. This is what I’m trying to do. I suspect JSON will be easier now than XPATH

I’ve been playing around some more with this. Whilst it was fairly intuitive using the UI, I found it quite slow. It is also not so easy to share configurations of the Items (and Links, which would come as a separate JSON) from the UI, so tonight I’ve had a play with using Things and Items files and it was a breeze!

At the moment I’m just playing around with daily forecasts, grabbing the temperature, feels-like temperature, precipitation and weather type for today and the next 4 days.

Things

Replace SITEID and APIKEY

Thing http:url:datapointforecast "Data Point Forecast" [
	baseURL = "http://datapoint.metoffice.gov.uk/public/data/val/wxfcs/all/json/SITEID?res=daily&key=APIKEY",
	refresh = "900",
	ignoreSSLErrors = "true"
]
{
	Channels:
		Type number : forecast_today_temperature_maximum "Forecast Today Temperature Maximum" [
			mode = "READONLY",
			stateTransformation = "JSONPATH:$.SiteRep.DV.Location.Period[0].Rep[0].Dm"
		]
		Type number : forecast_today_temperature_feels_like_maximum "Forecast Today Temperature Maximum" [
			mode = "READONLY",
			stateTransformation = "JSONPATH:$.SiteRep.DV.Location.Period[0].Rep[0].FDm"
		]
		Type number : forecast_today_precipitation "Forecast Today Precipitation" [
			mode = "READONLY",
			stateTransformation = "JSONPATH:$.SiteRep.DV.Location.Period[0].Rep[0].PPd"
		]
		Type string : forecast_today_weather_type "Forecast Today Weather Type" [
			mode = "READONLY",
			stateTransformation = "JSONPATH:$.SiteRep.DV.Location.Period[0].Rep[0].W∩MAP:weathertype.map"
		]
		Type number : forecast_tomorrow_temperature_maximum "Forecast Tomorrow Temperature Maximum" [
			mode = "READONLY",
			stateTransformation = "JSONPATH:$.SiteRep.DV.Location.Period[1].Rep[0].Dm"
		]
		Type number : forecast_tomorrow_temperature_feels_like_maximum "Forecast Tomorrow Temperature Maximum" [
			mode = "READONLY",
			stateTransformation = "JSONPATH:$.SiteRep.DV.Location.Period[1].Rep[0].FDm"
		]
		Type number : forecast_tomorrow_precipitation "Forecast Tomorrow Precipitation" [
			mode = "READONLY",
			stateTransformation = "JSONPATH:$.SiteRep.DV.Location.Period[1].Rep[0].PPd"
		]
		Type string : forecast_tomorrow_weather_type "Forecast Tomorrow Weather Type" [
			mode = "READONLY",
			stateTransformation = "JSONPATH:$.SiteRep.DV.Location.Period[1].Rep[0].W∩MAP:weathertype.map"
		]
		Type number : forecast_day3_temperature_maximum "Forecast Day3 Temperature Maximum" [
			mode = "READONLY",
			stateTransformation = "JSONPATH:$.SiteRep.DV.Location.Period[2].Rep[0].Dm"
		]
		Type number : forecast_day3_temperature_feels_like_maximum "Forecast Day3 Temperature Maximum" [
			mode = "READONLY",
			stateTransformation = "JSONPATH:$.SiteRep.DV.Location.Period[2].Rep[0].FDm"
		]
		Type number : forecast_day3_precipitation "Forecast Day3 Precipitation" [
			mode = "READONLY",
			stateTransformation = "JSONPATH:$.SiteRep.DV.Location.Period[2].Rep[0].PPd"
		]
		Type string : forecast_day3_weather_type "Forecast Day3 Weather Type" [
			mode = "READONLY",
			stateTransformation = "JSONPATH:$.SiteRep.DV.Location.Period[2].Rep[0].W∩MAP:weathertype.map"
		]
		Type number : forecast_day4_temperature_maximum "Forecast Day4 Temperature Maximum" [
			mode = "READONLY",
			stateTransformation = "JSONPATH:$.SiteRep.DV.Location.Period[3].Rep[0].Dm"
		]
		Type number : forecast_day4_temperature_feels_like_maximum "Forecast Day4 Temperature Maximum" [
			mode = "READONLY",
			stateTransformation = "JSONPATH:$.SiteRep.DV.Location.Period[3].Rep[0].FDm"
		]
		Type number : forecast_day4_precipitation "Forecast Day4 Precipitation" [
			mode = "READONLY",
			stateTransformation = "JSONPATH:$.SiteRep.DV.Location.Period[3].Rep[0].PPd"
		]
		Type string : forecast_day4_weather_type "Forecast Day4 Weather Type" [
			mode = "READONLY",
			stateTransformation = "JSONPATH:$.SiteRep.DV.Location.Period[3].Rep[0].W∩MAP:weathertype.map"
		]
		Type number : forecast_day5_temperature_maximum "Forecast Day5 Temperature Maximum" [
			mode = "READONLY",
			stateTransformation = "JSONPATH:$.SiteRep.DV.Location.Period[4].Rep[0].Dm"
		]
		Type number : forecast_day5_temperature_feels_like_maximum "Forecast Day5 Temperature Maximum" [
			mode = "READONLY",
			stateTransformation = "JSONPATH:$.SiteRep.DV.Location.Period[4].Rep[0].FDm"
		]
		Type number : forecast_day5_precipitation "Forecast Day5 Precipitation" [
			mode = "READONLY",
			stateTransformation = "JSONPATH:$.SiteRep.DV.Location.Period[4].Rep[0].PPd"
		]
		Type string : forecast_day5_weather_type "Forecast Day5 Weather Type" [
			mode = "READONLY",
			stateTransformation = "JSONPATH:$.SiteRep.DV.Location.Period[4].Rep[0].W∩MAP:weathertype.map"
		]
}

Items

These include semantic notation. Today’s forecast should appear in your model inside a Met Office equipment, outdoors.

//OUTDOOR GROUP
Group gOutdoor "Outdoor" <outdoor> ["Outdoor"]

//EQUIPMENT
Group gMetOfficeForecast "Met Office Forecast []" <sensor> (gOutdoor) ["Sensor"]

//TODAY
Number nForecastTodayTemperatureMaximum "Maximum Temperature [%d°C]" <temperature> (gMetOfficeForecast) ["Temperature", "Measurement"] { channel="http:url:datapointforecast:forecast_today_temperature_maximum" }
Number nForecastTodayTemperatureFeelsLikeMaximum "Feels like [%d°C]" <temperature> (gMetOfficeForecast) ["Temperature", "Measurement"] { channel="http:url:datapointforecast:forecast_today_temperature_feels_like_maximum" }
Number nForecastTodayPrecipitation "Rain [%d%%]" <rain> (gMetOfficeForecast) ["Rain", "Measurement"] { channel="http:url:datapointforecast:forecast_today_precipitation" }
String strForecastTodayWeatherType "Forecast" <status> (gMetOfficeForecast) ["Status"] { channel="http:url:datapointforecast:forecast_today_weather_type" }

//TOMORROW
Number nForecastTomorrowTemperatureMaximum "Forecast Tomorrow Temperature Maximum [%d°C]" <temperature> (gMetOfficeForecast) { channel="http:url:datapointforecast:forecast_tomorrow_temperature_maximum" }
Number nForecastTomorrowTemperatureFeelsLikeMaximum "Forecast Tomorrow Temperature Feels Like Maximum [%d°C]" <temperature> (gMetOfficeForecast) { channel="http:url:datapointforecast:forecast_tomorrow_temperature_feels_like_maximum" }
Number nForecastTomorrowPrecipitation "Forecast Tomorrow Precipitation [%d%%]" <rain> (gMetOfficeForecast) { channel="http:url:datapointforecast:forecast_tomorrow_precipitation" }
String strForecastTomorrowWeatherType "Forecast Tomorrow Weather Type" <status> (gMetOfficeForecast) { channel="http:url:datapointforecast:forecast_tomorrow_weather_type" }

//DAY3
Number nForecastDay3TemperatureMaximum "Forecast Day3 Temperature Maximum [%d°C]" <temperature> (gMetOfficeForecast) { channel="http:url:datapointforecast:forecast_day3_temperature_maximum" }
Number nForecastDay3TemperatureFeelsLikeMaximum "Forecast Day3 Temperature Feels Like Maximum [%d°C]" <temperature> (gMetOfficeForecast) { channel="http:url:datapointforecast:forecast_day3_temperature_feels_like_maximum" }
Number nForecastDay3Precipitation "Forecast Day3 Precipitation [%d%%]" <rain> (gMetOfficeForecast) { channel="http:url:datapointforecast:forecast_day3_precipitation" }
String strForecastDay3WeatherType "Forecast Day3 Weather Type" <status> (gMetOfficeForecast) { channel="http:url:datapointforecast:forecast_day3_weather_type" }

//DAY4
Number nForecastDay4TemperatureMaximum "Forecast Day4 Temperature Maximum [%d°C]" <temperature> (gMetOfficeForecast) { channel="http:url:datapointforecast:forecast_day4_temperature_maximum" }
Number nForecastDay4TemperatureFeelsLikeMaximum "Forecast Day4 Temperature Feels Like Maximum [%d°C]" <temperature> (gMetOfficeForecast) { channel="http:url:datapointforecast:forecast_day4_temperature_feels_like_maximum" }
Number nForecastDay4Precipitation "Forecast Day4 Precipitation [%d%%]" <rain> (gMetOfficeForecast) { channel="http:url:datapointforecast:forecast_day4_precipitation" }
String strForecastDay4WeatherType "Forecast Day4 Weather Type" <status> (gMetOfficeForecast) { channel="http:url:datapointforecast:forecast_day4_weather_type" }

//DAY5
Number nForecastDay5TemperatureMaximum "Forecast Day5 Temperature Maximum [%d°C]" <temperature> (gMetOfficeForecast) { channel="http:url:datapointforecast:forecast_day5_temperature_maximum" }
Number nForecastDay5TemperatureFeelsLikeMaximum "Forecast Day5 Temperature Feels Like Maximum [%d°C]" <temperature> (gMetOfficeForecast) { channel="http:url:datapointforecast:forecast_day5_temperature_feels_like_maximum" }
Number nForecastDay5Precipitation "Forecast Day5 Precipitation [%d%%]" <rain> (gMetOfficeForecast) { channel="http:url:datapointforecast:forecast_day5_precipitation" }
String strForecastDay5WeatherType "Forecast Day5 Weather Type" <status> (gMetOfficeForecast) { channel="http:url:datapointforecast:forecast_day5_weather_type" }

Transforms

Ensure that the JSONPATH and MAP transforms are installed. I use the MAP transform to convert the weather type number into a description (from page 10 of the DataPoint reference PDF)

Save the below into a new file called weathertype.map into the transform folder.

NA=Not available
0=Clear night
1=Sunny day
2=Partly cloudy (night)
3=Partly cloudy (day)
4=Not used
5=Mist
6=Fog
7=Cloudy
8=Overcast
9=Light rain shower (night)
10=Light rain shower (day)
11=Drizzle
12=Light rain
13=Heavy rain shower (night)
14=Heavy rain shower (day)
15=Heavy rain
16=Sleet shower (night)
17=Sleet shower (day)
18=Sleet
19=Hail shower (night)
20=Hail shower (day)
21=Hail
22=Light snow shower (night)
23=Light snow shower (day)
24=Light snow
25=Heavy snow shower (night)
26=Heavy snow shower (day)
27=Heavy snow
28=Thunder shower (night)
29=Thunder shower (day)
30=Thunder
1 Like

I started migration yesterday - and yes using UI is very intensive.
I had a few other problems on migration I needed to resolve.
I can much more easily adapt what you have done above esp as my items are already defined in file - just needs a change to add the channel.
At some point datapoint is being turned off. Need work on a solution for that

They’ve been threatening that for well over a year, but it will be replaced by the unknown DataHub.

Yup - registered for datahub - cant access anything though.
Had a few problems with your code - my openhab didnt like MAP on the channel - so I stuck it on the sitemap…or the item now all is well

Interesting.

Is the MAP Transformation Service installed - presumably yes, because it works on an Item? Someone yesterday had an issue with a Transformation Service not being recognised, but uninstalling and reinstalling the Transformation Service worked!

Both are installed - Jsonpath is giving me the info
MAP is working when used elsewhere just not as you have used it

Hi, when migrating to OH3 my previous approach using XPATH failed. I learned in this thread this is due to the novel http binding. However, I am not able to change this code snippet from OH 2.5 to OH 3 compatible code.
String MyStatus “Status [%s]” {http="<[http://user:pw@192.168.0.167/api.html?part=redstats&label=smr:30000:XPATH(//reader/@status)]"}

Unfortunately, I am also not able to format it ithe proper way for this forum as well. Anyway, any hint greatly appreciated.

Please show us what you have tried so far!

Sorry, if I had any clue I would try it.

The contents of the file

http://client1:client1@192.168.0.167:83/api.html?part=redstats&label=smr

I want to parse is

 <?xml version="1.0" encoding="UTF-8"?>
 <os version="1uild r11643" revision="11643" starttime="2021-01-12T09:25:12+0100" uptime="4570" readonly="0">
	<reader label="smr" status="CARDOK" cadid="123">
	</reader>
 </os>

I want to check whether the status of reader is CARDOK.

According to OH3 XPath - #3 by garyfree
I created in Main a thing named URL1 with base url

http://user:pw@192.168.0.167/api.html?part=redstats&label=smr

with channel

URLchannel

and State transformation

//reader/@status

as in my OH 2.5 case.

However, this generates an Error:

HANDLER_INITIALIZING_ERROR
The transformation pattern must consist of the type and the pattern separated by a colon

This is where I am stuck.

The transformation field must include the name of the transformation you’re trying to use - openHAB doesn’t try to guess, because there’s too many!

Try:

XPATH://reader/@status

though be warned that I don’t use this transform so don’t know the proper syntax.

Thank you. For clarity, I have described my problem in a more detailed manner.

I will check your proposal this eveneing. Thanks!

@hafniumzinc : Success. Thank you very much for your valuable hint!!!

  1. I had to delete user:pw from base url and transfer this information to the advanced options of the thing. I use basic authentication.
  2. In linked item, I used profile XPATH and Xpath expression //reader/@status. This seems to be equivalent to your proposal “XPATH://reader/@status”.
    Thanks!!

It is fine for me to achieve this by using the new main ui.
Can I achieve this as well using the textual way? Formerly, one line of code was sufficient like this
String MyStatus “Status [%s]” {http="<[http://user:pw@192.168.0.167/api.html?part=redstats&label=smr:30000:XPATH(//reader/@status)]"}

Yes. Show us the YAML for your Thing and we can help convert. But bear in mind that you will have to edit two files: an Items file and a Things file. It’s not all in a single Item line anymore!

This is thing’s code:
UID: http:url:011692df79
label: URL_Easy
thingTypeUID: http:url
configuration:
authMode: BASIC
ignoreSSLErrors: false
baseURL: http://192.168.0.167:83/api.html?part=redstats&label=em1
password: client1
refresh: 30
commandMethod: GET
timeout: 3000
username: client1
bufferSize: 2048
channels:

  • id: URLEasy
    channelTypeUID: http:string
    label: URL Easy
    description: “”
    configuration:
    stateTransformation: XPATH://reader/@status

Something like the following might work:

Thing http:url:URL_Easy "URL_Easy" [
	baseURL = "http://192.168.0.167:83/api.html?part=redstats&label=em1",
	refresh = "30",
	ignoreSSLErrors = "false",
	username = "client1",
	password = "client1"
]
{
	Channels:
		Type string : URLEasy "URL Easy" [
			mode = "READONLY",
			stateTransformation = "XPATH://reader/@status"
		]
}

Your Item then becomes:

String MyStatus "Status [%s]" { channel="http:url:URL_Easy:URLEasy" }

Thanks!!

First, to double check did you install the Xpath Transformation Service?