[openweathermap] Add support for persisting OneCall API forecasts (#15963)
Implement time series support introduced by https://github.com/openhab/openhab-core/pull/3597. Signed-off-by: Florian Hotze <florianh_dev@icloud.com>
This commit is contained in:
@@ -50,6 +50,7 @@ New Subscribers to the One Call API will require setting the API version to 3.0
|
|||||||
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.
|
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.
|
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.
|
You can add as many `onecall` things for different locations to your setup as you like to observe.
|
||||||
|
It also supports persisting forecast data using time series support, please read [Persisting Time Series](#persisting-time-series).
|
||||||
|
|
||||||
### One Call API History Data
|
### One Call API History Data
|
||||||
|
|
||||||
@@ -70,7 +71,7 @@ Once the system location will be changed, the background discovery updates the c
|
|||||||
| Parameter | Description |
|
| Parameter | Description |
|
||||||
|-----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|-----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| apikey | API key to access the OpenWeatherMap API. **Mandatory** |
|
| apikey | API key to access the OpenWeatherMap API. **Mandatory** |
|
||||||
| refreshInterval | Specifies the refresh interval (in minutes). Optional, the default value is 60, the minimum value is 1. |
|
| refreshInterval | Specifies the refresh interval (in minutes). Optional, the default value is 60, the minimum value is 1. |
|
||||||
| language | Language to be used by the OpenWeatherMap API. Optional, valid values are: `ar`, `bg`, `ca`, `de`, `el`, `en`, `es`, `fa`, `fi`, `fr`, `gl`, `hr`, `hu`, `it`, `ja`, `kr`, `la`, `lt`, `mk`, `nl`, `pl`, `pt`, `ro`, `ru`, `se`, `sk`, `sl`, `tr`, `ua`, `vi`, `zh_cn`, `zh_tw`. |
|
| language | Language to be used by the OpenWeatherMap API. Optional, valid values are: `ar`, `bg`, `ca`, `de`, `el`, `en`, `es`, `fa`, `fi`, `fr`, `gl`, `hr`, `hu`, `it`, `ja`, `kr`, `la`, `lt`, `mk`, `nl`, `pl`, `pt`, `ro`, `ru`, `se`, `sk`, `sl`, `tr`, `ua`, `vi`, `zh_cn`, `zh_tw`. |
|
||||||
|
|
||||||
### Current Weather And Forecast
|
### Current Weather And Forecast
|
||||||
@@ -103,13 +104,16 @@ Once the parameter `forecastHours` will be changed, the available channel groups
|
|||||||
|
|
||||||
### One Call API Weather and Forecast
|
### One Call API Weather and Forecast
|
||||||
|
|
||||||
| Parameter | Description |
|
| Parameter | Description |
|
||||||
|----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|-----------------|---------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| location | Location of weather in geographical coordinates (latitude/longitude/altitude). **Mandatory** |
|
| 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"). |
|
| forecastMinutes | Number of minutes for minutely precipitation forecast as minutely channels. Optional, the default value is 0 (min="0", max="60"). |
|
||||||
| forecastHours | Number of hours for hourly forecast. Optional, the default value is 24 (min="0", max="48"). |
|
| forecastHours | Number of hours for hourly forecast as hourly channels. Optional, the default value is 12 (min="0", max="48"). |
|
||||||
| forecastDays | Number of days for daily forecast (including todays forecast). Optional, the default value is 6 (min="0", max="8"). |
|
| forecastDays | Number of days for daily forecast (including todays forecast) as daily channels. Optional, the default value is 6 (min="0", max="8"). |
|
||||||
| numberOfAlerts | Number of alerts to be shown. Optional, the default value is 0 (min="0", max="5"). |
|
| numberOfAlerts | Number of alerts to be shown. Optional, the default value is 0 (min="0", max="5"). |
|
||||||
|
|
||||||
|
Set `forecastMinutes`, `forecastHours` and `forecastDays` to `0` if you only want to use the channels with time series support.
|
||||||
|
In a future release, this will become the default setting as usage of the time series channels instead is encouraged.
|
||||||
|
|
||||||
### One Call API History Data
|
### One Call API History Data
|
||||||
|
|
||||||
@@ -128,7 +132,7 @@ Once the parameter `forecastHours` will be changed, the available channel groups
|
|||||||
| station | name | String | Name of the weather station or the city. |
|
| station | name | String | Name of the weather station or the city. |
|
||||||
| station | location | Location | Location 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
|
These channels are not supported in the One Call API.
|
||||||
|
|
||||||
### Current Weather
|
### Current Weather
|
||||||
|
|
||||||
@@ -165,10 +169,12 @@ The "3h" value will be divided by three to always have an estimated value for on
|
|||||||
|
|
||||||
Where available, the One Call API provides a minutely precipitation forecast for the next 60 minutes.
|
Where available, the One Call API provides a minutely precipitation forecast for the next 60 minutes.
|
||||||
|
|
||||||
| Channel Group ID | Channel ID | Item Type | Description |
|
| Channel Group ID | Channel ID | Item Type | Description |
|
||||||
|--------------------------------------------------------|----------------------|----------------------|----------------------------------------------------------------------------|
|
|-----------------------------------------------------------|---------------|---------------|-----------------------------------------------------------------|
|
||||||
| forecastMinutes01 ... forecastMinutes60 | time-stamp | DateTime | Time of data forecasted. |
|
| forecastMinutes01 ... forecastMinutes60 | time-stamp | DateTime | Time of data forecasted. |
|
||||||
| forecastMinutes01 ... forecastMinutes60 | precipitation | Number:Length | Expected precipitation volume. |
|
| forecastMinutely, forecastMinutes01 ... forecastMinutes60 | precipitation | Number:Length | Expected precipitation volume. |
|
||||||
|
|
||||||
|
The `forecastMinutely` channel group provides [time series support](#persisting-time-series).
|
||||||
|
|
||||||
### 3 Hour Forecast
|
### 3 Hour Forecast
|
||||||
|
|
||||||
@@ -197,42 +203,49 @@ Where available, the One Call API provides a minutely precipitation forecast for
|
|||||||
### One Call API Hourly Forecast
|
### One Call API Hourly Forecast
|
||||||
|
|
||||||
The One Call API provides hourly forecasts for 48 hours.
|
The One Call API provides hourly forecasts for 48 hours.
|
||||||
The Channel Group IDs for those are `forecastHours01` to `forecastHours48`.
|
The Channel Group IDs for those are `forecastHours01` to `forecastHours48`, and `forecastHourly` for channels with time series support.
|
||||||
See above for a description of the available channels.
|
See above for a description of the available channels.
|
||||||
|
The `forecastHourly` channel group provides all channels as described above with [time series support](#persisting-time-series), except `time-stamp`.
|
||||||
|
|
||||||
|
In a future release, the `forecastHours01` to `forecastHours48` channel groups won't be created anymore by default as usage of the time series channels instead is encouraged.
|
||||||
|
|
||||||
### Daily Forecast
|
### Daily Forecast
|
||||||
|
|
||||||
| Channel Group ID | Channel ID | Item Type | Description |
|
| Channel Group ID | Channel ID | Item Type | Description |
|
||||||
|------------------------------------------------------------------|----------------------|----------------------|-----------------------------------------------------------------------------------|
|
|---------------------------------------------------------------------------------|----------------------|----------------------|----------------------------------------------------------------------------------|
|
||||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | time-stamp | DateTime | Date of data forecasted. |
|
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | time-stamp | DateTime | Date of data forecasted. |
|
||||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | sunrise | DateTime | Time of sunrise for the given day. |
|
| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | sunrise | DateTime | Time of sunrise for the given day. |
|
||||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | sunset | DateTime | Time of sunset for the given day. |
|
| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | sunset | DateTime | Time of sunset for the given day. |
|
||||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | condition | String | Forecast weather condition. |
|
| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | condition | String | Forecast weather condition. |
|
||||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | condition-id | String | Id of the forecasted weather condition. **Advanced** |
|
| forecastDaily, 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. |
|
| forecastDaily, 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** |
|
| forecastDaily, 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. Not available in the One Call API |
|
| forecastDaily, 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. |
|
| forecastDaily, 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. |
|
| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | max-temperature | Number:Temperature | Maximum forecasted temperature of a day. |
|
||||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | pressure | Number:Pressure | Forecasted barometric pressure. |
|
| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | pressure | Number:Pressure | Forecasted barometric pressure. |
|
||||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | humidity | Number:Dimensionless | Forecasted atmospheric humidity. |
|
| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | humidity | Number:Dimensionless | Forecasted atmospheric humidity. |
|
||||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | wind-speed | Number:Speed | Forecasted wind speed. |
|
| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | wind-speed | Number:Speed | Forecasted wind speed. |
|
||||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | wind-direction | Number:Angle | Forecasted wind direction. |
|
| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | wind-direction | Number:Angle | Forecasted wind direction. |
|
||||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | gust-speed | Number:Speed | Forecasted gust speed. **Advanced** |
|
| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | gust-speed | Number:Speed | Forecasted gust speed. **Advanced** |
|
||||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | cloudiness | Number:Dimensionless | Forecasted cloudiness. |
|
| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | cloudiness | Number:Dimensionless | Forecasted cloudiness. |
|
||||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | rain | Number:Length | Expected rain volume of a day. |
|
| forecastDaily, 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. |
|
| forecastDaily, 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 |
|
| forecastDaily, 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 |
|
| forecastDaily, 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. |
|
| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | precip-probability | Number:Dimensionless | Precipitation probability. |
|
||||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | morning-temperature | Number:Temperature | Expected morning temperature. Only available in the One Call API |
|
| forecastDaily, 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 |
|
| forecastDaily, 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 |
|
| forecastDaily, 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 |
|
| forecastDaily, 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 |
|
| forecastDaily, 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 |
|
| forecastDaily, 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 |
|
| forecastDaily, 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 |
|
| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | apparent-night | Number:Temperature | Expected apparent temperature in the night. Only available in the One Call API |
|
||||||
|
|
||||||
|
The `forecastDaily` channel group provides [time series support](#persisting-time-series).
|
||||||
|
|
||||||
|
In a future release, the `forecastToday` to `forecastDay7` channel groups won't be created anymore by default as usage of the time series channels instead is encouraged.
|
||||||
|
|
||||||
### One Call API Weather Warnings
|
### One Call API Weather Warnings
|
||||||
|
|
||||||
@@ -268,6 +281,21 @@ The `uvindex` channel is also available in the current data and the daily foreca
|
|||||||
| current, forecastHours01, forecastHours02, ... forecastHours120 | sulphurDioxide | Number:Density | Current or forecasted concentration of sulphur dioxide. |
|
| current, forecastHours01, forecastHours02, ... forecastHours120 | sulphurDioxide | Number:Density | Current or forecasted concentration of sulphur dioxide. |
|
||||||
| current, forecastHours01, forecastHours02, ... forecastHours120 | ammonia | Number:Density | Current or forecasted concentration of ammonia. |
|
| current, forecastHours01, forecastHours02, ... forecastHours120 | ammonia | Number:Density | Current or forecasted concentration of ammonia. |
|
||||||
|
|
||||||
|
## Persisting Time Series
|
||||||
|
|
||||||
|
The binding offers support for persisting forecast values for most channels of the [One Call API Weather and Forecast](#one-call-api-weather-and-forecast) Thing.
|
||||||
|
The recommended persistence strategy is `forecast`, as it ensures a clean history without redundancy.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
Make sure you have a persistence service installed and ready for use.
|
||||||
|
|
||||||
|
To configure persisting forecast data, create and link Items to those channels with time series support (as usual).
|
||||||
|
Next, enable persistence for these Items using the `forecast` persistence strategy.
|
||||||
|
Finally, open the UI, search for one of the newly created Items, open the analyzer and select a future time range.
|
||||||
|
|
||||||
|
To access forecast data stored in persistence from scripts and rules, use the [Persistence Extensions]({{base}}/configuration/persistence.html#persistence-extensions-in-scripts-and-rules).
|
||||||
|
|
||||||
## Full Example
|
## Full Example
|
||||||
|
|
||||||
### Things
|
### Things
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ import static org.openhab.binding.openweathermap.internal.OpenWeatherMapBindingC
|
|||||||
import static org.openhab.core.library.unit.MetricPrefix.*;
|
import static org.openhab.core.library.unit.MetricPrefix.*;
|
||||||
import static org.openhab.core.library.unit.SIUnits.*;
|
import static org.openhab.core.library.unit.SIUnits.*;
|
||||||
import static org.openhab.core.library.unit.Units.*;
|
import static org.openhab.core.library.unit.Units.*;
|
||||||
|
import static org.openhab.core.types.TimeSeries.Policy.REPLACE;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
@@ -30,6 +32,8 @@ import org.openhab.binding.openweathermap.internal.dto.OpenWeatherMapOneCallAPID
|
|||||||
import org.openhab.binding.openweathermap.internal.dto.forecast.daily.FeelsLikeTemp;
|
import org.openhab.binding.openweathermap.internal.dto.forecast.daily.FeelsLikeTemp;
|
||||||
import org.openhab.binding.openweathermap.internal.dto.forecast.daily.Temp;
|
import org.openhab.binding.openweathermap.internal.dto.forecast.daily.Temp;
|
||||||
import org.openhab.binding.openweathermap.internal.dto.onecall.Alert;
|
import org.openhab.binding.openweathermap.internal.dto.onecall.Alert;
|
||||||
|
import org.openhab.binding.openweathermap.internal.dto.onecall.Daily;
|
||||||
|
import org.openhab.binding.openweathermap.internal.dto.onecall.Hourly;
|
||||||
import org.openhab.binding.openweathermap.internal.dto.onecall.Precipitation;
|
import org.openhab.binding.openweathermap.internal.dto.onecall.Precipitation;
|
||||||
import org.openhab.core.i18n.CommunicationException;
|
import org.openhab.core.i18n.CommunicationException;
|
||||||
import org.openhab.core.i18n.ConfigurationException;
|
import org.openhab.core.i18n.ConfigurationException;
|
||||||
@@ -42,6 +46,7 @@ import org.openhab.core.thing.ThingStatus;
|
|||||||
import org.openhab.core.thing.ThingStatusDetail;
|
import org.openhab.core.thing.ThingStatusDetail;
|
||||||
import org.openhab.core.thing.binding.builder.ThingBuilder;
|
import org.openhab.core.thing.binding.builder.ThingBuilder;
|
||||||
import org.openhab.core.types.State;
|
import org.openhab.core.types.State;
|
||||||
|
import org.openhab.core.types.TimeSeries;
|
||||||
import org.openhab.core.types.UnDefType;
|
import org.openhab.core.types.UnDefType;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -54,6 +59,7 @@ import com.google.gson.JsonSyntaxException;
|
|||||||
*
|
*
|
||||||
* @author Wolfgang Klimt - Initial contribution
|
* @author Wolfgang Klimt - Initial contribution
|
||||||
* @author Christoph Weitkamp - Added weather alerts
|
* @author Christoph Weitkamp - Added weather alerts
|
||||||
|
* @author Florian Hotze - Added support for persisting forecasts
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler {
|
public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler {
|
||||||
@@ -61,8 +67,11 @@ public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler
|
|||||||
private final Logger logger = LoggerFactory.getLogger(OpenWeatherMapOneCallHandler.class);
|
private final Logger logger = LoggerFactory.getLogger(OpenWeatherMapOneCallHandler.class);
|
||||||
|
|
||||||
private static final String CHANNEL_GROUP_MINUTELY_FORECAST_PREFIX = "forecastMinutes";
|
private static final String CHANNEL_GROUP_MINUTELY_FORECAST_PREFIX = "forecastMinutes";
|
||||||
|
private static final String CHANNEL_GROUP_MINUTELY_TIMESERIES_PREFIX = "forecastMinutely";
|
||||||
private static final String CHANNEL_GROUP_HOURLY_FORECAST_PREFIX = "forecastHours";
|
private static final String CHANNEL_GROUP_HOURLY_FORECAST_PREFIX = "forecastHours";
|
||||||
|
private static final String CHANNEL_GROUP_HOURLY_TIMESERIES_PREFIX = "forecastHourly";
|
||||||
private static final String CHANNEL_GROUP_DAILY_FORECAST_PREFIX = "forecastDay";
|
private static final String CHANNEL_GROUP_DAILY_FORECAST_PREFIX = "forecastDay";
|
||||||
|
private static final String CHANNEL_GROUP_DAILY_TIMESERIES_PREFIX = "forecastDaily";
|
||||||
private static final String CHANNEL_GROUP_ALERTS_PREFIX = "alerts";
|
private static final String CHANNEL_GROUP_ALERTS_PREFIX = "alerts";
|
||||||
private static final Pattern CHANNEL_GROUP_HOURLY_FORECAST_PREFIX_PATTERN = Pattern
|
private static final Pattern CHANNEL_GROUP_HOURLY_FORECAST_PREFIX_PATTERN = Pattern
|
||||||
.compile(CHANNEL_GROUP_HOURLY_FORECAST_PREFIX + "([0-9]*)");
|
.compile(CHANNEL_GROUP_HOURLY_FORECAST_PREFIX + "([0-9]*)");
|
||||||
@@ -75,9 +84,10 @@ public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler
|
|||||||
|
|
||||||
private @Nullable OpenWeatherMapOneCallAPIData weatherData;
|
private @Nullable OpenWeatherMapOneCallAPIData weatherData;
|
||||||
|
|
||||||
private int forecastMinutes = 60;
|
// forecastMinutes, -Hours and -Days determine the number of channel groups to create for each type
|
||||||
private int forecastHours = 24;
|
private int forecastMinutes = 0;
|
||||||
private int forecastDays = 8;
|
private int forecastHours = 12;
|
||||||
|
private int forecastDays = 6;
|
||||||
private int numberOfAlerts = 0;
|
private int numberOfAlerts = 0;
|
||||||
|
|
||||||
public OpenWeatherMapOneCallHandler(Thing thing, final TimeZoneProvider timeZoneProvider) {
|
public OpenWeatherMapOneCallHandler(Thing thing, final TimeZoneProvider timeZoneProvider) {
|
||||||
@@ -217,8 +227,8 @@ public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler
|
|||||||
throws CommunicationException, ConfigurationException {
|
throws CommunicationException, ConfigurationException {
|
||||||
logger.debug("Update weather and forecast data of thing '{}'.", getThing().getUID());
|
logger.debug("Update weather and forecast data of thing '{}'.", getThing().getUID());
|
||||||
try {
|
try {
|
||||||
weatherData = connection.getOneCallAPIData(location, forecastMinutes == 0, forecastHours == 0,
|
// Include minutely, hourly and daily data as this is needed for the time series channels
|
||||||
forecastDays == 0, numberOfAlerts == 0);
|
weatherData = connection.getOneCallAPIData(location, false, false, false, numberOfAlerts == 0);
|
||||||
return true;
|
return true;
|
||||||
} catch (JsonSyntaxException e) {
|
} catch (JsonSyntaxException e) {
|
||||||
logger.debug("JsonSyntaxException occurred during execution: {}", e.getMessage(), e);
|
logger.debug("JsonSyntaxException occurred during execution: {}", e.getMessage(), e);
|
||||||
@@ -240,6 +250,15 @@ public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler
|
|||||||
case CHANNEL_GROUP_ONECALL_TOMORROW:
|
case CHANNEL_GROUP_ONECALL_TOMORROW:
|
||||||
updateDailyForecastChannel(channelUID, 1);
|
updateDailyForecastChannel(channelUID, 1);
|
||||||
break;
|
break;
|
||||||
|
case CHANNEL_GROUP_MINUTELY_TIMESERIES_PREFIX:
|
||||||
|
updateMinutelyForecastTimeSeries(channelUID);
|
||||||
|
break;
|
||||||
|
case CHANNEL_GROUP_HOURLY_TIMESERIES_PREFIX:
|
||||||
|
updateHourlyForecastTimeSeries(channelUID);
|
||||||
|
break;
|
||||||
|
case CHANNEL_GROUP_DAILY_TIMESERIES_PREFIX:
|
||||||
|
updateDailyForecastTimeSeries(channelUID);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
int i;
|
int i;
|
||||||
Matcher hourlyForecastMatcher = CHANNEL_GROUP_HOURLY_FORECAST_PREFIX_PATTERN.matcher(channelGroupId);
|
Matcher hourlyForecastMatcher = CHANNEL_GROUP_HOURLY_FORECAST_PREFIX_PATTERN.matcher(channelGroupId);
|
||||||
@@ -412,8 +431,41 @@ public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateMinutelyForecastTimeSeries(ChannelUID channelUID) {
|
||||||
|
String channelId = channelUID.getIdWithoutGroup();
|
||||||
|
String channelGroupId = channelUID.getGroupId();
|
||||||
|
OpenWeatherMapOneCallAPIData localWeatherData = weatherData;
|
||||||
|
if (channelId.equals(CHANNEL_TIME_STAMP)) {
|
||||||
|
logger.debug("Channel `{}` of group '{}' is no supported time-series channel.", channelId, channelGroupId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (localWeatherData != null && !localWeatherData.getMinutely().isEmpty()) {
|
||||||
|
List<org.openhab.binding.openweathermap.internal.dto.onecall.Minutely> forecastData = localWeatherData
|
||||||
|
.getMinutely();
|
||||||
|
TimeSeries timeSeries = new TimeSeries(REPLACE);
|
||||||
|
forecastData.forEach((m) -> {
|
||||||
|
if (channelId.equals(CHANNEL_PRECIPITATION)) {
|
||||||
|
State state = UnDefType.UNDEF;
|
||||||
|
Instant timestamp = Instant.ofEpochSecond(m.getDt());
|
||||||
|
double precipitation = m.getPrecipitation();
|
||||||
|
state = getQuantityTypeState(precipitation, MILLI(METRE));
|
||||||
|
timeSeries.add(timestamp, state);
|
||||||
|
} else {
|
||||||
|
// This should not happen
|
||||||
|
logger.warn("Unknown channel id {} in onecall minutely weather data", channelId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
logger.debug("Update channel '{}' of group '{}' with new time-series '{}'.", channelId, channelGroupId,
|
||||||
|
timeSeries);
|
||||||
|
sendTimeSeries(channelUID, timeSeries);
|
||||||
|
} else {
|
||||||
|
logger.debug("No weather data available to update channel '{}' of group '{}'.", channelId, channelGroupId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the channel from the last OpenWeatherMap data retrieved.
|
* Update the hourly forecast channel from the last OpenWeatherMap data retrieved.
|
||||||
*
|
*
|
||||||
* @param channelUID the id identifying the channel to be updated
|
* @param channelUID the id identifying the channel to be updated
|
||||||
* @param count the index of the hourly data referenced by the channel (hour 1 is count 0)
|
* @param count the index of the hourly data referenced by the channel (hour 1 is count 0)
|
||||||
@@ -431,79 +483,7 @@ public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler
|
|||||||
if (localWeatherData != null && localWeatherData.getHourly().size() > count) {
|
if (localWeatherData != null && localWeatherData.getHourly().size() > count) {
|
||||||
org.openhab.binding.openweathermap.internal.dto.onecall.Hourly forecastData = localWeatherData.getHourly()
|
org.openhab.binding.openweathermap.internal.dto.onecall.Hourly forecastData = localWeatherData.getHourly()
|
||||||
.get(count);
|
.get(count);
|
||||||
State state = UnDefType.UNDEF;
|
State state = getHourlyForecastState(channelId, forecastData, localWeatherData);
|
||||||
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:
|
|
||||||
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:
|
|
||||||
Precipitation rain = forecastData.getRain();
|
|
||||||
state = getQuantityTypeState(rain == null ? 0 : rain.get1h(), MILLI(METRE));
|
|
||||||
break;
|
|
||||||
case CHANNEL_SNOW:
|
|
||||||
Precipitation 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);
|
logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
|
||||||
updateState(channelUID, state);
|
updateState(channelUID, state);
|
||||||
} else {
|
} else {
|
||||||
@@ -512,7 +492,115 @@ public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the channel from the last OpenWeatherMap data retrieved.
|
* Update the hourly forecast time series channel from the last OpenWeatherMap data retrieved.
|
||||||
|
*
|
||||||
|
* @param channelUID the id identifying the channel to be updated
|
||||||
|
*/
|
||||||
|
private void updateHourlyForecastTimeSeries(ChannelUID channelUID) {
|
||||||
|
String channelId = channelUID.getIdWithoutGroup();
|
||||||
|
String channelGroupId = channelUID.getGroupId();
|
||||||
|
if (channelId.equals(CHANNEL_TIME_STAMP)) {
|
||||||
|
logger.debug("Channel `{}` of group '{}' is no supported time-series channel.", channelId, channelGroupId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
OpenWeatherMapOneCallAPIData localWeatherData = weatherData;
|
||||||
|
if (localWeatherData != null && !localWeatherData.getHourly().isEmpty()) {
|
||||||
|
List<org.openhab.binding.openweathermap.internal.dto.onecall.Hourly> forecastData = localWeatherData
|
||||||
|
.getHourly();
|
||||||
|
TimeSeries timeSeries = new TimeSeries(REPLACE);
|
||||||
|
forecastData.forEach((h) -> {
|
||||||
|
Instant timestamp = Instant.ofEpochSecond(h.getDt());
|
||||||
|
State state = getHourlyForecastState(channelId, h, localWeatherData);
|
||||||
|
timeSeries.add(timestamp, state);
|
||||||
|
});
|
||||||
|
logger.debug("Update channel '{}' of group '{}' with new time-series '{}'.", channelId, channelGroupId,
|
||||||
|
timeSeries);
|
||||||
|
sendTimeSeries(channelUID, timeSeries);
|
||||||
|
} else {
|
||||||
|
logger.debug("No weather data available to update channel '{}'.", channelId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private State getHourlyForecastState(String channelId, Hourly forecastData,
|
||||||
|
OpenWeatherMapOneCallAPIData localWeatherData) {
|
||||||
|
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:
|
||||||
|
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:
|
||||||
|
Precipitation rain = forecastData.getRain();
|
||||||
|
state = getQuantityTypeState(rain == null ? 0 : rain.get1h(), MILLI(METRE));
|
||||||
|
break;
|
||||||
|
case CHANNEL_SNOW:
|
||||||
|
Precipitation 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;
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the daily forecast channel from the last OpenWeatherMap data retrieved.
|
||||||
*
|
*
|
||||||
* @param channelUID the id identifying the channel to be updated
|
* @param channelUID the id identifying the channel to be updated
|
||||||
* @param count the index of the daily data referenced by the channel (today is count 0)
|
* @param count the index of the daily data referenced by the channel (today is count 0)
|
||||||
@@ -530,143 +618,7 @@ public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler
|
|||||||
if (localWeatherData != null && localWeatherData.getDaily().size() > count) {
|
if (localWeatherData != null && localWeatherData.getDaily().size() > count) {
|
||||||
org.openhab.binding.openweathermap.internal.dto.onecall.Daily forecastData = localWeatherData.getDaily()
|
org.openhab.binding.openweathermap.internal.dto.onecall.Daily forecastData = localWeatherData.getDaily()
|
||||||
.get(count);
|
.get(count);
|
||||||
State state = UnDefType.UNDEF;
|
State state = getDailyForecastState(channelId, forecastData, localWeatherData);
|
||||||
Temp temp;
|
|
||||||
FeelsLikeTemp 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:
|
|
||||||
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);
|
logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
|
||||||
updateState(channelUID, state);
|
updateState(channelUID, state);
|
||||||
} else {
|
} else {
|
||||||
@@ -674,6 +626,173 @@ public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateDailyForecastTimeSeries(ChannelUID channelUID) {
|
||||||
|
String channelId = channelUID.getIdWithoutGroup();
|
||||||
|
String channelGroupId = channelUID.getGroupId();
|
||||||
|
if (channelId.equals(CHANNEL_TIME_STAMP)) {
|
||||||
|
logger.debug("Channel `{}` of group '{}' is no supported time-series channel.", channelId, channelGroupId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
OpenWeatherMapOneCallAPIData localWeatherData = weatherData;
|
||||||
|
if (localWeatherData != null && !localWeatherData.getDaily().isEmpty()) {
|
||||||
|
List<org.openhab.binding.openweathermap.internal.dto.onecall.Daily> forecastData = localWeatherData
|
||||||
|
.getDaily();
|
||||||
|
TimeSeries timeSeries = new TimeSeries(REPLACE);
|
||||||
|
forecastData.forEach((d) -> {
|
||||||
|
Instant timestamp = Instant.ofEpochSecond(d.getDt());
|
||||||
|
State state = getDailyForecastState(channelId, d, localWeatherData);
|
||||||
|
timeSeries.add(timestamp, state);
|
||||||
|
});
|
||||||
|
logger.debug("Update channel '{}' of group '{}' with new time-series '{}'.", channelId, channelGroupId,
|
||||||
|
timeSeries);
|
||||||
|
sendTimeSeries(channelUID, timeSeries);
|
||||||
|
} else {
|
||||||
|
logger.debug("No weather data available to update channel '{}'.", channelId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private State getDailyForecastState(String channelId, Daily forecastData,
|
||||||
|
OpenWeatherMapOneCallAPIData localWeatherData) {
|
||||||
|
State state = UnDefType.UNDEF;
|
||||||
|
FeelsLikeTemp feelsLike;
|
||||||
|
Temp temp;
|
||||||
|
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:
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the channel from the last OpenWeaterhMap data retrieved.
|
* Update the channel from the last OpenWeaterhMap data retrieved.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -130,18 +130,20 @@
|
|||||||
<description>Location of weather in geographical coordinates (latitude/longitude/altitude).</description>
|
<description>Location of weather in geographical coordinates (latitude/longitude/altitude).</description>
|
||||||
</parameter>
|
</parameter>
|
||||||
<parameter name="forecastDays" type="integer" min="0" max="8" step="1">
|
<parameter name="forecastDays" type="integer" min="0" max="8" step="1">
|
||||||
<label>Number of Days</label>
|
<label>Number of Daily Forecast Channels</label>
|
||||||
<description>Number of days for daily forecast, including the current day.</description>
|
<description>Number of days for daily forecast, including the current day and determining how many daily channels are
|
||||||
|
created.</description>
|
||||||
<default>6</default>
|
<default>6</default>
|
||||||
</parameter>
|
</parameter>
|
||||||
<parameter name="forecastHours" type="integer" min="0" max="48" step="1">
|
<parameter name="forecastHours" type="integer" min="0" max="48" step="1">
|
||||||
<label>Number of Hours</label>
|
<label>Number of Hourly Forecast Channels</label>
|
||||||
<description>Number of hours for hourly forecast.</description>
|
<description>Number of hours for hourly forecast, determining how many hourly channels are created.</description>
|
||||||
<default>12</default>
|
<default>12</default>
|
||||||
</parameter>
|
</parameter>
|
||||||
<parameter name="forecastMinutes" type="integer" min="0" max="60" step="1">
|
<parameter name="forecastMinutes" type="integer" min="0" max="60" step="1">
|
||||||
<label>Number of Minutes</label>
|
<label>Number of Minutely Forecast Channels</label>
|
||||||
<description>Number of minutes for minutely precipitation forecast.</description>
|
<description>Number of minutes for minutely precipitation forecast, determining how many minutely channels are
|
||||||
|
created.</description>
|
||||||
<default>0</default>
|
<default>0</default>
|
||||||
</parameter>
|
</parameter>
|
||||||
<parameter name="numberOfAlerts" type="integer" min="0" max="5" step="1">
|
<parameter name="numberOfAlerts" type="integer" min="0" max="5" step="1">
|
||||||
|
|||||||
@@ -74,10 +74,10 @@ thing-type.openweathermap.weather-api.description = Provides access to the OpenW
|
|||||||
|
|
||||||
# thing types config
|
# thing types config
|
||||||
|
|
||||||
bridge-type.config.openweathermap.weather-api.apikey.label = API Key
|
|
||||||
bridge-type.config.openweathermap.weather-api.apikey.description = API key to access the OpenWeatherMap API.
|
|
||||||
bridge-type.config.openweathermap.weather-api.apiVersion.label = One Call API Version
|
bridge-type.config.openweathermap.weather-api.apiVersion.label = One Call API Version
|
||||||
bridge-type.config.openweathermap.weather-api.apiVersion.description = One Call API version (defaults to 2.5, version 3.0 is available, but needs different subscription).
|
bridge-type.config.openweathermap.weather-api.apiVersion.description = One Call API version (defaults to 2.5, version 3.0 is available, but needs different subscription).
|
||||||
|
bridge-type.config.openweathermap.weather-api.apikey.label = API Key
|
||||||
|
bridge-type.config.openweathermap.weather-api.apikey.description = API key to access the OpenWeatherMap API.
|
||||||
bridge-type.config.openweathermap.weather-api.language.label = Language
|
bridge-type.config.openweathermap.weather-api.language.label = Language
|
||||||
bridge-type.config.openweathermap.weather-api.language.description = Language to be used by the OpenWeatherMap API.
|
bridge-type.config.openweathermap.weather-api.language.description = Language to be used by the OpenWeatherMap API.
|
||||||
bridge-type.config.openweathermap.weather-api.language.option.af = Afrikaans
|
bridge-type.config.openweathermap.weather-api.language.option.af = Afrikaans
|
||||||
@@ -136,12 +136,12 @@ thing-type.config.openweathermap.onecall-history.historyDay.label = History Day
|
|||||||
thing-type.config.openweathermap.onecall-history.historyDay.description = Relative number of days in the past for historical data.
|
thing-type.config.openweathermap.onecall-history.historyDay.description = Relative number of days in the past for historical data.
|
||||||
thing-type.config.openweathermap.onecall-history.location.label = Location of Weather
|
thing-type.config.openweathermap.onecall-history.location.label = Location of Weather
|
||||||
thing-type.config.openweathermap.onecall-history.location.description = Location of weather in geographical coordinates (latitude/longitude/altitude).
|
thing-type.config.openweathermap.onecall-history.location.description = Location of weather in geographical coordinates (latitude/longitude/altitude).
|
||||||
thing-type.config.openweathermap.onecall.forecastDays.label = Number of Days
|
thing-type.config.openweathermap.onecall.forecastDays.label = Number of Daily Forecast Channels
|
||||||
thing-type.config.openweathermap.onecall.forecastDays.description = Number of days for daily forecast, including the current day.
|
thing-type.config.openweathermap.onecall.forecastDays.description = Number of days for daily forecast, including the current day and determining how many daily channels are created.
|
||||||
thing-type.config.openweathermap.onecall.forecastHours.label = Number of Hours
|
thing-type.config.openweathermap.onecall.forecastHours.label = Number of Hourly Forecast Channels
|
||||||
thing-type.config.openweathermap.onecall.forecastHours.description = Number of hours for hourly forecast.
|
thing-type.config.openweathermap.onecall.forecastHours.description = Number of hours for hourly forecast, determining how many hourly channels are created.
|
||||||
thing-type.config.openweathermap.onecall.forecastMinutes.label = Number of Minutes
|
thing-type.config.openweathermap.onecall.forecastMinutes.label = Number of Minutely Forecast Channels
|
||||||
thing-type.config.openweathermap.onecall.forecastMinutes.description = Number of minutes for minutely precipitation forecast.
|
thing-type.config.openweathermap.onecall.forecastMinutes.description = Number of minutes for minutely precipitation forecast, determining how many minutely channels are created.
|
||||||
thing-type.config.openweathermap.onecall.location.label = Location of Weather
|
thing-type.config.openweathermap.onecall.location.label = Location of Weather
|
||||||
thing-type.config.openweathermap.onecall.location.description = Location of weather in geographical coordinates (latitude/longitude/altitude).
|
thing-type.config.openweathermap.onecall.location.description = Location of weather in geographical coordinates (latitude/longitude/altitude).
|
||||||
thing-type.config.openweathermap.onecall.numberOfAlerts.label = Number of Alerts
|
thing-type.config.openweathermap.onecall.numberOfAlerts.label = Number of Alerts
|
||||||
@@ -173,14 +173,20 @@ channel-group-type.openweathermap.oneCallCurrent.label = One Call API Current We
|
|||||||
channel-group-type.openweathermap.oneCallCurrent.description = Current weather data from the One Call API.
|
channel-group-type.openweathermap.oneCallCurrent.description = Current weather data from the One Call API.
|
||||||
channel-group-type.openweathermap.oneCallDaily.label = One Call API Daily Forecast
|
channel-group-type.openweathermap.oneCallDaily.label = One Call API Daily Forecast
|
||||||
channel-group-type.openweathermap.oneCallDaily.description = Daily weather forecast delivered by the One Call API.
|
channel-group-type.openweathermap.oneCallDaily.description = Daily weather forecast delivered by the One Call API.
|
||||||
|
channel-group-type.openweathermap.oneCallDailyTimeSeries.label = One Call API Daily Forecast
|
||||||
|
channel-group-type.openweathermap.oneCallDailyTimeSeries.description = Daily weather forecast delivered by the One Call API.
|
||||||
channel-group-type.openweathermap.oneCallHistory.label = One Call API Historical Weather
|
channel-group-type.openweathermap.oneCallHistory.label = One Call API Historical Weather
|
||||||
channel-group-type.openweathermap.oneCallHistory.description = Historical weather data from the One Call API at this point in time the given day.
|
channel-group-type.openweathermap.oneCallHistory.description = Historical weather data from the One Call API at this point in time the given day.
|
||||||
channel-group-type.openweathermap.oneCallHistoryHours.label = One Call API Hourly Historical Weather Data
|
channel-group-type.openweathermap.oneCallHistoryHours.label = One Call API Hourly Historical Weather Data
|
||||||
channel-group-type.openweathermap.oneCallHistoryHours.description = Historical weather data from the One Call API per hour.
|
channel-group-type.openweathermap.oneCallHistoryHours.description = Historical weather data from the One Call API per hour.
|
||||||
channel-group-type.openweathermap.oneCallHourly.label = One Call API Hourly Forecast
|
channel-group-type.openweathermap.oneCallHourly.label = One Call API Hourly Forecast
|
||||||
channel-group-type.openweathermap.oneCallHourly.description = Hourly weather forecast delivered by the One Call API.
|
channel-group-type.openweathermap.oneCallHourly.description = Hourly weather forecast delivered by the One Call API.
|
||||||
|
channel-group-type.openweathermap.oneCallHourlyTimeSeries.label = One Call API Hourly Forecast
|
||||||
|
channel-group-type.openweathermap.oneCallHourlyTimeSeries.description = Hourly weather forecast delivered by the One Call API.
|
||||||
channel-group-type.openweathermap.oneCallMinutely.label = One Call API Minutely Forecast
|
channel-group-type.openweathermap.oneCallMinutely.label = One Call API Minutely Forecast
|
||||||
channel-group-type.openweathermap.oneCallMinutely.description = Minutely precipitation delivered by the One Call API.
|
channel-group-type.openweathermap.oneCallMinutely.description = Minutely precipitation delivered by the One Call API.
|
||||||
|
channel-group-type.openweathermap.oneCallMinutelyTimeSeries.label = One Call API Minutely Forecast
|
||||||
|
channel-group-type.openweathermap.oneCallMinutelyTimeSeries.description = Minutely precipitation delivered by the One Call API.
|
||||||
channel-group-type.openweathermap.station.label = Weather Station
|
channel-group-type.openweathermap.station.label = Weather Station
|
||||||
channel-group-type.openweathermap.station.description = This is a weather station.
|
channel-group-type.openweathermap.station.description = This is a weather station.
|
||||||
channel-group-type.openweathermap.station.channel.location.description = Location of the weather station or the city.
|
channel-group-type.openweathermap.station.channel.location.description = Location of the weather station or the city.
|
||||||
|
|||||||
@@ -169,6 +169,14 @@
|
|||||||
</channels>
|
</channels>
|
||||||
</channel-group-type>
|
</channel-group-type>
|
||||||
|
|
||||||
|
<channel-group-type id="oneCallMinutelyTimeSeries">
|
||||||
|
<label>One Call API Minutely Forecast</label>
|
||||||
|
<description>Minutely precipitation delivered by the One Call API.</description>
|
||||||
|
<channels>
|
||||||
|
<channel id="precipitation" typeId="precipitation"/>
|
||||||
|
</channels>
|
||||||
|
</channel-group-type>
|
||||||
|
|
||||||
<channel-group-type id="oneCallMinutely">
|
<channel-group-type id="oneCallMinutely">
|
||||||
<label>One Call API Minutely Forecast</label>
|
<label>One Call API Minutely Forecast</label>
|
||||||
<description>Minutely precipitation delivered by the One Call API.</description>
|
<description>Minutely precipitation delivered by the One Call API.</description>
|
||||||
@@ -178,6 +186,30 @@
|
|||||||
</channels>
|
</channels>
|
||||||
</channel-group-type>
|
</channel-group-type>
|
||||||
|
|
||||||
|
<channel-group-type id="oneCallHourlyTimeSeries">
|
||||||
|
<label>One Call API Hourly Forecast</label>
|
||||||
|
<description>Hourly weather forecast delivered by the One Call API.</description>
|
||||||
|
<channels>
|
||||||
|
<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="oneCallHourly">
|
<channel-group-type id="oneCallHourly">
|
||||||
<label>One Call API Hourly Forecast</label>
|
<label>One Call API Hourly Forecast</label>
|
||||||
<description>Hourly weather forecast delivered by the One Call API.</description>
|
<description>Hourly weather forecast delivered by the One Call API.</description>
|
||||||
@@ -203,6 +235,40 @@
|
|||||||
</channels>
|
</channels>
|
||||||
</channel-group-type>
|
</channel-group-type>
|
||||||
|
|
||||||
|
<channel-group-type id="oneCallDailyTimeSeries">
|
||||||
|
<label>One Call API Daily Forecast</label>
|
||||||
|
<description>Daily weather forecast delivered by the One Call API.</description>
|
||||||
|
<channels>
|
||||||
|
<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="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="uvindex" typeId="forecasted-uvindex"/>
|
||||||
|
<channel id="precip-probability" typeId="precip-probability"/>
|
||||||
|
<channel id="rain" typeId="rain"/>
|
||||||
|
<channel id="snow" typeId="snow"/>
|
||||||
|
</channels>
|
||||||
|
</channel-group-type>
|
||||||
|
|
||||||
<channel-group-type id="oneCallDaily">
|
<channel-group-type id="oneCallDaily">
|
||||||
<label>One Call API Daily Forecast</label>
|
<label>One Call API Daily Forecast</label>
|
||||||
<description>Daily weather forecast delivered by the One Call API.</description>
|
<description>Daily weather forecast delivered by the One Call API.</description>
|
||||||
|
|||||||
@@ -142,6 +142,9 @@
|
|||||||
|
|
||||||
<channel-groups>
|
<channel-groups>
|
||||||
<channel-group id="current" typeId="oneCallCurrent"/>
|
<channel-group id="current" typeId="oneCallCurrent"/>
|
||||||
|
|
||||||
|
<channel-group id="forecastMinutely" typeId="oneCallMinutelyTimeSeries"/>
|
||||||
|
|
||||||
<channel-group id="forecastMinutes01" typeId="oneCallMinutely"/>
|
<channel-group id="forecastMinutes01" typeId="oneCallMinutely"/>
|
||||||
<channel-group id="forecastMinutes02" typeId="oneCallMinutely"/>
|
<channel-group id="forecastMinutes02" typeId="oneCallMinutely"/>
|
||||||
<channel-group id="forecastMinutes03" typeId="oneCallMinutely"/>
|
<channel-group id="forecastMinutes03" typeId="oneCallMinutely"/>
|
||||||
@@ -208,6 +211,8 @@
|
|||||||
<channel-group id="forecastMinutes59" typeId="oneCallMinutely"/>
|
<channel-group id="forecastMinutes59" typeId="oneCallMinutely"/>
|
||||||
<channel-group id="forecastMinutes60" typeId="oneCallMinutely"/>
|
<channel-group id="forecastMinutes60" typeId="oneCallMinutely"/>
|
||||||
|
|
||||||
|
<channel-group id="forecastHourly" typeId="oneCallHourlyTimeSeries"/>
|
||||||
|
|
||||||
<channel-group id="forecastHours01" typeId="oneCallHourly"/>
|
<channel-group id="forecastHours01" typeId="oneCallHourly"/>
|
||||||
<channel-group id="forecastHours02" typeId="oneCallHourly"/>
|
<channel-group id="forecastHours02" typeId="oneCallHourly"/>
|
||||||
<channel-group id="forecastHours03" typeId="oneCallHourly"/>
|
<channel-group id="forecastHours03" typeId="oneCallHourly"/>
|
||||||
@@ -233,6 +238,8 @@
|
|||||||
<channel-group id="forecastHours23" typeId="oneCallHourly"/>
|
<channel-group id="forecastHours23" typeId="oneCallHourly"/>
|
||||||
<channel-group id="forecastHours24" typeId="oneCallHourly"/>
|
<channel-group id="forecastHours24" typeId="oneCallHourly"/>
|
||||||
|
|
||||||
|
<channel-group id="forecastDaily" typeId="oneCallDailyTimeSeries"/>
|
||||||
|
|
||||||
<channel-group id="forecastToday" typeId="oneCallDaily">
|
<channel-group id="forecastToday" typeId="oneCallDaily">
|
||||||
<label>One Call API Todays Forecast</label>
|
<label>One Call API Todays Forecast</label>
|
||||||
<description>This is the weather forecast for today from the one call API.</description>
|
<description>This is the weather forecast for today from the one call API.</description>
|
||||||
@@ -267,6 +274,9 @@
|
|||||||
</channel-group>
|
</channel-group>
|
||||||
</channel-groups>
|
</channel-groups>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<property name="thingTypeVersion">1</property>
|
||||||
|
</properties>
|
||||||
<representation-property>location</representation-property>
|
<representation-property>location</representation-property>
|
||||||
|
|
||||||
<config-description-ref uri="thing-type:openweathermap:onecall"/>
|
<config-description-ref uri="thing-type:openweathermap:onecall"/>
|
||||||
|
|||||||
@@ -0,0 +1,148 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||||
|
<update:update-descriptions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:update="https://openhab.org/schemas/update-description/v1.0.0"
|
||||||
|
xsi:schemaLocation="https://openhab.org/schemas/update-description/v1.0.0 https://openhab.org/schemas/update-description-1.0.0.xsd">
|
||||||
|
|
||||||
|
<thing-type uid="openweathermap:onecall">
|
||||||
|
<instruction-set targetVersion="1">
|
||||||
|
<add-channel id="precipitation" groupIds="forecastMinutely">
|
||||||
|
<type>openweathermap:precipitation</type>
|
||||||
|
</add-channel>
|
||||||
|
|
||||||
|
<add-channel id="condition" groupIds="forecastHourly">
|
||||||
|
<type>openweathermap:condition</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="condition-id" groupIds="forecastHourly">
|
||||||
|
<type>openweathermap:condition-id</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="icon" groupIds="forecastHourly">
|
||||||
|
<type>openweathermap:condition-icon</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="icon-id" groupIds="forecastHourly">
|
||||||
|
<type>openweathermap:condition-icon-id</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="temperature" groupIds="forecastHourly">
|
||||||
|
<type>system:outdoor-temperature</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="apperent-temperature" groupIds="forecastHourly">
|
||||||
|
<type>openweathermap:apparent-temperature</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="pressure" groupIds="forecastHourly">
|
||||||
|
<type>system:barometric-pressure</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="humidity" groupIds="forecastHourly">
|
||||||
|
<type>system:atmospheric-humidity</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="dew-point" groupIds="forecastHourly">
|
||||||
|
<type>openweathermap:dew-point</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="wind-speed" groupIds="forecastHourly">
|
||||||
|
<type>system:wind-speed</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="wind-direction" groupIds="forecastHourly">
|
||||||
|
<type>system:wind-direction</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="gust-speed" groupIds="forecastHourly">
|
||||||
|
<type>openweathermap:gust-speed</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="cloudiness" groupIds="forecastHourly">
|
||||||
|
<type>openweathermap:cloudiness</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="precip-probability" groupIds="forecastHourly">
|
||||||
|
<type>openweathermap:precip-probability</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="rain" groupIds="forecastHourly">
|
||||||
|
<type>openweathermap:rain</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="snow" groupIds="forecastHourly">
|
||||||
|
<type>openweathermap:snow</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="visbility" groupIds="forecastHourly">
|
||||||
|
<type>openweathermap:visibility</type>
|
||||||
|
</add-channel>
|
||||||
|
|
||||||
|
<add-channel id="sunrise" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:sunrise</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="sunset" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:sunset</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="condition" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:condition</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="condition-id" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:condition-id</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="icon" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:condition-icon</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="icon-id" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:condition-icon-id</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="morning-temperature" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:morning-temperature</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="day-temperature" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:day-temperature</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="evening-temperature" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:evening-temperature</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="night-temperature" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:night-temperature</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="min-temperature" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:forecasted-min-outdoor-temperature</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="max-temperature" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:forecasted-max-outdoor-temperature</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="apparent-morning" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:apparent-morning</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="apparent-day" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:apparent-day</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="apparent-evening" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:apparent-evening</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="apparent-night" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:apparent-night</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="pressure" groupIds="forecastDaily">
|
||||||
|
<type>system:barometric-pressure</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="humidity" groupIds="forecastDaily">
|
||||||
|
<type>system:atmospheric-humidity</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="dew-point" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:dew-point</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="wind-speed" groupIds="forecastDaily">
|
||||||
|
<type>system:wind-speed</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="wind-direction" groupIds="forecastDaily">
|
||||||
|
<type>system:wind-direction</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="gust-speed" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:gust-speed</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="cloudiness" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:cloudiness</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="uvindex" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:forecasted-uvindex</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="precip-probability" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:precip-probability</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="rain" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:rain</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="snow" groupIds="forecastDaily">
|
||||||
|
<type>openweathermap:snow</type>
|
||||||
|
</add-channel>
|
||||||
|
</instruction-set>
|
||||||
|
</thing-type>
|
||||||
|
|
||||||
|
</update:update-descriptions>
|
||||||
Reference in New Issue
Block a user