[openweathermap] Add support for One Call API #7308 (#9062)

* OH 3.0 version of the Openweathermap Onecall API Binding extension

Signed-off-by: wolfii <wolfgang.klimt@consol.de>
pull/8844/head
Wolfgang Klimt 2020-11-30 21:09:20 +01:00 committed by GitHub
parent 7fe7b60f83
commit 6afbe23ea6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 3831 additions and 17 deletions

View File

@ -10,7 +10,7 @@ This binding integrates the [OpenWeatherMap weather API](https://openweathermap.
## Supported Things
There are three supported things.
There are five supported things.
### OpenWeatherMap Account
@ -27,12 +27,25 @@ You can add as many `weather-and-forecast` things for different locations to you
The binding tries to request daily forecast data from the OpenWeatherMap API.
If the request fails, all daily forecast channel groups will be removed from the thing and further request will be omitted.
### Current UV Index And Forceast
### Current UV Index And Forecast
The third thing `uvindex` supports the [current UV Index](https://openweathermap.org/api/uvi#current) and [forecasted UV Index](https://openweathermap.org/api/uvi#forecast) for a specific location.
It requires coordinates of the location of your interest.
You can add as much `uvindex` things for different locations to your setup as you like to observe.
### One Call API Weather and Forecast
The thing `onecall` supports the [current and forecast weather data](https://openweathermap.org/api/one-call-api#how) for a specific location using the One Call API.
It requires coordinates of the location of your interest.
You can add as many `onecall` things for different locations to your setup as you like to observe.
### One Call API History Data
The thing `onecall-history` supports the [historical weather data](https://openweathermap.org/api/one-call-api#history) for a specific location using the One Call API.
It requires coordinates of the location of your interest.
You can add as many `onecall-history` things for different locations to your setup as you like to observe.
For every day in history you have to create a different thing.
## Discovery
If a system location is set, a "Local Weather And Forecast" (`weather-and-forecast`) thing and "Local UV Index" (`uvindex`) thing will be automatically discovered for this location.
@ -67,6 +80,22 @@ Once the parameters `forecastHours` or `forecastDays` will be changed, the avail
Once the parameter `forecastDays` will be changed, the available channel groups on the thing will be created or removed accordingly.
### One Call API Weather and Forecast
| Parameter | Description |
|----------------|--------------------------------------------------------------------------------------------------------------------------------|
| location | Location of weather in geographical coordinates (latitude/longitude/altitude). **Mandatory** |
| forecastMinutes| Number of minutes for minutely precipitation forecast. Optional, the default value is 0, so by default **no** minutely forecast data is fetched. (min="0", max="60"). |
| forecastHours | Number of hours for hourly forecast. Optional, the default value is 24 (min="0", max="48"). |
| forecastDays | Number of days for daily forecast (including todays forecast). Optional, the default value is 6 (min="0", max="8"). |
### One Call API History Data
| Parameter | Description |
|----------------|--------------------------------------------------------------------------------------------------------------------------------|
| location | Location of weather in geographical coordinates (latitude/longitude/altitude). **Mandatory** |
| historyDay | Number of days back in history. The API supports going back up to 5 days at the moment. **Mandatory** |
## Channels
### Station
@ -77,11 +106,15 @@ Once the parameter `forecastDays` will be changed, the available channel groups
| station | name | String | Name of the weather station or the city. |
| station | location | Location | Location of the weather station or the city. |
These channels are not supported in the One Call API
### Current Weather
| Channel Group ID | Channel ID | Item Type | Description |
|------------------|----------------------|----------------------|-------------------------------------------------------------------------|
| current | time-stamp | DateTime | Time of data observation. |
| current | sunrise | DateTime | Sunrise time of current day. Only available in the One Call API |
| current | sunset | DateTime | Sunset time of current day. Only available in the One Call API |
| current | condition | String | Current weather condition. |
| current | condition-id | String | Id of the current weather condition. **Advanced** |
| current | icon | Image | Icon representing the current weather condition. |
@ -90,6 +123,7 @@ Once the parameter `forecastDays` will be changed, the available channel groups
| current | apparent-temperature | Number:Temperature | Current apparent temperature. |
| current | pressure | Number:Pressure | Current barometric pressure. |
| current | humidity | Number:Dimensionless | Current atmospheric humidity. |
| current | dew-point | Number:Temperature | Current dew-point. Only available in the One Call API |
| current | wind-speed | Number:Speed | Current wind speed. |
| current | wind-direction | Number:Angle | Current wind direction. |
| current | gust-speed | Number:Speed | Current gust speed. **Advanced** |
@ -97,6 +131,8 @@ Once the parameter `forecastDays` will be changed, the available channel groups
| current | rain | Number:Length | Rain volume of the last hour. |
| current | snow | Number:Length | Snow volume of the last hour. |
| current | visibility | Number:Length | Current visibility. |
| current | uvindex | Number | Current UV Index. Only available in the One Call API |
**Attention**: Rain item is showing "1h" in the case when data are received from weather stations directly.
The fact is that some METAR stations do not have precipitation indicators or do not measure precipitation conditions due to some other technical reasons.
@ -104,6 +140,15 @@ In this case, we use model data.
So, rain item is showing "3h" when the API response based on model data.
The "3h" value will be divided by three to always have an estimated value for one hour.
### One Call API Minutely Forecast
Where available, the One Call API provides a minutely precipitation forecast for the next 60 minutes.
| Channel Group ID | Channel ID | Item Type | Description |
|--------------------------------------------------------|----------------------|----------------------|----------------------------------------------------------------------------|
| forecastMinutes01 ... forecastMinutes60 | time-stamp | DateTime | Time of data forecasted. |
| forecastMinutes01 ... forecastMinutes60 | precipitation | Number:Length | Expected precipitation volume. |
### 3 Hour Forecast
| Channel Group ID | Channel ID | Item Type | Description |
@ -115,8 +160,8 @@ The "3h" value will be divided by three to always have an estimated value for on
| forecastHours03, forecastHours06, ... forecastHours120 | icon-id | String | Id of the icon representing the forecasted weather condition. **Advanced** |
| forecastHours03, forecastHours06, ... forecastHours120 | temperature | Number:Temperature | Forecasted temperature. |
| forecastHours03, forecastHours06, ... forecastHours120 | apparent-temperature | Number:Temperature | Forecasted apparent temperature. |
| forecastHours03, forecastHours06, ... forecastHours120 | min-temperature | Number:Temperature | Minimum forecasted temperature. |
| forecastHours03, forecastHours06, ... forecastHours120 | max-temperature | Number:Temperature | Maximum forecasted temperature. |
| forecastHours03, forecastHours06, ... forecastHours120 | min-temperature | Number:Temperature | Minimum forecasted temperature. Not available in One Call API |
| forecastHours03, forecastHours06, ... forecastHours120 | max-temperature | Number:Temperature | Maximum forecasted temperature. Not available in One Call API |
| forecastHours03, forecastHours06, ... forecastHours120 | pressure | Number:Pressure | Forecasted barometric pressure. |
| forecastHours03, forecastHours06, ... forecastHours120 | humidity | Number:Dimensionless | Forecasted atmospheric humidity. |
| forecastHours03, forecastHours06, ... forecastHours120 | wind-speed | Number:Speed | Forecasted wind speed. |
@ -125,6 +170,14 @@ The "3h" value will be divided by three to always have an estimated value for on
| forecastHours03, forecastHours06, ... forecastHours120 | cloudiness | Number:Dimensionless | Forecasted cloudiness. |
| forecastHours03, forecastHours06, ... forecastHours120 | rain | Number:Length | Expected rain volume. |
| forecastHours03, forecastHours06, ... forecastHours120 | snow | Number:Length | Expected snow volume. |
| forecastHours01 ... forecastHours48 | dew-point | Number:Temperature | Expected dew-point. Only available in the One Call API |
| forecastHours01 ... forecastHours48 | precip-probability | Number:Dimensionles | Precipitation probability. Only available in the One Call API |
### One Call API Hourly Forecast
The One Call API provides hourly forecasts for 48 hours.
The Channel Group IDs for those are `forecastHours01` to `forecastHours48`.
See above for a description of the available channels.
### Daily Forecast
@ -135,7 +188,7 @@ The "3h" value will be divided by three to always have an estimated value for on
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | condition-id | String | Id of the forecasted weather condition. **Advanced** |
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | icon | Image | Icon representing the forecasted weather condition. |
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | icon-id | String | Id of the icon representing the forecasted weather condition. **Advanced** |
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | apparent-temperature | Number:Temperature | Forecasted apparent temperature. |
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | apparent-temperature | Number:Temperature | Forecasted apparent temperature. Not available in the One Call API |
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | min-temperature | Number:Temperature | Minimum forecasted temperature of a day. |
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | max-temperature | Number:Temperature | Maximum forecasted temperature of a day. |
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | pressure | Number:Pressure | Forecasted barometric pressure. |
@ -146,7 +199,18 @@ The "3h" value will be divided by three to always have an estimated value for on
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | cloudiness | Number:Dimensionless | Forecasted cloudiness. |
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | rain | Number:Length | Expected rain volume of a day. |
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | snow | Number:Length | Expected snow volume of a day. |
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | dew-point | Number:Temperature | Expected dew-point. Only available in the One Call API |
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | uvindex | Number | Forecasted Midday UV Index. Only available in the One Call API |
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | precip-probability | Number:Dimensionless | Precipitation probability. Only available in the One Call API |
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | morning-temperature | Number:Temperature | Expected morning temperature. Only available in the One Call API |
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | day-temperature | Number:Temperature | Expected day-temperature. Only available in the One Call API |
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | evening-temperature | Number:Temperature | Expected evening-temperature. Only available in the One Call API |
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | night-temperature | Number:Temperature | Expected night-temperature. Only available in the One Call API |
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | apparent-morning | Number:Temperature | Expected apparent temperature in the morning. Only available in the One Call API |
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | apparent-day | Number:Temperature | Expected apparent temperature in the day. Only available in the One Call API |
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | apparent-evening | Number:Temperature | Expected apparent temperature in the evening. Only available in the One Call API |
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | apparent-night | Number:Temperature | Expected apparent temperature in the night. Only available in the One Call API |
### UV Index
| Channel Group ID | Channel ID | Item Type | Description |
@ -154,6 +218,8 @@ The "3h" value will be divided by three to always have an estimated value for on
| current, forecastTomorrow, forecastDay2, ... forecastDay7 | time-stamp | DateTime | Date of data observation / forecast. |
| current, forecastTomorrow, forecastDay2, ... forecastDay7 | uvindex | Number | Current or forecasted UV Index. |
The `uvindex` channel is also available in the current data and the daily forecast of the One Call API.
## Full Example
### Things
@ -168,6 +234,15 @@ Bridge openweathermap:weather-api:api "OpenWeatherMap Account" [apikey="AAA", re
}
```
#### One Call API version
```java
Bridge openweathermap:weather-api:api "OpenWeatherMap Account" [apikey="Add your API key", refreshInterval=60, language="de"] {
Thing onecall local "Local Weather and Forecast" [location="xxx,yyy"]
Thing onecall-history local-history "Local History" [location="xxx,yyy", historyDay=1]
}
```
### Items
demo.items
@ -240,6 +315,205 @@ Number localForecastTomorrowUVIndex "UV Index for tomorrow [%d]" { channel="open
...
```
#### One Call API version
```java
DateTime localLastMeasurement "Timestamp of Last Measurement [%1$tY-%1$tm-%1$tdT%1$tH:%1$tM:%1$tS]" <time> { channel="openweathermap:onecall:api:local:current#time-stamp" }
DateTime localTodaySunrise "Todays Sunrise [%1$tY-%1$tm-%1$tdT%1$tH:%1$tM:%1$tS]" <time> { channel="openweathermap:onecall:api:local:current#sunrise" }
DateTime localTodaySunset "Todays Sunset [%1$tY-%1$tm-%1$tdT%1$tH:%1$tM:%1$tS]" <time> { channel="openweathermap:onecall:api:local:current#sunset" }
String localCurrentCondition "Current Condition [%s]" <sun_clouds> { channel="openweathermap:onecall:api:local:current#condition" }
Image localCurrentConditionIcon "Icon" { channel="openweathermap:onecall:api:local:current#Icon" }
Number:Temperature localCurrentTemperature "Current Temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:current#temperature" }
Number:Temperature localCurrentApparentTemperature "Current Apparent Temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:current#apparent-temperature" }
Number:Pressure localCurrentPressure "Current barometric Pressure [%.1f %unit%]" <pressure> { channel="openweathermap:onecall:api:local:current#pressure" }
Number:Dimensionless localCurrentHumidity "Current atmospheric Humidity [%d %unit%]" <humidity> { channel="openweathermap:onecall:api:local:current#humidity" }
Number:Temperature localCurrentDewpoint "Current Dew-point [%.1f %unit%]" <Temperature> { channea="openweathermap:onecall:api:local:eurrent#dew-point" }
Number:Speed localCurrentWindSpeed "Current wind Speed [%.1f km/h]" <wind> { channel="openweathermap:onecall:api:local:current#wind-speed" }
Number:Angle localCurrentWindDirection "Current wind Direction [%d %unit%]" <wind> { channel="openweathermap:onecall:api:local:current#wind-direction" }
Number:Speed localCurrentGustSpeed "Current Gust Speed [%.1f km/h]" <wind> { channel="openweathermap:onecall:api:local:current#gust-speed" }
Number:Dimensionless localCurrentCloudiness "Current cloudiness [%d %unit%]" <clouds> { channel="openweathermap:onecall:api:local:current#cloudiness" }
Number:Dimensionless localCurrentUvindex "Current UV Index [%d]" { channel="openweathermap:onecall:api:local:current#uvindex" }
Number:Length localCurrentRainVolume "Current rain volume [%.1f %unit%]" <rain> { channel="openweathermap:onecall:api:local:current#rain" }
Number:Length localCurrentSnowVolume "Current snow volume [%.1f %unit%]" <snow> { channel="openweathermap:onecall:api:local:current#snow" }
Number:Length localCurrentVisibility "Current visibility [%.1f km]" <visibility> { channel="openweathermap:onecall:api:local:current#visibility" }
DateTime localMinutes01ForecastTimestamp "Timestamp of forecast [%1$tY-%1$tm-%1$td]" <time> { channel="openweathermap:onecall:api:local:forecastMinutes01#time-stamp" }
Number:Length localMinutes01Precipitation "Precipitation Volume [%.1f %unit%]" <rain> { channel="openweathermap:onecall:api:local:forecastMinutes01#precipitation" }
DateTime localMinutes60ForecastTimestamp "Timestamp of forecast [%1$tY-%1$tm-%1$td]" <time> { channel="openweathermap:onecall:api:local:forecastMinutes60#time-stamp" }
Number:Length localMinutes60Precipitation "Precipitation Volume [%.1f %unit%]" <rain> { channel="openweathermap:onecall:api:local:forecastMinutes60#precipitation" }
DateTime localHours01ForecastTimestamp "Timestamp of forecast [%1$tY-%1$tm-%1$td]" <time> { channel="openweathermap:onecall:api:local:forecastHours01#time-stamp" }
String localHours01Condition "Condition [%s]" <sun_clouds> { channel="openweathermap:onecall:api:local:forecastHours01#condition" }
Image localHours01ConditionIcon "Icon" { channel="openweathermap:onecall:api:local:forecastHours01#icon" }
Number:Temperature localHours01Temperature "Temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastHours01#temperature" }
Number:Temperature localHours01ApparentTemperature "Apparent temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastHours01#apparent-temperature" }
Number:Pressure localHours01Pressure "Barometric pressure [%.1f %unit%]" <pressure> { channel="openweathermap:onecall:api:local:forecastHours01#pressure" }
Number:Dimensionless localHours01Humidity "Atmospheric humidity [%d %unit%]" <humidity> { channel="openweathermap:onecall:api:local:forecastHours01#humidity" }
Number:Temperature localHours01Dewpoint "Dew point [%.1f %unit%]" <Temperature> { channea="openweathermap:onecall:api:local:eurrent#dew-point" }
Number:Speed localHours01WindSpeed "Wind speed [%.1f km/h]" <wind> { channel="openweathermap:onecall:api:local:forecastHours01#wind-speed" }
Number:Angle localHours01WindDirection "Wind direction [%d %unit%]" <wind> { channel="openweathermap:onecall:api:local:forecastHours01#wind-direction" }
Number:Speed localHours01GustSpeed "Gust speed [%.1f km/h]" <wind> { channel="openweathermap:onecall:api:local:forecastHours01#gust-speed" }
Number:Dimensionless localHours01Cloudiness "Cloudiness [%d %unit%]" <clouds> { channel="openweathermap:onecall:api:local:forecastHours01#cloudiness" }
Number:Length localHours01RainVolume "Rain volume [%.1f %unit%]" <rain> { channel="openweathermap:onecall:api:local:forecastHours01#rain" }
Number:Length localHours01SnowVolume "Snow volume [%.1f %unit%]" <snow> { channel="openweathermap:onecall:api:local:forecastHours01#snow" }
Number:Length localHours01Visibility "Visibility [%.1f km]" <visibility> { channel="openweathermap:onecall:api:local:forecastHours01#visibility" }
DateTime localHours48ForecastTimestamp "Timestamp of forecast [%1$tY-%1$tm-%1$td]" <time> { channel="openweathermap:onecall:api:local:forecastHours48#time-stamp" }
String localHours48Condition "Condition [%s]" <sun_clouds> { channel="openweathermap:onecall:api:local:forecastHours48#condition" }
Image localHours48ConditionIcon "Icon" { channel="openweathermap:onecall:api:local:forecastHours48#icon" }
Number:Temperature localHours48Temperature "Temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastHours48#temperature" }
Number:Temperature localHours48ApparentTemperature "Apparent temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastHours48#apparent-temperature" }
Number:Pressure localHours48Pressure "Barometric pressure [%.1f %unit%]" <pressure> { channel="openweathermap:onecall:api:local:forecastHours48#pressure" }
Number:Dimensionless localHours48Humidity "Atmospheric humidity [%d %unit%]" <humidity> { channel="openweathermap:onecall:api:local:forecastHours48#humidity" }
Number:Temperature localHours48Dewpoint "Dew point [%.1f %unit%]" <Temperature> { channea="openweathermap:onecall:api:local:eurrent#dew-point" }
Number:Speed localHours48WindSpeed "Wind speed [%.1f km/h]" <wind> { channel="openweathermap:onecall:api:local:forecastHours48#wind-speed" }
Number:Angle localHours48WindDirection "Wind direction [%d %unit%]" <wind> { channel="openweathermap:onecall:api:local:forecastHours48#wind-direction" }
Number:Speed localHours48GustSpeed "Gust speed [%.1f km/h]" <wind> { channel="openweathermap:onecall:api:local:forecastHours48#gust-speed" }
Number:Dimensionless localHours48Cloudiness "Cloudiness [%d %unit%]" <clouds> { channel="openweathermap:onecall:api:local:forecastHours48#cloudiness" }
Number:Length localHours48RainVolume "Rain volume [%.1f %unit%]" <rain> { channel="openweathermap:onecall:api:local:forecastHours48#rain" }
Number:Length localHours48SnowVolume "Snow volume [%.1f %unit%]" <snow> { channel="openweathermap:onecall:api:local:forecastHours48#snow" }
Number:Length localHours48Visibility "Visibility [%.1f km]" <visibility> { channel="openweathermap:onecall:api:local:forecastHours48#visibility" }
DateTime localTodayTimestamp "Timestamp of forecast [%1$tY-%1$tm-%1$td]" <time> { channel="openweathermap:onecall:api:local:forecastToday#time-stamp" }
String localTodayCondition "Condition [%s]" <sun_clouds> { channel="openweathermap:onecall:api:local:forecastToday#condition" }
Image localTodayConditionIcon "Icon" { channel="openweathermap:onecall:api:local:forecastToday#icon" }
Number:Temperature localTodayMinTemperature "Minimum temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastToday#min-temperature" }
Number:Temperature localTodayMaxTemperature "Maximum temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastToday#max-temperature" }
Number:Temperature localTodayMorningTemperature "Morning temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastToday#morning-temperature" }
Number:Temperature localTodayDayTemperature "Day temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastToday#day-temperature" }
Number:Temperature localTodayEveningTemperature "Evening temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastToday#evening-temperature" }
Number:Temperature localTodayNightTemperature "Night temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastToday#night-temperature" }
Number:Temperature localTodayMorningApparent "Morning apparent Temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastToday#apparent-morning" }
Number:Temperature localTodayDayApparent "Day apparent Temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastToday#apparent-day" }
Number:Temperature localTodayEveningApparent "Evening apparent Temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastToday#apparent-evening" }
Number:Temperature localTodayNightApparent "Night apparent Temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastToday#apparent-night" }
Number:Pressure localTodayPressure "Barometric pressure [%.1f %unit%]" <pressure> { channel="openweathermap:onecall:api:local:forecastToday#pressure" }
Number:Dimensionless localTodayHumidity "Atmospheric humidity [%d %unit%]" <humidity> { channel="openweathermap:onecall:api:local:forecastToday#humidity" }
Number:Temperature localTodayDewpoint "Dew point [%.1f %unit%]" <Temperature> { channea="openweathermap:onecall:api:local:forecastToday#dew-point" }
Number:Speed localTodayWindSpeed "Wind speed [%.1f km/h]" <wind> { channel="openweathermap:onecall:api:local:forecastToday#wind-speed" }
Number:Angle localTodayWindDirection "Wind direction [%d %unit%]" <wind> { channel="openweathermap:onecall:api:local:forecastToday#wind-direction" }
Number:Speed localTodayGustSpeed "Gust speed [%.1f km/h]" <wind> { channel="openweathermap:onecall:api:local:forecastToday#gust-speed" }
Number:Dimensionless localTodayPrecipProbability "Precipitation probability [%.1f]" { channel="openweathermap:onecall:api:local:forecastToday#probability" }
Number:Dimensionless localTodayCloudiness "Cloudiness [%d %unit%]" <clouds> { channel="openweathermap:onecall:api:local:forecastToday#cloudiness" }
Number:Dimensionless localTodayUvindex "Current UV Index [%d]" { channel="openweathermap:onecall:api:local:forecastToday#uvindex" }
Number:Length localTodayRainVolume "Rain volume [%.1f %unit%]" <rain> { channel="openweathermap:onecall:api:local:forecastToday#rain" }
Number:Length localTodaySnowVolume "Snow volume [%.1f %unit%]" <snow> { channel="openweathermap:onecall:api:local:forecastToday#snow" }
Number:Length localTodayVisibility "Visibility [%.1f km]" <visibility> { channel="openweathermap:onecall:api:local:forecastToday#visibility" }
DateTime localTomorrowTimestamp "Timestamp of forecast [%1$tY-%1$tm-%1$td]" <time> { channel="openweathermap:onecall:api:local:forecastTomorrow#time-stamp" }
DateTime localTomorrowSunrise "Tomorrow Sunrise [%1$tY-%1$tm-%1$tdT%1$tH:%1$tM:%1$tS]" <time> { channel="openweathermap:onecall:api:local:forecastTomorrow#sunrise" }
DateTime localTomorrowSunset "Tomorrow Sunset [%1$tY-%1$tm-%1$tdT%1$tH:%1$tM:%1$tS]" <time> { channel="openweathermap:onecall:api:local:forecastTomorrow#sunset" }
String localTomorrowCondition "Condition [%s]" <sun_clouds> { channel="openweathermap:onecall:api:local:forecastTomorrow#condition" }
Image localTomorrowConditionIcon "Icon" { channel="openweathermap:onecall:api:local:forecastTomorrow#icon" }
Number:Temperature localTomorrowMinTemperature "Minimum temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastTomorrow#min-temperature" }
Number:Temperature localTomorrowMaxTemperature "Maximum temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastTomorrow#max-temperature" }
Number:Temperature localTomorrowMorningTemperature "Morning temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastTomorrow#morning-temperature" }
Number:Temperature localTomorrowDayTemperature "Day temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastTomorrow#day-temperature" }
Number:Temperature localTomorrowEveningTemperature "Evening temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastTomorrow#evening-temperature" }
Number:Temperature localTomorrowNightTemperature "Night temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastTomorrow#night-temperature" }
Number:Temperature localTomorrowMorningApparent "Morning apparent Temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastTomorrow#apparent-morning" }
Number:Temperature localTomorrowDayApparent "Day apparent Temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastTomorrow#apparent-day" }
Number:Temperature localTomorrowEveningApparent "Evening apparent Temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastTomorrow#apparent-evening" }
Number:Temperature localTomorrowNightApparent "Night apparent Temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastTomorrow#apparent-night" }
Number:Pressure localTomorrowPressure "Barometric pressure [%.1f %unit%]" <pressure> { channel="openweathermap:onecall:api:local:forecastTomorrow#pressure" }
Number:Dimensionless localTomorrowHumidity "Atmospheric humidity [%d %unit%]" <humidity> { channel="openweathermap:onecall:api:local:forecastTomorrow#humidity" }
Number:Temperature localTomorrowDewpoint "Dew point [%.1f %unit%]" <Temperature> { channea="openweathermap:onecall:api:local:forecastTomorrow#dew-point" }
Number:Speed localTomorrowWindSpeed "Wind speed [%.1f km/h]" <wind> { channel="openweathermap:onecall:api:local:forecastTomorrow#wind-speed" }
Number:Angle localTomorrowWindDirection "Wind direction [%d %unit%]" <wind> { channel="openweathermap:onecall:api:local:forecastTomorrow#wind-direction" }
Number:Speed localTomorrowGustSpeed "Gust speed [%.1f km/h]" <wind> { channel="openweathermap:onecall:api:local:forecastTomorrow#gust-speed" }
Number:Dimensionless localTomorrowPrecipProbability "Precipitation probability [%.1f]" { channel="openweathermap:onecall:api:local:forecastTomorrow#probability" }
Number:Dimensionless localTomorrowCloudiness "Cloudiness [%d %unit%]" <clouds> { channel="openweathermap:onecall:api:local:forecastTomorrow#cloudiness" }
Number:Dimensionless localTomorrowUvindex "Current UV Index [%d]" { channel="openweathermap:onecall:api:local:forecastTomorrow#uvindex" }
Number:Length localTomorrowRainVolume "Rain volume [%.1f %unit%]" <rain> { channel="openweathermap:onecall:api:local:forecastTomorrow#rain" }
Number:Length localTomorrowSnowVolume "Snow volume [%.1f %unit%]" <snow> { channel="openweathermap:onecall:api:local:forecastTomorrow#snow" }
Number:Length localTomorrowVisibility "Visibility [%.1f km]" <visibility> { channel="openweathermap:onecall:api:local:forecastTomorrow#visibility" }
DateTime localDay6Timestamp "Timestamp of forecast [%1$tY-%1$tm-%1$td]" <time> { channel="openweathermap:onecall:api:local:forecastDay6#time-stamp" }
DateTime localDay6Sunrise "Sunrise [%1$tY-%1$tm-%1$tdT%1$tH:%1$tM:%1$tS]" <time> { channel="openweathermap:onecall:api:local:forecastDay6#sunrise" }
DateTime localDay6Sunset "Sunset [%1$tY-%1$tm-%1$tdT%1$tH:%1$tM:%1$tS]" <time> { channel="openweathermap:onecall:api:local:forecastDay6#sunset" }
String localDay6Condition "Condition [%s]" <sun_clouds> { channel="openweathermap:onecall:api:local:forecastDay6#condition" }
Image localDay6ConditionIcon "Icon" { channel="openweathermap:onecall:api:local:forecastDay6#icon" }
Number:Temperature localDay6MinTemperature "Minimum temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastDay6#min-temperature" }
Number:Temperature localDay6MaxTemperature "Maximum temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastDay6#max-temperature" }
Number:Temperature localDay6MorningTemperature "Morning temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastDay6#morning-temperature" }
Number:Temperature localDay6DayTemperature "Day temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastDay6#day-temperature" }
Number:Temperature localDay6EveningTemperature "Evening temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastDay6#evening-temperature" }
Number:Temperature localDay6NightTemperature "Night temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastDay6#night-temperature" }
Number:Temperature localDay6MorningApparent "Morning apparent Temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastDay6#apparent-morning" }
Number:Temperature localDay6DayApparent "Day apparent Temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastDay6#apparent-day" }
Number:Temperature localDay6EveningApparent "Evening apparent Temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastDay6#apparent-evening" }
Number:Temperature localDay6NightApparent "Night apparent Temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall:api:local:forecastDay6#apparent-night" }
Number:Pressure localDay6Pressure "Barometric pressure [%.1f %unit%]" <pressure> { channel="openweathermap:onecall:api:local:forecastDay6#pressure" }
Number:Dimensionless localDay6Humidity "Atmospheric humidity [%d %unit%]" <humidity> { channel="openweathermap:onecall:api:local:forecastDay6#humidity" }
Number:Temperature localDay6Dewpoint "Dew point [%.1f %unit%]" <Temperature> { channea="openweathermap:onecall:api:local:forecastDay6#dew-point" }
Number:Speed localDay6WindSpeed "Wind speed [%.1f km/h]" <wind> { channel="openweathermap:onecall:api:local:forecastDay6#wind-speed" }
Number:Angle localDay6WindDirection "Wind direction [%d %unit%]" <wind> { channel="openweathermap:onecall:api:local:forecastDay6#wind-direction" }
Number:Speed localDay6GustSpeed "Gust speed [%.1f km/h]" <wind> { channel="openweathermap:onecall:api:local:forecastDay6#gust-speed" }
Number:Dimensionless localDay6PrecipProbability "Precipitation probability [%.1f]" { channel="openweathermap:onecall:api:local:forecastDay6#probability" }
Number:Dimensionless localDay6Cloudiness "Cloudiness [%d %unit%]" <clouds> { channel="openweathermap:onecall:api:local:forecastDay6#cloudiness" }
Number:Dimensionless localDay6Uvindex "Current UV Index [%d]" { channel="openweathermap:onecall:api:local:forecastDay6#uvindex" }
Number:Length localDay6RainVolume "Rain volume [%.1f %unit%]" <rain> { channel="openweathermap:onecall:api:local:forecastDay6#rain" }
Number:Length localDay6SnowVolume "Snow volume [%.1f %unit%]" <snow> { channel="openweathermap:onecall:api:local:forecastDay6#snow" }
Number:Length localDay6Visibility "Visibility [%.1f km]" <visibility> { channel="openweathermap:onecall:api:local:forecastDay6#visibility" }
DateTime localHistory1LastMeasurement "Timestamp of history [%1$tY-%1$tm-%1$td]" <time> { channel="openweathermap:onecall-history:api:local-history:history#time-stamp" }
DateTime localHistory1Sunrise "Sunrise [%1$tY-%1$tm-%1$tdT%1$tH:%1$tM:%1$tS]" <time> { channel="openweathermap:onecall-history:api:local-history:history#sunrise" }
DateTime localHistory1Sunset "Sunset [%1$tY-%1$tm-%1$tdT%1$tH:%1$tM:%1$tS]" <time> { channel="openweathermap:onecall-history:api:local-history:history#sunset" }
String localHistory1Condition "Condition [%s]" <sun_clouds> { channel="openweathermap:onecall-history:api:local-history:history#condition" }
Image localHistory1ConditionIcon "Icon" { channel="openweathermap:onecall-history:api:local-history:history#icon" }
Number:Temperature localHistory1Temperature "Temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall-history:api:local-history:history#temperature" }
Number:Temperature localHistory1ApparentTemperature "Apparent temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall-history:api:local-history:history#apparent-temperature" }
Number:Pressure localHistory1Pressure "Barometric pressure [%.1f %unit%]" <pressure> { channel="openweathermap:onecall-history:api:local-history:history#pressure" }
Number:Dimensionless localHistory1Humidity "Atmospheric humidity [%d %unit%]" <humidity> { channel="openweathermap:onecall-history:api:local-history:history#humidity" }
Number:Temperature localHistory1Dewpoint "Dew point [%.1f %unit%]" <Temperature> { channea="openweathermap:onecall-history:api:local-history:eurrent#dew-point" }
Number:Speed localHistory1WindSpeed "Wind speed [%.1f km/h]" <wind> { channel="openweathermap:onecall-history:api:local-history:history#wind-speed" }
Number:Angle localHistory1WindDirection "Wind direction [%d %unit%]" <wind> { channel="openweathermap:onecall-history:api:local-history:history#wind-direction" }
Number:Speed localHistory1GustSpeed "Gust speed [%.1f km/h]" <wind> { channel="openweathermap:onecall-history:api:local-history:history#gust-speed" }
Number:Dimensionless localHistory1Cloudiness "Cloudiness [%d %unit%]" <clouds> { channel="openweathermap:onecall-history:api:local-history:history#cloudiness" }
Number:Dimensionless localHistory1Uvindex "UV Index [%d]" { channel="openweathermap:onecall-history:api:local-history:history#uvindex" }
Number:Length localHistory1RainVolume "Rain volume [%.1f %unit%]" <rain> { channel="openweathermap:onecall-history:api:local-history:history#rain" }
Number:Length localHistory1SnowVolume "Snow volume [%.1f %unit%]" <snow> { channel="openweathermap:onecall-history:api:local-history:history#snow" }
Number:Length localHistory1Visibility "Visibility [%.1f km]" <visibility> { channel="openweathermap:onecall-history:api:local-history:history#visibility" }
DateTime localHistory1Hours01LastMeasurement "Timestamp of history [%1$tY-%1$tm-%1$td]" <time> { channel="openweathermap:onecall-history:api:local-history:historyHours01#time-stamp" }
DateTime localHistory1Hours01Sunrise "Sunrise [%1$tY-%1$tm-%1$tdT%1$tH:%1$tM:%1$tS]" <time> { channel="openweathermap:onecall-history:api:local-history:historyHours01#sunrise" }
DateTime localHistory1Hours01Sunset "Sunset [%1$tY-%1$tm-%1$tdT%1$tH:%1$tM:%1$tS]" <time> { channel="openweathermap:onecall-history:api:local-history:historyHours01#sunset" }
String localHistory1Hours01Condition "Condition [%s]" <sun_clouds> { channel="openweathermap:onecall-history:api:local-history:historyHours01#condition" }
Image localHistory1Hours01ConditionIcon "Icon" { channel="openweathermap:onecall-history:api:local-history:historyHours01#icon" }
Number:Temperature localHistory1Hours01Temperature "Minimum temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall-history:api:local-history:historyHours01#temperature" }
Number:Temperature localHistory1Hours01ApparentTemperature "Minimum temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall-history:api:local-history:historyHours01#apparent-temperature" }
Number:Pressure localHistory1Hours01Pressure "Barometric pressure [%.1f %unit%]" <pressure> { channel="openweathermap:onecall-history:api:local-history:historyHours01#pressure" }
Number:Dimensionless localHistory1Hours01Humidity "Atmospheric humidity [%d %unit%]" <humidity> { channel="openweathermap:onecall-history:api:local-history:historyHours01#humidity" }
Number:Temperature localHistory1Hours01Dewpoint "Dew point [%.1f %unit%]" <Temperature> { channea="openweathermap:onecall-history:api:local-history:eurrent#dew-point" }
Number:Speed localHistory1Hours01WindSpeed "Wind speed [%.1f km/h]" <wind> { channel="openweathermap:onecall-history:api:local-history:historyHours01#wind-speed" }
Number:Angle localHistory1Hours01WindDirection "Wind direction [%d %unit%]" <wind> { channel="openweathermap:onecall-history:api:local-history:historyHours01#wind-direction" }
Number:Speed localHistory1Hours01GustSpeed "Gust speed [%.1f km/h]" <wind> { channel="openweathermap:onecall-history:api:local-history:historyHours01#gust-speed" }
Number:Dimensionless localHistory1Hours01Cloudiness "Cloudiness [%d %unit%]" <clouds> { channel="openweathermap:onecall-history:api:local-history:historyHours01#cloudiness" }
Number:Dimensionless localHistory1Hours01Uvindex "Current UV Index [%d]" { channel="openweathermap:onecall-history:api:local-history:historyHours01#uvindex" }
Number:Length localHistory1Hours01RainVolume "Rain volume [%.1f %unit%]" <rain> { channel="openweathermap:onecall-history:api:local-history:historyHours01#rain" }
Number:Length localHistory1Hours01SnowVolume "Snow volume [%.1f %unit%]" <snow> { channel="openweathermap:onecall-history:api:local-history:historyHours01#snow" }
Number:Length localHistory1Hours01Visibility "Visibility [%.1f km]" <visibility> { channel="openweathermap:onecall-history:api:local-history:historyHours01#visibility" }
DateTime localHistory1Hours24LastMeasurement "Timestamp of history [%1$tY-%1$tm-%1$td]" <time> { channel="openweathermap:onecall-history:api:local-history:historyHours24#time-stamp" }
DateTime localHistory1Hours24Sunrise "Sunrise [%1$tY-%1$tm-%1$tdT%1$tH:%1$tM:%1$tS]" <time> { channel="openweathermap:onecall-history:api:local-history:historyHours24#sunrise" }
DateTime localHistory1Hours24Sunset "Sunset [%1$tY-%1$tm-%1$tdT%1$tH:%1$tM:%1$tS]" <time> { channel="openweathermap:onecall-history:api:local-history:historyHours24#sunset" }
String localHistory1Hours24Condition "Condition [%s]" <sun_clouds> { channel="openweathermap:onecall-history:api:local-history:historyHours24#condition" }
Image localHistory1Hours24ConditionIcon "Icon" { channel="openweathermap:onecall-history:api:local-history:historyHours24#icon" }
Number:Temperature localHistory1Hours24Temperature "Minimum temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall-history:api:local-history:historyHours24#temperature" }
Number:Temperature localHistory1Hours24ApparentTemperature "Minimum temperature [%.1f %unit%]" <temperature> { channel="openweathermap:onecall-history:api:local-history:historyHours24#apparent-temperature" }
Number:Pressure localHistory1Hours24Pressure "Barometric pressure [%.1f %unit%]" <pressure> { channel="openweathermap:onecall-history:api:local-history:historyHours24#pressure" }
Number:Dimensionless localHistory1Hours24Humidity "Atmospheric humidity [%d %unit%]" <humidity> { channel="openweathermap:onecall-history:api:local-history:historyHours24#humidity" }
Number:Temperature localHistory1Hours24Dewpoint "Dew point [%.1f %unit%]" <Temperature> { channea="openweathermap:onecall-history:api:local-history:eurrent#dew-point" }
Number:Speed localHistory1Hours24WindSpeed "Wind speed [%.1f km/h]" <wind> { channel="openweathermap:onecall-history:api:local-history:historyHours24#wind-speed" }
Number:Angle localHistory1Hours24WindDirection "Wind direction [%d %unit%]" <wind> { channel="openweathermap:onecall-history:api:local-history:historyHours24#wind-direction" }
Number:Speed localHistory1Hours24GustSpeed "Gust speed [%.1f km/h]" <wind> { channel="openweathermap:onecall-history:api:local-history:historyHours24#gust-speed" }
Number:Dimensionless localHistory1Hours24Cloudiness "Cloudiness [%d %unit%]" <clouds> { channel="openweathermap:onecall-history:api:local-history:historyHours24#cloudiness" }
Number:Dimensionless localHistory1Hours24Uvindex "Current UV Index [%d]" { channel="openweathermap:onecall-history:api:local-history:historyHours24#uvindex" }
Number:Length localHistory1Hours24RainVolume "Rain volume [%.1f %unit%]" <rain> { channel="openweathermap:onecall-history:api:local-history:historyHours24#rain" }
Number:Length localHistory1Hours24SnowVolume "Snow volume [%.1f %unit%]" <snow> { channel="openweathermap:onecall-history:api:local-history:historyHours24#snow" }
Number:Length localHistory1Hours24visibility "Visibility [%.1f km]" <visibility> { channel="openweathermap:onecall-history:api:local-history:historyHours24#visibility" }
```
### Sitemap
demo.sitemap
@ -323,3 +597,139 @@ sitemap demo label="OpenWeatherMap" {
}
}
```
#### One Call API version
Please note that this sitemap does not cover all items of the example above.
```perl
sitemap demo label="OpenWeatherMapOneCall" {
Frame label="Current local weather" {
Text item=localLastMeasurement
Text item=localCurrentCondition
Image item=localCurrentConditionIcon
Text item=localCurrentTemperature
Text item=localCurrentApparentTemperature
Text item=localCurrentPressure
Text item=localCurrentHumidity
Text item=localCurrentDewpoint
Text item=localCurrentWindSpeed
Text item=localCurrentWindDirection
Text item=localCurrentGustSpeed
Text item=localCurrentCloudiness
Text item=localCurrentUvindex
Text item=localCurrentRainVolume
Text item=localCurrentSnowVolume
Text item=localCurrentVisibility
}
Frame label="Local forecast for today" {
Text item=localTodayTimestamp
Text item=localTodayPrecipProbability
Text item=localTodaySunrise
Text item=localTodaySunset
Text item=localTodayCondition
Image item=localTodayConditionIcon
Text item=localTodayMinTemperature
Text item=localTodayMaxTemperature
Text item=localTodayMorningTemperature
Text item=localTodayMorningApparent
Text item=localTodayDayTemperature
Text item=localTodayDayApparent
Text item=localTodayEveningTemperature
Text item=localTodayEveningApparent
Text item=localTodayNightTemperature
Text item=localTodayNightApparent
Text item=localTodayPressure
Text item=localTodayHumidity
Text item=localTodayDewpoint
Text item=localTodayWindSpeed
Text item=localTodayWindDirection
Text item=localTodayGustSpeed
Text item=localTodayCloudiness
Text item=localTodayUvindex
Text item=localTodayRainVolume
Text item=localTodaySnowVolume
Text item=localTodayVisibility
}
Frame label="Local forecast for tomorrow" {
Text item=localTomorrowTimestamp
Text item=localTomorrowPrecipProbability
Text item=localTomorrowSunrise
Text item=localTomorrowSunset
Text item=localTomorrowCondition
Image item=localTomorrowConditionIcon
Text item=localTomorrowMinTemperature
Text item=localTomorrowMaxTemperature
Text item=localTomorrowMorningTemperature
Text item=localTomorrowMorningApparent
Text item=localTomorrowDayTemperature
Text item=localTomorrowDayApparent
Text item=localTomorrowEveningTemperature
Text item=localTomorrowEveningApparent
Text item=localTomorrowNightTemperature
Text item=localTomorrowNightApparent
Text item=localTomorrowPressure
Text item=localTomorrowHumidity
Text item=localTomorrowDewpoint
Text item=localTomorrowWindSpeed
Text item=localTomorrowWindDirection
Text item=localTomorrowGustSpeed
Text item=localTomorrowCloudiness
Text item=localTomorrowUvindex
Text item=localTomorrowRainVolume
Text item=localTomorrowSnowVolume
Text item=localTomorrowVisibility
}
Frame label="Local forecast in 6 days" {
Text item=localDay6Timestamp
Text item=localDay6PrecipProbability
Text item=localDay6Sunrise
Text item=localDay6Sunset
Text item=localDay6Condition
Image item=localDay6ConditionIcon
Text item=localDay6MinTemperature
Text item=localDay6MaxTemperature
Text item=localDay6MorningTemperature
Text item=localDay6MorningApparent
Text item=localDay6DayTemperature
Text item=localDay6DayApparent
Text item=localDay6EveningTemperature
Text item=localDay6EveningApparent
Text item=localDay6NightTemperature
Text item=localDay6NightApparent
Text item=localDay6Pressure
Text item=localDay6Humidity
Text item=localDay6Dewpoint
Text item=localDay6WindSpeed
Text item=localDay6WindDirection
Text item=localDay6GustSpeed
Text item=localDay6Cloudiness
Text item=localDay6Uvindex
Text item=localDay6RainVolume
Text item=localDay6SnowVolume
Text item=localDay6Visibility
Text item=localDay6SnowVolume
}
Frame label="Yesterdays local weather" {
Text item=localHistory1LastMeasurement
Text item=localHistory1Condition
Text item=localHistory1Sunrise
Text item=localHistory1Sunset
Image item=localHistory1ConditionIcon
Text item=localHistory1Temperature
Text item=localHistory1ApparentTemperature
Text item=localHistory1Pressure
Text item=localHistory1Humidity
Text item=localHistory1Dewpoint
Text item=localHistory1WindSpeed
Text item=localHistory1WindDirection
Text item=localHistory1GustSpeed
Text item=localHistory1Cloudiness
Text item=localHistory1Uvindex
Text item=localHistory1RainVolume
Text item=localHistory1SnowVolume
Text item=localHistory1Visibility
}
}
```

View File

@ -36,6 +36,10 @@ public class OpenWeatherMapBindingConstants {
public static final ThingTypeUID THING_TYPE_WEATHER_AND_FORECAST = new ThingTypeUID(BINDING_ID,
"weather-and-forecast");
public static final ThingTypeUID THING_TYPE_UVINDEX = new ThingTypeUID(BINDING_ID, "uvindex");
// One Call API forecast
public static final ThingTypeUID THING_TYPE_ONECALL_WEATHER_AND_FORECAST = new ThingTypeUID(BINDING_ID, "onecall");
// One Call API historical data
public static final ThingTypeUID THING_TYPE_ONECALL_HISTORY = new ThingTypeUID(BINDING_ID, "onecall-history");
// List of all properties
public static final String CONFIG_API_KEY = "apikey";
@ -49,6 +53,14 @@ public class OpenWeatherMapBindingConstants {
public static final ChannelGroupTypeUID CHANNEL_GROUP_TYPE_DAILY_FORECAST = new ChannelGroupTypeUID(BINDING_ID,
"dailyForecast");
public static final ChannelGroupTypeUID CHANNEL_GROUP_TYPE_UVINDEX = new ChannelGroupTypeUID(BINDING_ID, "uvindex");
public static final ChannelGroupTypeUID CHANNEL_GROUP_TYPE_ONECALL_MINUTELY_FORECAST = new ChannelGroupTypeUID(
BINDING_ID, "oneCallMinutely");
public static final ChannelGroupTypeUID CHANNEL_GROUP_TYPE_ONECALL_HOURLY_FORECAST = new ChannelGroupTypeUID(
BINDING_ID, "oneCallHourly");
public static final ChannelGroupTypeUID CHANNEL_GROUP_TYPE_ONECALL_DAILY_FORECAST = new ChannelGroupTypeUID(
BINDING_ID, "oneCallDaily");
public static final ChannelGroupTypeUID CHANNEL_GROUP_TYPE_ONECALL_CURRENT = new ChannelGroupTypeUID(BINDING_ID,
"oneCallCurrent");
// List of all channel groups
public static final String CHANNEL_GROUP_STATION = "station";
@ -56,30 +68,47 @@ public class OpenWeatherMapBindingConstants {
public static final String CHANNEL_GROUP_FORECAST_TODAY = "forecastToday";
public static final String CHANNEL_GROUP_FORECAST_TOMORROW = "forecastTomorrow";
public static final String CHANNEL_GROUP_CURRENT_UVINDEX = "current";
public static final String CHANNEL_GROUP_ONECALL_CURRENT = "current";
public static final String CHANNEL_GROUP_ONECALL_HISTORY = "history";
public static final String CHANNEL_GROUP_ONECALL_TODAY = "forecastToday";
public static final String CHANNEL_GROUP_ONECALL_TOMORROW = "forecastTomorrow";
// List of all channels
public static final String CHANNEL_STATION_ID = "id";
public static final String CHANNEL_STATION_NAME = "name";
public static final String CHANNEL_STATION_LOCATION = "location";
public static final String CHANNEL_TIME_STAMP = "time-stamp";
public static final String CHANNEL_SUNRISE = "sunrise";
public static final String CHANNEL_SUNSET = "sunset";
public static final String CHANNEL_CONDITION = "condition";
public static final String CHANNEL_CONDITION_ID = "condition-id";
public static final String CHANNEL_CONDITION_ICON = "icon";
public static final String CHANNEL_CONDITION_ICON_ID = "icon-id";
public static final String CHANNEL_TEMPERATURE = "temperature";
public static final String CHANNEL_APPARENT_TEMPERATURE = "apparent-temperature";
public static final String CHANNEL_APPARENT_MORNING = "apparent-morning";
public static final String CHANNEL_APPARENT_DAY = "apparent-day";
public static final String CHANNEL_APPARENT_EVENING = "apparent-evening";
public static final String CHANNEL_APPARENT_NIGHT = "apparent-night";
public static final String CHANNEL_MIN_TEMPERATURE = "min-temperature";
public static final String CHANNEL_MAX_TEMPERATURE = "max-temperature";
public static final String CHANNEL_MORNING_TEMPERATURE = "morning-temperature";
public static final String CHANNEL_DAY_TEMPERATURE = "day-temperature";
public static final String CHANNEL_EVENING_TEMPERATURE = "evening-temperature";
public static final String CHANNEL_NIGHT_TEMPERATURE = "night-temperature";
public static final String CHANNEL_DEW_POINT = "dew-point";
public static final String CHANNEL_PRESSURE = "pressure";
public static final String CHANNEL_HUMIDITY = "humidity";
public static final String CHANNEL_WIND_SPEED = "wind-speed";
public static final String CHANNEL_WIND_DIRECTION = "wind-direction";
public static final String CHANNEL_GUST_SPEED = "gust-speed";
public static final String CHANNEL_CLOUDINESS = "cloudiness";
public static final String CHANNEL_PRECIP_PROBABILITY = "precip-probability";
public static final String CHANNEL_RAIN = "rain";
public static final String CHANNEL_SNOW = "snow";
public static final String CHANNEL_VISIBILITY = "visibility";
public static final String CHANNEL_UVINDEX = "uvindex";
public static final String CHANNEL_PRECIPITATION = "precipitation";
// List of all configuration
public static final String CONFIG_FORECAST_DAYS = "forecastDays";

View File

@ -0,0 +1,28 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openweathermap.internal.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link OpenWeatherMapOneCallConfiguration} is the class used to match the
* {@link org.openhab.binding.openweathermap.internal.handler.OpenWeatherMapOneCallHandler}s configuration.
*
* @author Wolfgang Klimt - Initial contribution
*/
@NonNullByDefault
public class OpenWeatherMapOneCallConfiguration extends OpenWeatherMapLocationConfiguration {
public int forecastMinutes;
public int forecastHours;
public int forecastDays;
}

View File

@ -0,0 +1,26 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openweathermap.internal.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link OpenWeatherMapOneCallHistoryConfiguration} is the class used to match the
* {@link org.openhab.binding.openweathermap.internal.handler.OpenWeatherMapOneCallHistoryHandler}s configuration.
*
* @author Wolfgang Klimt - Initial contribution
*/
@NonNullByDefault
public class OpenWeatherMapOneCallHistoryConfiguration extends OpenWeatherMapLocationConfiguration {
public int historyDay;
}

View File

@ -16,10 +16,11 @@ import static java.util.stream.Collectors.joining;
import static org.eclipse.jetty.http.HttpMethod.GET;
import static org.eclipse.jetty.http.HttpStatus.*;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@ -38,6 +39,8 @@ import org.openhab.binding.openweathermap.internal.dto.OpenWeatherMapJsonDailyFo
import org.openhab.binding.openweathermap.internal.dto.OpenWeatherMapJsonHourlyForecastData;
import org.openhab.binding.openweathermap.internal.dto.OpenWeatherMapJsonUVIndexData;
import org.openhab.binding.openweathermap.internal.dto.OpenWeatherMapJsonWeatherData;
import org.openhab.binding.openweathermap.internal.dto.onecall.OpenWeatherMapOneCallAPIData;
import org.openhab.binding.openweathermap.internal.dto.onecallhist.OpenWeatherMapOneCallHistAPIData;
import org.openhab.binding.openweathermap.internal.handler.OpenWeatherMapAPIHandler;
import org.openhab.core.cache.ByteArrayFileCache;
import org.openhab.core.cache.ExpiringCacheMap;
@ -73,6 +76,8 @@ public class OpenWeatherMapConnection {
private static final String PARAM_LON = "lon";
private static final String PARAM_LANG = "lang";
private static final String PARAM_FORECAST_CNT = "cnt";
private static final String PARAM_HISTORY_DATE = "dt";
private static final String PARAM_EXCLUDE = "exclude";
// Current weather data (see https://openweathermap.org/current)
private static final String WEATHER_URL = "https://api.openweathermap.org/data/2.5/weather";
@ -85,6 +90,9 @@ public class OpenWeatherMapConnection {
private static final String UVINDEX_FORECAST_URL = "https://api.openweathermap.org/data/2.5/uvi/forecast";
// Weather icons (see https://openweathermap.org/weather-conditions)
private static final String ICON_URL = "https://openweathermap.org/img/w/%s.png";
// One Call API (see https://openweathermap.org/api/one-call-api )
private static final String ONECALL_URL = "https://api.openweathermap.org/data/2.5/onecall";
private static final String ONECALL_HISTORY_URL = "https://api.openweathermap.org/data/2.5/onecall/timemachine";
private final OpenWeatherMapAPIHandler handler;
private final HttpClient httpClient;
@ -227,7 +235,7 @@ public class OpenWeatherMapConnection {
if (IMAGE_CACHE.containsKey(url)) {
try {
return new RawType(IMAGE_CACHE.get(url), PNG_CONTENT_TYPE);
} catch (IOException e) {
} catch (Exception e) {
LoggerFactory.getLogger(OpenWeatherMapConnection.class)
.trace("Failed to download the content of URL '{}'", url, e);
}
@ -245,6 +253,65 @@ public class OpenWeatherMapConnection {
return HttpUtil.downloadImage(url);
}
/**
* Get Weather data from the OneCall API for the given location. See https://openweathermap.org/api/one-call-api for
* details
*
* @param location location represented as {@link PointType}
* @param excludeMinutely if true, will not fetch minutely forecast data from the server
* @param excludeHourly if true, will not fethh hourly forecast data from the server
* @param excludeDaily if true, will not fetch hourly forecast data from the server
* @return
* @throws JsonSyntaxException
* @throws OpenWeatherMapCommunicationException
* @throws OpenWeatherMapConfigurationException
*/
public synchronized @Nullable OpenWeatherMapOneCallAPIData getOneCallAPIData(@Nullable PointType location,
boolean excludeMinutely, boolean excludeHourly, boolean excludeDaily)
throws JsonSyntaxException, OpenWeatherMapCommunicationException, OpenWeatherMapConfigurationException {
Map<String, String> params = getRequestParams(handler.getOpenWeatherMapAPIConfig(), location);
StringBuilder exclude = new StringBuilder("");
if (excludeMinutely) {
exclude.append("minutely");
}
if (excludeHourly) {
exclude.append(exclude.length() > 0 ? "," : "").append("hourly");
}
if (excludeDaily) {
exclude.append(exclude.length() > 0 ? "," : "").append("daily");
}
logger.debug("Exclude: '{}'", exclude);
if (exclude.length() > 0) {
params.put(PARAM_EXCLUDE, exclude.toString());
}
return gson.fromJson(getResponseFromCache(buildURL(ONECALL_URL, params)), OpenWeatherMapOneCallAPIData.class);
}
/**
* Get the historical weather data from the OneCall API for the given location and the given number of days in the
* past.
* As of now, OpenWeatherMap supports this function for up to 5 days in the past. However, this may change in the
* future,
* so we don't enforce this limit here. See https://openweathermap.org/api/one-call-api for details
*
* @param location location represented as {@link PointType}
* @param days number of days in the past, relative to the current time.
* @return
* @throws JsonSyntaxException
* @throws OpenWeatherMapCommunicationException
* @throws OpenWeatherMapConfigurationException
*/
public synchronized @Nullable OpenWeatherMapOneCallHistAPIData getOneCallHistAPIData(@Nullable PointType location,
int days)
throws JsonSyntaxException, OpenWeatherMapCommunicationException, OpenWeatherMapConfigurationException {
Map<String, String> params = getRequestParams(handler.getOpenWeatherMapAPIConfig(), location);
// the API requests the history as timestamp in Unix time format.
params.put(PARAM_HISTORY_DATE,
Long.toString(ZonedDateTime.now(ZoneId.of("UTC")).minusDays(days).toEpochSecond()));
return gson.fromJson(getResponseFromCache(buildURL(ONECALL_HISTORY_URL, params)),
OpenWeatherMapOneCallHistAPIData.class);
}
private Map<String, String> getRequestParams(OpenWeatherMapAPIConfiguration config, @Nullable PointType location) {
if (location == null) {
throw new OpenWeatherMapConfigurationException("@text/offline.conf-error-missing-location");

View File

@ -128,6 +128,8 @@ public class OpenWeatherMapDiscoveryService extends AbstractDiscoveryService {
ThingUID bridgeUID = bridgeHandler.getThing().getUID();
createWeatherAndForecastResult(locationString, bridgeUID);
createUVIndexResult(locationString, bridgeUID);
createOneCallResult(locationString, bridgeUID);
createOneCallHistoryResult(locationString, bridgeUID);
}
private void createWeatherAndForecastResult(String location, ThingUID bridgeUID) {
@ -141,4 +143,17 @@ public class OpenWeatherMapDiscoveryService extends AbstractDiscoveryService {
.withLabel("Local UV Index").withProperty(CONFIG_LOCATION, location)
.withRepresentationProperty(CONFIG_LOCATION).withBridge(bridgeUID).build());
}
private void createOneCallResult(String location, ThingUID bridgeUID) {
thingDiscovered(
DiscoveryResultBuilder.create(new ThingUID(THING_TYPE_ONECALL_WEATHER_AND_FORECAST, bridgeUID, LOCAL))
.withLabel("One Call API weather and forecast").withProperty(CONFIG_LOCATION, location)
.withRepresentationProperty(CONFIG_LOCATION).withBridge(bridgeUID).build());
}
private void createOneCallHistoryResult(String location, ThingUID bridgeUID) {
thingDiscovered(DiscoveryResultBuilder.create(new ThingUID(THING_TYPE_ONECALL_HISTORY, bridgeUID, LOCAL))
.withLabel("One Call API history data").withProperty(CONFIG_LOCATION, location)
.withRepresentationProperty(CONFIG_LOCATION).withBridge(bridgeUID).build());
}
}

View File

@ -0,0 +1,219 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openweathermap.internal.dto.onecall;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Holds the data from the deserialised JSON response. Created using http://www.jsonschema2pojo.org/.
* Settings:
* Annotation Style: GSON
* Use primitive types
* Use double numbers
* allow additional properties
*
* @author Wolfgang Klimt - Initial contribution
*/
public class Current {
@SerializedName("dt")
@Expose
private int dt;
@SerializedName("sunrise")
@Expose
private int sunrise;
@SerializedName("sunset")
@Expose
private int sunset;
@SerializedName("temp")
@Expose
private double temp;
@SerializedName("feels_like")
@Expose
private double feelsLike;
@SerializedName("pressure")
@Expose
private int pressure;
@SerializedName("humidity")
@Expose
private int humidity;
@SerializedName("dew_point")
@Expose
private double dewPoint;
@SerializedName("uvi")
@Expose
private double uvi;
@SerializedName("clouds")
@Expose
private int clouds;
@SerializedName("visibility")
@Expose
private int visibility;
@SerializedName("wind_speed")
@Expose
private double windSpeed;
@SerializedName("wind_deg")
@Expose
private int windDeg;
@SerializedName("wind_gust")
@Expose
private double windGust;
@SerializedName("weather")
@Expose
private List<Weather> weather = null;
@SerializedName("rain")
@Expose
private Rain rain;
@SerializedName("snow")
@Expose
private Snow snow;
public int getDt() {
return dt;
}
public void setDt(int dt) {
this.dt = dt;
}
public int getSunrise() {
return sunrise;
}
public void setSunrise(int sunrise) {
this.sunrise = sunrise;
}
public int getSunset() {
return sunset;
}
public void setSunset(int sunset) {
this.sunset = sunset;
}
public double getTemp() {
return temp;
}
public void setTemp(double temp) {
this.temp = temp;
}
public double getFeelsLike() {
return feelsLike;
}
public void setFeelsLike(double feelsLike) {
this.feelsLike = feelsLike;
}
public int getPressure() {
return pressure;
}
public void setPressure(int pressure) {
this.pressure = pressure;
}
public int getHumidity() {
return humidity;
}
public void setHumidity(int humidity) {
this.humidity = humidity;
}
public double getDewPoint() {
return dewPoint;
}
public void setDewPoint(double dewPoint) {
this.dewPoint = dewPoint;
}
public double getUvi() {
return uvi;
}
public void setUvi(double uvi) {
this.uvi = uvi;
}
public int getClouds() {
return clouds;
}
public void setClouds(int clouds) {
this.clouds = clouds;
}
public int getVisibility() {
return visibility;
}
public void setVisibility(int visibility) {
this.visibility = visibility;
}
public double getWindSpeed() {
return windSpeed;
}
public void setWindSpeed(double windSpeed) {
this.windSpeed = windSpeed;
}
public int getWindDeg() {
return windDeg;
}
public void setWindDeg(int windDeg) {
this.windDeg = windDeg;
}
public double getWindGust() {
return windGust;
}
public void setWindGust(double windGust) {
this.windGust = windGust;
}
public List<Weather> getWeather() {
return weather;
}
public void setWeather(List<Weather> weather) {
this.weather = weather;
}
public Rain getRain() {
return rain;
}
public void setRain(Rain rain) {
this.rain = rain;
}
public Snow getSnow() {
return snow;
}
public void setSnow(Snow snow) {
this.snow = snow;
}
}

View File

@ -0,0 +1,230 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openweathermap.internal.dto.onecall;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Holds the data from the deserialised JSON response. Created using http://www.jsonschema2pojo.org/.
* Settings:
* Annotation Style: GSON
* Use primitive types
* Use double numbers
* allow additional properties
*
* @author Wolfgang Klimt - Initial contribution
*/
public class Daily {
@SerializedName("dt")
@Expose
private int dt;
@SerializedName("sunrise")
@Expose
private int sunrise;
@SerializedName("sunset")
@Expose
private int sunset;
@SerializedName("temp")
@Expose
private Temp temp;
@SerializedName("feels_like")
@Expose
private FeelsLike feelsLike;
@SerializedName("pressure")
@Expose
private int pressure;
@SerializedName("humidity")
@Expose
private int humidity;
@SerializedName("dew_point")
@Expose
private double dewPoint;
@SerializedName("wind_speed")
@Expose
private double windSpeed;
@SerializedName("wind_deg")
@Expose
private int windDeg;
@SerializedName("wind_gust")
@Expose
private double windGust;
@SerializedName("weather")
@Expose
private List<Weather> weather = null;
@SerializedName("clouds")
@Expose
private int clouds;
@SerializedName("pop")
@Expose
private double pop;
@SerializedName("visibility")
@Expose
private int visibility;
@SerializedName("rain")
@Expose
private double rain;
@SerializedName("snow")
@Expose
private double snow;
@SerializedName("uvi")
@Expose
private double uvi;
public int getDt() {
return dt;
}
public void setDt(int dt) {
this.dt = dt;
}
public int getSunrise() {
return sunrise;
}
public void setSunrise(int sunrise) {
this.sunrise = sunrise;
}
public int getSunset() {
return sunset;
}
public void setSunset(int sunset) {
this.sunset = sunset;
}
public Temp getTemp() {
return temp;
}
public void setTemp(Temp temp) {
this.temp = temp;
}
public FeelsLike getFeelsLike() {
return feelsLike;
}
public void setFeelsLike(FeelsLike feelsLike) {
this.feelsLike = feelsLike;
}
public int getPressure() {
return pressure;
}
public void setPressure(int pressure) {
this.pressure = pressure;
}
public int getHumidity() {
return humidity;
}
public void setHumidity(int humidity) {
this.humidity = humidity;
}
public double getDewPoint() {
return dewPoint;
}
public void setDewPoint(double dewPoint) {
this.dewPoint = dewPoint;
}
public double getWindSpeed() {
return windSpeed;
}
public void setWindSpeed(double windSpeed) {
this.windSpeed = windSpeed;
}
public int getWindDeg() {
return windDeg;
}
public void setWindDeg(int windDeg) {
this.windDeg = windDeg;
}
public double getWindGust() {
return windGust;
}
public void setWindGust(double windGust) {
this.windGust = windGust;
}
public List<Weather> getWeather() {
return weather;
}
public void setWeather(List<Weather> weather) {
this.weather = weather;
}
public int getClouds() {
return clouds;
}
public void setClouds(int clouds) {
this.clouds = clouds;
}
public double getPop() {
return pop;
}
public void setPop(double pop) {
this.pop = pop;
}
public double getRain() {
return rain;
}
public void setRain(double rain) {
this.rain = rain;
}
public double getUvi() {
return uvi;
}
public void setUvi(double uvi) {
this.uvi = uvi;
}
public int getVisibility() {
return visibility;
}
public void setVisibility(int visibility) {
this.visibility = visibility;
}
public double getSnow() {
return snow;
}
public void setSnow(double snow) {
this.snow = snow;
}
}

View File

@ -0,0 +1,74 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openweathermap.internal.dto.onecall;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Holds the data from the deserialised JSON response. Created using http://www.jsonschema2pojo.org/.
* Settings:
* Annotation Style: GSON
* Use primitive types
* Use double numbers
* allow additional properties
*
* @author Wolfgang Klimt - Initial contribution
*/
public class FeelsLike {
@SerializedName("day")
@Expose
private double day;
@SerializedName("night")
@Expose
private double night;
@SerializedName("eve")
@Expose
private double eve;
@SerializedName("morn")
@Expose
private double morn;
public double getDay() {
return day;
}
public void setDay(double day) {
this.day = day;
}
public double getNight() {
return night;
}
public void setNight(double night) {
this.night = night;
}
public double getEve() {
return eve;
}
public void setEve(double eve) {
this.eve = eve;
}
public double getMorn() {
return morn;
}
public void setMorn(double morn) {
this.morn = morn;
}
}

View File

@ -0,0 +1,197 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openweathermap.internal.dto.onecall;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Holds the data from the deserialised JSON response. Created using http://www.jsonschema2pojo.org/.
* Settings:
* Annotation Style: GSON
* Use primitive types
* Use double numbers
* allow additional properties
*
* @author Wolfgang Klimt - Initial contribution
*/
public class Hourly {
@SerializedName("dt")
@Expose
private int dt;
@SerializedName("temp")
@Expose
private double temp;
@SerializedName("feels_like")
@Expose
private double feelsLike;
@SerializedName("pressure")
@Expose
private int pressure;
@SerializedName("humidity")
@Expose
private int humidity;
@SerializedName("dew_point")
@Expose
private double dewPoint;
@SerializedName("clouds")
@Expose
private int clouds;
@SerializedName("visibility")
@Expose
private int visibility;
@SerializedName("wind_speed")
@Expose
private double windSpeed;
@SerializedName("wind_deg")
@Expose
private int windDeg;
@SerializedName("wind_gust")
@Expose
private double windGust;
@SerializedName("weather")
@Expose
private List<Weather> weather = null;
@SerializedName("pop")
@Expose
private double pop;
@SerializedName("rain")
@Expose
private Rain rain;
@SerializedName("snow")
@Expose
private Snow snow;
public int getDt() {
return dt;
}
public void setDt(int dt) {
this.dt = dt;
}
public double getTemp() {
return temp;
}
public void setTemp(double temp) {
this.temp = temp;
}
public double getFeelsLike() {
return feelsLike;
}
public void setFeelsLike(double feelsLike) {
this.feelsLike = feelsLike;
}
public int getPressure() {
return pressure;
}
public void setPressure(int pressure) {
this.pressure = pressure;
}
public int getHumidity() {
return humidity;
}
public void setHumidity(int humidity) {
this.humidity = humidity;
}
public double getDewPoint() {
return dewPoint;
}
public void setDewPoint(double dewPoint) {
this.dewPoint = dewPoint;
}
public int getClouds() {
return clouds;
}
public void setClouds(int clouds) {
this.clouds = clouds;
}
public int getVisibility() {
return visibility;
}
public void setVisibility(int visibility) {
this.visibility = visibility;
}
public double getWindSpeed() {
return windSpeed;
}
public void setWindSpeed(double windSpeed) {
this.windSpeed = windSpeed;
}
public int getWindDeg() {
return windDeg;
}
public void setWindDeg(int windDeg) {
this.windDeg = windDeg;
}
public double getWindGust() {
return windGust;
}
public void setWindGust(double windGust) {
this.windGust = windGust;
}
public List<Weather> getWeather() {
return weather;
}
public void setWeather(List<Weather> weather) {
this.weather = weather;
}
public double getPop() {
return pop;
}
public void setPop(double pop) {
this.pop = pop;
}
public Rain getRain() {
return rain;
}
public void setRain(Rain rain) {
this.rain = rain;
}
public Snow getSnow() {
return snow;
}
public void setSnow(Snow snow) {
this.snow = snow;
}
}

View File

@ -0,0 +1,52 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openweathermap.internal.dto.onecall;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Holds the data from the deserialised JSON response. Created using http://www.jsonschema2pojo.org/.
* Settings:
* Annotation Style: GSON
* Use primitive types
* Use double numbers
* allow additional properties
*
* @author Wolfgang Klimt - Initial contribution
*/
public class Minutely {
@SerializedName("dt")
@Expose
private int dt;
@SerializedName("precipitation")
@Expose
private double precipitation;
public int getDt() {
return dt;
}
public void setDt(int dt) {
this.dt = dt;
}
public double getPrecipitation() {
return precipitation;
}
public void setPrecipitation(double precipitation) {
this.precipitation = precipitation;
}
}

View File

@ -0,0 +1,120 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openweathermap.internal.dto.onecall;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Holds the data from the deserialised JSON response. Created using http://www.jsonschema2pojo.org/.
* Settings:
* Annotation Style: GSON
* Use primitive types
* Use double numbers
* allow additional properties
*
* @author Wolfgang Klimt - Initial contribution
*/
public class OpenWeatherMapOneCallAPIData {
@SerializedName("lat")
@Expose
private double lat;
@SerializedName("lon")
@Expose
private double lon;
@SerializedName("timezone")
@Expose
private String timezone;
@SerializedName("timezone_offset")
@Expose
private int timezoneOffset;
@SerializedName("current")
@Expose
private Current current;
@SerializedName("minutely")
@Expose
private List<Minutely> minutely = null;
@SerializedName("hourly")
@Expose
private List<Hourly> hourly = null;
@SerializedName("daily")
@Expose
private List<Daily> daily = null;
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public double getLon() {
return lon;
}
public void setLon(double lon) {
this.lon = lon;
}
public String getTimezone() {
return timezone;
}
public void setTimezone(String timezone) {
this.timezone = timezone;
}
public int getTimezoneOffset() {
return timezoneOffset;
}
public void setTimezoneOffset(int timezoneOffset) {
this.timezoneOffset = timezoneOffset;
}
public Current getCurrent() {
return current;
}
public void setCurrent(Current current) {
this.current = current;
}
public List<Minutely> getMinutely() {
return minutely;
}
public void setMinutely(List<Minutely> minutely) {
this.minutely = minutely;
}
public List<Hourly> getHourly() {
return hourly;
}
public void setHourly(List<Hourly> hourly) {
this.hourly = hourly;
}
public List<Daily> getDaily() {
return daily;
}
public void setDaily(List<Daily> daily) {
this.daily = daily;
}
}

View File

@ -0,0 +1,41 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openweathermap.internal.dto.onecall;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Holds the data from the deserialised JSON response. Created using http://www.jsonschema2pojo.org/.
* Settings:
* Annotation Style: GSON
* Use primitive types
* Use double numbers
* allow additional properties
*
* @author Wolfgang Klimt - Initial contribution
*/
public class Rain {
@SerializedName("1h")
@Expose
private double _1h;
public double get1h() {
return _1h;
}
public void set1h(double _1h) {
this._1h = _1h;
}
}

View File

@ -0,0 +1,41 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openweathermap.internal.dto.onecall;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Holds the data from the deserialised JSON response. Created using http://www.jsonschema2pojo.org/.
* Settings:
* Annotation Style: GSON
* Use primitive types
* Use double numbers
* allow additional properties
*
* @author Wolfgang Klimt - Initial contribution
*/
public class Snow {
@SerializedName("1h")
@Expose
private double _1h;
public double get1h() {
return _1h;
}
public void set1h(double _1h) {
this._1h = _1h;
}
}

View File

@ -0,0 +1,96 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openweathermap.internal.dto.onecall;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Holds the data from the deserialised JSON response. Created using http://www.jsonschema2pojo.org/.
* Settings:
* Annotation Style: GSON
* Use primitive types
* Use double numbers
* allow additional properties
*
* @author Wolfgang Klimt - Initial contribution
*/
public class Temp {
@SerializedName("day")
@Expose
private double day;
@SerializedName("min")
@Expose
private double min;
@SerializedName("max")
@Expose
private double max;
@SerializedName("night")
@Expose
private double night;
@SerializedName("eve")
@Expose
private double eve;
@SerializedName("morn")
@Expose
private double morn;
public double getDay() {
return day;
}
public void setDay(double day) {
this.day = day;
}
public double getMin() {
return min;
}
public void setMin(double min) {
this.min = min;
}
public double getMax() {
return max;
}
public void setMax(double max) {
this.max = max;
}
public double getNight() {
return night;
}
public void setNight(double night) {
this.night = night;
}
public double getEve() {
return eve;
}
public void setEve(double eve) {
this.eve = eve;
}
public double getMorn() {
return morn;
}
public void setMorn(double morn) {
this.morn = morn;
}
}

View File

@ -0,0 +1,74 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openweathermap.internal.dto.onecall;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Holds the data from the deserialised JSON response. Created using http://www.jsonschema2pojo.org/.
* Settings:
* Annotation Style: GSON
* Use primitive types
* Use double numbers
* allow additional properties
*
* @author Wolfgang Klimt - Initial contribution
*/
public class Weather {
@SerializedName("id")
@Expose
private int id;
@SerializedName("main")
@Expose
private String main;
@SerializedName("description")
@Expose
private String description;
@SerializedName("icon")
@Expose
private String icon;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getMain() {
return main;
}
public void setMain(String main) {
this.main = main;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
}

View File

@ -0,0 +1,219 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openweathermap.internal.dto.onecallhist;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Holds the data from the deserialised JSON response. Created using http://www.jsonschema2pojo.org/.
* Settings:
* Annotation Style: GSON
* Use primitive types
* Use double numbers
* allow additional properties
*
* @author Wolfgang Klimt - Initial contribution
*/
public class Current {
@SerializedName("dt")
@Expose
private int dt;
@SerializedName("sunrise")
@Expose
private int sunrise;
@SerializedName("sunset")
@Expose
private int sunset;
@SerializedName("temp")
@Expose
private double temp;
@SerializedName("feels_like")
@Expose
private double feelsLike;
@SerializedName("pressure")
@Expose
private int pressure;
@SerializedName("humidity")
@Expose
private int humidity;
@SerializedName("dew_point")
@Expose
private double dewPoint;
@SerializedName("uvi")
@Expose
private double uvi;
@SerializedName("clouds")
@Expose
private int clouds;
@SerializedName("visibility")
@Expose
private int visibility;
@SerializedName("wind_speed")
@Expose
private double windSpeed;
@SerializedName("wind_deg")
@Expose
private int windDeg;
@SerializedName("wind_gust")
@Expose
private double windGust;
@SerializedName("weather")
@Expose
private List<Weather> weather = null;
@SerializedName("rain")
@Expose
private Rain rain;
@SerializedName("snow")
@Expose
private Snow snow;
public int getDt() {
return dt;
}
public void setDt(int dt) {
this.dt = dt;
}
public int getSunrise() {
return sunrise;
}
public void setSunrise(int sunrise) {
this.sunrise = sunrise;
}
public int getSunset() {
return sunset;
}
public void setSunset(int sunset) {
this.sunset = sunset;
}
public double getTemp() {
return temp;
}
public void setTemp(double temp) {
this.temp = temp;
}
public double getFeelsLike() {
return feelsLike;
}
public void setFeelsLike(double feelsLike) {
this.feelsLike = feelsLike;
}
public int getPressure() {
return pressure;
}
public void setPressure(int pressure) {
this.pressure = pressure;
}
public int getHumidity() {
return humidity;
}
public void setHumidity(int humidity) {
this.humidity = humidity;
}
public double getDewPoint() {
return dewPoint;
}
public void setDewPoint(double dewPoint) {
this.dewPoint = dewPoint;
}
public double getUvi() {
return uvi;
}
public void setUvi(double uvi) {
this.uvi = uvi;
}
public int getClouds() {
return clouds;
}
public void setClouds(int clouds) {
this.clouds = clouds;
}
public int getVisibility() {
return visibility;
}
public void setVisibility(int visibility) {
this.visibility = visibility;
}
public double getWindSpeed() {
return windSpeed;
}
public void setWindSpeed(double windSpeed) {
this.windSpeed = windSpeed;
}
public int getWindDeg() {
return windDeg;
}
public void setWindDeg(int windDeg) {
this.windDeg = windDeg;
}
public double getWindGust() {
return windGust;
}
public void setWindGust(double windGust) {
this.windGust = windGust;
}
public List<Weather> getWeather() {
return weather;
}
public void setWeather(List<Weather> weather) {
this.weather = weather;
}
public Rain getRain() {
return rain;
}
public void setRain(Rain rain) {
this.rain = rain;
}
public Snow getSnow() {
return snow;
}
public void setSnow(Snow snow) {
this.snow = snow;
}
}

View File

@ -0,0 +1,186 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openweathermap.internal.dto.onecallhist;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Holds the data from the deserialised JSON response. Created using http://www.jsonschema2pojo.org/.
* Settings:
* Annotation Style: GSON
* Use primitive types
* Use double numbers
* allow additional properties
*
* @author Wolfgang Klimt - Initial contribution
*/
public class Hourly {
@SerializedName("dt")
@Expose
private int dt;
@SerializedName("temp")
@Expose
private double temp;
@SerializedName("feels_like")
@Expose
private double feelsLike;
@SerializedName("pressure")
@Expose
private int pressure;
@SerializedName("humidity")
@Expose
private int humidity;
@SerializedName("dew_point")
@Expose
private double dewPoint;
@SerializedName("clouds")
@Expose
private int clouds;
@SerializedName("visibility")
@Expose
private int visibility;
@SerializedName("wind_speed")
@Expose
private double windSpeed;
@SerializedName("wind_deg")
@Expose
private int windDeg;
@SerializedName("wind_gust")
@Expose
private double windGust;
@SerializedName("weather")
@Expose
private List<Weather> weather = null;
@SerializedName("rain")
@Expose
private Rain rain;
@SerializedName("snow")
@Expose
private Snow snow;
public int getDt() {
return dt;
}
public void setDt(int dt) {
this.dt = dt;
}
public double getTemp() {
return temp;
}
public void setTemp(double temp) {
this.temp = temp;
}
public double getFeelsLike() {
return feelsLike;
}
public void setFeelsLike(double feelsLike) {
this.feelsLike = feelsLike;
}
public int getPressure() {
return pressure;
}
public void setPressure(int pressure) {
this.pressure = pressure;
}
public int getHumidity() {
return humidity;
}
public void setHumidity(int humidity) {
this.humidity = humidity;
}
public double getDewPoint() {
return dewPoint;
}
public void setDewPoint(double dewPoint) {
this.dewPoint = dewPoint;
}
public int getClouds() {
return clouds;
}
public void setClouds(int clouds) {
this.clouds = clouds;
}
public int getVisibility() {
return visibility;
}
public void setVisibility(int visibility) {
this.visibility = visibility;
}
public double getWindSpeed() {
return windSpeed;
}
public void setWindSpeed(double windSpeed) {
this.windSpeed = windSpeed;
}
public int getWindDeg() {
return windDeg;
}
public void setWindDeg(int windDeg) {
this.windDeg = windDeg;
}
public double getWindGust() {
return windGust;
}
public void setWindGust(double windGust) {
this.windGust = windGust;
}
public List<Weather> getWeather() {
return weather;
}
public void setWeather(List<Weather> weather) {
this.weather = weather;
}
public Rain getRain() {
return rain;
}
public void setRain(Rain rain) {
this.rain = rain;
}
public Snow getSnow() {
return snow;
}
public void setSnow(Snow snow) {
this.snow = snow;
}
}

View File

@ -0,0 +1,98 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openweathermap.internal.dto.onecallhist;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Holds the data from the deserialised JSON response. Created using http://www.jsonschema2pojo.org/.
* Settings:
* Annotation Style: GSON
* Use primitive types
* Use double numbers
* allow additional properties
*
* @author Wolfgang Klimt - Initial contribution
*/
public class OpenWeatherMapOneCallHistAPIData {
@SerializedName("lat")
@Expose
private double lat;
@SerializedName("lon")
@Expose
private double lon;
@SerializedName("timezone")
@Expose
private String timezone;
@SerializedName("timezone_offset")
@Expose
private int timezoneOffset;
@SerializedName("current")
@Expose
private Current current;
@SerializedName("hourly")
@Expose
private List<Hourly> hourly = null;
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public double getLon() {
return lon;
}
public void setLon(double lon) {
this.lon = lon;
}
public String getTimezone() {
return timezone;
}
public void setTimezone(String timezone) {
this.timezone = timezone;
}
public int getTimezoneOffset() {
return timezoneOffset;
}
public void setTimezoneOffset(int timezoneOffset) {
this.timezoneOffset = timezoneOffset;
}
public Current getCurrent() {
return current;
}
public void setCurrent(Current current) {
this.current = current;
}
public List<Hourly> getHourly() {
return hourly;
}
public void setHourly(List<Hourly> hourly) {
this.hourly = hourly;
}
}

View File

@ -0,0 +1,41 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openweathermap.internal.dto.onecallhist;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Holds the data from the deserialised JSON response. Created using http://www.jsonschema2pojo.org/.
* Settings:
* Annotation Style: GSON
* Use primitive types
* Use double numbers
* allow additional properties
*
* @author Wolfgang Klimt - Initial contribution
*/
public class Rain {
@SerializedName("1h")
@Expose
private double _1h;
public double get1h() {
return _1h;
}
public void set1h(double _1h) {
this._1h = _1h;
}
}

View File

@ -0,0 +1,41 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openweathermap.internal.dto.onecallhist;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Holds the data from the deserialised JSON response. Created using http://www.jsonschema2pojo.org/.
* Settings:
* Annotation Style: GSON
* Use primitive types
* Use double numbers
* allow additional properties
*
* @author Wolfgang Klimt - Initial contribution
*/
public class Snow {
@SerializedName("1h")
@Expose
private double _1h;
public double get1h() {
return _1h;
}
public void set1h(double _1h) {
this._1h = _1h;
}
}

View File

@ -0,0 +1,74 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openweathermap.internal.dto.onecallhist;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Holds the data from the deserialised JSON response. Created using http://www.jsonschema2pojo.org/.
* Settings:
* Annotation Style: GSON
* Use primitive types
* Use double numbers
* allow additional properties
*
* @author Wolfgang Klimt - Initial contribution
*/
public class Weather {
@SerializedName("id")
@Expose
private int id;
@SerializedName("main")
@Expose
private String main;
@SerializedName("description")
@Expose
private String description;
@SerializedName("icon")
@Expose
private String icon;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getMain() {
return main;
}
public void setMain(String main) {
this.main = main;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
}

View File

@ -26,10 +26,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.openweathermap.internal.discovery.OpenWeatherMapDiscoveryService;
import org.openhab.binding.openweathermap.internal.handler.AbstractOpenWeatherMapHandler;
import org.openhab.binding.openweathermap.internal.handler.OpenWeatherMapAPIHandler;
import org.openhab.binding.openweathermap.internal.handler.OpenWeatherMapUVIndexHandler;
import org.openhab.binding.openweathermap.internal.handler.OpenWeatherMapWeatherAndForecastHandler;
import org.openhab.binding.openweathermap.internal.handler.*;
import org.openhab.core.config.discovery.DiscoveryService;
import org.openhab.core.i18n.LocaleProvider;
import org.openhab.core.i18n.LocationProvider;
@ -100,6 +97,10 @@ public class OpenWeatherMapHandlerFactory extends BaseThingHandlerFactory {
return new OpenWeatherMapWeatherAndForecastHandler(thing, timeZoneProvider);
} else if (THING_TYPE_UVINDEX.equals(thingTypeUID)) {
return new OpenWeatherMapUVIndexHandler(thing, timeZoneProvider);
} else if (THING_TYPE_ONECALL_WEATHER_AND_FORECAST.equals(thingTypeUID)) {
return new OpenWeatherMapOneCallHandler(thing, timeZoneProvider);
} else if (THING_TYPE_ONECALL_HISTORY.equals(thingTypeUID)) {
return new OpenWeatherMapOneCallHistoryHandler(thing, timeZoneProvider);
}
return null;

View File

@ -69,8 +69,9 @@ public abstract class AbstractOpenWeatherMapHandler extends BaseThingHandler {
private final Logger logger = LoggerFactory.getLogger(AbstractOpenWeatherMapHandler.class);
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.unmodifiableSet(
Stream.of(THING_TYPE_WEATHER_AND_FORECAST, THING_TYPE_UVINDEX).collect(Collectors.toSet()));
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections
.unmodifiableSet(Stream.of(THING_TYPE_WEATHER_AND_FORECAST, THING_TYPE_UVINDEX,
THING_TYPE_ONECALL_WEATHER_AND_FORECAST, THING_TYPE_ONECALL_HISTORY).collect(Collectors.toSet()));
private final TimeZoneProvider timeZoneProvider;
@ -151,8 +152,8 @@ public abstract class AbstractOpenWeatherMapHandler extends BaseThingHandler {
*
* @param connection {@link OpenWeatherMapConnection} instance
* @return true, if the request for the OpenWeatherMap data was successful
* @throws OpenWeatherMapCommunicationException
* @throws OpenWeatherMapConfigurationException
* @throws OpenWeatherMapCommunicationException if there is a problem retrieving the data
* @throws OpenWeatherMapConfigurationException if there is a configuration error
*/
protected abstract boolean requestData(OpenWeatherMapConnection connection)
throws OpenWeatherMapCommunicationException, OpenWeatherMapConfigurationException;
@ -205,7 +206,8 @@ public abstract class AbstractOpenWeatherMapHandler extends BaseThingHandler {
}
protected List<Channel> createChannelsForGroup(String channelGroupId, ChannelGroupTypeUID channelGroupTypeUID) {
logger.debug("Building channel group '{}' for thing '{}'.", channelGroupId, getThing().getUID());
logger.debug("Building channel group '{}' for thing '{}' and GroupType '{}'.", channelGroupId,
getThing().getUID(), channelGroupTypeUID);
List<Channel> channels = new ArrayList<>();
ThingHandlerCallback callback = getCallback();
if (callback != null) {
@ -221,6 +223,7 @@ public abstract class AbstractOpenWeatherMapHandler extends BaseThingHandler {
channels.add(newChannel);
}
}
logger.debug("Built channels: {}", channels);
return channels;
}

View File

@ -0,0 +1,636 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openweathermap.internal.handler;
import static org.openhab.binding.openweathermap.internal.OpenWeatherMapBindingConstants.*;
import static org.openhab.core.library.unit.MetricPrefix.*;
import static org.openhab.core.library.unit.SIUnits.*;
import static org.openhab.core.library.unit.SmartHomeUnits.*;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.openweathermap.internal.config.OpenWeatherMapOneCallConfiguration;
import org.openhab.binding.openweathermap.internal.connection.OpenWeatherMapCommunicationException;
import org.openhab.binding.openweathermap.internal.connection.OpenWeatherMapConfigurationException;
import org.openhab.binding.openweathermap.internal.connection.OpenWeatherMapConnection;
import org.openhab.binding.openweathermap.internal.dto.onecall.*;
import org.openhab.core.i18n.TimeZoneProvider;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.thing.*;
import org.openhab.core.thing.binding.builder.ThingBuilder;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonSyntaxException;
/**
* The {@link OpenWeatherMapOneCallHandler} is responsible for handling commands, which are sent to one of
* the channels.
*
* @author Wolfgang Klimt - Initial contribution
*/
@NonNullByDefault
public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler {
private final Logger logger = LoggerFactory.getLogger(OpenWeatherMapOneCallHandler.class);
private static final String CHANNEL_GROUP_MINUTELY_FORECAST_PREFIX = "forecastMinutes";
private static final String CHANNEL_GROUP_HOURLY_FORECAST_PREFIX = "forecastHours";
private static final String CHANNEL_GROUP_DAILY_FORECAST_PREFIX = "forecastDay";
private static final Pattern CHANNEL_GROUP_HOURLY_FORECAST_PREFIX_PATTERN = Pattern
.compile(CHANNEL_GROUP_HOURLY_FORECAST_PREFIX + "([0-9]*)");
private static final Pattern CHANNEL_GROUP_DAILY_FORECAST_PREFIX_PATTERN = Pattern
.compile(CHANNEL_GROUP_DAILY_FORECAST_PREFIX + "([0-9]*)");
private static final Pattern CHANNEL_GROUP_MINUTELY_FORECAST_PREFIX_PATTERN = Pattern
.compile(CHANNEL_GROUP_MINUTELY_FORECAST_PREFIX + "([0-9]*)");
private @Nullable OpenWeatherMapOneCallAPIData weatherData;
private int forecastMinutes = 60;
private int forecastHours = 24;
private int forecastDays = 8;
public OpenWeatherMapOneCallHandler(Thing thing, final TimeZoneProvider timeZoneProvider) {
super(thing, timeZoneProvider);
}
@Override
public void initialize() {
super.initialize();
logger.debug("Initialize OpenWeatherMapOneCallHandler handler '{}'.", getThing().getUID());
OpenWeatherMapOneCallConfiguration config = getConfigAs(OpenWeatherMapOneCallConfiguration.class);
boolean configValid = true;
int newForecastMinutes = config.forecastMinutes;
if (newForecastMinutes < 0 || newForecastMinutes > 60) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
"@text/offline.conf-error-not-supported-onecall-number-of-minutes");
configValid = false;
}
int newForecastHours = config.forecastHours;
if (newForecastHours < 0 || newForecastHours > 48) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
"@text/offline.conf-error-not-supported-onecall-number-of-hours");
configValid = false;
}
int newForecastDays = config.forecastDays;
if (newForecastDays < 0 || newForecastDays > 8) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
"@text/offline.conf-error-not-supported-onecall-number-of-days");
configValid = false;
}
if (configValid) {
logger.debug("Rebuilding thing '{}'.", getThing().getUID());
List<Channel> toBeAddedChannels = new ArrayList<>();
List<Channel> toBeRemovedChannels = new ArrayList<>();
toBeAddedChannels
.addAll(createChannelsForGroup(CHANNEL_GROUP_ONECALL_CURRENT, CHANNEL_GROUP_TYPE_ONECALL_CURRENT));
if (forecastMinutes != newForecastMinutes) {
logger.debug("forecastMinutes changed from {} to {}. Rebuilding minutely forecast channel groups.",
forecastMinutes, newForecastMinutes);
if (forecastMinutes > newForecastMinutes) {
for (int i = newForecastMinutes + 1; i <= forecastMinutes; i++) {
toBeRemovedChannels.addAll(removeChannelsOfGroup(
CHANNEL_GROUP_MINUTELY_FORECAST_PREFIX + ((i < 10) ? "0" : "") + Integer.toString(i)));
}
} else {
for (int i = forecastMinutes + 1; i <= newForecastMinutes; i++) {
toBeAddedChannels.addAll(createChannelsForGroup(
CHANNEL_GROUP_MINUTELY_FORECAST_PREFIX + ((i < 10) ? "0" : "") + Integer.toString(i),
CHANNEL_GROUP_TYPE_ONECALL_MINUTELY_FORECAST));
}
}
forecastMinutes = newForecastMinutes;
}
if (forecastHours != newForecastHours) {
logger.debug("ForecastHours changed from {} to {}. Rebuilding hourly forecast channel groups.",
forecastHours, newForecastHours);
if (forecastHours > newForecastHours) {
for (int i = newForecastHours + 1; i <= forecastHours; i++) {
toBeRemovedChannels.addAll(removeChannelsOfGroup(
CHANNEL_GROUP_HOURLY_FORECAST_PREFIX + ((i < 10) ? "0" : "") + Integer.toString(i)));
}
} else {
for (int i = forecastHours + 1; i <= newForecastHours; i++) {
toBeAddedChannels.addAll(createChannelsForGroup(
CHANNEL_GROUP_HOURLY_FORECAST_PREFIX + ((i < 10) ? "0" : "") + Integer.toString(i),
CHANNEL_GROUP_TYPE_ONECALL_HOURLY_FORECAST));
}
}
forecastHours = newForecastHours;
}
if (forecastDays != newForecastDays) {
logger.debug("ForecastDays changed from {} to {}. Rebuilding daily forecast channel groups.",
forecastDays, newForecastDays);
if (forecastDays > newForecastDays) {
if (newForecastDays < 1) {
toBeRemovedChannels.addAll(removeChannelsOfGroup(CHANNEL_GROUP_FORECAST_TODAY));
}
if (newForecastDays < 2) {
toBeRemovedChannels.addAll(removeChannelsOfGroup(CHANNEL_GROUP_FORECAST_TOMORROW));
}
for (int i = newForecastDays; i < forecastDays; ++i) {
toBeRemovedChannels.addAll(
removeChannelsOfGroup(CHANNEL_GROUP_DAILY_FORECAST_PREFIX + Integer.toString(i)));
}
} else {
if (forecastDays == 0 && newForecastDays > 0) {
toBeAddedChannels.addAll(createChannelsForGroup(CHANNEL_GROUP_FORECAST_TODAY,
CHANNEL_GROUP_TYPE_ONECALL_DAILY_FORECAST));
}
if (forecastDays <= 1 && newForecastDays > 1) {
toBeAddedChannels.addAll(createChannelsForGroup(CHANNEL_GROUP_FORECAST_TOMORROW,
CHANNEL_GROUP_TYPE_ONECALL_DAILY_FORECAST));
}
for (int i = Math.max(forecastDays, 2); i < newForecastDays; i++) {
toBeAddedChannels.addAll(
createChannelsForGroup(CHANNEL_GROUP_DAILY_FORECAST_PREFIX + Integer.toString(i),
CHANNEL_GROUP_TYPE_ONECALL_DAILY_FORECAST));
}
}
forecastDays = newForecastDays;
}
logger.debug("toBeRemovedChannels: {}. toBeAddedChannels: {}", toBeRemovedChannels, toBeAddedChannels);
ThingBuilder builder = editThing().withoutChannels(toBeRemovedChannels);
for (Channel channel : toBeAddedChannels) {
builder.withChannel(channel);
}
updateThing(builder.build());
updateStatus(ThingStatus.ONLINE);
}
}
@Override
protected boolean requestData(OpenWeatherMapConnection connection)
throws OpenWeatherMapCommunicationException, OpenWeatherMapConfigurationException {
logger.debug("Update weather and forecast data of thing '{}'.", getThing().getUID());
try {
weatherData = connection.getOneCallAPIData(location, forecastMinutes == 0, forecastHours == 0,
forecastDays == 0);
return true;
} catch (JsonSyntaxException e) {
logger.debug("JsonSyntaxException occurred during execution: {}", e.getLocalizedMessage(), e);
return false;
}
}
@Override
protected void updateChannel(ChannelUID channelUID) {
String channelGroupId = channelUID.getGroupId();
logger.debug("OneCallHandler: updateChannel {}, groupID {}", channelUID, channelGroupId);
switch (channelGroupId) {
case CHANNEL_GROUP_ONECALL_CURRENT:
updateCurrentChannel(channelUID);
break;
case CHANNEL_GROUP_ONECALL_TODAY:
updateDailyForecastChannel(channelUID, 0);
break;
case CHANNEL_GROUP_ONECALL_TOMORROW:
updateDailyForecastChannel(channelUID, 1);
break;
default:
int i;
Matcher hourlyForecastMatcher = CHANNEL_GROUP_HOURLY_FORECAST_PREFIX_PATTERN.matcher(channelGroupId);
if (hourlyForecastMatcher.find() && (i = Integer.parseInt(hourlyForecastMatcher.group(1))) >= 1
&& i <= 48) {
updateHourlyForecastChannel(channelUID, (i - 1));
break;
}
Matcher dailyForecastMatcher = CHANNEL_GROUP_DAILY_FORECAST_PREFIX_PATTERN.matcher(channelGroupId);
if (dailyForecastMatcher.find() && (i = Integer.parseInt(dailyForecastMatcher.group(1))) >= 1
&& i <= 7) {
updateDailyForecastChannel(channelUID, i);
break;
}
Matcher minutelyForecastMatcher = CHANNEL_GROUP_MINUTELY_FORECAST_PREFIX_PATTERN
.matcher(channelGroupId);
if (minutelyForecastMatcher.find() && (i = Integer.parseInt(minutelyForecastMatcher.group(1))) >= 1
&& i <= 60) {
updateMinutelyForecastChannel(channelUID, i - 1);
break;
}
break;
}
}
/**
* Update the channel from the last OpenWeatherMap data retrieved.
*
* @param channelUID the id identifying the channel to be updated
*/
private void updateCurrentChannel(ChannelUID channelUID) {
String channelId = channelUID.getIdWithoutGroup();
String channelGroupId = channelUID.getGroupId();
OpenWeatherMapOneCallAPIData localWeatherData = weatherData;
if (localWeatherData != null) {
State state = UnDefType.UNDEF;
switch (channelId) {
case CHANNEL_STATION_LOCATION:
state = getPointTypeState(localWeatherData.getLat(), localWeatherData.getLon());
break;
case CHANNEL_TIME_STAMP:
state = getDateTimeTypeState(localWeatherData.getCurrent().getDt());
break;
case CHANNEL_SUNRISE:
state = getDateTimeTypeState(localWeatherData.getCurrent().getSunrise());
break;
case CHANNEL_SUNSET:
state = getDateTimeTypeState(localWeatherData.getCurrent().getSunset());
break;
case CHANNEL_CONDITION:
if (!localWeatherData.getCurrent().getWeather().isEmpty()) {
state = getStringTypeState(localWeatherData.getCurrent().getWeather().get(0).getDescription());
}
break;
case CHANNEL_CONDITION_ID:
if (!localWeatherData.getCurrent().getWeather().isEmpty()) {
state = getStringTypeState(
Integer.toString(localWeatherData.getCurrent().getWeather().get(0).getId()));
}
break;
case CHANNEL_CONDITION_ICON:
if (!localWeatherData.getCurrent().getWeather().isEmpty()) {
state = getRawTypeState(OpenWeatherMapConnection
.getWeatherIcon(localWeatherData.getCurrent().getWeather().get(0).getIcon()));
}
break;
case CHANNEL_CONDITION_ICON_ID:
if (!localWeatherData.getCurrent().getWeather().isEmpty()) {
state = getStringTypeState(localWeatherData.getCurrent().getWeather().get(0).getIcon());
}
break;
case CHANNEL_TEMPERATURE:
state = getQuantityTypeState(localWeatherData.getCurrent().getTemp(), CELSIUS);
break;
case CHANNEL_APPARENT_TEMPERATURE:
state = getQuantityTypeState(localWeatherData.getCurrent().getFeelsLike(), CELSIUS);
break;
case CHANNEL_PRESSURE:
state = getQuantityTypeState(localWeatherData.getCurrent().getPressure(), HECTO(PASCAL));
break;
case CHANNEL_HUMIDITY:
state = getQuantityTypeState(localWeatherData.getCurrent().getHumidity(), PERCENT);
break;
case CHANNEL_DEW_POINT:
state = getQuantityTypeState(localWeatherData.getCurrent().getDewPoint(), CELSIUS);
break;
case CHANNEL_WIND_SPEED:
state = getQuantityTypeState(localWeatherData.getCurrent().getWindSpeed(), METRE_PER_SECOND);
break;
case CHANNEL_WIND_DIRECTION:
state = getQuantityTypeState(localWeatherData.getCurrent().getWindDeg(), DEGREE_ANGLE);
break;
case CHANNEL_GUST_SPEED:
state = getQuantityTypeState(localWeatherData.getCurrent().getWindGust(), METRE_PER_SECOND);
break;
case CHANNEL_CLOUDINESS:
state = getQuantityTypeState(localWeatherData.getCurrent().getClouds(), PERCENT);
break;
case CHANNEL_UVINDEX:
state = getDecimalTypeState(localWeatherData.getCurrent().getUvi());
break;
case CHANNEL_RAIN:
Rain rain = localWeatherData.getCurrent().getRain();
state = getQuantityTypeState(rain == null ? 0 : rain.get1h(), MILLI(METRE));
break;
case CHANNEL_SNOW:
Snow snow = localWeatherData.getCurrent().getSnow();
state = getQuantityTypeState(snow == null ? 0 : snow.get1h(), MILLI(METRE));
break;
case CHANNEL_VISIBILITY:
@Nullable
State tempstate = new QuantityType<>(localWeatherData.getCurrent().getVisibility(), METRE)
.toUnit(KILO(METRE));
state = (tempstate == null ? state : tempstate);
break;
default:
// This should not happen
logger.warn("Unknown channel id {} in onecall current weather data", channelId);
break;
}
logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
updateState(channelUID, state);
} else {
logger.debug("No weather data available to update channel '{}' of group '{}'.", channelId, channelGroupId);
}
}
private void updateMinutelyForecastChannel(ChannelUID channelUID, int count) {
String channelId = channelUID.getIdWithoutGroup();
String channelGroupId = channelUID.getGroupId();
OpenWeatherMapOneCallAPIData localWeatherData = weatherData;
if (forecastMinutes == 0) {
logger.warn(
"Can't update channel group {} because forecastMinutes is set to '0'. Please adjust config accordingly",
channelGroupId);
return;
}
if (localWeatherData != null && localWeatherData.getMinutely().size() > count) {
org.openhab.binding.openweathermap.internal.dto.onecall.Minutely forecastData = localWeatherData
.getMinutely().get(count);
State state = UnDefType.UNDEF;
switch (channelId) {
case CHANNEL_TIME_STAMP:
state = getDateTimeTypeState(forecastData.getDt());
break;
case CHANNEL_PRECIPITATION:
double precipitation = forecastData.getPrecipitation();
state = getQuantityTypeState(precipitation, MILLI(METRE));
break;
default:
// This should not happen
logger.warn("Unknown channel id {} in onecall minutely weather data", channelId);
break;
}
logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
updateState(channelUID, state);
} else {
logger.debug("No weather data available to update channel '{}' of group '{}'.", channelId, channelGroupId);
}
}
/**
* Update the channel from the last OpenWeatherMap data retrieved.
*
* @param channelUID the id identifying the channel to be updated
* @param count the number of the hour referenced by the channel
*/
private void updateHourlyForecastChannel(ChannelUID channelUID, int count) {
String channelId = channelUID.getIdWithoutGroup();
String channelGroupId = channelUID.getGroupId();
if (forecastHours == 0) {
logger.warn(
"Can't update channel group {} because forecastHours is set to '0'. Please adjust config accordingly",
channelGroupId);
return;
}
OpenWeatherMapOneCallAPIData localWeatherData = weatherData;
if (localWeatherData != null && localWeatherData.getHourly().size() > count) {
org.openhab.binding.openweathermap.internal.dto.onecall.Hourly forecastData = localWeatherData.getHourly()
.get(count);
State state = UnDefType.UNDEF;
switch (channelId) {
case CHANNEL_TIME_STAMP:
state = getDateTimeTypeState(forecastData.getDt());
break;
case CHANNEL_CONDITION:
if (!forecastData.getWeather().isEmpty()) {
state = getStringTypeState(forecastData.getWeather().get(0).getDescription());
}
break;
case CHANNEL_CONDITION_ID:
if (!forecastData.getWeather().isEmpty()) {
state = getStringTypeState(Integer.toString(forecastData.getWeather().get(0).getId()));
}
break;
case CHANNEL_CONDITION_ICON:
if (!forecastData.getWeather().isEmpty()) {
state = getRawTypeState(
OpenWeatherMapConnection.getWeatherIcon(forecastData.getWeather().get(0).getIcon()));
}
break;
case CHANNEL_CONDITION_ICON_ID:
if (!forecastData.getWeather().isEmpty()) {
state = getStringTypeState(forecastData.getWeather().get(0).getIcon());
}
break;
case CHANNEL_TEMPERATURE:
state = getQuantityTypeState(forecastData.getTemp(), CELSIUS);
break;
case CHANNEL_APPARENT_TEMPERATURE:
state = getQuantityTypeState(forecastData.getFeelsLike(), CELSIUS);
break;
case CHANNEL_PRESSURE:
state = getQuantityTypeState(forecastData.getPressure(), HECTO(PASCAL));
break;
case CHANNEL_HUMIDITY:
state = getQuantityTypeState(forecastData.getHumidity(), PERCENT);
break;
case CHANNEL_DEW_POINT:
state = getQuantityTypeState(forecastData.getDewPoint(), CELSIUS);
break;
case CHANNEL_WIND_SPEED:
state = getQuantityTypeState(forecastData.getWindSpeed(), METRE_PER_SECOND);
break;
case CHANNEL_WIND_DIRECTION:
state = getQuantityTypeState(forecastData.getWindDeg(), DEGREE_ANGLE);
break;
case CHANNEL_GUST_SPEED:
state = getQuantityTypeState(forecastData.getWindGust(), METRE_PER_SECOND);
break;
case CHANNEL_CLOUDINESS:
state = getQuantityTypeState(forecastData.getClouds(), PERCENT);
break;
case CHANNEL_VISIBILITY:
@Nullable
State tempstate = new QuantityType<>(localWeatherData.getCurrent().getVisibility(), METRE)
.toUnit(KILO(METRE));
state = (tempstate == null ? state : tempstate);
case CHANNEL_PRECIP_PROBABILITY:
state = getQuantityTypeState(forecastData.getPop() * 100.0, PERCENT);
break;
case CHANNEL_RAIN:
Rain rain = forecastData.getRain();
state = getQuantityTypeState(rain == null ? 0 : rain.get1h(), MILLI(METRE));
break;
case CHANNEL_SNOW:
Snow snow = forecastData.getSnow();
state = getQuantityTypeState(snow == null ? 0 : snow.get1h(), MILLI(METRE));
break;
default:
// This should not happen
logger.warn("Unknown channel id {} in onecall hourly weather data", channelId);
break;
}
logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
updateState(channelUID, state);
} else {
logger.debug("No weather data available to update channel '{}' of group '{}'.", channelId, channelGroupId);
}
}
/**
* Update the channel from the last OpenWeatherMap data retrieved.
*
* @param channelUID the id identifying the channel to be updated
* @param count
*/
private void updateDailyForecastChannel(ChannelUID channelUID, int count) {
String channelId = channelUID.getIdWithoutGroup();
String channelGroupId = channelUID.getGroupId();
if (forecastDays == 0) {
logger.warn(
"Can't update channel group {} because forecastDays is set to '0'. Please adjust config accordingly",
channelGroupId);
return;
}
@Nullable
OpenWeatherMapOneCallAPIData localWeatherData = weatherData;
if (localWeatherData != null && localWeatherData.getDaily().size() > count) {
org.openhab.binding.openweathermap.internal.dto.onecall.Daily forecastData = localWeatherData.getDaily()
.get(count);
State state = UnDefType.UNDEF;
Temp temp;
FeelsLike feelsLike;
switch (channelId) {
case CHANNEL_TIME_STAMP:
state = getDateTimeTypeState(forecastData.getDt());
break;
case CHANNEL_SUNRISE:
state = getDateTimeTypeState(forecastData.getSunrise());
break;
case CHANNEL_SUNSET:
state = getDateTimeTypeState(forecastData.getSunset());
break;
case CHANNEL_CONDITION:
if (!forecastData.getWeather().isEmpty()) {
state = getStringTypeState(forecastData.getWeather().get(0).getDescription());
}
break;
case CHANNEL_CONDITION_ID:
if (!forecastData.getWeather().isEmpty()) {
state = getStringTypeState(Integer.toString(forecastData.getWeather().get(0).getId()));
}
break;
case CHANNEL_CONDITION_ICON:
if (!forecastData.getWeather().isEmpty()) {
state = getRawTypeState(
OpenWeatherMapConnection.getWeatherIcon(forecastData.getWeather().get(0).getIcon()));
}
break;
case CHANNEL_CONDITION_ICON_ID:
if (!forecastData.getWeather().isEmpty()) {
state = getStringTypeState(forecastData.getWeather().get(0).getIcon());
}
break;
case CHANNEL_MIN_TEMPERATURE:
temp = forecastData.getTemp();
if (temp != null) {
state = getQuantityTypeState(temp.getMin(), CELSIUS);
}
break;
case CHANNEL_MAX_TEMPERATURE:
temp = forecastData.getTemp();
if (temp != null) {
state = getQuantityTypeState(temp.getMax(), CELSIUS);
}
break;
case CHANNEL_MORNING_TEMPERATURE:
temp = forecastData.getTemp();
if (temp != null) {
state = getQuantityTypeState(temp.getMorn(), CELSIUS);
}
break;
case CHANNEL_DAY_TEMPERATURE:
temp = forecastData.getTemp();
if (temp != null) {
state = getQuantityTypeState(temp.getDay(), CELSIUS);
}
break;
case CHANNEL_EVENING_TEMPERATURE:
temp = forecastData.getTemp();
if (temp != null) {
state = getQuantityTypeState(temp.getEve(), CELSIUS);
}
break;
case CHANNEL_NIGHT_TEMPERATURE:
temp = forecastData.getTemp();
if (temp != null) {
state = getQuantityTypeState(temp.getNight(), CELSIUS);
}
break;
case CHANNEL_APPARENT_DAY:
feelsLike = forecastData.getFeelsLike();
if (feelsLike != null) {
state = getQuantityTypeState(feelsLike.getDay(), CELSIUS);
}
break;
case CHANNEL_APPARENT_MORNING:
feelsLike = forecastData.getFeelsLike();
if (feelsLike != null) {
state = getQuantityTypeState(feelsLike.getMorn(), CELSIUS);
}
break;
case CHANNEL_APPARENT_EVENING:
feelsLike = forecastData.getFeelsLike();
if (feelsLike != null) {
state = getQuantityTypeState(feelsLike.getEve(), CELSIUS);
}
break;
case CHANNEL_APPARENT_NIGHT:
feelsLike = forecastData.getFeelsLike();
if (feelsLike != null) {
state = getQuantityTypeState(feelsLike.getNight(), CELSIUS);
}
break;
case CHANNEL_PRESSURE:
state = getQuantityTypeState(forecastData.getPressure(), HECTO(PASCAL));
break;
case CHANNEL_HUMIDITY:
state = getQuantityTypeState(forecastData.getHumidity(), PERCENT);
break;
case CHANNEL_WIND_SPEED:
state = getQuantityTypeState(forecastData.getWindSpeed(), METRE_PER_SECOND);
break;
case CHANNEL_WIND_DIRECTION:
state = getQuantityTypeState(forecastData.getWindDeg(), DEGREE_ANGLE);
break;
case CHANNEL_GUST_SPEED:
state = getQuantityTypeState(forecastData.getWindGust(), METRE_PER_SECOND);
break;
case CHANNEL_CLOUDINESS:
state = getQuantityTypeState(forecastData.getClouds(), PERCENT);
break;
case CHANNEL_DEW_POINT:
state = getQuantityTypeState(forecastData.getDewPoint(), CELSIUS);
break;
case CHANNEL_UVINDEX:
state = getDecimalTypeState(forecastData.getUvi());
break;
case CHANNEL_VISIBILITY:
@Nullable
State tempstate = new QuantityType<>(localWeatherData.getCurrent().getVisibility(), METRE)
.toUnit(KILO(METRE));
state = (tempstate == null ? state : tempstate);
case CHANNEL_PRECIP_PROBABILITY:
state = getQuantityTypeState(forecastData.getPop() * 100.0, PERCENT);
break;
case CHANNEL_RAIN:
state = getQuantityTypeState(forecastData.getRain(), MILLI(METRE));
break;
case CHANNEL_SNOW:
state = getQuantityTypeState(forecastData.getSnow(), MILLI(METRE));
break;
default:
// This should not happen
logger.warn("Unknown channel id {} in onecall daily weather data", channelId);
break;
}
logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
updateState(channelUID, state);
} else {
logger.debug("No weather data available to update channel '{}' of group '{}'.", channelId, channelGroupId);
}
}
}

View File

@ -0,0 +1,317 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openweathermap.internal.handler;
import static org.openhab.binding.openweathermap.internal.OpenWeatherMapBindingConstants.*;
import static org.openhab.core.library.unit.MetricPrefix.HECTO;
import static org.openhab.core.library.unit.MetricPrefix.KILO;
import static org.openhab.core.library.unit.MetricPrefix.MILLI;
import static org.openhab.core.library.unit.SIUnits.*;
import static org.openhab.core.library.unit.SmartHomeUnits.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.openweathermap.internal.config.OpenWeatherMapOneCallHistoryConfiguration;
import org.openhab.binding.openweathermap.internal.connection.OpenWeatherMapCommunicationException;
import org.openhab.binding.openweathermap.internal.connection.OpenWeatherMapConfigurationException;
import org.openhab.binding.openweathermap.internal.connection.OpenWeatherMapConnection;
import org.openhab.binding.openweathermap.internal.dto.onecallhist.*;
import org.openhab.binding.openweathermap.internal.dto.onecallhist.OpenWeatherMapOneCallHistAPIData;
import org.openhab.core.i18n.TimeZoneProvider;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonSyntaxException;
/**
* The {@link OpenWeatherMapOneCallHistoryHandler} is responsible for handling commands, which are sent to one of
* the channels.
*
* @author Wolfgang Klimt - Initial contribution
*/
@NonNullByDefault
public class OpenWeatherMapOneCallHistoryHandler extends AbstractOpenWeatherMapHandler {
private final Logger logger = LoggerFactory.getLogger(OpenWeatherMapOneCallHistoryHandler.class);
private static final String CHANNEL_GROUP_HOURLY_FORECAST_PREFIX = "historyHours";
private static final Pattern CHANNEL_GROUP_HOURLY_FORECAST_PREFIX_PATTERN = Pattern
.compile(CHANNEL_GROUP_HOURLY_FORECAST_PREFIX + "([0-9]*)");
private @Nullable OpenWeatherMapOneCallHistAPIData weatherData;
// the relative day in history.
private int day = 0;
public OpenWeatherMapOneCallHistoryHandler(Thing thing, final TimeZoneProvider timeZoneProvider) {
super(thing, timeZoneProvider);
}
@Override
public void initialize() {
super.initialize();
OpenWeatherMapOneCallHistoryConfiguration config = getConfigAs(OpenWeatherMapOneCallHistoryConfiguration.class);
if (config.historyDay <= 0) {
logger.warn("historyDay value of {} is not supported", config.historyDay);
return;
}
/*
* As of now, only 5 days in history are supported by the one call API. As this may change in the future,
* we allow any value here and only log a warning if the value exceeds 5.
*/
if (config.historyDay > 5) {
logger.warn("History configuration of {} days may cause errors. You have been warned :-)",
config.historyDay);
}
day = config.historyDay;
logger.debug("Initialize OpenWeatherMapOneCallHistoryHandler handler '{}' with historyDay {}.",
getThing().getUID(), day);
updateStatus(ThingStatus.ONLINE);
}
@Override
protected boolean requestData(OpenWeatherMapConnection connection)
throws OpenWeatherMapCommunicationException, OpenWeatherMapConfigurationException {
logger.debug("Update weather and forecast data of thing '{}'.", getThing().getUID());
try {
weatherData = connection.getOneCallHistAPIData(location, day);
return true;
} catch (JsonSyntaxException e) {
logger.debug("JsonSyntaxException occurred during execution: {}", e.getLocalizedMessage(), e);
return false;
}
}
@Override
protected void updateChannel(ChannelUID channelUID) {
String channelGroupId = channelUID.getGroupId();
switch (channelGroupId) {
case CHANNEL_GROUP_ONECALL_HISTORY:
updateHistoryCurrentChannel(channelUID);
break;
default:
int i;
Matcher hourlyForecastMatcher = CHANNEL_GROUP_HOURLY_FORECAST_PREFIX_PATTERN.matcher(channelGroupId);
if (hourlyForecastMatcher.find() && (i = Integer.parseInt(hourlyForecastMatcher.group(1))) >= 1
&& i <= 48) {
updateHourlyHistoryChannel(channelUID, i - 1);
break;
}
break;
}
}
/**
* Update the channel from the last OpenWeatherMap data retrieved.
*
* @param channelUID the id identifying the channel to be updated
*/
private void updateHistoryCurrentChannel(ChannelUID channelUID) {
String channelId = channelUID.getIdWithoutGroup();
String channelGroupId = channelUID.getGroupId();
OpenWeatherMapOneCallHistAPIData localWeatherData = weatherData;
if (localWeatherData != null) {
State state = UnDefType.UNDEF;
switch (channelId) {
case CHANNEL_STATION_LOCATION:
state = getPointTypeState(localWeatherData.getLat(), localWeatherData.getLon());
break;
case CHANNEL_TIME_STAMP:
state = getDateTimeTypeState(localWeatherData.getCurrent().getDt());
break;
case CHANNEL_SUNRISE:
state = getDateTimeTypeState(localWeatherData.getCurrent().getSunrise());
break;
case CHANNEL_SUNSET:
state = getDateTimeTypeState(localWeatherData.getCurrent().getSunset());
break;
case CHANNEL_CONDITION:
if (!localWeatherData.getCurrent().getWeather().isEmpty()) {
state = getStringTypeState(localWeatherData.getCurrent().getWeather().get(0).getDescription());
}
break;
case CHANNEL_CONDITION_ID:
if (!localWeatherData.getCurrent().getWeather().isEmpty()) {
state = getStringTypeState(
Integer.toString(localWeatherData.getCurrent().getWeather().get(0).getId()));
}
break;
case CHANNEL_CONDITION_ICON:
if (!localWeatherData.getCurrent().getWeather().isEmpty()) {
state = getRawTypeState(OpenWeatherMapConnection
.getWeatherIcon(localWeatherData.getCurrent().getWeather().get(0).getIcon()));
}
break;
case CHANNEL_CONDITION_ICON_ID:
if (!localWeatherData.getCurrent().getWeather().isEmpty()) {
state = getStringTypeState(localWeatherData.getCurrent().getWeather().get(0).getIcon());
}
break;
case CHANNEL_TEMPERATURE:
state = getQuantityTypeState(localWeatherData.getCurrent().getTemp(), CELSIUS);
break;
case CHANNEL_APPARENT_TEMPERATURE:
state = getQuantityTypeState(localWeatherData.getCurrent().getFeelsLike(), CELSIUS);
break;
case CHANNEL_PRESSURE:
state = getQuantityTypeState(localWeatherData.getCurrent().getPressure(), HECTO(PASCAL));
break;
case CHANNEL_HUMIDITY:
state = getQuantityTypeState(localWeatherData.getCurrent().getHumidity(), PERCENT);
break;
case CHANNEL_DEW_POINT:
state = getQuantityTypeState(localWeatherData.getCurrent().getDewPoint(), CELSIUS);
break;
case CHANNEL_WIND_SPEED:
state = getQuantityTypeState(localWeatherData.getCurrent().getWindSpeed(), METRE_PER_SECOND);
break;
case CHANNEL_WIND_DIRECTION:
state = getQuantityTypeState(localWeatherData.getCurrent().getWindDeg(), DEGREE_ANGLE);
break;
case CHANNEL_GUST_SPEED:
state = getQuantityTypeState(localWeatherData.getCurrent().getWindGust(), METRE_PER_SECOND);
break;
case CHANNEL_CLOUDINESS:
state = getQuantityTypeState(localWeatherData.getCurrent().getClouds(), PERCENT);
break;
case CHANNEL_UVINDEX:
state = getDecimalTypeState(localWeatherData.getCurrent().getUvi());
break;
case CHANNEL_RAIN:
Rain rain = localWeatherData.getCurrent().getRain();
state = getQuantityTypeState(rain == null ? 0 : rain.get1h(), MILLI(METRE));
break;
case CHANNEL_SNOW:
Snow snow = localWeatherData.getCurrent().getSnow();
state = getQuantityTypeState(snow == null ? 0 : snow.get1h(), MILLI(METRE));
break;
case CHANNEL_VISIBILITY:
@Nullable
State tempstate = new QuantityType<>(localWeatherData.getCurrent().getVisibility(), METRE)
.toUnit(KILO(METRE));
state = (tempstate == null ? state : tempstate);
break;
default:
// This should not happen
logger.warn("Unknown channel id {} in onecall current weather data", channelId);
break;
}
logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
updateState(channelUID, state);
} else {
logger.debug("No weather data available to update channel '{}' of group '{}'.", channelId, channelGroupId);
}
}
/**
* Update the channel from the last OpenWeatherMap data retrieved.
*
* @param channelUID the id identifying the channel to be updated
* @param count the number of the hour referenced by the channel
*/
private void updateHourlyHistoryChannel(ChannelUID channelUID, int count) {
String channelId = channelUID.getIdWithoutGroup();
String channelGroupId = channelUID.getGroupId();
logger.debug("Updating hourly history data for channel {}, group {}, count {}", channelId, channelGroupId,
count);
OpenWeatherMapOneCallHistAPIData localWeatherData = weatherData;
if (localWeatherData != null && localWeatherData.getHourly().size() > count) {
Hourly historyData = localWeatherData.getHourly().get(count);
State state = UnDefType.UNDEF;
switch (channelId) {
case CHANNEL_TIME_STAMP:
state = getDateTimeTypeState(historyData.getDt());
break;
case CHANNEL_CONDITION:
if (!historyData.getWeather().isEmpty()) {
state = getStringTypeState(historyData.getWeather().get(0).getDescription());
}
break;
case CHANNEL_CONDITION_ID:
if (!historyData.getWeather().isEmpty()) {
state = getStringTypeState(Integer.toString(historyData.getWeather().get(0).getId()));
}
break;
case CHANNEL_CONDITION_ICON:
if (!historyData.getWeather().isEmpty()) {
state = getRawTypeState(
OpenWeatherMapConnection.getWeatherIcon(historyData.getWeather().get(0).getIcon()));
}
break;
case CHANNEL_CONDITION_ICON_ID:
if (!historyData.getWeather().isEmpty()) {
state = getStringTypeState(historyData.getWeather().get(0).getIcon());
}
break;
case CHANNEL_TEMPERATURE:
state = getQuantityTypeState(historyData.getTemp(), CELSIUS);
break;
case CHANNEL_APPARENT_TEMPERATURE:
state = getQuantityTypeState(historyData.getFeelsLike(), CELSIUS);
break;
case CHANNEL_PRESSURE:
state = getQuantityTypeState(historyData.getPressure(), HECTO(PASCAL));
break;
case CHANNEL_HUMIDITY:
state = getQuantityTypeState(historyData.getHumidity(), PERCENT);
break;
case CHANNEL_DEW_POINT:
state = getQuantityTypeState(historyData.getDewPoint(), CELSIUS);
break;
case CHANNEL_WIND_SPEED:
state = getQuantityTypeState(historyData.getWindSpeed(), METRE_PER_SECOND);
break;
case CHANNEL_WIND_DIRECTION:
state = getQuantityTypeState(historyData.getWindDeg(), DEGREE_ANGLE);
break;
case CHANNEL_GUST_SPEED:
state = getQuantityTypeState(historyData.getWindGust(), METRE_PER_SECOND);
break;
case CHANNEL_CLOUDINESS:
state = getQuantityTypeState(historyData.getClouds(), PERCENT);
break;
case CHANNEL_VISIBILITY:
@Nullable
State tempstate = new QuantityType<>(historyData.getVisibility(), METRE).toUnit(KILO(METRE));
state = (tempstate == null ? state : tempstate);
case CHANNEL_RAIN:
Rain rain = historyData.getRain();
state = getQuantityTypeState(rain == null ? 0 : rain.get1h(), MILLI(METRE));
break;
case CHANNEL_SNOW:
Snow snow = historyData.getSnow();
state = getQuantityTypeState(snow == null ? 0 : snow.get1h(), MILLI(METRE));
break;
default:
// This should not happen
logger.warn("Unknown channel id {} in onecall hourly weather data", channelId);
break;
}
logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
updateState(channelUID, state);
} else {
logger.debug("No weather data available to update channel '{}' of group '{}'.", channelId, channelGroupId);
}
}
}

View File

@ -88,4 +88,40 @@
</parameter>
</config-description>
<config-description uri="thing-type:openweathermap:onecall">
<parameter name="location" type="text" required="true">
<context>location</context>
<label>Location of Weather</label>
<description>Location of weather in geographical coordinates (latitude/longitude/altitude).</description>
</parameter>
<parameter name="forecastDays" type="integer" min="0" max="8" step="1">
<label>Number of Days</label>
<description>Number of days for daily forecast, including the current day.</description>
<default>6</default>
</parameter>
<parameter name="forecastHours" type="integer" min="0" max="48" step="1">
<label>Number of Hours</label>
<description>Number of hours for hourly forecast.</description>
<default>12</default>
</parameter>
<parameter name="forecastMinutes" type="integer" min="0" max="60" step="1">
<label>Number of Minutes</label>
<description>Number of minutes for minutely precipitation forecast.</description>
<default>0</default>
</parameter>
</config-description>
<config-description uri="thing-type:openweathermap:onecall-history">
<parameter name="location" type="text" required="true">
<context>location</context>
<label>Location of Weather</label>
<description>Location of weather in geographical coordinates (latitude/longitude/altitude).</description>
</parameter>
<parameter name="historyDay" type="integer" min="1" max="5" step="1">
<label>History Day</label>
<description>Relative number of days in the past for historical data.</description>
<default>1</default>
</parameter>
</config-description>
</config-description:config-descriptions>

View File

@ -10,6 +10,10 @@ offline.conf-error-not-supported-number-of-hours = The 'forecastHours' parameter
offline.conf-error-not-supported-number-of-days = The 'forecastDays' parameter must be between 0 and 16.
offline.conf-error-not-supported-uvindex-number-of-days = The 'forecastDays' parameter must be between 1 and 8.
offline.conf-error-not-supported-onecall-number-of-minutes = The 'forecastMinutes' parameter must be between 0 and 60.
offline.conf-error-not-supported-onecall-number-of-hours = The 'forecastHours' parameter must be between 0 and 48.
offline.conf-error-not-supported-onecall-number-of-days = The 'forecastDays' parameter must be between 0 and 7.
# discovery result
discovery.openweathermap.weather-and-forecast.api.local.label = Local Weather And Forecast
discovery.openweathermap.uvindex.api.local.label = Local UV Index

View File

@ -258,6 +258,10 @@ offline.conf-error-not-supported-number-of-hours = Der Parameter 'forecastHours'
offline.conf-error-not-supported-number-of-days = Der Parameter 'forecastDays' muss zwischen 0 und 16 liegen.
offline.conf-error-not-supported-uvindex-number-of-days = Der Parameter 'forecastDays' muss zwischen 1 und 8 liegen.
offline.conf-error-not-supported-onecall-number-of-minutes = Der Parameter 'forecastMinutes' muss zwischen 0 and 60 liegen.
offline.conf-error-not-supported-onecall-number-of-hours = Der Parameter 'forecastHours' muss zwischen 0 und 48 liegen.
offline.conf-error-not-supported-onecall-number-of-days = Der Parameter 'forecastDays' muss zwischen 0 und 7 liegen.
# discovery result
discovery.openweathermap.weather-and-forecast.api.local.label = Lokales Wetter und Wettervorhersage
discovery.openweathermap.uvindex.api.local.label = Lokaler UV-Index

View File

@ -252,6 +252,10 @@ offline.conf-error-not-supported-number-of-hours = Le param
offline.conf-error-not-supported-number-of-days = Le paramètre 'forecastDays' doit être compris entre 0 et 16.
offline.conf-error-not-supported-uvindex-number-of-days = Le paramètre 'forecastDays' doit être compris entre 1 et 8.
offline.conf-error-not-supported-onecall-number-of-minutes = Le paramètre 'forecastMinutes' doit être compris entre 0 et 60.
offline.conf-error-not-supported-onecall-number-of-hours = Le paramètre 'forecastHours' doit être compris entre 0 et 48.
offline.conf-error-not-supported-onecall-number-of-days = Le paramètre 'forecastDays' doit être compris entre 0 et 7.
# discovery result
discovery.openweathermap.weather-and-forecast.api.local.label = Météo locale et prévisions
discovery.openweathermap.uvindex.api.local.label = Indice UV local

View File

@ -105,6 +105,155 @@
</channels>
</channel-group-type>
<channel-group-type id="oneCallCurrent">
<label>One Call API Current Weather</label>
<description>Current weather data from the One Call API.</description>
<channels>
<channel id="time-stamp" typeId="time-stamp"/>
<channel id="sunrise" typeId="sunrise"/>
<channel id="sunset" typeId="sunset"/>
<channel id="condition" typeId="condition"/>
<channel id="condition-id" typeId="condition-id"/>
<channel id="icon" typeId="condition-icon"/>
<channel id="icon-id" typeId="condition-icon-id"/>
<channel id="temperature" typeId="system.outdoor-temperature"/>
<channel id="apparent-temperature" typeId="apparent-temperature"/>
<channel id="pressure" typeId="system.barometric-pressure"/>
<channel id="humidity" typeId="system.atmospheric-humidity"/>
<channel id="dew-point" typeId="dew-point"/>
<channel id="uvindex" typeId="uvindex"/>
<channel id="wind-speed" typeId="system.wind-speed"/>
<channel id="wind-direction" typeId="system.wind-direction"/>
<channel id="gust-speed" typeId="gust-speed"/>
<channel id="cloudiness" typeId="cloudiness"/>
<channel id="rain" typeId="rain"/>
<channel id="snow" typeId="snow"/>
<channel id="visibility" typeId="visibility"/>
</channels>
</channel-group-type>
<channel-group-type id="oneCallMinutely">
<label>One Call API Minutely Forecast</label>
<description>Minutely precipitation delivered by the One Call API.</description>
<channels>
<channel id="time-stamp" typeId="time-stamp"/>
<channel id="precipitation" typeId="precipitation"/>
</channels>
</channel-group-type>
<channel-group-type id="oneCallHourly">
<label>One Call API Hourly Forecast</label>
<description>Hourly weather forecast delivered by the One Call API.</description>
<channels>
<channel id="time-stamp" typeId="hourly-forecast-time-stamp"/>
<channel id="condition" typeId="condition"/>
<channel id="condition-id" typeId="condition-id"/>
<channel id="icon" typeId="condition-icon"/>
<channel id="icon-id" typeId="condition-icon-id"/>
<channel id="temperature" typeId="system.outdoor-temperature"/>
<channel id="apparent-temperature" typeId="apparent-temperature"/>
<channel id="pressure" typeId="system.barometric-pressure"/>
<channel id="humidity" typeId="system.atmospheric-humidity"/>
<channel id="dew-point" typeId="dew-point"/>
<channel id="wind-speed" typeId="system.wind-speed"/>
<channel id="wind-direction" typeId="system.wind-direction"/>
<channel id="gust-speed" typeId="gust-speed"/>
<channel id="cloudiness" typeId="cloudiness"/>
<channel id="precip-probability" typeId="precip-probability"/>
<channel id="rain" typeId="rain"/>
<channel id="snow" typeId="snow"/>
<channel id="visibility" typeId="visibility"/>
</channels>
</channel-group-type>
<channel-group-type id="oneCallDaily">
<label>One Call API Daily Forecast</label>
<description>Daily weather forecast delivered by the One Call API.</description>
<channels>
<channel id="time-stamp" typeId="daily-forecast-time-stamp"/>
<channel id="sunrise" typeId="sunrise"/>
<channel id="sunset" typeId="sunset"/>
<channel id="condition" typeId="condition"/>
<channel id="condition-id" typeId="condition-id"/>
<channel id="icon" typeId="condition-icon"/>
<channel id="icon-id" typeId="condition-icon-id"/>
<channel id="morning-temperature" typeId="morning-temperature"/>
<channel id="day-temperature" typeId="day-temperature"/>
<channel id="evening-temperature" typeId="evening-temperature"/>
<channel id="night-temperature" typeId="night-temperature"/>
<channel id="min-temperature" typeId="forecasted-min-outdoor-temperature"/>
<channel id="max-temperature" typeId="forecasted-max-outdoor-temperature"/>
<channel id="apparent-morning" typeId="apparent-morning"/>
<channel id="apparent-day" typeId="apparent-day"/>
<channel id="apparent-evening" typeId="apparent-evening"/>
<channel id="apparent-night" typeId="apparent-night"/>
<channel id="pressure" typeId="system.barometric-pressure"/>
<channel id="humidity" typeId="system.atmospheric-humidity"/>
<channel id="wind-speed" typeId="system.wind-speed"/>
<channel id="wind-direction" typeId="system.wind-direction"/>
<channel id="gust-speed" typeId="gust-speed"/>
<channel id="cloudiness" typeId="cloudiness"/>
<channel id="uvindex" typeId="forecasted-uvindex"/>
<channel id="precip-probability" typeId="precip-probability"/>
<channel id="rain" typeId="rain"/>
<channel id="snow" typeId="snow"/>
<channel id="visibility" typeId="visibility"/>
</channels>
</channel-group-type>
<channel-group-type id="oneCallHistory">
<label>One Call API Historical Weather</label>
<description>Historical weather data from the One Call API at this point in time the given day.</description>
<channels>
<channel id="time-stamp" typeId="time-stamp"/>
<channel id="sunrise" typeId="sunrise"/>
<channel id="sunset" typeId="sunset"/>
<channel id="condition" typeId="condition"/>
<channel id="condition-id" typeId="condition-id"/>
<channel id="icon" typeId="condition-icon"/>
<channel id="icon-id" typeId="condition-icon-id"/>
<channel id="temperature" typeId="system.outdoor-temperature"/>
<channel id="apparent-temperature" typeId="apparent-temperature"/>
<channel id="pressure" typeId="system.barometric-pressure"/>
<channel id="humidity" typeId="system.atmospheric-humidity"/>
<channel id="dew-point" typeId="dew-point"/>
<channel id="uvindex" typeId="uvindex"/>
<channel id="wind-speed" typeId="system.wind-speed"/>
<channel id="wind-direction" typeId="system.wind-direction"/>
<channel id="gust-speed" typeId="gust-speed"/>
<channel id="cloudiness" typeId="cloudiness"/>
<channel id="rain" typeId="rain"/>
<channel id="snow" typeId="snow"/>
<channel id="visibility" typeId="visibility"/>
</channels>
</channel-group-type>
<channel-group-type id="oneCallHistoryHours">
<label>One Call API Hourly Historical Weather Data</label>
<description>Historical weather data from the One Call API per hour.</description>
<channels>
<channel id="time-stamp" typeId="time-stamp"/>
<channel id="condition" typeId="condition"/>
<channel id="condition-id" typeId="condition-id"/>
<channel id="icon" typeId="condition-icon"/>
<channel id="icon-id" typeId="condition-icon-id"/>
<channel id="temperature" typeId="system.outdoor-temperature"/>
<channel id="apparent-temperature" typeId="apparent-temperature"/>
<channel id="pressure" typeId="system.barometric-pressure"/>
<channel id="humidity" typeId="system.atmospheric-humidity"/>
<channel id="dew-point" typeId="dew-point"/>
<channel id="uvindex" typeId="uvindex"/>
<channel id="wind-speed" typeId="system.wind-speed"/>
<channel id="wind-direction" typeId="system.wind-direction"/>
<channel id="gust-speed" typeId="gust-speed"/>
<channel id="cloudiness" typeId="cloudiness"/>
<channel id="rain" typeId="rain"/>
<channel id="snow" typeId="snow"/>
<channel id="visibility" typeId="visibility"/>
</channels>
</channel-group-type>
<!-- Channels for OpenWeatherMap Binding -->
<channel-type id="station-id">
<item-type>String</item-type>
@ -128,6 +277,22 @@
<state readOnly="true" pattern="%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS"/>
</channel-type>
<channel-type id="sunrise">
<item-type>DateTime</item-type>
<label>Sunrise Time</label>
<description>Time of sunrise for the given day.</description>
<category>Time</category>
<state readOnly="true" pattern="%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS"/>
</channel-type>
<channel-type id="sunset">
<item-type>DateTime</item-type>
<label>Sunset Time</label>
<description>Time of sunset for the given day.</description>
<category>Time</category>
<state readOnly="true" pattern="%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS"/>
</channel-type>
<channel-type id="hourly-forecast-time-stamp">
<item-type>DateTime</item-type>
<label>Forecast Time</label>
@ -205,6 +370,38 @@
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="day-temperature">
<item-type>Number:Temperature</item-type>
<label>Day Temperature</label>
<description>Forecasted outdoor temperature for the day.</description>
<category>Temperature</category>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="morning-temperature">
<item-type>Number:Temperature</item-type>
<label>Morning Temperature</label>
<description>Forecasted outdoor temperature for the morning.</description>
<category>Temperature</category>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="evening-temperature">
<item-type>Number:Temperature</item-type>
<label>Evening Temperature</label>
<description>Forecasted outdoor temperature for the evening.</description>
<category>Temperature</category>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="night-temperature">
<item-type>Number:Temperature</item-type>
<label>Night Temperature</label>
<description>Forecasted outdoor temperature for the night.</description>
<category>Temperature</category>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="apparent-temperature">
<item-type>Number:Temperature</item-type>
<label>Apparent Temperature</label>
@ -213,6 +410,54 @@
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="apparent-morning">
<item-type>Number:Temperature</item-type>
<label>Apparent Morning Temperature</label>
<description>Forecasted apparent temperature in the morning.</description>
<category>Temperature</category>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="apparent-day">
<item-type>Number:Temperature</item-type>
<label>Apparent Day Temperature</label>
<description>Forecasted apparent temperature during the day.</description>
<category>Temperature</category>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="apparent-evening">
<item-type>Number:Temperature</item-type>
<label>Apparent Evening Temperature</label>
<description>Forecasted apparent temperature at the evening.</description>
<category>Temperature</category>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="apparent-night">
<item-type>Number:Temperature</item-type>
<label>Apparent Night Temperature</label>
<description>Forecasted apparent temperature in the night.</description>
<category>Temperature</category>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="dew-point" advanced="true">
<item-type>Number:Temperature</item-type>
<label>Dew-Point Temperature</label>
<description>Forecasted dew-point temperature.</description>
<category>Temperature</category>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="precipitation">
<item-type>Number:Length</item-type>
<label>Precipitation</label>
<description>Precipitation volume of the related timespan.</description>
<category>Precipitation</category>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<channel-type id="forecasted-apparent-temperature">
<item-type>Number:Temperature</item-type>
<label>Forecasted Apparent Temperature</label>
@ -338,4 +583,11 @@
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="precip-probability">
<item-type>Number:Dimensionless</item-type>
<label>Probability</label>
<description>Forecasted precipitation probability.</description>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
</thing:thing-descriptions>

View File

@ -116,4 +116,183 @@
<config-description-ref uri="thing-type:openweathermap:uvindex"/>
</thing-type>
<thing-type id="onecall">
<supported-bridge-type-refs>
<bridge-type-ref id="weather-api"/>
</supported-bridge-type-refs>
<label>One Call API Weather and Forecast</label>
<description>Provides current weather and forecast data from the OpenWeatherMap One Call API.</description>
<channel-groups>
<channel-group id="current" typeId="oneCallCurrent"/>
<channel-group id="forecastMinutes01" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes02" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes03" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes04" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes05" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes06" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes07" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes08" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes09" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes10" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes11" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes12" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes13" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes14" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes15" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes16" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes17" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes18" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes19" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes20" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes21" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes22" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes23" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes24" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes25" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes26" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes27" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes28" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes29" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes30" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes31" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes32" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes33" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes34" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes35" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes36" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes37" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes38" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes39" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes40" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes41" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes42" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes43" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes44" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes45" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes46" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes47" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes48" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes49" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes50" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes51" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes52" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes53" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes54" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes55" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes56" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes57" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes58" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes59" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes60" typeId="oneCallMinutely"/>
<channel-group id="forecastHours01" typeId="oneCallHourly"/>
<channel-group id="forecastHours02" typeId="oneCallHourly"/>
<channel-group id="forecastHours03" typeId="oneCallHourly"/>
<channel-group id="forecastHours04" typeId="oneCallHourly"/>
<channel-group id="forecastHours05" typeId="oneCallHourly"/>
<channel-group id="forecastHours06" typeId="oneCallHourly"/>
<channel-group id="forecastHours07" typeId="oneCallHourly"/>
<channel-group id="forecastHours08" typeId="oneCallHourly"/>
<channel-group id="forecastHours09" typeId="oneCallHourly"/>
<channel-group id="forecastHours10" typeId="oneCallHourly"/>
<channel-group id="forecastHours11" typeId="oneCallHourly"/>
<channel-group id="forecastHours12" typeId="oneCallHourly"/>
<channel-group id="forecastHours13" typeId="oneCallHourly"/>
<channel-group id="forecastHours14" typeId="oneCallHourly"/>
<channel-group id="forecastHours15" typeId="oneCallHourly"/>
<channel-group id="forecastHours16" typeId="oneCallHourly"/>
<channel-group id="forecastHours17" typeId="oneCallHourly"/>
<channel-group id="forecastHours18" typeId="oneCallHourly"/>
<channel-group id="forecastHours19" typeId="oneCallHourly"/>
<channel-group id="forecastHours20" typeId="oneCallHourly"/>
<channel-group id="forecastHours21" typeId="oneCallHourly"/>
<channel-group id="forecastHours22" typeId="oneCallHourly"/>
<channel-group id="forecastHours23" typeId="oneCallHourly"/>
<channel-group id="forecastHours24" typeId="oneCallHourly"/>
<channel-group id="forecastToday" typeId="oneCallDaily">
<label>One Call API Todays Forecast</label>
<description>This is the weather forecast for today from the one call API.</description>
</channel-group>
<channel-group id="forecastTomorrow" typeId="oneCallDaily">
<label>One Call API Tomorrows Forecast</label>
<description>This is the weather forecast for tomorrow from the one call API.</description>
</channel-group>
<channel-group id="forecastDay2" typeId="oneCallDaily">
<label>One Call API 2 Day Forecast</label>
<description>This is the weather forecast in two days from the one call API.</description>
</channel-group>
<channel-group id="forecastDay3" typeId="oneCallDaily">
<label>One Call API 3 Day Forecast</label>
<description>This is the weather forecast in three days from the one call API.</description>
</channel-group>
<channel-group id="forecastDay4" typeId="oneCallDaily">
<label>One Call API 4 Day Forecast</label>
<description>This is the weather forecast in four days from the one call API.</description>
</channel-group>
<channel-group id="forecastDay5" typeId="oneCallDaily">
<label>One Call API 5 Day Forecast</label>
<description>This is the weather forecast in five days from the one call API.</description>
</channel-group>
<channel-group id="forecastDay6" typeId="oneCallDaily">
<label>One Call API 6 Day Forecast</label>
<description>This is the weather forecast in six days from the one call API.</description>
</channel-group>
<channel-group id="forecastDay7" typeId="oneCallDaily">
<label>One Call API 7 Day Forecast</label>
<description>This is the weather forecast in seven days from the one call API.</description>
</channel-group>
</channel-groups>
<representation-property>location</representation-property>
<config-description-ref uri="thing-type:openweathermap:onecall"/>
</thing-type>
<thing-type id="onecall-history">
<supported-bridge-type-refs>
<bridge-type-ref id="weather-api"/>
</supported-bridge-type-refs>
<label>One Call API Historical data</label>
<description>Provides historical weather data from the OpenWeatherMap One Call API.</description>
<channel-groups>
<channel-group id="history" typeId="oneCallHistory"/>
<channel-group id="historyHours01" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours02" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours03" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours04" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours05" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours06" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours07" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours08" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours09" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours10" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours11" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours12" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours13" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours14" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours15" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours16" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours17" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours18" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours19" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours20" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours21" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours22" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours23" typeId="oneCallHistoryHours"/>
<channel-group id="historyHours24" typeId="oneCallHistoryHours"/>
</channel-groups>
<representation-property>location</representation-property>
<config-description-ref uri="thing-type:openweathermap:onecall-history"/>
</thing-type>
</thing:thing-descriptions>