diff --git a/bundles/org.openhab.binding.openweathermap/README.md b/bundles/org.openhab.binding.openweathermap/README.md index 1543fbeb45d44..23eb14c0723b9 100644 --- a/bundles/org.openhab.binding.openweathermap/README.md +++ b/bundles/org.openhab.binding.openweathermap/README.md @@ -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. 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. +It also supports persisting forecast data using time series support, please read [Persisting Time Series](#persisting-time-series). ### One Call API History Data @@ -70,7 +71,7 @@ Once the system location will be changed, the background discovery updates the c | Parameter | Description | |-----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 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`. | ### 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 -| Parameter | Description | -|----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| location | Location of weather in geographical coordinates (latitude/longitude/altitude). **Mandatory** | -| forecastMinutes| Number of minutes for minutely precipitation forecast. Optional, the default value is 0, so by default **no** minutely forecast data is fetched. (min="0", max="60"). | -| forecastHours | Number of hours for hourly forecast. Optional, the default value is 24 (min="0", max="48"). | -| forecastDays | Number of days for daily forecast (including todays forecast). Optional, the default value is 6 (min="0", max="8"). | -| numberOfAlerts | Number of alerts to be shown. Optional, the default value is 0 (min="0", max="5"). | +| Parameter | Description | +|-----------------|---------------------------------------------------------------------------------------------------------------------------------------| +| location | Location of weather in geographical coordinates (latitude/longitude/altitude). **Mandatory** | +| 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 as hourly channels. Optional, the default value is 12 (min="0", max="48"). | +| 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"). | + +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 @@ -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 | 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 @@ -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. -| Channel Group ID | Channel ID | Item Type | Description | -|--------------------------------------------------------|----------------------|----------------------|----------------------------------------------------------------------------| -| forecastMinutes01 ... forecastMinutes60 | time-stamp | DateTime | Time of data forecasted. | -| forecastMinutes01 ... forecastMinutes60 | precipitation | Number:Length | Expected precipitation volume. | +| Channel Group ID | Channel ID | Item Type | Description | +|-----------------------------------------------------------|---------------|---------------|-----------------------------------------------------------------| +| forecastMinutes01 ... forecastMinutes60 | time-stamp | DateTime | Time of data forecasted. | +| forecastMinutely, forecastMinutes01 ... forecastMinutes60 | precipitation | Number:Length | Expected precipitation volume. | + +The `forecastMinutely` channel group provides [time series support](#persisting-time-series). ### 3 Hour Forecast @@ -197,42 +203,49 @@ Where available, the One Call API provides a minutely precipitation forecast for ### One Call API Hourly Forecast The One Call API provides hourly forecasts for 48 hours. -The Channel Group IDs for those are `forecastHours01` to `forecastHours48`. +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. +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 -| Channel Group ID | Channel ID | Item Type | Description | -|------------------------------------------------------------------|----------------------|----------------------|-----------------------------------------------------------------------------------| -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | time-stamp | DateTime | Date of data forecasted. | -| 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. | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | condition | String | Forecast weather condition. | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | condition-id | String | Id of the forecasted weather condition. **Advanced** | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | icon | Image | Icon representing the forecasted weather condition. | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | icon-id | String | Id of the icon representing the forecasted weather condition. **Advanced** | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | apparent-temperature | Number:Temperature | Forecasted apparent temperature. Not available in the One Call API | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | min-temperature | Number:Temperature | Minimum forecasted temperature of a day. | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | max-temperature | Number:Temperature | Maximum forecasted temperature of a day. | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | pressure | Number:Pressure | Forecasted barometric pressure. | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | humidity | Number:Dimensionless | Forecasted atmospheric humidity. | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | wind-speed | Number:Speed | Forecasted wind speed. | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | wind-direction | Number:Angle | Forecasted wind direction. | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | gust-speed | Number:Speed | Forecasted gust speed. **Advanced** | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | cloudiness | Number:Dimensionless | Forecasted cloudiness. | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | rain | Number:Length | Expected rain volume of a day. | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | snow | Number:Length | Expected snow volume of a day. | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | dew-point | Number:Temperature | Expected dew-point. Only available in the One Call API | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | uvindex | Number | Forecasted Midday UV Index. Only available in the One Call API | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | precip-probability | Number:Dimensionless | Precipitation probability. | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | morning-temperature | Number:Temperature | Expected morning temperature. Only available in the One Call API | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | day-temperature | Number:Temperature | Expected day-temperature. Only available in the One Call API | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | evening-temperature | Number:Temperature | Expected evening-temperature. Only available in the One Call API | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | night-temperature | Number:Temperature | Expected night-temperature. Only available in the One Call API | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | apparent-morning | Number:Temperature | Expected apparent temperature in the morning. Only available in the One Call API | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | apparent-day | Number:Temperature | Expected apparent temperature in the day. Only available in the One Call API | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | apparent-evening | Number:Temperature | Expected apparent temperature in the evening. Only available in the One Call API | -| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | apparent-night | Number:Temperature | Expected apparent temperature in the night. Only available in the One Call API | +| Channel Group ID | Channel ID | Item Type | Description | +|---------------------------------------------------------------------------------|----------------------|----------------------|----------------------------------------------------------------------------------| +| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | time-stamp | DateTime | Date of data forecasted. | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | sunrise | DateTime | Time of sunrise for the given day. | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | sunset | DateTime | Time of sunset for the given day. | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | condition | String | Forecast weather condition. | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | condition-id | String | Id of the forecasted weather condition. **Advanced** | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | icon | Image | Icon representing the forecasted weather condition. | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | icon-id | String | Id of the icon representing the forecasted weather condition. **Advanced** | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | apparent-temperature | Number:Temperature | Forecasted apparent temperature. Not available in the One Call API | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | min-temperature | Number:Temperature | Minimum forecasted temperature of a day. | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | max-temperature | Number:Temperature | Maximum forecasted temperature of a day. | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | pressure | Number:Pressure | Forecasted barometric pressure. | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | humidity | Number:Dimensionless | Forecasted atmospheric humidity. | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | wind-speed | Number:Speed | Forecasted wind speed. | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | wind-direction | Number:Angle | Forecasted wind direction. | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | gust-speed | Number:Speed | Forecasted gust speed. **Advanced** | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | cloudiness | Number:Dimensionless | Forecasted cloudiness. | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | rain | Number:Length | Expected rain volume of a day. | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | snow | Number:Length | Expected snow volume of a day. | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | dew-point | Number:Temperature | Expected dew-point. 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 | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | precip-probability | Number:Dimensionless | Precipitation probability. | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | morning-temperature | Number:Temperature | Expected morning 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 | +| forecastDaily, forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | evening-temperature | Number:Temperature | Expected evening-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 | +| forecastDaily, 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-day | Number:Temperature | Expected apparent temperature in the day. 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 | +| 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 @@ -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 | 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 ### Things diff --git a/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/handler/OpenWeatherMapOneCallHandler.java b/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/handler/OpenWeatherMapOneCallHandler.java index 6049aaf71ec53..ef3ceb3c58f5e 100644 --- a/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/handler/OpenWeatherMapOneCallHandler.java +++ b/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/handler/OpenWeatherMapOneCallHandler.java @@ -16,7 +16,9 @@ import static org.openhab.core.library.unit.MetricPrefix.*; import static org.openhab.core.library.unit.SIUnits.*; 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.List; import java.util.regex.Matcher; @@ -30,6 +32,8 @@ 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.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.core.i18n.CommunicationException; import org.openhab.core.i18n.ConfigurationException; @@ -42,6 +46,7 @@ import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.binding.builder.ThingBuilder; import org.openhab.core.types.State; +import org.openhab.core.types.TimeSeries; import org.openhab.core.types.UnDefType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -54,6 +59,7 @@ * * @author Wolfgang Klimt - Initial contribution * @author Christoph Weitkamp - Added weather alerts + * @author Florian Hotze - Added support for persisting forecasts */ @NonNullByDefault public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler { @@ -61,8 +67,11 @@ public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler private final Logger logger = LoggerFactory.getLogger(OpenWeatherMapOneCallHandler.class); private static final String CHANNEL_GROUP_MINUTELY_FORECAST_PREFIX = "forecastMinutes"; + private static final String CHANNEL_GROUP_MINUTELY_TIMESERIES_PREFIX = "forecastMinutely"; 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_TIMESERIES_PREFIX = "forecastDaily"; private static final String CHANNEL_GROUP_ALERTS_PREFIX = "alerts"; private static final Pattern CHANNEL_GROUP_HOURLY_FORECAST_PREFIX_PATTERN = Pattern .compile(CHANNEL_GROUP_HOURLY_FORECAST_PREFIX + "([0-9]*)"); @@ -75,9 +84,10 @@ public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler private @Nullable OpenWeatherMapOneCallAPIData weatherData; - private int forecastMinutes = 60; - private int forecastHours = 24; - private int forecastDays = 8; + // forecastMinutes, -Hours and -Days determine the number of channel groups to create for each type + private int forecastMinutes = 0; + private int forecastHours = 12; + private int forecastDays = 6; private int numberOfAlerts = 0; public OpenWeatherMapOneCallHandler(Thing thing, final TimeZoneProvider timeZoneProvider) { @@ -217,8 +227,8 @@ protected boolean requestData(OpenWeatherMapConnection connection) throws CommunicationException, ConfigurationException { logger.debug("Update weather and forecast data of thing '{}'.", getThing().getUID()); try { - weatherData = connection.getOneCallAPIData(location, forecastMinutes == 0, forecastHours == 0, - forecastDays == 0, numberOfAlerts == 0); + // Include minutely, hourly and daily data as this is needed for the time series channels + weatherData = connection.getOneCallAPIData(location, false, false, false, numberOfAlerts == 0); return true; } catch (JsonSyntaxException e) { logger.debug("JsonSyntaxException occurred during execution: {}", e.getMessage(), e); @@ -240,6 +250,15 @@ protected void updateChannel(ChannelUID channelUID) { case CHANNEL_GROUP_ONECALL_TOMORROW: updateDailyForecastChannel(channelUID, 1); 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: int i; Matcher hourlyForecastMatcher = CHANNEL_GROUP_HOURLY_FORECAST_PREFIX_PATTERN.matcher(channelGroupId); @@ -412,8 +431,41 @@ private void updateMinutelyForecastChannel(ChannelUID channelUID, int count) { } } + 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 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 count the index of the hourly data referenced by the channel (hour 1 is count 0) @@ -431,79 +483,7 @@ private void updateHourlyForecastChannel(ChannelUID channelUID, int count) { if (localWeatherData != null && localWeatherData.getHourly().size() > count) { org.openhab.binding.openweathermap.internal.dto.onecall.Hourly forecastData = localWeatherData.getHourly() .get(count); - State state = UnDefType.UNDEF; - switch (channelId) { - case CHANNEL_TIME_STAMP: - state = getDateTimeTypeState(forecastData.getDt()); - break; - case CHANNEL_CONDITION: - if (!forecastData.getWeather().isEmpty()) { - state = getStringTypeState(forecastData.getWeather().get(0).getDescription()); - } - break; - case CHANNEL_CONDITION_ID: - if (!forecastData.getWeather().isEmpty()) { - state = getStringTypeState(Integer.toString(forecastData.getWeather().get(0).getId())); - } - break; - case CHANNEL_CONDITION_ICON: - if (!forecastData.getWeather().isEmpty()) { - state = getRawTypeState( - OpenWeatherMapConnection.getWeatherIcon(forecastData.getWeather().get(0).getIcon())); - } - break; - case CHANNEL_CONDITION_ICON_ID: - if (!forecastData.getWeather().isEmpty()) { - state = getStringTypeState(forecastData.getWeather().get(0).getIcon()); - } - break; - case CHANNEL_TEMPERATURE: - state = getQuantityTypeState(forecastData.getTemp(), CELSIUS); - break; - case CHANNEL_APPARENT_TEMPERATURE: - state = getQuantityTypeState(forecastData.getFeelsLike(), CELSIUS); - break; - case CHANNEL_PRESSURE: - state = getQuantityTypeState(forecastData.getPressure(), HECTO(PASCAL)); - break; - case CHANNEL_HUMIDITY: - state = getQuantityTypeState(forecastData.getHumidity(), PERCENT); - break; - case CHANNEL_DEW_POINT: - state = getQuantityTypeState(forecastData.getDewPoint(), CELSIUS); - break; - case CHANNEL_WIND_SPEED: - state = getQuantityTypeState(forecastData.getWindSpeed(), METRE_PER_SECOND); - break; - case CHANNEL_WIND_DIRECTION: - state = getQuantityTypeState(forecastData.getWindDeg(), DEGREE_ANGLE); - break; - case CHANNEL_GUST_SPEED: - state = getQuantityTypeState(forecastData.getWindGust(), METRE_PER_SECOND); - break; - case CHANNEL_CLOUDINESS: - state = getQuantityTypeState(forecastData.getClouds(), PERCENT); - break; - case CHANNEL_VISIBILITY: - 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; - } + State state = getHourlyForecastState(channelId, forecastData, localWeatherData); logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state); updateState(channelUID, state); } else { @@ -512,7 +492,115 @@ private void updateHourlyForecastChannel(ChannelUID channelUID, int count) { } /** - * 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 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 count the index of the daily data referenced by the channel (today is count 0) @@ -530,143 +618,7 @@ private void updateDailyForecastChannel(ChannelUID channelUID, int count) { if (localWeatherData != null && localWeatherData.getDaily().size() > count) { org.openhab.binding.openweathermap.internal.dto.onecall.Daily forecastData = localWeatherData.getDaily() .get(count); - State state = UnDefType.UNDEF; - Temp temp; - 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; - } + State state = getDailyForecastState(channelId, forecastData, localWeatherData); logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state); updateState(channelUID, state); } else { @@ -674,6 +626,173 @@ private void updateDailyForecastChannel(ChannelUID channelUID, int count) { } } + 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 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. * diff --git a/bundles/org.openhab.binding.openweathermap/src/main/resources/OH-INF/config/config.xml b/bundles/org.openhab.binding.openweathermap/src/main/resources/OH-INF/config/config.xml index 728a2c7a96ce6..58c40dc36e1ca 100644 --- a/bundles/org.openhab.binding.openweathermap/src/main/resources/OH-INF/config/config.xml +++ b/bundles/org.openhab.binding.openweathermap/src/main/resources/OH-INF/config/config.xml @@ -130,18 +130,20 @@ Location of weather in geographical coordinates (latitude/longitude/altitude). - - Number of days for daily forecast, including the current day. + + Number of days for daily forecast, including the current day and determining how many daily channels are + created. 6 - - Number of hours for hourly forecast. + + Number of hours for hourly forecast, determining how many hourly channels are created. 12 - - Number of minutes for minutely precipitation forecast. + + Number of minutes for minutely precipitation forecast, determining how many minutely channels are + created. 0 diff --git a/bundles/org.openhab.binding.openweathermap/src/main/resources/OH-INF/i18n/openweathermap.properties b/bundles/org.openhab.binding.openweathermap/src/main/resources/OH-INF/i18n/openweathermap.properties index 8bfd0c26132f3..8bc59e69b3a79 100644 --- a/bundles/org.openhab.binding.openweathermap/src/main/resources/OH-INF/i18n/openweathermap.properties +++ b/bundles/org.openhab.binding.openweathermap/src/main/resources/OH-INF/i18n/openweathermap.properties @@ -74,10 +74,10 @@ thing-type.openweathermap.weather-api.description = Provides access to the OpenW # 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.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.description = Language to be used by the OpenWeatherMap API. 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.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.forecastDays.label = Number of Days -thing-type.config.openweathermap.onecall.forecastDays.description = Number of days for daily forecast, including the current day. -thing-type.config.openweathermap.onecall.forecastHours.label = Number of Hours -thing-type.config.openweathermap.onecall.forecastHours.description = Number of hours for hourly forecast. -thing-type.config.openweathermap.onecall.forecastMinutes.label = Number of Minutes -thing-type.config.openweathermap.onecall.forecastMinutes.description = Number of minutes for minutely precipitation forecast. +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 and determining how many daily channels are created. +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, determining how many hourly channels are created. +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, determining how many minutely channels are created. 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.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.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.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.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.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.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.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.description = This is a weather station. channel-group-type.openweathermap.station.channel.location.description = Location of the weather station or the city. diff --git a/bundles/org.openhab.binding.openweathermap/src/main/resources/OH-INF/thing/channel-types.xml b/bundles/org.openhab.binding.openweathermap/src/main/resources/OH-INF/thing/channel-types.xml index fc11c45e22dbc..8b353c1524550 100644 --- a/bundles/org.openhab.binding.openweathermap/src/main/resources/OH-INF/thing/channel-types.xml +++ b/bundles/org.openhab.binding.openweathermap/src/main/resources/OH-INF/thing/channel-types.xml @@ -169,6 +169,14 @@ + + + Minutely precipitation delivered by the One Call API. + + + + + Minutely precipitation delivered by the One Call API. @@ -178,6 +186,30 @@ + + + Hourly weather forecast delivered by the One Call API. + + + + + + + + + + + + + + + + + + + + + Hourly weather forecast delivered by the One Call API. @@ -203,6 +235,40 @@ + + + Daily weather forecast delivered by the One Call API. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Daily weather forecast delivered by the One Call API. diff --git a/bundles/org.openhab.binding.openweathermap/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.openweathermap/src/main/resources/OH-INF/thing/thing-types.xml index 2fab59a36fc61..bc9a2aad61b89 100644 --- a/bundles/org.openhab.binding.openweathermap/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.openweathermap/src/main/resources/OH-INF/thing/thing-types.xml @@ -142,6 +142,9 @@ + + + @@ -208,6 +211,8 @@ + + @@ -233,6 +238,8 @@ + + This is the weather forecast for today from the one call API. @@ -267,6 +274,9 @@ + + 1 + location diff --git a/bundles/org.openhab.binding.openweathermap/src/main/resources/OH-INF/update/instructions.xml b/bundles/org.openhab.binding.openweathermap/src/main/resources/OH-INF/update/instructions.xml new file mode 100644 index 0000000000000..238adb654cc8d --- /dev/null +++ b/bundles/org.openhab.binding.openweathermap/src/main/resources/OH-INF/update/instructions.xml @@ -0,0 +1,148 @@ + + + + + + + openweathermap:precipitation + + + + openweathermap:condition + + + openweathermap:condition-id + + + openweathermap:condition-icon + + + openweathermap:condition-icon-id + + + system:outdoor-temperature + + + openweathermap:apparent-temperature + + + system:barometric-pressure + + + system:atmospheric-humidity + + + openweathermap:dew-point + + + system:wind-speed + + + system:wind-direction + + + openweathermap:gust-speed + + + openweathermap:cloudiness + + + openweathermap:precip-probability + + + openweathermap:rain + + + openweathermap:snow + + + openweathermap:visibility + + + + openweathermap:sunrise + + + openweathermap:sunset + + + openweathermap:condition + + + openweathermap:condition-id + + + openweathermap:condition-icon + + + openweathermap:condition-icon-id + + + openweathermap:morning-temperature + + + openweathermap:day-temperature + + + openweathermap:evening-temperature + + + openweathermap:night-temperature + + + openweathermap:forecasted-min-outdoor-temperature + + + openweathermap:forecasted-max-outdoor-temperature + + + openweathermap:apparent-morning + + + openweathermap:apparent-day + + + openweathermap:apparent-evening + + + openweathermap:apparent-night + + + system:barometric-pressure + + + system:atmospheric-humidity + + + openweathermap:dew-point + + + system:wind-speed + + + system:wind-direction + + + openweathermap:gust-speed + + + openweathermap:cloudiness + + + openweathermap:forecasted-uvindex + + + openweathermap:precip-probability + + + openweathermap:rain + + + openweathermap:snow + + + + +