[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:
Florian Hotze
2023-12-14 20:21:54 +01:00
committed by GitHub
parent ea3e608c81
commit c81a263b91
7 changed files with 655 additions and 276 deletions

View File

@@ -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

View File

@@ -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.
* *

View File

@@ -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">

View File

@@ -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.

View File

@@ -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>

View File

@@ -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"/>

View File

@@ -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>