diff --git a/CODEOWNERS b/CODEOWNERS index 3513dc5a8c6a3..f5386c50cd680 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -41,6 +41,7 @@ /bundles/org.openhab.binding.doorbird/ @mhilbush /bundles/org.openhab.binding.dscalarm/ @RSStephens /bundles/org.openhab.binding.dsmr/ @Hilbrand +/bundles/org.openhab.binding.dwdpollenflug/ @DerOetzi /bundles/org.openhab.binding.dwdunwetter/ @limdul79 /bundles/org.openhab.binding.elerotransmitterstick/ @vbier /bundles/org.openhab.binding.enocean/ @fruggy83 diff --git a/bom/openhab-addons/pom.xml b/bom/openhab-addons/pom.xml index bdf9078065638..2b07da53437d5 100644 --- a/bom/openhab-addons/pom.xml +++ b/bom/openhab-addons/pom.xml @@ -194,6 +194,11 @@ org.openhab.binding.dsmr ${project.version} + + org.openhab.addons.bundles + org.openhab.binding.dwdpollenflug + ${project.version} + org.openhab.addons.bundles org.openhab.binding.dwdunwetter diff --git a/bundles/org.openhab.binding.dwdpollenflug/.classpath b/bundles/org.openhab.binding.dwdpollenflug/.classpath new file mode 100644 index 0000000000000..14ba193a4882c --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/.classpath @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.dwdpollenflug/.project b/bundles/org.openhab.binding.dwdpollenflug/.project new file mode 100644 index 0000000000000..3cf695e17193f --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/.project @@ -0,0 +1,23 @@ + + + org.openhab.binding.dwdpollenflug + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/bundles/org.openhab.binding.dwdpollenflug/NOTICE b/bundles/org.openhab.binding.dwdpollenflug/NOTICE new file mode 100644 index 0000000000000..38d625e349232 --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/NOTICE @@ -0,0 +1,13 @@ +This content is produced and maintained by the openHAB project. + +* Project home: https://www.openhab.org + +== Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License 2.0 which is available at +https://www.eclipse.org/legal/epl-2.0/. + +== Source Code + +https://github.com/openhab/openhab-addons diff --git a/bundles/org.openhab.binding.dwdpollenflug/README.md b/bundles/org.openhab.binding.dwdpollenflug/README.md new file mode 100644 index 0000000000000..af20a6a7c2580 --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/README.md @@ -0,0 +1,198 @@ +# DWDPollenflug Binding + +The "Deutsche Wetterdienst" (DWD) reports the current pollen count index for Germany on a daily base and a forecast for tomorrow and the day after tomorrow. +This binding allows you to retrieve this data for your region or partregion. You can find a map of the data here: + +https://isabel.dwd.de/DE/leistungen/gefahrenindizespollen/gefahrenindexpollen.html + + +## Supported Things + +This binding supports a bridge thing (`bridge`), which polls the dataset for Germany in an adjustable interval. +And it supports a region thing (`region`), representing the data for all pollen types of a region or partregion. + +## Thing Configuration + +### Bridge + +| Property | Default | Required | Description | +| --------- | :-----: | :------: | ------------------------------------------------------------------------------------ | +| `refresh` | 30 | no | Define the interval for polling the data from DWD in minutes. Minimum is 15 minutes. | + +### Region + +| Property | Default | Required | Description | +| ---------- | :-----: | :------: | -------------------------------------------------------------------------------------------------------- | +| `regionID` | - | yes | In PaperUI just select the region you want to display data for. For files-configuration see table below. | + +#### Manual region or partregion selection #### + +The region ID is the partregion_id or if there is no partregion the region_id from this [json](https://opendata.dwd.de/climate_environment/health/alerts/s31fg.json) of DWD. +You can refer to the following table. + +| regionID | Region | Partregion | +| -------- | ------------------------------ | -------------------------------------------------- | +| 11 | Schleswig-Holstein und Hamburg | Inseln und Marschen | +| 12 | Schleswig-Holstein und Hamburg | Geest, Schleswig-Holstein und Hamburg | +| 20 | Mecklenburg-Vorpommern | - | +| 31 | Niedersachsen und Bremen | Westl. Niedersachsen/Bremen | +| 32 | Niedersachsen und Bremen | Östl. Niedersachsen | +| 41 | Nordrhein-Westfalen | Rhein.-Westfäl. Tiefland | +| 42 | Nordrhein-Westfalen | Ostwestfalen | +| 43 | Nordrhein-Westfalen | Mittelgebirge NRW | +| 50 | Brandenburg und Berlin | - | +| 61 | Sachsen-Anhalt | Tiefland Sachsen-Anhalt | +| 62 | Sachsen-Anhalt | Harz | +| 71 | Thüringen | Tiefland Thüringen | +| 72 | Thüringen | Mittelgebirge Thüringen | +| 81 | Sachsen | Tiefland Sachsen | +| 82 | Sachsen | Mittelgebirge Sachsen | +| 91 | Hessen | Nordhessen und hess. Mittelgebirge | +| 92 | Hessen | Rhein-Main | +| 101 | Rheinland-Pfalz und Saarland | Rhein, Pfalz, Nahe und Mosel | +| 102 | Rheinland-Pfalz und Saarland | Mittelgebirgsbereich Rheinland-Pfalz | +| 103 | Rheinland-Pfalz und Saarland | Saarland | +| 111 | Baden-Württemberg | Oberrhein und unteres Neckartal | +| 112 | Baden-Württemberg | Hohenlohe/mittlerer Neckar/Oberschwaben | +| 113 | Baden-Württemberg | Mittelgebirge Baden-Württemberg | +| 121 | Bayern | Allgäu/Oberbayern/Bay. Wald | +| 122 | Bayern | Donauniederungen | +| 123 | Bayern | Bayern n. der Donau, o. Bayr. Wald, o. Mainfranken | +| 124 | Bayern | Mainfranken | + +## Channels + +The bridge thing has following channels: + +| channel | description | +| --------------------- | ---------------------------------------------- | +| `updates#refreshed` | Hold the time of the bridge's last refresh | +| `updates#last_update` | The time when data was last updated by DWD | +| `updates#next_update` | The time when data will be updated next by DWD | + +For each of the eight pollen types reported by DWD the region thing has three channels for today, tomorrow and the day after tomorrow. + +| channels | pollen type | german name | +| ---------------------- | ----------- | ----------- | +| `alder#today` | alder | Erle | +| `alder#tomorrow` | | | +| `alder#dayafter_to` | | | +| `ambrosia#today` | ambrosia | Ambrosia | +| `ambrosia#tomorrow` | | | +| `ambrosia#dayafter_to` | | | +| `ash#today` | ash-tree | Esche | +| `ash#tomorrow` | | | +| `ash#dayafter_to` | | | +| `birch#today` | birch | Birke | +| `birch#tomorrow` | | | +| `birch#dayafter_to` | | | +| `grasses#today` | grasses | Gräser | +| `grasses#tomorrow` | | | +| `grasses#dayafter_to` | | | +| `hazel#today` | hazel | Hasel | +| `hazel#tomorrow` | | | +| `hazel#dayafter_to` | | | +| `mugwort#today` | mugwort | Beifuß | +| `mugwort#tomorrow` | | | +| `mugwort#dayafter_to` | | | +| `rye#today` | rye | Roggen | +| `rye#tomorrow` | | | +| `rye#dayafter_to` | | | + +There are the following possible string values: + +| value | description | +| ----- | --------------------------- | +| -1 | not specified | +| 0 | no pollen pollution | +| 0-1 | no to low pollen count | +| 1 | low pollen count | +| 1-2 | low to medium pollen count | +| 2 | medium pollen count | +| 2-3 | medium to high pollen count | +| 3 | high pollen count | + +## Full Example + +### Things file for region "Brandenburg und Berlin" and partregion "Bayern - Mainfranken" ### + +``` +Bridge dwdpollenflug:bridge:dwd "DWD pollen count Bridge" [refresh="15"] { + Thing region region50 "DWD pollen count region" @ "APIS" [regionID="50"] + Thing region partregion124 "DWD pollen count partregion" @ "APIS" [regionID="124"] +} +``` + +### Items example for region "Brandenburg und Berlin" and pollen type ash-tree ### + +``` +String pollenTodayEsche + "Esche [MAP(pollen.map):%s]" + {channel="dwdpollenflug:region:dwd:region50:ash#today"} + +String pollenTomorrowEsche + "Esche morgen [MAP(pollen.map):%s]" + {channel="dwdpollenflug:region:dwd:region50:ash#tomorrow"} + +String pollenDayAfterTomorrowEsche + "Esche übermorgen [MAP(pollen.map):%s]" + {channel="dwdpollenflug:region:dwd:region50:ash#dayafter_to"} + +``` + +### Transform map file pollen.map ### + +``` +0=keine (0) +0-1=keine bis gering (0-1) +1=gering (1) +1-2=gering bis mittel (1-2) +2=mittel (2) +2-3=mittel bis hoch (2-3) +3=hoch (3) +-1=keine Daten +-=keine Daten +NULL=keine Daten +``` + +### Sitemap example for region "Brandenburg und Berlin" and pollen type ash-tree ### + +``` +Text label="Pollenflugindex" { + Frame { + Text item=pollenTodayEsche + valuecolor=[=="3"="#f00014", + =="2-3"="#f00014", + =="2"="#ff9900", + =="1-2"="#ff9900", + =="1"="#ffff00", + =="0-1"="#00c83c"] { + Frame { + Text item=pollenTodayEsche + valuecolor=[=="3"="#f00014", + =="2-3"="#f00014", + =="2"="#ff9900", + =="1-2"="#ff9900", + =="1"="#ffff00", + =="0-1"="#00c83c"] + + Text item=pollenTomorrowEsche + valuecolor=[=="3"="#f00014", + =="2-3"="#f00014", + =="2"="#ff9900", + =="1-2"="#ff9900", + =="1"="#ffff00", + =="0-1"="#00c83c"] + + Text item=pollenDayAfterTomorrowEsche + valuecolor=[=="3"="#f00014", + =="2-3"="#f00014", + =="2"="#ff9900", + =="1-2"="#ff9900", + =="1"="#ffff00", + =="0-1"="#00c83c"] + } + } + } +} +``` diff --git a/bundles/org.openhab.binding.dwdpollenflug/pom.xml b/bundles/org.openhab.binding.dwdpollenflug/pom.xml new file mode 100644 index 0000000000000..d98e4238b45ad --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/pom.xml @@ -0,0 +1,16 @@ + + + + 4.0.0 + + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 2.5.4-SNAPSHOT + + + org.openhab.binding.dwdpollenflug + + openHAB Add-ons :: Bundles :: DWDPollenflug Binding + + diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/feature/feature.xml b/bundles/org.openhab.binding.dwdpollenflug/src/main/feature/feature.xml new file mode 100644 index 0000000000000..e4e5901453f68 --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/feature/feature.xml @@ -0,0 +1,9 @@ + + + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.dwdpollenflug/${project.version} + + diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollenflugBindingConstants.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollenflugBindingConstants.java new file mode 100644 index 0000000000000..83498093978af --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollenflugBindingConstants.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2010-2020 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.dwdpollenflug.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.thing.ThingTypeUID; + +/** + * The {@link DWDPollenflugBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class DWDPollenflugBindingConstants { + + private static final String BINDING_ID = "dwdpollenflug"; + + // bridge + public static final ThingTypeUID THING_TYPE_BRIDGE = new ThingTypeUID(BINDING_ID, "bridge"); + + // List of all Thing Type UIDs + public static final ThingTypeUID THING_TYPE_REGION = new ThingTypeUID(BINDING_ID, "region"); + + // Channels of pollen groups + public static final String CHANNEL_TODAY = "today"; + public static final String CHANNEL_TOMORROW = "tomorrow"; + public static final String CHANNEL_DAYAFTER_TO = "dayafter_to"; + + // Channels of region update + public static final String CHANNEL_UPDATES = "updates"; + public static final String CHANNEL_REFRESHED = "refreshed"; + public static final String CHANNEL_NEXT_UPDATE = "next_update"; + public static final String CHANNEL_LAST_UPDATE = "last_update"; + public static final String CHANNEL_UPDATED = "updated"; + + public static final String TRIGGER_REFRESHED = "REFRESHED"; + + // Bridge config properties + public static final String REFRESH = "refresh"; + + // Bridge properties + public static final String PROPERTY_SENDER = "sender"; + public static final String PROPERTY_NAME = "name"; + + // Region config properties + public static final String REGION_ID = "regionID"; + + // Region properties + public static final String PROPERTY_REGION_NAME = "region_name"; + public static final String PROPERTY_PARTREGION_NAME = "partregion_name"; +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollenflugHandlerFactory.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollenflugHandlerFactory.java new file mode 100644 index 0000000000000..4e236775e30de --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollenflugHandlerFactory.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2010-2020 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.dwdpollenflug.internal; + +import static org.openhab.binding.dwdpollenflug.internal.DWDPollenflugBindingConstants.*; + +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.eclipse.smarthome.io.net.http.HttpClientFactory; +import org.openhab.binding.dwdpollenflug.internal.handler.DWDPollenflugBridgeHandler; +import org.openhab.binding.dwdpollenflug.internal.handler.DWDPollenflugRegionHandler; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +/** + * The {@link DWDPollenflugHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +@Component(configurationPid = "binding.dwdpollenflug", service = ThingHandlerFactory.class) +public class DWDPollenflugHandlerFactory extends BaseThingHandlerFactory { + + private static final Set SUPPORTED_THING_TYPES_UIDS = Collections + .unmodifiableSet(Stream.of(THING_TYPE_BRIDGE, THING_TYPE_REGION).collect(Collectors.toSet())); + + private final HttpClient httpClient; + + @Activate + public DWDPollenflugHandlerFactory(final @Reference HttpClientFactory httpClientFactory) { + this.httpClient = httpClientFactory.getCommonHttpClient(); + } + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (THING_TYPE_BRIDGE.equals(thingTypeUID)) { + return new DWDPollenflugBridgeHandler((Bridge) thing, httpClient); + } else if (THING_TYPE_REGION.equals(thingTypeUID)) { + return new DWDPollenflugRegionHandler(thing); + } + + return null; + } +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollingException.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollingException.java new file mode 100644 index 0000000000000..26d3de7073652 --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollingException.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2010-2020 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.dwdpollenflug.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link DWDPollingException} class is the exception for all polling errors. + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class DWDPollingException extends Exception { + + private static final long serialVersionUID = 1L; + + public DWDPollingException(String message) { + super(message); + } + + public DWDPollingException(String message, Throwable throwable) { + super(message, throwable); + } +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/config/DWDPollenflugBridgeConfiguration.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/config/DWDPollenflugBridgeConfiguration.java new file mode 100644 index 0000000000000..ea73d371cc69f --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/config/DWDPollenflugBridgeConfiguration.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2010-2020 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.dwdpollenflug.internal.config; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Configuration for the {@link DWDPollenflugBridgeHandler} + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class DWDPollenflugBridgeConfiguration { + public int refresh = 30; + + public boolean isValid() { + return refresh >= 15; + } +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/config/DWDPollenflugRegionConfiguration.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/config/DWDPollenflugRegionConfiguration.java new file mode 100644 index 0000000000000..87fe8de2661ee --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/config/DWDPollenflugRegionConfiguration.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2010-2020 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.dwdpollenflug.internal.config; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Configuration for the {@link DWDPollenflugRegionHandler} + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class DWDPollenflugRegionConfiguration { + public int regionID; + + public boolean isValid() { + return regionID > 0; + } +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollenflug.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollenflug.java new file mode 100644 index 0000000000000..b3edfa797bc7e --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollenflug.java @@ -0,0 +1,111 @@ +/** + * Copyright (c) 2010-2020 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.dwdpollenflug.internal.dto; + +import static org.openhab.binding.dwdpollenflug.internal.DWDPollenflugBindingConstants.*; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import com.google.gson.annotations.SerializedName; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.DateTimeType; +import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.types.UnDefType; + +/** + * The {@link DWDPollenflug} class is internal DWD data structure. + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class DWDPollenflug { + private String sender = ""; + + private String name = ""; + + private final Date created = new Date(); + + @SerializedName("next_update") + private @Nullable String nextUpdate; + + @SerializedName("last_update") + private @Nullable String lastUpdate; + + @SerializedName("content") + private @Nullable Set regions; + + public Map getProperties() { + Map map = new HashMap<>(); + + map.put(PROPERTY_NAME, name); + map.put(PROPERTY_SENDER, sender); + + return Collections.unmodifiableMap(map); + } + + public Map getChannelsStateMap() { + Map map = new HashMap<>(); + + map.put(CHANNEL_UPDATES + "#" + CHANNEL_REFRESHED, parseDate(created)); + map.put(CHANNEL_UPDATES + "#" + CHANNEL_LAST_UPDATE, parseDate(lastUpdate)); + map.put(CHANNEL_UPDATES + "#" + CHANNEL_NEXT_UPDATE, parseDate(nextUpdate)); + + return Collections.unmodifiableMap(map); + } + + private State parseDate(final @Nullable String dateString) { + try { + if (dateString != null) { + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + Date date = formatter.parse(dateString.replace("Uhr", "").trim()); + return parseDate(date); + } + + return UnDefType.NULL; + } catch (ParseException e) { + return UnDefType.NULL; + } + } + + private State parseDate(final @Nullable Date date) { + if (date == null) { + return UnDefType.NULL; + } else { + ZonedDateTime zoned = ZonedDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); + return new DateTimeType(zoned); + } + } + + public @Nullable DWDRegion getRegion(int key) { + final Set localRegions = regions; + if (localRegions != null) { + for (DWDRegion region : localRegions) { + if (region.getRegionID() == key) { + return region; + } + } + } + + return null; + } +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollenflugPollen.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollenflugPollen.java new file mode 100644 index 0000000000000..4e03734e74518 --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollenflugPollen.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2010-2020 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.dwdpollenflug.internal.dto; + +/** + * The {@link DWDPollenflug} class is internal DWD data structure. + * + * @author Johannes Ott - Initial contribution + */ +public enum DWDPollenflugPollen { + AMBROSIA("ambrosia"), + BEIFUSS("mugwort"), + BIRKE("birch"), + ERLE("alder"), + ESCHE("ash"), + GRAESER("grasses"), + HASEL("hazel"), + ROGGEN("rye"); + + private final String channelName; + + private DWDPollenflugPollen(String channelName) { + this.channelName = channelName; + } + + public String getChannelName() { + return channelName; + } +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollentypeJSON.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollentypeJSON.java new file mode 100644 index 0000000000000..e1188299f460d --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollentypeJSON.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2010-2020 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.dwdpollenflug.internal.dto; + +import com.google.gson.annotations.SerializedName; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * DTO for data per pollen type + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class DWDPollentypeJSON { + public String today = "-1"; + + public String tomorrow = "-1"; + + @SerializedName("dayafter_to") + public String dayAfterTomorrow = "-1"; +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDRegion.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDRegion.java new file mode 100644 index 0000000000000..aa1772346411f --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDRegion.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2010-2020 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.dwdpollenflug.internal.dto; + +import static org.openhab.binding.dwdpollenflug.internal.DWDPollenflugBindingConstants.*; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import com.google.gson.annotations.SerializedName; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.types.State; + +/** + * The {@link DWDRegion} class holds the internal data representation of each Region + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class DWDRegion { + @SerializedName("region_id") + public int regionID = 0; + + @SerializedName("region_name") + public String regionName = ""; + + @SerializedName("partregion_id") + public int partRegionID = 0; + + @SerializedName("partregion_name") + public String partRegionName = ""; + + @SerializedName("Pollen") + private @Nullable Map pollen; + + public Map getProperties() { + Map map = new HashMap<>(); + map.put(PROPERTY_REGION_NAME, regionName); + map.put(PROPERTY_PARTREGION_NAME, partRegionName); + return Collections.unmodifiableMap(map); + } + + public int getRegionID() { + if (partRegionID > 0) { + return partRegionID; + } + return regionID; + } + + public Map getChannelsStateMap() { + final Map localPollen = pollen; + if (localPollen != null) { + Map map = new HashMap<>(); + localPollen.forEach((k, jsonType) -> { + final String pollenType = DWDPollenflugPollen.valueOf(k.toUpperCase()).getChannelName(); + map.put(pollenType + "#" + CHANNEL_TODAY, new StringType(jsonType.today)); + map.put(pollenType + "#" + CHANNEL_TOMORROW, new StringType(jsonType.tomorrow)); + map.put(pollenType + "#" + CHANNEL_DAYAFTER_TO, new StringType(jsonType.dayAfterTomorrow)); + }); + + return Collections.unmodifiableMap(map); + } + + return Collections.emptyMap(); + } +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/handler/DWDPollenflugBridgeHandler.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/handler/DWDPollenflugBridgeHandler.java new file mode 100644 index 0000000000000..a34bcbb159122 --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/handler/DWDPollenflugBridgeHandler.java @@ -0,0 +1,211 @@ +/** + * Copyright (c) 2010-2020 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.dwdpollenflug.internal.handler; + +import java.net.URI; +import java.util.Set; +import java.net.SocketTimeoutException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.HttpResponse; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.api.Result; +import org.eclipse.jetty.client.util.BufferingResponseListener; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.dwdpollenflug.internal.DWDPollingException; +import org.openhab.binding.dwdpollenflug.internal.config.DWDPollenflugBridgeConfiguration; +import org.openhab.binding.dwdpollenflug.internal.dto.DWDPollenflug; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link DWDPollenflugBridgeHandler} is the handler for bridge thing + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class DWDPollenflugBridgeHandler extends BaseBridgeHandler { + private static final String DWD_URL = "https://opendata.dwd.de/climate_environment/health/alerts/s31fg.json"; + + private final Logger logger = LoggerFactory.getLogger(DWDPollenflugBridgeHandler.class); + + private DWDPollenflugBridgeConfiguration bridgeConfig = new DWDPollenflugBridgeConfiguration(); + private @Nullable ScheduledFuture pollingJob; + private @Nullable DWDPollenflug pollenflug; + private final Set regionListeners = ConcurrentHashMap.newKeySet(); + private final HttpClient client; + private final Gson gson = new Gson(); + + public DWDPollenflugBridgeHandler(Bridge bridge, HttpClient client) { + super(bridge); + this.client = client; + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (command instanceof RefreshType) { + final DWDPollenflug localPollenflug = pollenflug; + if (localPollenflug != null) { + notifyOnUpdate(localPollenflug); + } + } + } + + @Override + public void initialize() { + logger.debug("Initializing DWD Pollenflug bridge handler"); + bridgeConfig = getConfigAs(DWDPollenflugBridgeConfiguration.class); + + if (bridgeConfig.isValid()) { + startPolling(); + updateStatus(ThingStatus.ONLINE); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Refresh interval has to be at least 15 minutes."); + } + } + + @Override + public void dispose() { + logger.debug("Handler disposed."); + stopPolling(); + } + + private void startPolling() { + final ScheduledFuture localPollingJob = this.pollingJob; + if (localPollingJob == null || localPollingJob.isCancelled()) { + logger.debug("Start polling."); + pollingJob = scheduler.scheduleWithFixedDelay(this::poll, 0, bridgeConfig.refresh, TimeUnit.MINUTES); + } + } + + private void stopPolling() { + final ScheduledFuture localPollingJob = this.pollingJob; + if (localPollingJob != null && !localPollingJob.isCancelled()) { + logger.debug("Stop polling."); + localPollingJob.cancel(true); + pollingJob = null; + } + } + + private void poll() { + logger.debug("Polling"); + requestRefresh().handle((resultPollenflug, pollException) -> { + if (resultPollenflug == null) { + if (pollException == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + pollException.getMessage()); + } + } else { + updateStatus(ThingStatus.ONLINE); + notifyOnUpdate(resultPollenflug); + } + + return null; + }); + } + + private CompletableFuture<@Nullable DWDPollenflug> requestRefresh() { + CompletableFuture<@Nullable DWDPollenflug> f = new CompletableFuture<>(); + Request request = client.newRequest(URI.create(DWD_URL)); + + request.method(HttpMethod.GET).timeout(2000, TimeUnit.SECONDS).send(new BufferingResponseListener() { + @NonNullByDefault({}) + @Override + public void onComplete(Result result) { + final HttpResponse response = (HttpResponse) result.getResponse(); + if (result.getFailure() != null) { + Throwable e = result.getFailure(); + if (e instanceof SocketTimeoutException || e instanceof TimeoutException) { + f.completeExceptionally(new DWDPollingException("Request timeout", e)); + } else { + f.completeExceptionally(new DWDPollingException("Request failed", e)); + } + } else if (response.getStatus() != 200) { + f.completeExceptionally(new DWDPollingException(getContentAsString())); + } else { + try { + DWDPollenflug pollenflugJSON = gson.fromJson(getContentAsString(), DWDPollenflug.class); + f.complete(pollenflugJSON); + } catch (JsonSyntaxException ex2) { + f.completeExceptionally(new DWDPollingException("Parsing of response failed")); + } + } + } + }); + + return f; + } + + @Override + public void childHandlerInitialized(ThingHandler childHandler, Thing childThing) { + if (childHandler instanceof DWDPollenflugRegionHandler) { + logger.debug("Register region listener."); + final DWDPollenflugRegionHandler regionListener = (DWDPollenflugRegionHandler) childHandler; + if (regionListeners.add(regionListener)) { + final DWDPollenflug localPollenflug = pollenflug; + if (localPollenflug != null) { + regionListener.notifyOnUpdate(localPollenflug); + } + } else { + logger.warn("Tried to add listener {} but it was already present. This is probably an error.", + childHandler); + } + } + } + + @Override + public void childHandlerDisposed(ThingHandler childHandler, Thing childThing) { + if (childHandler instanceof DWDPollenflugRegionHandler) { + logger.debug("Unregister region listener."); + if (!regionListeners.remove((DWDPollenflugRegionHandler) childHandler)) { + logger.warn("Tried to remove listener {} but it was not registered. This is probably an error.", + childHandler); + } + } + } + + public void notifyOnUpdate(@Nullable DWDPollenflug newPollenflug) { + if (newPollenflug != null) { + pollenflug = newPollenflug; + updateProperties(newPollenflug.getProperties()); + regionListeners.forEach(listener -> listener.notifyOnUpdate(newPollenflug)); + newPollenflug.getChannelsStateMap().forEach(this::updateState); + } + } + + public @Nullable DWDPollenflug getPollenflug() { + return pollenflug; + } +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/handler/DWDPollenflugRegionHandler.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/handler/DWDPollenflugRegionHandler.java new file mode 100644 index 0000000000000..a4482e7527d02 --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/handler/DWDPollenflugRegionHandler.java @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2010-2020 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.dwdpollenflug.internal.handler; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.dwdpollenflug.internal.config.DWDPollenflugRegionConfiguration; +import org.openhab.binding.dwdpollenflug.internal.dto.DWDPollenflug; +import org.openhab.binding.dwdpollenflug.internal.dto.DWDRegion; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link DWDPollenflugRegionHandler} is the handler for bridge thing + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class DWDPollenflugRegionHandler extends BaseThingHandler { + + private final Logger logger = LoggerFactory.getLogger(DWDPollenflugRegionHandler.class); + + private DWDPollenflugRegionConfiguration thingConfig = new DWDPollenflugRegionConfiguration(); + + public DWDPollenflugRegionHandler(Thing thing) { + super(thing); + } + + @Override + public void initialize() { + logger.debug("Initializing DWD Pollenflug region handler"); + thingConfig = getConfigAs(DWDPollenflugRegionConfiguration.class); + + if (thingConfig.isValid()) { + DWDPollenflugBridgeHandler handler = getBridgeHandler(); + if (handler == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Bridge handler missing"); + } else { + updateStatus(ThingStatus.ONLINE); + } + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No valid region id given."); + } + } + + private synchronized @Nullable DWDPollenflugBridgeHandler getBridgeHandler() { + Bridge bridge = getBridge(); + if (bridge != null) { + ThingHandler handler = bridge.getHandler(); + if (handler instanceof DWDPollenflugBridgeHandler) { + DWDPollenflugBridgeHandler bridgeHandler = (DWDPollenflugBridgeHandler) handler; + return bridgeHandler; + } + } + + return null; + } + + @Override + public void dispose() { + logger.debug("DWDPollenflug region handler disposes."); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (command instanceof RefreshType) { + refresh(); + } + } + + private void refresh() { + DWDPollenflugBridgeHandler handler = getBridgeHandler(); + if (handler != null) { + DWDPollenflug pollenflug = handler.getPollenflug(); + if (pollenflug != null) { + notifyOnUpdate(pollenflug); + } + } + } + + public void notifyOnUpdate(DWDPollenflug pollenflug) { + DWDRegion region = pollenflug.getRegion(thingConfig.regionID); + if (region == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Region not found"); + return; + } + + updateStatus(ThingStatus.ONLINE); + updateProperties(region.getProperties()); + + region.getChannelsStateMap().forEach(this::updateState); + } +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/binding/binding.xml new file mode 100644 index 0000000000000..8ba0620c7c198 --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/binding/binding.xml @@ -0,0 +1,10 @@ + + + + DWD Pollenflug Binding + This is the binding for DWDPollenflug. + Johannes Ott + + diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/i18n/dwdpollenflug_de.properties b/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/i18n/dwdpollenflug_de.properties new file mode 100644 index 0000000000000..4c23588250dc8 --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/i18n/dwdpollenflug_de.properties @@ -0,0 +1,46 @@ +#binding +binding.dwdpollenflug.name = DWD Pollenflugindex +binding.dwdpollenflug.description = Binding um den Pollenflugindex des deutschen Wetterdienstes anzuzeigen + +#bridge +thing-type.dwdpollenflug.bridge.label = DWD Pollenflugindex - Bridge +thing-type.dwdpollenflug.bridge.description = Bridge um den Pollenflugindex des DWDs abzurufen. + +#bridge config +thing-type.config.dwdpollenflug.bridge.refresh.label = Aktualisierungsinterval +thing-type.config.dwdpollenflug.bridge.refresh.description = Zeit zwischen zwei API-Anfragen in Minuten. Minimum 15 Minuten. + +#thing types +thing-type.dwdpollenflug.region.label = DWD Pollenflugindex Region +thing-type.dwdpollenflug.region.description = Pollenflugindex f\u00FCr eine bestimmte Region oder Teilregion +thing-type.dwdpollenflug.region.group.updates.label = Aktualisierung +thing-type.dwdpollenflug.region.group.updates.description = Informationen zur Aktualisierung +thing-type.dwdpollenflug.region.group.alder.label=Erle +thing-type.dwdpollenflug.region.group.alder.description=Informationen f\u00FCr Erle +thing-type.dwdpollenflug.region.group.ambrosia.label=Ambrosia +thing-type.dwdpollenflug.region.group.ambrosia.description=Informationen f\u00FCr Ambrosia +thing-type.dwdpollenflug.region.group.ash.label=Esche +thing-type.dwdpollenflug.region.group.ash.description=Informationen f\u00FCr Esche +thing-type.dwdpollenflug.region.group.birch.label=Birke +thing-type.dwdpollenflug.region.group.birch.description=Informationen f\u00FCr Birke +thing-type.dwdpollenflug.region.group.grasses.label=Gr\u00E4sser +thing-type.dwdpollenflug.region.group.grasses.description=Informationen f\u00FCr Gr\u00E4sser +thing-type.dwdpollenflug.region.group.hazel.label=Hasel +thing-type.dwdpollenflug.region.group.hazel.description=Informationen f\u00FCr Hasel +thing-type.dwdpollenflug.region.group.mugwort.label=Beifu\u00DF +thing-type.dwdpollenflug.region.group.mugwort.description=Informationen f\u00FCr Beifu\u00DF +thing-type.dwdpollenflug.region.group.rye.label=Roggen +thing-type.dwdpollenflug.region.group.rye.description=Informationen f\u00FCr Roggen + +#thing region config +thing-type.config.dwdpollenflug.region.regionID.label = Region +thing-type.config.dwdpollenflug.region.regionID.description = Die Teilregion oder Region die angezeigt werden soll. + +#channel-group-type +channel-group-type.dwdpollenflug.pollentype.channel.today.label = Heute +channel-group-type.dwdpollenflug.pollentype.channel.tomorrow.label = Morgen +channel-group-type.dwdpollenflug.pollentype.channel.dayafter_to.label = \u00DCbermorgen + +channel-group-type.dwdpollenflug.updates.channel.refreshed.label = Letzte Aktualisierung Bridge +channel-group-type.dwdpollenflug.updates.channel.last_update.label = Letzte Aktualisierung DWD +channel-group-type.dwdpollenflug.updates.channel.next_update.label = N\u00E4chste Aktualisierung DWD diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/thing/bridge.xml new file mode 100644 index 0000000000000..d103e0ac2aa67 --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/thing/bridge.xml @@ -0,0 +1,51 @@ + + + + + + Bridge for accessing pollen count index data of the DWD + + + + + + + + + + + + + 30 + + Time between two API requests in minutes. Minimum 15 minutes. + + + + + + + + Information about data state + + + + + + + + + + + + + + + DateTime + + + + diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/thing/region.xml b/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/thing/region.xml new file mode 100644 index 0000000000000..eaf5b7968a3fd --- /dev/null +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/thing/region.xml @@ -0,0 +1,113 @@ + + + + + + + + + + Pollen count index for a region or partregion + + + + + Information for alder + + + + Information for ambrosia + + + + Information for ash tree + + + + Information for birch + + + + Information for grasses + + + + Information for hazel + + + + Information for mugwort + + + + Information for rye + + + + + + + + + + + + The partregion or region that should be reported. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + For each pollen type there are three channels for today, tomorrow and day after tomorrow + + + + + + + + + + + + + + + String + + + + diff --git a/bundles/pom.xml b/bundles/pom.xml index 33c23dab3bb6e..33d563d63b33e 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -74,6 +74,7 @@ org.openhab.binding.doorbird org.openhab.binding.dscalarm org.openhab.binding.dsmr + org.openhab.binding.dwdpollenflug org.openhab.binding.dwdunwetter org.openhab.binding.elerotransmitterstick org.openhab.binding.enocean