### One Call API Weather and Forecast
-| Parameter | Description |
-|----------------|--------------------------------------------------------------------------------------------------------------------------------|
-| location | Location of weather in geographical coordinates (latitude/longitude/altitude). **Mandatory** |
+| 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"). |
+| 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"). |
### One Call API History Data
| 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 |
-
+
+### One Call API Weather Warnings
+
+| Channel Group ID | Channel ID | Item Type | Description |
+|-----------------------|-------------|-----------|-----------------------------------------------------|
+| alerts1, alerts2, ... | event | String | Type of the warning, e.g. FROST. |
+| alerts1, alerts2, ... | description | String | A detailed description of the alert. |
+| alerts1, alerts2, ... | onset | DateTime | Start Date and Time for which the warning is valid. |
+| alerts1, alerts2, ... | expires | DateTime | End Date and Time for which the warning is valid. |
+| alerts1, alerts2, ... | source | String | The source of the alert. **Advanced** |
+
### UV Index
| Channel Group ID | Channel ID | Item Type | Description |
BINDING_ID, "oneCallDaily");
public static final ChannelGroupTypeUID CHANNEL_GROUP_TYPE_ONECALL_CURRENT = new ChannelGroupTypeUID(BINDING_ID,
"oneCallCurrent");
+ public static final ChannelGroupTypeUID CHANNEL_GROUP_TYPE_ONECALL_ALERTS = new ChannelGroupTypeUID(BINDING_ID,
+ "oneCallAlerts");
// List of all channel groups
public static final String CHANNEL_GROUP_STATION = "station";
public static final String CHANNEL_SULPHUR_DIOXIDE = "sulphurDioxide";
public static final String CHANNEL_AMMONIA = "ammonia";
public static final String CHANNEL_PRECIPITATION = "precipitation";
+ public static final String CHANNEL_ALERT_EVENT = "event";
+ public static final String CHANNEL_ALERT_DESCRIPTION = "description";
+ public static final String CHANNEL_ALERT_ONSET = "onset";
+ public static final String CHANNEL_ALERT_EXPIRES = "expires";
+ public static final String CHANNEL_ALERT_SOURCE = "source";
// List of all configuration
public static final String CONFIG_FORECAST_DAYS = "forecastDays";
package org.openhab.binding.openweathermap.internal.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.openweathermap.internal.handler.OpenWeatherMapOneCallHandler;
/**
- * The {@link OpenWeatherMapOneCallConfiguration} is the class used to match the
- * {@link org.openhab.binding.openweathermap.internal.handler.OpenWeatherMapOneCallHandler}s configuration.
+ * The {@link OpenWeatherMapOneCallConfiguration} is the class used to match the {@link OpenWeatherMapOneCallHandler}s
+ * configuration.
*
* @author Wolfgang Klimt - Initial contribution
+ * @author Christoph Weitkamp - Added weather alerts
*/
@NonNullByDefault
public class OpenWeatherMapOneCallConfiguration extends OpenWeatherMapLocationConfiguration {
public int forecastMinutes;
public int forecastHours;
public int forecastDays;
+ public int numberOfAlerts;
}
*/
package org.openhab.binding.openweathermap.internal.connection;
-import static java.util.stream.Collectors.joining;
import static org.eclipse.jetty.http.HttpMethod.GET;
import static org.eclipse.jetty.http.HttpStatus.*;
import java.nio.charset.StandardCharsets;
import java.time.ZoneId;
import java.time.ZonedDateTime;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.stream.Collectors;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
}
/**
- * Get Weather data from the OneCall API for the given location. See https://openweathermap.org/api/one-call-api for
- * details
+ * Get Weather data from the One Call API for the given location. See https://openweathermap.org/api/one-call-api
+ * for details.
*
* @param location location represented as {@link PointType}
* @param excludeMinutely if true, will not fetch minutely forecast data from the server
- * @param excludeHourly if true, will not fethh hourly forecast data from the server
+ * @param excludeHourly if true, will not fetch hourly forecast data from the server
* @param excludeDaily if true, will not fetch hourly forecast data from the server
* @return
* @throws JsonSyntaxException
* @throws OpenWeatherMapConfigurationException
*/
public synchronized @Nullable OpenWeatherMapOneCallAPIData getOneCallAPIData(@Nullable PointType location,
- boolean excludeMinutely, boolean excludeHourly, boolean excludeDaily)
+ boolean excludeMinutely, boolean excludeHourly, boolean excludeDaily, boolean excludeAlerts)
throws JsonSyntaxException, OpenWeatherMapCommunicationException, OpenWeatherMapConfigurationException {
Map<String, String> params = getRequestParams(handler.getOpenWeatherMapAPIConfig(), location);
- StringBuilder exclude = new StringBuilder("");
+ List<String> exclude = new ArrayList<>();
if (excludeMinutely) {
- exclude.append("minutely");
+ exclude.add("minutely");
}
if (excludeHourly) {
- exclude.append(exclude.length() > 0 ? "," : "").append("hourly");
+ exclude.add("hourly");
}
if (excludeDaily) {
- exclude.append(exclude.length() > 0 ? "," : "").append("daily");
+ exclude.add("daily");
+ }
+ if (excludeAlerts) {
+ exclude.add("alerts");
}
logger.debug("Exclude: '{}'", exclude);
- if (exclude.length() > 0) {
- params.put(PARAM_EXCLUDE, exclude.toString());
+ if (!exclude.isEmpty()) {
+ params.put(PARAM_EXCLUDE, exclude.stream().collect(Collectors.joining(",")));
}
return gson.fromJson(getResponseFromCache(buildURL(ONECALL_URL, params)), OpenWeatherMapOneCallAPIData.class);
}
/**
- * Get the historical weather data from the OneCall API for the given location and the given number of days in the
- * past.
- * As of now, OpenWeatherMap supports this function for up to 5 days in the past. However, this may change in the
- * future,
- * so we don't enforce this limit here. See https://openweathermap.org/api/one-call-api for details
+ * Get the historical weather data from the One Call API for the given location and the given number of days in the
+ * past. As of now, OpenWeatherMap supports this function for up to 5 days in the past. However, this may change in
+ * the future, so we don't enforce this limit here. See https://openweathermap.org/api/one-call-api for details.
*
* @param location location represented as {@link PointType}
* @param days number of days in the past, relative to the current time.
private String buildURL(String url, Map<String, String> requestParams) {
return requestParams.keySet().stream().map(key -> key + "=" + encodeParam(requestParams.get(key)))
- .collect(joining("&", url + "?", ""));
+ .collect(Collectors.joining("&", url + "?", ""));
}
private String encodeParam(@Nullable String value) {
--- /dev/null
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.openweathermap.internal.dto.onecall;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Generated Plain Old Java Objects class for {@link Alert} from JSON.
+ *
+ * @author Christoph Weitkamp - Initial contribution
+ */
+public class Alert {
+ public String event;
+ public int start;
+ public int end;
+ public String description;
+ @SerializedName("sender_name")
+ public String senderName;
+}
import java.util.List;
-import com.google.gson.annotations.Expose;
+import org.eclipse.jdt.annotation.Nullable;
+
import com.google.gson.annotations.SerializedName;
/**
* allow additional properties
*
* @author Wolfgang Klimt - Initial contribution
+ * @author Christoph Weitkamp - Added weather alerts
*/
public class OpenWeatherMapOneCallAPIData {
- @SerializedName("lat")
- @Expose
private double lat;
- @SerializedName("lon")
- @Expose
private double lon;
- @SerializedName("timezone")
- @Expose
private String timezone;
@SerializedName("timezone_offset")
- @Expose
private int timezoneOffset;
- @SerializedName("current")
- @Expose
private Current current;
- @SerializedName("minutely")
- @Expose
- private List<Minutely> minutely = null;
- @SerializedName("hourly")
- @Expose
- private List<Hourly> hourly = null;
- @SerializedName("daily")
- @Expose
- private List<Daily> daily = null;
+ private List<Minutely> minutely;
+ private List<Hourly> hourly;
+ private List<Daily> daily;
+
+ public @Nullable List<Alert> alerts;
public double getLat() {
return lat;
import org.openhab.binding.openweathermap.internal.connection.OpenWeatherMapCommunicationException;
import org.openhab.binding.openweathermap.internal.connection.OpenWeatherMapConfigurationException;
import org.openhab.binding.openweathermap.internal.connection.OpenWeatherMapConnection;
-import org.openhab.binding.openweathermap.internal.dto.onecall.*;
+import org.openhab.binding.openweathermap.internal.dto.onecall.Alert;
+import org.openhab.binding.openweathermap.internal.dto.onecall.FeelsLike;
+import org.openhab.binding.openweathermap.internal.dto.onecall.OpenWeatherMapOneCallAPIData;
+import org.openhab.binding.openweathermap.internal.dto.onecall.Rain;
+import org.openhab.binding.openweathermap.internal.dto.onecall.Snow;
+import org.openhab.binding.openweathermap.internal.dto.onecall.Temp;
import org.openhab.core.i18n.TimeZoneProvider;
import org.openhab.core.library.types.QuantityType;
-import org.openhab.core.thing.*;
+import org.openhab.core.thing.Channel;
+import org.openhab.core.thing.ChannelUID;
+import org.openhab.core.thing.Thing;
+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.UnDefType;
* the channels.
*
* @author Wolfgang Klimt - Initial contribution
+ * @author Christoph Weitkamp - Added weather alerts
*/
@NonNullByDefault
public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler {
private static final String CHANNEL_GROUP_MINUTELY_FORECAST_PREFIX = "forecastMinutes";
private static final String CHANNEL_GROUP_HOURLY_FORECAST_PREFIX = "forecastHours";
private static final String CHANNEL_GROUP_DAILY_FORECAST_PREFIX = "forecastDay";
+ 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 static final Pattern CHANNEL_GROUP_DAILY_FORECAST_PREFIX_PATTERN = Pattern
.compile(CHANNEL_GROUP_DAILY_FORECAST_PREFIX + "([0-9]*)");
private static final Pattern CHANNEL_GROUP_MINUTELY_FORECAST_PREFIX_PATTERN = Pattern
.compile(CHANNEL_GROUP_MINUTELY_FORECAST_PREFIX + "([0-9]*)");
+ private static final Pattern CHANNEL_GROUP_ALERTS_PREFIX_PATTERN = Pattern
+ .compile(CHANNEL_GROUP_ALERTS_PREFIX + "([0-9]*)");
private @Nullable OpenWeatherMapOneCallAPIData weatherData;
private int forecastMinutes = 60;
private int forecastHours = 24;
private int forecastDays = 8;
+ private int numberOfAlerts = 0;
public OpenWeatherMapOneCallHandler(Thing thing, final TimeZoneProvider timeZoneProvider) {
super(thing, timeZoneProvider);
"@text/offline.conf-error-not-supported-onecall-number-of-days");
configValid = false;
}
+ int newNumberOfAlerts = config.numberOfAlerts;
+ if (newNumberOfAlerts < 0) {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
+ "@text/offline.conf-error-not-supported-onecall-number-of-alerts");
+ configValid = false;
+ }
if (configValid) {
logger.debug("Rebuilding thing '{}'.", getThing().getUID());
List<Channel> toBeRemovedChannels = new ArrayList<>();
toBeAddedChannels
.addAll(createChannelsForGroup(CHANNEL_GROUP_ONECALL_CURRENT, CHANNEL_GROUP_TYPE_ONECALL_CURRENT));
-
if (forecastMinutes != newForecastMinutes) {
logger.debug("forecastMinutes changed from {} to {}. Rebuilding minutely forecast channel groups.",
forecastMinutes, newForecastMinutes);
toBeAddedChannels.addAll(createChannelsForGroup(CHANNEL_GROUP_FORECAST_TOMORROW,
CHANNEL_GROUP_TYPE_ONECALL_DAILY_FORECAST));
}
- for (int i = Math.max(forecastDays, 2); i < newForecastDays; i++) {
+ for (int i = Math.max(forecastDays, 2); i < newForecastDays; ++i) {
toBeAddedChannels.addAll(
createChannelsForGroup(CHANNEL_GROUP_DAILY_FORECAST_PREFIX + Integer.toString(i),
CHANNEL_GROUP_TYPE_ONECALL_DAILY_FORECAST));
}
}
forecastDays = newForecastDays;
+ if (numberOfAlerts != newNumberOfAlerts) {
+ logger.debug("Rebuilding alerts channel groups.");
+ if (numberOfAlerts > newNumberOfAlerts) {
+ for (int i = newNumberOfAlerts + 1; i <= numberOfAlerts; ++i) {
+ toBeRemovedChannels
+ .addAll(removeChannelsOfGroup(CHANNEL_GROUP_ALERTS_PREFIX + Integer.toString(i)));
+ }
+ } else {
+ for (int i = numberOfAlerts + 1; i <= newNumberOfAlerts; ++i) {
+ toBeAddedChannels
+ .addAll(createChannelsForGroup(CHANNEL_GROUP_ALERTS_PREFIX + Integer.toString(i),
+ CHANNEL_GROUP_TYPE_ONECALL_ALERTS));
+ }
+ }
+ numberOfAlerts = newNumberOfAlerts;
+ }
}
logger.debug("toBeRemovedChannels: {}. toBeAddedChannels: {}", toBeRemovedChannels, toBeAddedChannels);
ThingBuilder builder = editThing().withoutChannels(toBeRemovedChannels);
builder.withChannel(channel);
}
updateThing(builder.build());
- updateStatus(ThingStatus.ONLINE);
}
}
logger.debug("Update weather and forecast data of thing '{}'.", getThing().getUID());
try {
weatherData = connection.getOneCallAPIData(location, forecastMinutes == 0, forecastHours == 0,
- forecastDays == 0);
+ forecastDays == 0, numberOfAlerts == 0);
return true;
} catch (JsonSyntaxException e) {
logger.debug("JsonSyntaxException occurred during execution: {}", e.getLocalizedMessage(), e);
updateMinutelyForecastChannel(channelUID, i - 1);
break;
}
-
+ Matcher alertsMatcher = CHANNEL_GROUP_ALERTS_PREFIX_PATTERN.matcher(channelGroupId);
+ if (alertsMatcher.find() && (i = Integer.parseInt(alertsMatcher.group(1))) >= 1) {
+ updateAlertsChannel(channelUID, i);
+ break;
+ }
break;
}
}
state = getQuantityTypeState(snow == null ? 0 : snow.get1h(), MILLI(METRE));
break;
case CHANNEL_VISIBILITY:
- @Nullable
State tempstate = new QuantityType<>(localWeatherData.getCurrent().getVisibility(), METRE)
.toUnit(KILO(METRE));
state = (tempstate == null ? state : tempstate);
state = getQuantityTypeState(forecastData.getClouds(), PERCENT);
break;
case CHANNEL_VISIBILITY:
- @Nullable
State tempstate = new QuantityType<>(localWeatherData.getCurrent().getVisibility(), METRE)
.toUnit(KILO(METRE));
state = (tempstate == null ? state : tempstate);
channelGroupId);
return;
}
- @Nullable
OpenWeatherMapOneCallAPIData localWeatherData = weatherData;
if (localWeatherData != null && localWeatherData.getDaily().size() > count) {
org.openhab.binding.openweathermap.internal.dto.onecall.Daily forecastData = localWeatherData.getDaily()
state = getDecimalTypeState(forecastData.getUvi());
break;
case CHANNEL_VISIBILITY:
- @Nullable
State tempstate = new QuantityType<>(localWeatherData.getCurrent().getVisibility(), METRE)
.toUnit(KILO(METRE));
state = (tempstate == null ? state : tempstate);
logger.debug("No weather data available to update channel '{}' of group '{}'.", channelId, channelGroupId);
}
}
+
+ /**
+ * Update the channel from the last OpenWeaterhMap data retrieved.
+ *
+ * @param channelUID the id identifying the channel to be updated
+ * @param count
+ */
+ private void updateAlertsChannel(ChannelUID channelUID, int count) {
+ String channelId = channelUID.getIdWithoutGroup();
+ String channelGroupId = channelUID.getGroupId();
+ OpenWeatherMapOneCallAPIData localWeatherData = weatherData;
+ List<Alert> alerts = localWeatherData != null ? localWeatherData.alerts : null;
+ State state = UnDefType.UNDEF;
+ if (alerts != null && alerts.size() > count) {
+ Alert alert = alerts.get(count - 1);
+ switch (channelId) {
+ case CHANNEL_ALERT_EVENT:
+ state = getStringTypeState(alert.event);
+ break;
+ case CHANNEL_ALERT_DESCRIPTION:
+ state = getStringTypeState(alert.description);
+ break;
+ case CHANNEL_ALERT_ONSET:
+ state = getDateTimeTypeState(alert.start);
+ break;
+ case CHANNEL_ALERT_EXPIRES:
+ state = getDateTimeTypeState(alert.end);
+ break;
+ case CHANNEL_ALERT_SOURCE:
+ state = getStringTypeState(alert.senderName);
+ break;
+ }
+ logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
+ } else {
+ logger.debug("No data available to update channel '{}' of group '{}'.", channelId, channelGroupId);
+ }
+ updateState(channelUID, state);
+ }
}
<description>Number of minutes for minutely precipitation forecast.</description>
<default>0</default>
</parameter>
+ <parameter name="numberOfAlerts" type="integer" min="0" max="5" step="1">
+ <label>Number of Alerts</label>
+ <description>Number of alerts to be shown.</description>
+ <default>0</default>
+ </parameter>
</config-description>
<config-description uri="thing-type:openweathermap:onecall-history">
offline.conf-error-not-supported-onecall-number-of-minutes = The 'forecastMinutes' parameter must be between 0 and 60.
offline.conf-error-not-supported-onecall-number-of-hours = The 'forecastHours' parameter must be between 0 and 48.
offline.conf-error-not-supported-onecall-number-of-days = The 'forecastDays' parameter must be between 0 and 7.
+offline.conf-error-not-supported-onecall-number-of-alerts = The 'numberOfAlerts' parameter must be greater than or equals to 0.
# discovery result
discovery.openweathermap.weather-and-forecast.api.local.label = Local Weather And Forecast
thing-type.config.openweathermap.air-pollution.forecastHours.label = Stunden
thing-type.config.openweathermap.air-pollution.forecastHours.description = Anzahl der Stunden für die Vorhersage der Luftqualität.
+thing-type.config.openweathermap.onecall.location.label = Ort der Wetterdaten
+thing-type.config.openweathermap.onecall.location.description = Ort der Wetterdaten in geographischen Koordinaten (Breitengrad/Längengrad/Höhe).
+
+thing-type.config.openweathermap.onecall.forecastMinutes.label = Minuten
+thing-type.config.openweathermap.onecall.forecastMinutes.description = Anzahl der Minuten für die Vorhersage von Niederschlag.
+
+thing-type.config.openweathermap.onecall.forecastHours.label = Stunden
+thing-type.config.openweathermap.onecall.forecastHours.description = Anzahl der Stunden für die Wettervorhersage.
+
+thing-type.config.openweathermap.onecall.forecastDays.label = Tage
+thing-type.config.openweathermap.onecall.forecastDays.description = Anzahl der Tage für die Wettervorhersage, inklusive aktueller Tag.
+
+thing-type.config.openweathermap.onecall.numberOfAlerts.label = Wetterwarnungen
+thing-type.config.openweathermap.onecall.numberOfAlerts.description = Anzahl der Wetterwarnungen.
+
# channel group types
channel-group-type.openweathermap.station.label = Wetterstation
channel-group-type.openweathermap.station.description = Fasst Daten über die Wetterstation oder den Ort zusammen.
channel-group-type.openweathermap.airPollutionForecast.label = Vorhersage der Luftqualität
channel-group-type.openweathermap.airPollutionForecast.description = Fasst Daten über die vorhergesagte Luftqualität zusammen.
+channel-group-type.openweathermap.oneCallCurrent.label = Aktuelles Wetter
+channel-group-type.openweathermap.oneCallCurrent.description = Fasst aktuelle Wetterdaten der One Call API zusammen.
+
+channel-group-type.openweathermap.oneCallAlerts.label = Wetterwarnungen
+channel-group-type.openweathermap.oneCallAlerts.description = Fasst Daten von Wetterwarnungen zusammen.
+
# channel groups
thing-type.openweathermap.weather-and-forecast.group.forecastHours03.label = Wettervorhersage für 3 Stunden
thing-type.openweathermap.weather-and-forecast.group.forecastHours03.description = Fasst Daten der Wettervorhersage in den nächsten drei Stunden zusammen.
thing-type.openweathermap.uvindex.group.forecastDay5.label = UV-Index für 5 Tage
thing-type.openweathermap.uvindex.group.forecastDay5.description = Fasst Daten der UV-Index Vorhersage in fünf Tagen zusammen.
+thing-type.openweathermap.onecall.group.forecastToday.label = Wettervorhersage für heute
+thing-type.openweathermap.onecall.group.forecastToday.description = Fasst Daten der heutigen Wettervorhersage der One Call API zusammen.
+
+thing-type.openweathermap.onecall.group.forecastTomorrow.label = Wettervorhersage für morgen
+thing-type.openweathermap.onecall.group.forecastTomorrow.description = Fasst Daten der morgigen Wettervorhersage der One Call API zusammen.
+
+thing-type.openweathermap.onecall.group.forecastDay2.label = Wettervorhersage für übermorgen
+thing-type.openweathermap.onecall.group.forecastDay2.description = Fasst Daten der übermorgigen Wettervorhersage der One Call API zusammen.
+
+thing-type.openweathermap.onecall.group.forecastDay3.label = Wettervorhersage für 3 Tage
+thing-type.openweathermap.onecall.group.forecastDay3.description = Fasst Daten der Wettervorhersage in drei Tagen der One Call API zusammen.
+
+thing-type.openweathermap.onecall.group.forecastDay4.label = Wettervorhersage für 4 Tage
+thing-type.openweathermap.onecall.group.forecastDay4.description = Fasst Daten der Wettervorhersage in vier Tagen der One Call API zusammen.
+
+thing-type.openweathermap.onecall.group.forecastDay5.label = Wettervorhersage für 5 Tage
+thing-type.openweathermap.onecall.group.forecastDay5.description = Fasst Daten der Wettervorhersage in fünf Tagen der One Call API zusammen.
+
# channel types
channel-type.openweathermap.station-id.label = Station-ID
channel-type.openweathermap.station-id.description = Zeigt die ID der Wetterstation oder des Ortes an.
channel-type.openweathermap.forecasted-ammonia.label = Vorhergesagter Ammoniak
channel-type.openweathermap.forecasted-ammonia.description = Vorhergesagte Konzentration an Ammoniak.
+channel-type.openweathermap.alert-event.label = Art
+channel-type.openweathermap.alert-event.description = Art der Warnung, z.B. FROST.
+
+channel-type.openweathermap.alert-description.label = Beschreibung
+channel-type.openweathermap.alert-description.description = Zeigt die Beschreibung der Wetterwarnung an.
+
+channel-type.openweathermap.alert-onset.label = Gültig ab
+channel-type.openweathermap.alert-onset.description = Datum und Uhrzeit, ab dem die Warnung gültig ist.
+channel-type.openweathermap.alert-onset.state.pattern = %1$td.%1$tm.%1$tY %1$tH:%1$tM:%1$tS
+
+channel-type.openweathermap.alert-expires.label = Gültig bis
+channel-type.openweathermap.alert-expires.description = Datum und Uhrzeit, bis zu dem die Warnung gültig ist.
+channel-type.openweathermap.alert-expires.state.pattern = %1$td.%1$tm.%1$tY %1$tH:%1$tM:%1$tS
+
+channel-type.openweathermap.alert-source.label = Quelle
+channel-type.openweathermap.alert-source.description = Zeigt die Quelle der Wetterwarnung an.
+
# thing status
offline.conf-error-missing-apikey = Der Parameter 'API Schlüssel' muss konfiguriert werden.
offline.conf-error-invalid-apikey = Ungültiger 'API Schlüssel'. Mehr Infos unter https://openweathermap.org/faq#error401.
</channels>
</channel-group-type>
+ <channel-group-type id="oneCallAlerts">
+ <label>Weather Warnings</label>
+ <description>Weather warnings issued for the requested location.</description>
+ <channels>
+ <channel id="event" typeId="alert-event"/>
+ <channel id="description" typeId="alert-description"/>
+ <channel id="onset" typeId="alert-onset"/>
+ <channel id="expires" typeId="alert-expires"/>
+ <channel id="source" typeId="alert-source"/>
+ </channels>
+ </channel-group-type>
<!-- Channels for OpenWeatherMap Binding -->
<channel-type id="station-id">
<category>Rain</category>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
+
+ <channel-type id="alert-event">
+ <item-type>String</item-type>
+ <label>Type</label>
+ <description>Type of the warning, e.g. FROST.</description>
+ <state readOnly="true"/>
+ </channel-type>
+
+ <channel-type id="alert-description">
+ <item-type>String</item-type>
+ <label>Description</label>
+ <description>A detailed description of the alert.</description>
+ <state readOnly="true"/>
+ </channel-type>
+
+ <channel-type id="alert-onset">
+ <item-type>DateTime</item-type>
+ <label>Valid From</label>
+ <description>Start Date and Time for which the warning is valid.</description>
+ <category>Time</category>
+ <state readOnly="true" pattern="%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS"/>
+ </channel-type>
+
+ <channel-type id="alert-expires">
+ <item-type>DateTime</item-type>
+ <label>Valid To</label>
+ <description>End Date and Time for which the warning is valid.</description>
+ <category>Time</category>
+ <state readOnly="true" pattern="%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS"/>
+ </channel-type>
+
+ <channel-type id="alert-source" advanced="true">
+ <item-type>String</item-type>
+ <label>Source</label>
+ <description>Source of the alert.</description>
+ <state readOnly="true"/>
+ </channel-type>
</thing:thing-descriptions>
<channel-group id="forecastHours23" typeId="oneCallHourly"/>
<channel-group id="forecastHours24" typeId="oneCallHourly"/>
-
<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>