Skip to content

Commit 7fa43ea

Browse files
authored
[pegelonline] Initial contribution (openhab#16831)
* initial version Signed-off-by: Bernd Weymann <[email protected]>
1 parent 5e15726 commit 7fa43ea

File tree

26 files changed

+11055
-0
lines changed

26 files changed

+11055
-0
lines changed

CODEOWNERS

+1
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@
278278
/bundles/org.openhab.binding.orvibo/ @tavalin
279279
/bundles/org.openhab.binding.panasonicbdp/ @mlobstein
280280
/bundles/org.openhab.binding.paradoxalarm/ @theater
281+
/bundles/org.openhab.binding.pegelonline/ @weymann
281282
/bundles/org.openhab.binding.pentair/ @jsjames
282283
/bundles/org.openhab.binding.phc/ @gnlpfjh
283284
/bundles/org.openhab.binding.pilight/ @stefanroellin @niklasdoerfler

bom/openhab-addons/pom.xml

+5
Original file line numberDiff line numberDiff line change
@@ -1381,6 +1381,11 @@
13811381
<artifactId>org.openhab.binding.paradoxalarm</artifactId>
13821382
<version>${project.version}</version>
13831383
</dependency>
1384+
<dependency>
1385+
<groupId>org.openhab.addons.bundles</groupId>
1386+
<artifactId>org.openhab.binding.pegelonline</artifactId>
1387+
<version>${project.version}</version>
1388+
</dependency>
13841389
<dependency>
13851390
<groupId>org.openhab.addons.bundles</groupId>
13861391
<artifactId>org.openhab.binding.pentair</artifactId>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
This content is produced and maintained by the openHAB project.
2+
3+
* Project home: https://www.openhab.org
4+
5+
== Declared Project Licenses
6+
7+
This program and the accompanying materials are made available under the terms
8+
of the Eclipse Public License 2.0 which is available at
9+
https://www.eclipse.org/legal/epl-2.0/.
10+
11+
== Source Code
12+
13+
https://github.com/openhab/openhab-addons
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# PegelOnline Binding
2+
3+
Binding to observe water level from german rivers.
4+
Data is provided by german **Water-Route and Shipping Agency** [WSV](https://www.pegelonline.wsv.de/).
5+
Goal is to monitor actual water levels from rivers nearby your home.
6+
In case of changing water levels the corresponding warning level is lowered or raised.
7+
8+
## Supported Things
9+
10+
| Label | Description | ID |
11+
|---------------------|---------------------------------------------------------------------------------|---------|
12+
| Measurement Station | Station providing water level measurements | station |
13+
14+
15+
## Discovery
16+
17+
In case your home location coordinates are set the discovery will recognize all measurement stations within a radius of 50 km.
18+
Found Things are added in your Inbox.
19+
20+
21+
## Thing Configuration
22+
23+
Thing configuration contains 3 sections
24+
25+
* [Station selection](station_selection)
26+
* [Warning Levels of selected station](warning_levels)
27+
* [Refresh rate](configuration_parameters)
28+
29+
### Station selection
30+
31+
Stations can be selected with an Universally Unique Identifier (uuid).
32+
It's automatically added by the Discovery.
33+
Configure a station manually using [list of all available stations](https://pegelonline.wsv.de/gast/pegeltabelle) or [stations.json](https://www.pegelonline.wsv.de/webservices/rest-api/v2/stations.json) and choose the uuid of your desired measurement station.
34+
35+
### Warning Levels
36+
37+
<img align="right" src="./doc/Marburg.png" width="450" height="500"/>
38+
39+
Each station has specific warning levels
40+
41+
* Warning Levels 1 (*lowest*) to 3 (*highest*)
42+
* Flooding Levels
43+
44+
Unfortunately these levels cannot be queried automatically.
45+
Please select your [federal state](https://www.hochwasserzentralen.de/) and check if which levels they provide.
46+
The picture shows the levels of [measurement station Marburg of federal state Hesse](https://www.hlnug.de/static/pegel/wiskiweb2/stations/25830056/station.html?v=20210802152952)
47+
48+
If you cannot evaluate warning or flooding levels leave the parameter empty.
49+
50+
### Configuration parameters
51+
52+
| configuration | content | unit | description | required | default |
53+
|------------------|-----------|------|---------------------------|----------|---------|
54+
| uuid | text | - | Unique Station Identifier | X | N/A |
55+
| warningLevel1 | integer | cm | Warning Level 1 | | N/A |
56+
| warningLevel2 | integer | cm | Warning Level 2 | | N/A |
57+
| warningLevel3 | integer | cm | Warning Level 3 | | N/A |
58+
| hq10 | integer | cm | Decade Flooding | | N/A |
59+
| hq100 | integer | cm | Century Flooding | | N/A |
60+
| hqExtreme | integer | cm | Extreme Flooding | | N/A |
61+
| refreshInterval | integer | min | Refresh Interval | X | 15 |
62+
63+
## Channels
64+
65+
66+
| channel id | type | description |
67+
|----------------------|----------------------|--------------------------------|
68+
| timestamp | DateTime | Last Measurement |
69+
| level | Number:Length | Water Level |
70+
| trend | Number | Water Level Trend |
71+
| warning | Number | Current Warning |
72+
73+
### Trend
74+
75+
Possible values:
76+
77+
* 1 : Rising
78+
* 0 : Steady
79+
* -1 : Lowering
80+
81+
### Warning
82+
83+
Current warning according to configuration
84+
85+
* 0 : No Warning
86+
* 1 : Warning level 1
87+
* 2 : Warning Level 2
88+
* 3 : Warning Level 3
89+
* 4 : Decade Flooding
90+
* 5 : Century Flooding
91+
* 6 : Extreme Flooding
92+
93+
## Full Example
94+
95+
### Things
96+
97+
```java
98+
Thing pegelonline:station:giessen "Measurement Station Giessen" [
99+
uuid="4b386a6a-996e-4a4a-a440-15d6b40226d4",
100+
refreshInterval=15,
101+
warningLevel1=550,
102+
warningLevel2=600,
103+
warningLevel3=650,
104+
hq10=732,
105+
hq100=786
106+
]
107+
```
108+
109+
### Items
110+
111+
```java
112+
DateTime Lahn_Giessen_Timestamp "Measurement timestamp Lahn Giessen" {channel="pegelonline:station:giessen:timestamp" }
113+
Number:Length Lahn_Giessen_Level "Water Level Lahn Giessen]" {channel="pegelonline:station:giessen:level" }
114+
Number Lahn_Giessen_Trend "Water Level Trend Lahn Giessen" {channel="pegelonline:station:giessen:trend"}
115+
Number Lahn_Giessen_Warning "Warning Level Lahn Giessen" {channel="pegelonline:station:giessen:warning"}
116+
```
117+
118+
119+
## Links
120+
121+
[PegelOnline API Documentation](https://www.pegelonline.wsv.de/webservice/dokuRestapi#caching)
122+
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<parent>
8+
<groupId>org.openhab.addons.bundles</groupId>
9+
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
10+
<version>4.2.0-SNAPSHOT</version>
11+
</parent>
12+
13+
<artifactId>org.openhab.binding.pegelonline</artifactId>
14+
15+
<name>openHAB Add-ons :: Bundles :: PegelOnline Binding</name>
16+
17+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<features name="org.openhab.binding.pegelonline-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
3+
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
4+
5+
<feature name="openhab-binding-pegelonline" description="PegelOnline Binding" version="${project.version}">
6+
<feature>openhab-runtime-base</feature>
7+
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.pegelonline/${project.version}</bundle>
8+
</feature>
9+
</features>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* Copyright (c) 2010-2024 Contributors to the openHAB project
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Eclipse Public License 2.0 which is available at
9+
* http://www.eclipse.org/legal/epl-2.0
10+
*
11+
* SPDX-License-Identifier: EPL-2.0
12+
*/
13+
package org.openhab.binding.pegelonline.internal;
14+
15+
import java.util.Set;
16+
17+
import org.eclipse.jdt.annotation.NonNullByDefault;
18+
import org.openhab.core.library.types.PointType;
19+
import org.openhab.core.thing.ThingTypeUID;
20+
21+
import com.google.gson.Gson;
22+
23+
/**
24+
* The {@link PegelOnlineBindingConstants} class defines common constants, which are
25+
* used across the whole binding.
26+
*
27+
* @author Bernd Weymann - Initial contribution
28+
*/
29+
@NonNullByDefault
30+
public class PegelOnlineBindingConstants {
31+
32+
private static final String BINDING_ID = "pegelonline";
33+
34+
// List of all Thing Type UIDs
35+
public static final ThingTypeUID STATION_THING = new ThingTypeUID(BINDING_ID, "station");
36+
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(STATION_THING);
37+
38+
// List of all Channel ids
39+
public static final String TIMESTAMP_CHANNEL = "timestamp";
40+
public static final String LEVEL_CHANNEL = "level";
41+
public static final String TREND_CHANNEL = "trend";
42+
public static final String WARNING_CHANNEL = "warning";
43+
44+
public static final int NO_WARNING = 0;
45+
public static final int WARN_LEVEL_1 = 1;
46+
public static final int WARN_LEVEL_2 = 2;
47+
public static final int WARN_LEVEL_3 = 3;
48+
public static final int HQ10 = 4;
49+
public static final int HQ100 = 5;
50+
public static final int HQ_EXTREME = 6;
51+
52+
public static final Gson GSON = new Gson();
53+
54+
public static final String STATIONS_URI = "https://www.pegelonline.wsv.de/webservices/rest-api/v2/stations";
55+
public static final double DISCOVERY_RADIUS = 50;
56+
public static final PointType UNDEF_LOCATION = PointType.valueOf("-1,-1");
57+
58+
public static final String SPACE = " ";
59+
public static final String UNDERLINE = "_";
60+
public static final String HYPHEN = " - ";
61+
public static final String EMPTY = "";
62+
public static final String UNKNOWN = "Unknown";
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* Copyright (c) 2010-2024 Contributors to the openHAB project
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Eclipse Public License 2.0 which is available at
9+
* http://www.eclipse.org/legal/epl-2.0
10+
*
11+
* SPDX-License-Identifier: EPL-2.0
12+
*/
13+
package org.openhab.binding.pegelonline.internal;
14+
15+
import static org.openhab.binding.pegelonline.internal.PegelOnlineBindingConstants.STATION_THING;
16+
17+
import org.eclipse.jdt.annotation.NonNullByDefault;
18+
import org.eclipse.jdt.annotation.Nullable;
19+
import org.openhab.binding.pegelonline.internal.handler.PegelOnlineHandler;
20+
import org.openhab.core.i18n.LocationProvider;
21+
import org.openhab.core.io.net.http.HttpClientFactory;
22+
import org.openhab.core.thing.Thing;
23+
import org.openhab.core.thing.ThingTypeUID;
24+
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
25+
import org.openhab.core.thing.binding.ThingHandler;
26+
import org.openhab.core.thing.binding.ThingHandlerFactory;
27+
import org.osgi.service.component.annotations.Activate;
28+
import org.osgi.service.component.annotations.Component;
29+
import org.osgi.service.component.annotations.Reference;
30+
31+
/**
32+
* The {@link PegelOnlineHandlerFactory} is responsible for creating things and thing
33+
* handlers.
34+
*
35+
* @author Bernd Weymann - Initial contribution
36+
*/
37+
@NonNullByDefault
38+
@Component(configurationPid = "binding.pegelonline", service = ThingHandlerFactory.class)
39+
public class PegelOnlineHandlerFactory extends BaseThingHandlerFactory {
40+
private final HttpClientFactory httpClientFactory;
41+
42+
@Activate
43+
public PegelOnlineHandlerFactory(final @Reference HttpClientFactory hcf, final @Reference LocationProvider lp) {
44+
httpClientFactory = hcf;
45+
}
46+
47+
@Override
48+
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
49+
return PegelOnlineBindingConstants.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
50+
}
51+
52+
@Override
53+
protected @Nullable ThingHandler createHandler(Thing thing) {
54+
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
55+
if (STATION_THING.equals(thingTypeUID)) {
56+
return new PegelOnlineHandler(thing, httpClientFactory.getCommonHttpClient());
57+
}
58+
return null;
59+
}
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/**
2+
* Copyright (c) 2010-2024 Contributors to the openHAB project
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Eclipse Public License 2.0 which is available at
9+
* http://www.eclipse.org/legal/epl-2.0
10+
*
11+
* SPDX-License-Identifier: EPL-2.0
12+
*/
13+
package org.openhab.binding.pegelonline.internal.config;
14+
15+
import static org.openhab.binding.pegelonline.internal.PegelOnlineBindingConstants.*;
16+
17+
import java.util.Map.Entry;
18+
import java.util.TreeMap;
19+
20+
import org.eclipse.jdt.annotation.NonNullByDefault;
21+
22+
/**
23+
* The {@link PegelOnlineConfiguration} class contains fields mapping thing configuration parameters.
24+
*
25+
* @author Bernd Weymann - Initial contribution
26+
*/
27+
@NonNullByDefault
28+
public class PegelOnlineConfiguration {
29+
public String uuid = UNKNOWN;
30+
public int warningLevel1 = Integer.MAX_VALUE;
31+
public int warningLevel2 = Integer.MAX_VALUE;
32+
public int warningLevel3 = Integer.MAX_VALUE;
33+
public int hq10 = Integer.MAX_VALUE;
34+
public int hq100 = Integer.MAX_VALUE;
35+
public int hqExtreme = Integer.MAX_VALUE;
36+
public int refreshInterval = 15;
37+
38+
public boolean uuidCheck() {
39+
// https://stackoverflow.com/questions/20041051/how-to-judge-a-string-is-uuid-type
40+
return uuid.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$");
41+
}
42+
43+
/**
44+
* Check if configured warning levels are in ascending order
45+
*
46+
* @return true if ascending, false otherwise
47+
*/
48+
public boolean warningCheck() {
49+
TreeMap<Integer, Integer> warnMap = this.getWarnings();
50+
Entry<Integer, Integer> currentEntry = warnMap.firstEntry();
51+
Entry<Integer, Integer> nextEntry = warnMap.higherEntry(currentEntry.getKey());
52+
while (nextEntry != null) {
53+
// ignore non configured values
54+
if (nextEntry.getKey() != Integer.MAX_VALUE) {
55+
if (nextEntry.getValue() < currentEntry.getValue()) {
56+
return false;
57+
}
58+
}
59+
currentEntry = nextEntry;
60+
nextEntry = warnMap.higherEntry(currentEntry.getKey());
61+
}
62+
return true;
63+
}
64+
65+
/**
66+
* Calculate sorted map with level height and warning level based on configuration
67+
*
68+
* @return TreeMap with keys containing level height and values containing warning level
69+
*/
70+
public TreeMap<Integer, Integer> getWarnings() {
71+
TreeMap<Integer, Integer> warnMap = new TreeMap<>();
72+
warnMap.put(0, NO_WARNING);
73+
warnMap.put(warningLevel1, WARN_LEVEL_1);
74+
warnMap.put(warningLevel2, WARN_LEVEL_2);
75+
warnMap.put(warningLevel3, WARN_LEVEL_3);
76+
warnMap.put(hq10, HQ10);
77+
warnMap.put(hq100, HQ100);
78+
warnMap.put(hqExtreme, HQ_EXTREME);
79+
return warnMap;
80+
}
81+
}

0 commit comments

Comments
 (0)