Implement time series support introduced by https://github.com/openhab/openhab-core/pull/3597.
Signed-off-by: Florian Hotze <florianh_dev@icloud.com>
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
| 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
### 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
| 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
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
### 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
| 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
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;
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;
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;
*
* @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 {
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]*)");
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) {
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);
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);
}
}
+ 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 count the index of the hourly data referenced by the channel (hour 1 is count 0)
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 {
}
/**
- * 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 count the index of the daily data referenced by the channel (today is count 0)
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 {
}
}
+ 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.
*
<description>Location of weather in geographical coordinates (latitude/longitude/altitude).</description>
</parameter>
<parameter name="forecastDays" type="integer" min="0" max="8" step="1">
- <label>Number of Days</label>
- <description>Number of days for daily forecast, including the current day.</description>
+ <label>Number of Daily Forecast Channels</label>
+ <description>Number of days for daily forecast, including the current day and determining how many daily channels are
+ created.</description>
<default>6</default>
</parameter>
<parameter name="forecastHours" type="integer" min="0" max="48" step="1">
- <label>Number of Hours</label>
- <description>Number of hours for hourly forecast.</description>
+ <label>Number of Hourly Forecast Channels</label>
+ <description>Number of hours for hourly forecast, determining how many hourly channels are created.</description>
<default>12</default>
</parameter>
<parameter name="forecastMinutes" type="integer" min="0" max="60" step="1">
- <label>Number of Minutes</label>
- <description>Number of minutes for minutely precipitation forecast.</description>
+ <label>Number of Minutely Forecast Channels</label>
+ <description>Number of minutes for minutely precipitation forecast, determining how many minutely channels are
+ created.</description>
<default>0</default>
</parameter>
<parameter name="numberOfAlerts" type="integer" min="0" max="5" step="1">
# 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
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
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.
</channels>
</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">
<label>One Call API Minutely Forecast</label>
<description>Minutely precipitation delivered by the One Call API.</description>
</channels>
</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">
<label>One Call API Hourly Forecast</label>
<description>Hourly weather forecast delivered by the One Call API.</description>
</channels>
</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">
<label>One Call API Daily Forecast</label>
<description>Daily weather forecast delivered by the One Call API.</description>
<channel-groups>
<channel-group id="current" typeId="oneCallCurrent"/>
+
+ <channel-group id="forecastMinutely" typeId="oneCallMinutelyTimeSeries"/>
+
<channel-group id="forecastMinutes01" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes02" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes03" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes59" typeId="oneCallMinutely"/>
<channel-group id="forecastMinutes60" typeId="oneCallMinutely"/>
+ <channel-group id="forecastHourly" typeId="oneCallHourlyTimeSeries"/>
+
<channel-group id="forecastHours01" typeId="oneCallHourly"/>
<channel-group id="forecastHours02" typeId="oneCallHourly"/>
<channel-group id="forecastHours03" typeId="oneCallHourly"/>
<channel-group id="forecastHours23" typeId="oneCallHourly"/>
<channel-group id="forecastHours24" typeId="oneCallHourly"/>
+ <channel-group id="forecastDaily" typeId="oneCallDailyTimeSeries"/>
+
<channel-group id="forecastToday" typeId="oneCallDaily">
<label>One Call API Todays Forecast</label>
<description>This is the weather forecast for today from the one call API.</description>
</channel-group>
</channel-groups>
+ <properties>
+ <property name="thingTypeVersion">1</property>
+ </properties>
<representation-property>location</representation-property>
<config-description-ref uri="thing-type:openweathermap:onecall"/>
--- /dev/null
+<?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>