added migrated 2.x add-ons

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer
2020-09-21 01:58:32 +02:00
parent bbf1a7fd29
commit 6df6783b60
11662 changed files with 1302875 additions and 11 deletions

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.openhab.binding.vigicrues</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

View File

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

View File

@@ -0,0 +1,81 @@
# VigiCrues Binding
This binding allows you to get data regarding water flow and water height on major French rivers.
These data are made public through OpenDataSoft website.
## Supported Things
There is exactly one supported thing type, which represents a river level measurement station.
It is identified by the `id`.
To get your station id :
1. open https://www.vigicrues.gouv.fr/
2. Select your region on the France map
3. Select the station nearest to your location
4. In the 'Info Station' tab you'll get the id just near the station name (e.g. X9999999299)
Of course, you can add multiple Things, e.g. for getting measures for different locations.
## Discovery
This binding does not handle auto-discovery.
## Binding Configuration
The binding has no configuration options, all configuration is done at Thing level.
## Thing Configuration
The thing has a few configuration parameters:
| Parameter | Description |
|-----------|-------------------------------------------------------------------------|
| id | Id of the station. |
| refresh | Refresh interval in minutes. Optional, the default value is 30 minutes. |
## Channels
The VigiCrues information that retrieved are made available with these channels:
| Channel ID | Item Type | Description |
|------------------|---------------------------|-------------------------------|
| observation-time | DateTime | Date and time of measurement |
| flow | Number:VolumetricFlowRate | Volume of water per time unit |
| height | Number:Length | Water height of the river |
## Full Example
vigicrues.things:
```
Thing vigicrues:station:poissy "Station Poissy" @ "VigiCrues" [id="H300000201", refresh=30]
Thing vigicrues:station:vernon "Station Vernon" @ "VigiCrues" [id="H320000104", refresh=30]
```
vigicrues.items:
```
Group gVigiCrues "VigiCrues" <flow>
Number:Length VC_hauteur "Hauteur Eau Poissy [%.2f %unit%]" <none> (gVigiCrues) {channel="vigicrues:station:poissy:height"}
Number:VolumetricFlowRate VC_debit "Débit Eau Poissy [%.2f %unit%]" <flow> (gVigiCrues) {channel="vigicrues:station:poissy:flow"}
DateTime VC_ObservationPTS "Timestamp [%1$tH:%1$tM]" <time> (gVigiCrues) {channel="vigicrues:station:poissy:observation-time" }
```
vigicrues.sitemap:
```
sitemap vigicrues label="VigiCrues" {
Frame {
Default item=VC_hauteur
Default item=VC_debit
Default item=VC_ObservationPTS
}
}
```

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<artifactId>org.openhab.binding.vigicrues</artifactId>
<name>openHAB Add-ons :: Bundles :: VigiCrues Binding</name>
</project>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.vigicrues-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
<feature name="openhab-binding-vigicrues" description="VigiCrues Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.vigicrues/${project.version}</bundle>
</feature>
</features>

View File

@@ -0,0 +1,44 @@
/**
* 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.vigicrues.internal;
import java.util.Collections;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ThingTypeUID;
/**
* The {@link VigiCruesBindingConstants} class defines common constants, which are
* used across the whole binding.
*
* @author Gaël L'hopital - Initial contribution
*/
@NonNullByDefault
public class VigiCruesBindingConstants {
public static final String BINDING_ID = "vigicrues";
public static final String OPENDATASOFT_URL = "https://public.opendatasoft.com/api/records/1.0/search/";
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_VIGI_CRUES = new ThingTypeUID(BINDING_ID, "station");
// List of all Channel id's
public static final String OBSERVATION_TIME = "observation-time";
public static final String HEIGHT = "height";
public static final String FLOW = "flow";
public static final String COMMENT = "comment";
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_VIGI_CRUES);
}

View File

@@ -0,0 +1,27 @@
/**
* 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.vigicrues.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link VigiCruesConfiguration} is the class used to match the
* thing configuration.
*
* @author Gaël L'hopital - Initial contribution
*/
@NonNullByDefault
public class VigiCruesConfiguration {
public String id = "";
public int refresh = 30;
}

View File

@@ -0,0 +1,73 @@
/**
* 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.vigicrues.internal;
import static org.openhab.binding.vigicrues.internal.VigiCruesBindingConstants.*;
import java.time.ZonedDateTime;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.vigicrues.internal.handler.VigiCruesHandler;
import org.openhab.core.i18n.TimeZoneProvider;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerFactory;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializer;
/**
* The {@link VigiCruesHandlerFactory} is responsible for creating things and thing
* handlers.
*
* @author Gaël L'hopital - Initial contribution
*/
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.vigicrues")
@NonNullByDefault
public class VigiCruesHandlerFactory extends BaseThingHandlerFactory {
private final Gson gson;
// Needed for converting UTC time to local time
private final TimeZoneProvider timeZoneProvider;
@Activate
public VigiCruesHandlerFactory(@Reference TimeZoneProvider timeZoneProvider) {
this.timeZoneProvider = timeZoneProvider;
this.gson = new GsonBuilder()
.registerTypeAdapter(ZonedDateTime.class, (JsonDeserializer<ZonedDateTime>) (json, type,
jsonDeserializationContext) -> ZonedDateTime.parse(json.getAsJsonPrimitive().getAsString()))
.create();
}
@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 (thingTypeUID.equals(THING_TYPE_VIGI_CRUES)) {
return new VigiCruesHandler(thing, timeZoneProvider, gson);
}
return null;
}
}

View File

@@ -0,0 +1,140 @@
/**
* 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.vigicrues.internal.handler;
import static org.openhab.binding.vigicrues.internal.VigiCruesBindingConstants.*;
import static org.openhab.core.library.unit.SmartHomeUnits.CUBICMETRE_PER_SECOND;
import static tec.uom.se.unit.Units.METRE;
import java.io.IOException;
import java.net.MalformedURLException;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import javax.measure.Unit;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.vigicrues.internal.VigiCruesConfiguration;
import org.openhab.binding.vigicrues.internal.json.OpenDatasoftResponse;
import org.openhab.binding.vigicrues.internal.json.Record;
import org.openhab.core.i18n.TimeZoneProvider;
import org.openhab.core.io.net.http.HttpUtil;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.QuantityType;
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.BaseThingHandler;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
/**
* The {@link VigiCruesHandler} is responsible for querying the API and
* updating channels
*
* @author Gaël L'hopital - Initial contribution
*/
@NonNullByDefault
public class VigiCruesHandler extends BaseThingHandler {
private static final String URL = OPENDATASOFT_URL + "?dataset=vigicrues&sort=timestamp&q=";
private static final int TIMEOUT_MS = 30000;
private final Logger logger = LoggerFactory.getLogger(VigiCruesHandler.class);
// Time zone provider representing time zone configured in openHAB configuration
private final TimeZoneProvider timeZoneProvider;
private final Gson gson;
private @Nullable ScheduledFuture<?> refreshJob;
private @Nullable String queryUrl;
public VigiCruesHandler(Thing thing, TimeZoneProvider timeZoneProvider, Gson gson) {
super(thing);
this.timeZoneProvider = timeZoneProvider;
this.gson = gson;
}
@Override
public void initialize() {
logger.debug("Initializing VigiCrues handler.");
VigiCruesConfiguration config = getConfigAs(VigiCruesConfiguration.class);
logger.debug("config station = {}", config.id);
logger.debug("config refresh = {} min", config.refresh);
updateStatus(ThingStatus.UNKNOWN);
queryUrl = URL + config.id;
refreshJob = scheduler.scheduleWithFixedDelay(this::updateAndPublish, 0, config.refresh, TimeUnit.MINUTES);
}
@Override
public void dispose() {
logger.debug("Disposing the VigiCrues handler.");
ScheduledFuture<?> refreshJob = this.refreshJob;
if (refreshJob != null) {
refreshJob.cancel(true);
}
this.refreshJob = null;
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
if (command instanceof RefreshType) {
updateAndPublish();
}
}
private void updateAndPublish() {
try {
if (queryUrl != null) {
String response = HttpUtil.executeUrl("GET", queryUrl, TIMEOUT_MS);
updateStatus(ThingStatus.ONLINE);
OpenDatasoftResponse apiResponse = gson.fromJson(response, OpenDatasoftResponse.class);
Arrays.stream(apiResponse.getRecords()).findFirst().flatMap(Record::getFields).ifPresent(field -> {
field.getHeight().ifPresent(height -> updateQuantity(HEIGHT, height, METRE));
field.getFlow().ifPresent(flow -> updateQuantity(FLOW, flow, CUBICMETRE_PER_SECOND));
field.getTimestamp().ifPresent(date -> updateDate(OBSERVATION_TIME, date));
});
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.DISABLED,
"queryUrl should never be null, but it is !");
}
} catch (MalformedURLException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
String.format("Querying '%s' raised : %s", queryUrl, e.getMessage()));
} catch (IOException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
String.format("Error opening connection to VigiCrues webservice : {}", e.getMessage()));
}
}
private void updateQuantity(String channelId, Double value, Unit<?> unit) {
if (isLinked(channelId)) {
updateState(channelId, new QuantityType<>(value, unit));
}
}
public void updateDate(String channelId, ZonedDateTime zonedDateTime) {
if (isLinked(channelId)) {
ZonedDateTime localDateTime = zonedDateTime.withZoneSameInstant(timeZoneProvider.getTimeZone());
updateState(channelId, new DateTimeType(localDateTime));
}
}
}

View File

@@ -0,0 +1,50 @@
/**
* 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.vigicrues.internal.json;
import java.util.Optional;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import com.google.gson.annotations.SerializedName;
/**
* The {@link OpenDatasoftResponse} is the Java class used to map the JSON
* response to an opendatasoft endpoint request.
*
* @author Gaël L'hopital - Initial contribution
*/
@NonNullByDefault
public class OpenDatasoftResponse {
@SerializedName("nhits")
private int nHits;
private @Nullable Parameters parameters;
private Record[] records = {};
public int getNHits() {
return nHits;
}
public Optional<Parameters> getParameters() {
Parameters parameters = this.parameters;
if (parameters != null) {
return Optional.of(parameters);
}
return Optional.empty();
}
public Record[] getRecords() {
return records;
}
}

View File

@@ -0,0 +1,64 @@
/**
* 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.vigicrues.internal.json;
import java.time.ZoneId;
import java.util.Arrays;
import java.util.Optional;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
/**
* The {@link Parameters} is the Java class used to map the JSON
* response to the webservice request.
*
* @author Gaël L'hopital - Initial contribution
*/
@NonNullByDefault
public class Parameters {
private String[] dataset = {};
private String timezone = "";
private int rows;
private String format = "";
private @Nullable Refine refine;
private String[] facet = {};
public Optional<String> getDataset() {
return Arrays.stream(dataset).findFirst();
}
public ZoneId getTimezone() {
return ZoneId.of(timezone);
}
public int getRows() {
return rows;
}
public String getFormat() {
return format;
}
public Optional<Refine> getRefine() {
Refine refine = this.refine;
if (refine != null) {
return Optional.of(refine);
}
return Optional.empty();
}
public String[] getFacets() {
return facet;
}
}

View File

@@ -0,0 +1,57 @@
/**
* 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.vigicrues.internal.json;
import java.util.Optional;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import com.google.gson.annotations.SerializedName;
/**
* The {@link Record} is the Java class used to map the JSON
* response to the webservice request.
*
* @author Gaël L'hopital - Initial contribution
*/
@NonNullByDefault
public class Record {
@SerializedName("datasetid")
private String datasetId = "";
@SerializedName("recordid")
private String recordId = "";
@SerializedName("record_timestamp")
private String recordTimestamp = "";
private @Nullable VigiCruesFields fields;
public String getDatasetId() {
return datasetId;
}
public String getRecordId() {
return recordId;
}
public String getRecordTimestamp() {
return recordTimestamp;
}
public Optional<VigiCruesFields> getFields() {
VigiCruesFields fields = this.fields;
if (fields != null) {
return Optional.of(fields);
}
return Optional.empty();
}
}

View File

@@ -0,0 +1,33 @@
/**
* 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.vigicrues.internal.json;
import org.eclipse.jdt.annotation.NonNullByDefault;
import com.google.gson.annotations.SerializedName;
/**
* The {@link Refine} is the Java class used to map the JSON
* response to the webservice request.
*
* @author Gaël L'hopital - Initial contribution
*/
@NonNullByDefault
public class Refine {
@SerializedName("nom_dept")
private String departmentName = "";
public String getDepartmentName() {
return departmentName;
}
}

View File

@@ -0,0 +1,60 @@
/**
* 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.vigicrues.internal.json;
import java.time.ZonedDateTime;
import java.util.Optional;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import com.google.gson.annotations.SerializedName;
/**
* The {@link VigiCruesFields} is the Java class used to map the JSON
* response to the webservice request.
*
* @author Gaël L'hopital - Initial contribution
*/
@NonNullByDefault
public class VigiCruesFields {
@SerializedName("debit")
private @Nullable Double flow;
@SerializedName("hauteur")
private @Nullable Double height;
private @Nullable ZonedDateTime timestamp;
public Optional<ZonedDateTime> getTimestamp() {
ZonedDateTime timestamp = this.timestamp;
if (timestamp != null) {
return Optional.of(timestamp);
}
return Optional.empty();
}
public Optional<Double> getFlow() {
Double flow = this.flow;
if (flow != null) {
return Optional.of(flow);
}
return Optional.empty();
}
public Optional<Double> getHeight() {
Double height = this.height;
if (height != null) {
return Optional.of(height);
}
return Optional.empty();
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<binding:binding id="vigicrues" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
<name>VigiCrues Binding</name>
<description>Retrieves VigiCrues levels in France</description>
<author>Gaël L'hopital</author>
</binding:binding>

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="vigicrues"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="station">
<label>Station</label>
<description>
Provides river level informations for this station
</description>
<channels>
<channel id="height" typeId="height"/>
<channel id="flow" typeId="flow"/>
<channel id="observation-time" typeId="observation-time"/>
</channels>
<config-description>
<parameter name="id" type="text" required="true">
<label>Identifiant</label>
<description>Id of the station</description>
</parameter>
<parameter name="refresh" type="integer" min="1" required="true" unit="min">
<label>Refresh Interval</label>
<description>Specifies the refresh interval in minutes.</description>
<default>30</default>
</parameter>
</config-description>
</thing-type>
<channel-type id="flow">
<item-type>Number:VolumetricFlowRate</item-type>
<label>Current Flow</label>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<channel-type id="observation-time">
<item-type>DateTime</item-type>
<label>Observation Time</label>
<description>Observation date and time</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="height">
<item-type>Number:Length</item-type>
<label>Height</label>
<description>Water level in the river</description>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
</thing:thing-descriptions>