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