[openweathermap] Add support for persisting OneCall API forecasts (#15963)

Implement time series support introduced by https://github.com/openhab/openhab-core/pull/3597.

Signed-off-by: Florian Hotze <florianh_dev@icloud.com>
This commit is contained in:
Florian Hotze 2023-12-14 20:21:54 +01:00 committed by GitHub
parent ea3e608c81
commit c81a263b91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 655 additions and 276 deletions

View File

@ -50,6 +50,7 @@ New Subscribers to the One Call API will require setting the API version to 3.0
The thing `onecall` supports the [current and forecast weather data](https://openweathermap.org/api/one-call-api#how) for a specific location using the One Call API.
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

View File

@ -16,7 +16,9 @@ import static org.openhab.binding.openweathermap.internal.OpenWeatherMapBindingC
import static org.openhab.core.library.unit.MetricPrefix.*;
import static org.openhab.core.library.unit.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.OpenWeatherMapOneCallAPID
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.ThingStatus;
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 @@ import com.google.gson.JsonSyntaxException;
*
* @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 @@ public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler
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 @@ public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler
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 @@ public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler
}
}
private void updateMinutelyForecastTimeSeries(ChannelUID channelUID) {
String channelId = channelUID.getIdWithoutGroup();
String channelGroupId = channelUID.getGroupId();
OpenWeatherMapOneCallAPIData localWeatherData = weatherData;
if (channelId.equals(CHANNEL_TIME_STAMP)) {
logger.debug("Channel `{}` of group '{}' is no supported time-series channel.", channelId, channelGroupId);
return;
}
if (localWeatherData != null && !localWeatherData.getMinutely().isEmpty()) {
List<org.openhab.binding.openweathermap.internal.dto.onecall.Minutely> forecastData = localWeatherData
.getMinutely();
TimeSeries timeSeries = new TimeSeries(REPLACE);
forecastData.forEach((m) -> {
if (channelId.equals(CHANNEL_PRECIPITATION)) {
State state = UnDefType.UNDEF;
Instant timestamp = Instant.ofEpochSecond(m.getDt());
double precipitation = m.getPrecipitation();
state = getQuantityTypeState(precipitation, MILLI(METRE));
timeSeries.add(timestamp, state);
} else {
// This should not happen
logger.warn("Unknown channel id {} in onecall minutely weather data", channelId);
return;
}
});
logger.debug("Update channel '{}' of group '{}' with new time-series '{}'.", channelId, channelGroupId,
timeSeries);
sendTimeSeries(channelUID, timeSeries);
} else {
logger.debug("No weather data available to update channel '{}' of group '{}'.", channelId, channelGroupId);
}
}
/**
* Update the channel from the last OpenWeatherMap data retrieved.
* Update the hourly forecast channel from the last OpenWeatherMap data retrieved.
*
* @param channelUID the id identifying the channel to be updated
* @param count the index of the hourly data referenced by the channel (hour 1 is count 0)
@ -431,79 +483,7 @@ public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler
if (localWeatherData != null && localWeatherData.getHourly().size() > count) {
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 @@ public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler
}
/**
* Update the channel from the last OpenWeatherMap data retrieved.
* Update the hourly forecast time series channel from the last OpenWeatherMap data retrieved.
*
* @param channelUID the id identifying the channel to be updated
*/
private void updateHourlyForecastTimeSeries(ChannelUID channelUID) {
String channelId = channelUID.getIdWithoutGroup();
String channelGroupId = channelUID.getGroupId();
if (channelId.equals(CHANNEL_TIME_STAMP)) {
logger.debug("Channel `{}` of group '{}' is no supported time-series channel.", channelId, channelGroupId);
return;
}
OpenWeatherMapOneCallAPIData localWeatherData = weatherData;
if (localWeatherData != null && !localWeatherData.getHourly().isEmpty()) {
List<org.openhab.binding.openweathermap.internal.dto.onecall.Hourly> forecastData = localWeatherData
.getHourly();
TimeSeries timeSeries = new TimeSeries(REPLACE);
forecastData.forEach((h) -> {
Instant timestamp = Instant.ofEpochSecond(h.getDt());
State state = getHourlyForecastState(channelId, h, localWeatherData);
timeSeries.add(timestamp, state);
});
logger.debug("Update channel '{}' of group '{}' with new time-series '{}'.", channelId, channelGroupId,
timeSeries);
sendTimeSeries(channelUID, timeSeries);
} else {
logger.debug("No weather data available to update channel '{}'.", channelId);
}
}
private State getHourlyForecastState(String channelId, Hourly forecastData,
OpenWeatherMapOneCallAPIData localWeatherData) {
State state = UnDefType.UNDEF;
switch (channelId) {
case CHANNEL_TIME_STAMP:
state = getDateTimeTypeState(forecastData.getDt());
break;
case CHANNEL_CONDITION:
if (!forecastData.getWeather().isEmpty()) {
state = getStringTypeState(forecastData.getWeather().get(0).getDescription());
}
break;
case CHANNEL_CONDITION_ID:
if (!forecastData.getWeather().isEmpty()) {
state = getStringTypeState(Integer.toString(forecastData.getWeather().get(0).getId()));
}
break;
case CHANNEL_CONDITION_ICON:
if (!forecastData.getWeather().isEmpty()) {
state = getRawTypeState(
OpenWeatherMapConnection.getWeatherIcon(forecastData.getWeather().get(0).getIcon()));
}
break;
case CHANNEL_CONDITION_ICON_ID:
if (!forecastData.getWeather().isEmpty()) {
state = getStringTypeState(forecastData.getWeather().get(0).getIcon());
}
break;
case CHANNEL_TEMPERATURE:
state = getQuantityTypeState(forecastData.getTemp(), CELSIUS);
break;
case CHANNEL_APPARENT_TEMPERATURE:
state = getQuantityTypeState(forecastData.getFeelsLike(), CELSIUS);
break;
case CHANNEL_PRESSURE:
state = getQuantityTypeState(forecastData.getPressure(), HECTO(PASCAL));
break;
case CHANNEL_HUMIDITY:
state = getQuantityTypeState(forecastData.getHumidity(), PERCENT);
break;
case CHANNEL_DEW_POINT:
state = getQuantityTypeState(forecastData.getDewPoint(), CELSIUS);
break;
case CHANNEL_WIND_SPEED:
state = getQuantityTypeState(forecastData.getWindSpeed(), METRE_PER_SECOND);
break;
case CHANNEL_WIND_DIRECTION:
state = getQuantityTypeState(forecastData.getWindDeg(), DEGREE_ANGLE);
break;
case CHANNEL_GUST_SPEED:
state = getQuantityTypeState(forecastData.getWindGust(), METRE_PER_SECOND);
break;
case CHANNEL_CLOUDINESS:
state = getQuantityTypeState(forecastData.getClouds(), PERCENT);
break;
case CHANNEL_VISIBILITY:
State tempstate = new QuantityType<>(localWeatherData.getCurrent().getVisibility(), METRE)
.toUnit(KILO(METRE));
state = (tempstate == null ? state : tempstate);
case CHANNEL_PRECIP_PROBABILITY:
state = getQuantityTypeState(forecastData.getPop() * 100.0, PERCENT);
break;
case CHANNEL_RAIN:
Precipitation rain = forecastData.getRain();
state = getQuantityTypeState(rain == null ? 0 : rain.get1h(), MILLI(METRE));
break;
case CHANNEL_SNOW:
Precipitation snow = forecastData.getSnow();
state = getQuantityTypeState(snow == null ? 0 : snow.get1h(), MILLI(METRE));
break;
default:
// This should not happen
logger.warn("Unknown channel id {} in OneCall hourly weather data", channelId);
break;
}
return state;
}
/**
* Update the daily forecast channel from the last OpenWeatherMap data retrieved.
*
* @param channelUID the id identifying the channel to be updated
* @param count the index of the daily data referenced by the channel (today is count 0)
@ -530,143 +618,7 @@ public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler
if (localWeatherData != null && localWeatherData.getDaily().size() > count) {
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 @@ public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler
}
}
private void updateDailyForecastTimeSeries(ChannelUID channelUID) {
String channelId = channelUID.getIdWithoutGroup();
String channelGroupId = channelUID.getGroupId();
if (channelId.equals(CHANNEL_TIME_STAMP)) {
logger.debug("Channel `{}` of group '{}' is no supported time-series channel.", channelId, channelGroupId);
return;
}
OpenWeatherMapOneCallAPIData localWeatherData = weatherData;
if (localWeatherData != null && !localWeatherData.getDaily().isEmpty()) {
List<org.openhab.binding.openweathermap.internal.dto.onecall.Daily> forecastData = localWeatherData
.getDaily();
TimeSeries timeSeries = new TimeSeries(REPLACE);
forecastData.forEach((d) -> {
Instant timestamp = Instant.ofEpochSecond(d.getDt());
State state = getDailyForecastState(channelId, d, localWeatherData);
timeSeries.add(timestamp, state);
});
logger.debug("Update channel '{}' of group '{}' with new time-series '{}'.", channelId, channelGroupId,
timeSeries);
sendTimeSeries(channelUID, timeSeries);
} else {
logger.debug("No weather data available to update channel '{}'.", channelId);
}
}
private State getDailyForecastState(String channelId, Daily forecastData,
OpenWeatherMapOneCallAPIData localWeatherData) {
State state = UnDefType.UNDEF;
FeelsLikeTemp feelsLike;
Temp temp;
switch (channelId) {
case CHANNEL_TIME_STAMP:
state = getDateTimeTypeState(forecastData.getDt());
break;
case CHANNEL_SUNRISE:
state = getDateTimeTypeState(forecastData.getSunrise());
break;
case CHANNEL_SUNSET:
state = getDateTimeTypeState(forecastData.getSunset());
break;
case CHANNEL_CONDITION:
if (!forecastData.getWeather().isEmpty()) {
state = getStringTypeState(forecastData.getWeather().get(0).getDescription());
}
break;
case CHANNEL_CONDITION_ID:
if (!forecastData.getWeather().isEmpty()) {
state = getStringTypeState(Integer.toString(forecastData.getWeather().get(0).getId()));
}
break;
case CHANNEL_CONDITION_ICON:
if (!forecastData.getWeather().isEmpty()) {
state = getRawTypeState(
OpenWeatherMapConnection.getWeatherIcon(forecastData.getWeather().get(0).getIcon()));
}
break;
case CHANNEL_CONDITION_ICON_ID:
if (!forecastData.getWeather().isEmpty()) {
state = getStringTypeState(forecastData.getWeather().get(0).getIcon());
}
break;
case CHANNEL_MIN_TEMPERATURE:
temp = forecastData.getTemp();
if (temp != null) {
state = getQuantityTypeState(temp.getMin(), CELSIUS);
}
break;
case CHANNEL_MAX_TEMPERATURE:
temp = forecastData.getTemp();
if (temp != null) {
state = getQuantityTypeState(temp.getMax(), CELSIUS);
}
break;
case CHANNEL_MORNING_TEMPERATURE:
temp = forecastData.getTemp();
if (temp != null) {
state = getQuantityTypeState(temp.getMorn(), CELSIUS);
}
break;
case CHANNEL_DAY_TEMPERATURE:
temp = forecastData.getTemp();
if (temp != null) {
state = getQuantityTypeState(temp.getDay(), CELSIUS);
}
break;
case CHANNEL_EVENING_TEMPERATURE:
temp = forecastData.getTemp();
if (temp != null) {
state = getQuantityTypeState(temp.getEve(), CELSIUS);
}
break;
case CHANNEL_NIGHT_TEMPERATURE:
temp = forecastData.getTemp();
if (temp != null) {
state = getQuantityTypeState(temp.getNight(), CELSIUS);
}
break;
case CHANNEL_APPARENT_DAY:
feelsLike = forecastData.getFeelsLike();
if (feelsLike != null) {
state = getQuantityTypeState(feelsLike.getDay(), CELSIUS);
}
break;
case CHANNEL_APPARENT_MORNING:
feelsLike = forecastData.getFeelsLike();
if (feelsLike != null) {
state = getQuantityTypeState(feelsLike.getMorn(), CELSIUS);
}
break;
case CHANNEL_APPARENT_EVENING:
feelsLike = forecastData.getFeelsLike();
if (feelsLike != null) {
state = getQuantityTypeState(feelsLike.getEve(), CELSIUS);
}
break;
case CHANNEL_APPARENT_NIGHT:
feelsLike = forecastData.getFeelsLike();
if (feelsLike != null) {
state = getQuantityTypeState(feelsLike.getNight(), CELSIUS);
}
break;
case CHANNEL_PRESSURE:
state = getQuantityTypeState(forecastData.getPressure(), HECTO(PASCAL));
break;
case CHANNEL_HUMIDITY:
state = getQuantityTypeState(forecastData.getHumidity(), PERCENT);
break;
case CHANNEL_WIND_SPEED:
state = getQuantityTypeState(forecastData.getWindSpeed(), METRE_PER_SECOND);
break;
case CHANNEL_WIND_DIRECTION:
state = getQuantityTypeState(forecastData.getWindDeg(), DEGREE_ANGLE);
break;
case CHANNEL_GUST_SPEED:
state = getQuantityTypeState(forecastData.getWindGust(), METRE_PER_SECOND);
break;
case CHANNEL_CLOUDINESS:
state = getQuantityTypeState(forecastData.getClouds(), PERCENT);
break;
case CHANNEL_DEW_POINT:
state = getQuantityTypeState(forecastData.getDewPoint(), CELSIUS);
break;
case CHANNEL_UVINDEX:
state = getDecimalTypeState(forecastData.getUvi());
break;
case CHANNEL_VISIBILITY:
State tempstate = new QuantityType<>(localWeatherData.getCurrent().getVisibility(), METRE)
.toUnit(KILO(METRE));
state = (tempstate == null ? state : tempstate);
case CHANNEL_PRECIP_PROBABILITY:
state = getQuantityTypeState(forecastData.getPop() * 100.0, PERCENT);
break;
case CHANNEL_RAIN:
state = getQuantityTypeState(forecastData.getRain(), MILLI(METRE));
break;
case CHANNEL_SNOW:
state = getQuantityTypeState(forecastData.getSnow(), MILLI(METRE));
break;
default:
// This should not happen
logger.warn("Unknown channel id {} in OneCall daily weather data", channelId);
break;
}
return state;
}
/**
* Update the channel from the last OpenWeaterhMap data retrieved.
*

View File

@ -130,18 +130,20 @@
<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">

View File

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

View File

@ -169,6 +169,14 @@
</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>
@ -178,6 +186,30 @@
</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>
@ -203,6 +235,40 @@
</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>

View File

@ -142,6 +142,9 @@
<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"/>
@ -208,6 +211,8 @@
<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"/>
@ -233,6 +238,8 @@
<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>
@ -267,6 +274,9 @@
</channel-group>
</channel-groups>
<properties>
<property name="thingTypeVersion">1</property>
</properties>
<representation-property>location</representation-property>
<config-description-ref uri="thing-type:openweathermap:onecall"/>

View File

@ -0,0 +1,148 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<update:update-descriptions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:update="https://openhab.org/schemas/update-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/update-description/v1.0.0 https://openhab.org/schemas/update-description-1.0.0.xsd">
<thing-type uid="openweathermap:onecall">
<instruction-set targetVersion="1">
<add-channel id="precipitation" groupIds="forecastMinutely">
<type>openweathermap:precipitation</type>
</add-channel>
<add-channel id="condition" groupIds="forecastHourly">
<type>openweathermap:condition</type>
</add-channel>
<add-channel id="condition-id" groupIds="forecastHourly">
<type>openweathermap:condition-id</type>
</add-channel>
<add-channel id="icon" groupIds="forecastHourly">
<type>openweathermap:condition-icon</type>
</add-channel>
<add-channel id="icon-id" groupIds="forecastHourly">
<type>openweathermap:condition-icon-id</type>
</add-channel>
<add-channel id="temperature" groupIds="forecastHourly">
<type>system:outdoor-temperature</type>
</add-channel>
<add-channel id="apperent-temperature" groupIds="forecastHourly">
<type>openweathermap:apparent-temperature</type>
</add-channel>
<add-channel id="pressure" groupIds="forecastHourly">
<type>system:barometric-pressure</type>
</add-channel>
<add-channel id="humidity" groupIds="forecastHourly">
<type>system:atmospheric-humidity</type>
</add-channel>
<add-channel id="dew-point" groupIds="forecastHourly">
<type>openweathermap:dew-point</type>
</add-channel>
<add-channel id="wind-speed" groupIds="forecastHourly">
<type>system:wind-speed</type>
</add-channel>
<add-channel id="wind-direction" groupIds="forecastHourly">
<type>system:wind-direction</type>
</add-channel>
<add-channel id="gust-speed" groupIds="forecastHourly">
<type>openweathermap:gust-speed</type>
</add-channel>
<add-channel id="cloudiness" groupIds="forecastHourly">
<type>openweathermap:cloudiness</type>
</add-channel>
<add-channel id="precip-probability" groupIds="forecastHourly">
<type>openweathermap:precip-probability</type>
</add-channel>
<add-channel id="rain" groupIds="forecastHourly">
<type>openweathermap:rain</type>
</add-channel>
<add-channel id="snow" groupIds="forecastHourly">
<type>openweathermap:snow</type>
</add-channel>
<add-channel id="visbility" groupIds="forecastHourly">
<type>openweathermap:visibility</type>
</add-channel>
<add-channel id="sunrise" groupIds="forecastDaily">
<type>openweathermap:sunrise</type>
</add-channel>
<add-channel id="sunset" groupIds="forecastDaily">
<type>openweathermap:sunset</type>
</add-channel>
<add-channel id="condition" groupIds="forecastDaily">
<type>openweathermap:condition</type>
</add-channel>
<add-channel id="condition-id" groupIds="forecastDaily">
<type>openweathermap:condition-id</type>
</add-channel>
<add-channel id="icon" groupIds="forecastDaily">
<type>openweathermap:condition-icon</type>
</add-channel>
<add-channel id="icon-id" groupIds="forecastDaily">
<type>openweathermap:condition-icon-id</type>
</add-channel>
<add-channel id="morning-temperature" groupIds="forecastDaily">
<type>openweathermap:morning-temperature</type>
</add-channel>
<add-channel id="day-temperature" groupIds="forecastDaily">
<type>openweathermap:day-temperature</type>
</add-channel>
<add-channel id="evening-temperature" groupIds="forecastDaily">
<type>openweathermap:evening-temperature</type>
</add-channel>
<add-channel id="night-temperature" groupIds="forecastDaily">
<type>openweathermap:night-temperature</type>
</add-channel>
<add-channel id="min-temperature" groupIds="forecastDaily">
<type>openweathermap:forecasted-min-outdoor-temperature</type>
</add-channel>
<add-channel id="max-temperature" groupIds="forecastDaily">
<type>openweathermap:forecasted-max-outdoor-temperature</type>
</add-channel>
<add-channel id="apparent-morning" groupIds="forecastDaily">
<type>openweathermap:apparent-morning</type>
</add-channel>
<add-channel id="apparent-day" groupIds="forecastDaily">
<type>openweathermap:apparent-day</type>
</add-channel>
<add-channel id="apparent-evening" groupIds="forecastDaily">
<type>openweathermap:apparent-evening</type>
</add-channel>
<add-channel id="apparent-night" groupIds="forecastDaily">
<type>openweathermap:apparent-night</type>
</add-channel>
<add-channel id="pressure" groupIds="forecastDaily">
<type>system:barometric-pressure</type>
</add-channel>
<add-channel id="humidity" groupIds="forecastDaily">
<type>system:atmospheric-humidity</type>
</add-channel>
<add-channel id="dew-point" groupIds="forecastDaily">
<type>openweathermap:dew-point</type>
</add-channel>
<add-channel id="wind-speed" groupIds="forecastDaily">
<type>system:wind-speed</type>
</add-channel>
<add-channel id="wind-direction" groupIds="forecastDaily">
<type>system:wind-direction</type>
</add-channel>
<add-channel id="gust-speed" groupIds="forecastDaily">
<type>openweathermap:gust-speed</type>
</add-channel>
<add-channel id="cloudiness" groupIds="forecastDaily">
<type>openweathermap:cloudiness</type>
</add-channel>
<add-channel id="uvindex" groupIds="forecastDaily">
<type>openweathermap:forecasted-uvindex</type>
</add-channel>
<add-channel id="precip-probability" groupIds="forecastDaily">
<type>openweathermap:precip-probability</type>
</add-channel>
<add-channel id="rain" groupIds="forecastDaily">
<type>openweathermap:rain</type>
</add-channel>
<add-channel id="snow" groupIds="forecastDaily">
<type>openweathermap:snow</type>
</add-channel>
</instruction-set>
</thing-type>
</update:update-descriptions>