## Supported Things
-There are three supported things.
+There are five supported things.
### OpenWeatherMap Account
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.
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
| 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. |
| 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** |
| 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.
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 |
| 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. |
| 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
| 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. |
| 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 |
| 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
}
```
+#### 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
...
```
+#### 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
}
}
```
+
+#### 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
+ }
+
+}
+```
\ No newline at end of file
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";
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";
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";
--- /dev/null
+/**
+ * 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;
+}
--- /dev/null
+/**
+ * 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;
+}
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;
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;
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";
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;
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);
}
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");
ThingUID bridgeUID = bridgeHandler.getThing().getUID();
createWeatherAndForecastResult(locationString, bridgeUID);
createUVIndexResult(locationString, bridgeUID);
+ createOneCallResult(locationString, bridgeUID);
+ createOneCallHistoryResult(locationString, bridgeUID);
}
private void createWeatherAndForecastResult(String location, ThingUID bridgeUID) {
.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());
+ }
}
--- /dev/null
+/**
+ * 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;
+ }
+}
--- /dev/null
+/**
+ * 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;
+ }
+}
--- /dev/null
+/**
+ * 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;
+ }
+}
--- /dev/null
+/**
+ * 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;
+ }
+}
--- /dev/null
+/**
+ * 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;
+ }
+}
--- /dev/null
+/**
+ * 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;
+ }
+}
--- /dev/null
+/**
+ * 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;
+ }
+}
--- /dev/null
+/**
+ * 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;
+ }
+}
--- /dev/null
+/**
+ * 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;
+ }
+}
--- /dev/null
+/**
+ * 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;
+ }
+}
--- /dev/null
+/**
+ * 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;
+ }
+}
--- /dev/null
+/**
+ * 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;
+ }
+}
--- /dev/null
+/**
+ * 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;
+ }
+}
--- /dev/null
+/**
+ * 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;
+ }
+}
--- /dev/null
+/**
+ * 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;
+ }
+}
--- /dev/null
+/**
+ * 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;
+ }
+}
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;
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;
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;
*
* @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;
}
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) {
channels.add(newChannel);
}
}
+ logger.debug("Built channels: {}", channels);
return channels;
}
--- /dev/null
+/**
+ * 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);
+ }
+ }
+}
--- /dev/null
+/**
+ * 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);
+ }
+ }
+}
</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>
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
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
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
</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>
<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>
<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>
<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>
<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>
<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>