From 6a8f8de858482db017f608b2a09a0b22757c92c5 Mon Sep 17 00:00:00 2001 From: Marcel Verpaalen Date: Thu, 14 Jul 2016 18:11:03 +0200 Subject: [PATCH 1/3] WindCentrale binding Binding for windcentrale incl code reviews & updates Also-by: Wouter Born Also-by: Martin van Wingerden Signed-off-by: Marcel Verpaalen --- .../.classpath | 7 + .../org.openhab.binding.windcentrale/.project | 33 ++++ .../ESH-INF/binding/binding.xml | 10 ++ .../ESH-INF/i18n/windcentrale_nl.properties | 23 +++ .../ESH-INF/thing/millThing.xml | 109 ++++++++++++ .../META-INF/MANIFEST.MF | 24 +++ .../OSGI-INF/WindcentraleHandlerFactory.xml | 20 +++ .../README.md | 50 ++++++ .../about.html | 28 ++++ .../build.properties | 7 + .../org.openhab.binding.windcentrale/pom.xml | 19 +++ .../WindcentraleBindingConstants.java | 47 ++++++ .../handler/WindcentraleHandler.java | 157 ++++++++++++++++++ .../internal/WindcentraleHandlerFactory.java | 44 +++++ addons/binding/pom.xml | 1 + .../src/main/feature/feature.xml | 5 + 16 files changed, 584 insertions(+) create mode 100644 addons/binding/org.openhab.binding.windcentrale/.classpath create mode 100644 addons/binding/org.openhab.binding.windcentrale/.project create mode 100644 addons/binding/org.openhab.binding.windcentrale/ESH-INF/binding/binding.xml create mode 100644 addons/binding/org.openhab.binding.windcentrale/ESH-INF/i18n/windcentrale_nl.properties create mode 100644 addons/binding/org.openhab.binding.windcentrale/ESH-INF/thing/millThing.xml create mode 100644 addons/binding/org.openhab.binding.windcentrale/META-INF/MANIFEST.MF create mode 100644 addons/binding/org.openhab.binding.windcentrale/OSGI-INF/WindcentraleHandlerFactory.xml create mode 100644 addons/binding/org.openhab.binding.windcentrale/README.md create mode 100644 addons/binding/org.openhab.binding.windcentrale/about.html create mode 100644 addons/binding/org.openhab.binding.windcentrale/build.properties create mode 100644 addons/binding/org.openhab.binding.windcentrale/pom.xml create mode 100644 addons/binding/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/WindcentraleBindingConstants.java create mode 100644 addons/binding/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/handler/WindcentraleHandler.java create mode 100644 addons/binding/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/internal/WindcentraleHandlerFactory.java diff --git a/addons/binding/org.openhab.binding.windcentrale/.classpath b/addons/binding/org.openhab.binding.windcentrale/.classpath new file mode 100644 index 0000000000000..a95e0906ca013 --- /dev/null +++ b/addons/binding/org.openhab.binding.windcentrale/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/addons/binding/org.openhab.binding.windcentrale/.project b/addons/binding/org.openhab.binding.windcentrale/.project new file mode 100644 index 0000000000000..dee5b4ae2a8b2 --- /dev/null +++ b/addons/binding/org.openhab.binding.windcentrale/.project @@ -0,0 +1,33 @@ + + + org.openhab.binding.windcentrale + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.ds.core.builder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/addons/binding/org.openhab.binding.windcentrale/ESH-INF/binding/binding.xml b/addons/binding/org.openhab.binding.windcentrale/ESH-INF/binding/binding.xml new file mode 100644 index 0000000000000..d768a64e37580 --- /dev/null +++ b/addons/binding/org.openhab.binding.windcentrale/ESH-INF/binding/binding.xml @@ -0,0 +1,10 @@ + + + + Windcentrale Binding + Binding for Windcentrale windmills + Marcel Verpaalen + + diff --git a/addons/binding/org.openhab.binding.windcentrale/ESH-INF/i18n/windcentrale_nl.properties b/addons/binding/org.openhab.binding.windcentrale/ESH-INF/i18n/windcentrale_nl.properties new file mode 100644 index 0000000000000..fa8b147b98cdb --- /dev/null +++ b/addons/binding/org.openhab.binding.windcentrale/ESH-INF/i18n/windcentrale_nl.properties @@ -0,0 +1,23 @@ +# binding +binding.windcentrale.name = Windcentrale Binding +binding.windcentrale.description = Binding voor Windcentrale windmolens + +# thing types +thing-type.windcentrale.mill.label = Windcentrale windmolen +thing-type.config.windcentrale.mill.millId.label = Windmolen +thing-type.config.windcentrale.mill.wd.label = Aantal Winddelen +thing-type.config.windcentrale.mill.wd.description = Aantal Winddelen in bezit +thing-type.config.windcentrale.mill.refreshInterval.label = Ververs interval +thing-type.config.windcentrale.mill.refreshInterval.description = Ververs interval in seconden + +# channels +channel.windcentrale.windSpeed.label = Windsnelheid (Bft) +channel.windcentrale.windDirection.label = Windrichting +channel.windcentrale.powerAbsTot.label = Productie vermogen molen +channel.windcentrale.powerAbsWd.label = Vermogen van de Winddelen +channel.windcentrale.powerRel.label = Relatief vermogen +channel.windcentrale.kwh.label = Productie +channel.windcentrale.kwhForecast.label = Verwachte productie +channel.windcentrale.runPercentage.label = Molen productie percentage +channel.windcentrale.runPercentage.description = Molen productie percentage dit jaar +channel.windcentrale.timestamp.label = Ververs tijdstip diff --git a/addons/binding/org.openhab.binding.windcentrale/ESH-INF/thing/millThing.xml b/addons/binding/org.openhab.binding.windcentrale/ESH-INF/thing/millThing.xml new file mode 100644 index 0000000000000..aa85261bffe1a --- /dev/null +++ b/addons/binding/org.openhab.binding.windcentrale/ESH-INF/thing/millThing.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + Windcentrale + + + + + + + + + + + + + + + + + + 131 + + + + Number of wind shares ("Winddelen") + 1 + + + + Refresh interval for refreshing the data in seconds + 30 + true + + + + + + Number + + Wind + + + + String + + + + + Number + + Energy + + + + Number + + Run percentage this year + Energy + + + + Number + + Energy + + + + Number + + Energy + + + + Number + + Energy + + + + Number + + Energy + + + + DateTime + + + + diff --git a/addons/binding/org.openhab.binding.windcentrale/META-INF/MANIFEST.MF b/addons/binding/org.openhab.binding.windcentrale/META-INF/MANIFEST.MF new file mode 100644 index 0000000000000..67d536f345946 --- /dev/null +++ b/addons/binding/org.openhab.binding.windcentrale/META-INF/MANIFEST.MF @@ -0,0 +1,24 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Windcentrale Binding +Bundle-SymbolicName: org.openhab.binding.windcentrale;singleton:=true +Bundle-Vendor: openHAB +Bundle-Version: 2.1.0.qualifier +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ClassPath: . +Import-Package: com.google.common.collect, + com.google.gson, + org.apache.commons.io, + org.eclipse.smarthome.config.core, + org.eclipse.smarthome.config.discovery, + org.eclipse.smarthome.core.library.types, + org.eclipse.smarthome.core.thing, + org.eclipse.smarthome.core.thing.binding, + org.eclipse.smarthome.core.types, + org.openhab.binding.windcentrale, + org.openhab.binding.windcentrale.handler, + org.slf4j +Service-Component: OSGI-INF/*.xml +Export-Package: org.openhab.binding.windcentrale, + org.openhab.binding.windcentrale.handler +Bundle-ActivationPolicy: lazy diff --git a/addons/binding/org.openhab.binding.windcentrale/OSGI-INF/WindcentraleHandlerFactory.xml b/addons/binding/org.openhab.binding.windcentrale/OSGI-INF/WindcentraleHandlerFactory.xml new file mode 100644 index 0000000000000..4775a5fa3ad99 --- /dev/null +++ b/addons/binding/org.openhab.binding.windcentrale/OSGI-INF/WindcentraleHandlerFactory.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + diff --git a/addons/binding/org.openhab.binding.windcentrale/README.md b/addons/binding/org.openhab.binding.windcentrale/README.md new file mode 100644 index 0000000000000..5b089a983f9f1 --- /dev/null +++ b/addons/binding/org.openhab.binding.windcentrale/README.md @@ -0,0 +1,50 @@ +# Windcentrale Binding + +This Binding is used to display the details of a Windcentrale windmill. + +## Supported Things + +This Binding supports Windcentrale mill devices. + +## Discovery + +There is no discovery available for this binding. + +## Binding Configuration + +No binding configuration required. + +## Thing Configuration + +The thing mandatory configuration is the selection of the mill. +Optional configuration is the number of wind shares ("Winddelen") and the refresh interval. + +## Channels + +- **windSpeed** Measured current wind speed +- **windDirection** Current wind direction +- **powerAbsTot** Total power +- **powerAbsWd** Power provided for your wind shares +- **powerRel** Relative power +- **kwh** Current energy +- **kwhForecast** Energy forecast +- **runPercentage** Run percentage this year +- **timestamp** Timestamp of the last update + + +## Full example + +``` +Group gReiger "Windcentrale Reiger" + +Number ReigerWindSpeed "Windsnelheid [%1.0f Bft]" (gReiger) {channel="windcentrale:mill:reiger:windSpeed") +String ReigerWindDirection "Windrichting [%s]" (gReiger) {channel="windcentrale:mill:reiger:windDirection") +Number ReigerPowerAbsTot "Productie molen [%1.0f kW]" (gReiger) {channel="windcentrale:mill:reiger:powerAbsTot") +Number ReigerPowerAbsWd "WD power [%1.0f W]" (gReiger) {channel="windcentrale:mill:reiger:powerAbsWd") +Number ReigerPowerRel "Productie vermogen [%1.0f %%]" (gReiger) {channel="windcentrale:mill:reiger:powerRel") +Number ReigerKwh "kwh [%1.0f]" (gReiger) {channel="windcentrale:mill:reiger:kwh") +Number ReigerKwhForecast "Productie forecast [%1.0f]" (gReiger) {channel="windcentrale:mill:reiger:kwhForecast") +Number ReigerRunPercentage "Run percentage [%1.0f %%]" (gReiger) {channel="windcentrale:mill:reiger:runPercentage") +Number ReigerTimestamp "Update timestamp [%1$ta %1$tR]" (gReiger) {channel="windcentrale:mill:reiger:timestamp") + +``` diff --git a/addons/binding/org.openhab.binding.windcentrale/about.html b/addons/binding/org.openhab.binding.windcentrale/about.html new file mode 100644 index 0000000000000..d4a859344f2dc --- /dev/null +++ b/addons/binding/org.openhab.binding.windcentrale/about.html @@ -0,0 +1,28 @@ + + + + + About + + +

About This Content

+ +

June 5, 2006

+

License

+ +

The openHAB community makes available all content in this plug-in ("Content"). Unless otherwise + indicated below, the Content is provided to you under the terms and conditions of the + Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available + at http://www.eclipse.org/legal/epl-v10.html. + For purposes of the EPL, "Program" will mean the Content.

+ +

If you did not receive this Content directly from the openHAB community, the Content is + being redistributed by another party ("Redistributor") and different terms and conditions may + apply to your use of any object code in the Content. Check the Redistributor's license that was + provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise + indicated below, the terms and conditions of the EPL still apply to any source code in the Content + and such source code may be obtained at openhab.org.

+ + + diff --git a/addons/binding/org.openhab.binding.windcentrale/build.properties b/addons/binding/org.openhab.binding.windcentrale/build.properties new file mode 100644 index 0000000000000..1b6f95926babc --- /dev/null +++ b/addons/binding/org.openhab.binding.windcentrale/build.properties @@ -0,0 +1,7 @@ +source.. = src/main/java/ +output.. = target/classes +bin.includes = META-INF/,\ + .,\ + OSGI-INF/,\ + ESH-INF/,\ + about.html diff --git a/addons/binding/org.openhab.binding.windcentrale/pom.xml b/addons/binding/org.openhab.binding.windcentrale/pom.xml new file mode 100644 index 0000000000000..80e5b01c94279 --- /dev/null +++ b/addons/binding/org.openhab.binding.windcentrale/pom.xml @@ -0,0 +1,19 @@ + + + + 4.0.0 + + + org.openhab.binding + pom + 2.1.0-SNAPSHOT + + + org.openhab.binding + org.openhab.binding.windcentrale + 2.1.0-SNAPSHOT + + Windcentrale Binding + eclipse-plugin + + diff --git a/addons/binding/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/WindcentraleBindingConstants.java b/addons/binding/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/WindcentraleBindingConstants.java new file mode 100644 index 0000000000000..275cb45a620f7 --- /dev/null +++ b/addons/binding/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/WindcentraleBindingConstants.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2010-2017 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.windcentrale; + +import java.util.Collections; +import java.util.Set; + +import org.eclipse.smarthome.core.thing.ThingTypeUID; + +/** + * The {@link WindcentraleBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Marcel Verpaalen - Initial contribution + */ +public final class WindcentraleBindingConstants { + + public static final String BINDING_ID = "windcentrale"; + + // List of all Thing Type UIDs + public static final ThingTypeUID THING_TYPE_MILL = new ThingTypeUID(BINDING_ID, "mill"); + + public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_MILL); + + // List of all Channel IDs + public static final String CHANNEL_WIND_SPEED = "windSpeed"; + public static final String CHANNEL_WIND_DIRECTION = "windDirection"; + public static final String CHANNEL_POWER_TOTAL = "powerAbsTot"; + public static final String CHANNEL_POWER_PER_WD = "powerAbsWd"; + public static final String CHANNEL_POWER_RELATIVE = "powerRel"; + public static final String CHANNEL_ENERGY = "kwh"; + public static final String CHANNEL_ENERGY_FC = "kwhForecast"; + public static final String CHANNEL_RUNTIME = "hoursRunThisYear"; + public static final String CHANNEL_RUNTIME_PER = "runPercentage"; + public static final String CHANNEL_LAST_UPDATE = "timestamp"; + + public static final String PROPERTY_MILL_ID = "millId"; + public static final String PROPERTY_QTY_WINDDELEN = "wd"; + public static final String PROPERTY_REFRESH_INTERVAL = "refreshInterval"; + +} diff --git a/addons/binding/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/handler/WindcentraleHandler.java b/addons/binding/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/handler/WindcentraleHandler.java new file mode 100644 index 0000000000000..2c18a7c2ef591 --- /dev/null +++ b/addons/binding/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/handler/WindcentraleHandler.java @@ -0,0 +1,157 @@ +/** + * Copyright (c) 2010-2017 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.windcentrale.handler; + +import static org.openhab.binding.windcentrale.WindcentraleBindingConstants.*; + +import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.io.IOUtils; +import org.eclipse.smarthome.core.library.types.DateTimeType; +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.library.types.StringType; +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.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +/** + * The {@link WindcentraleHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Marcel Verpaalen - Initial contribution + */ +public class WindcentraleHandler extends BaseThingHandler { + private final Logger logger = LoggerFactory.getLogger(WindcentraleHandler.class); + + private static final String BASE_URL = "https://zep-api.windcentrale.nl/production/"; + private URL millUrl; + private BigDecimal wd = BigDecimal.ONE; + private ScheduledFuture pollingJob; + + public WindcentraleHandler(Thing thing) { + super(thing); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (command == RefreshType.REFRESH) { + logger.debug("Refreshing {}", channelUID); + updateData(); + } else { + logger.warn("This binding is a read-only binding and cannot handle commands"); + } + } + + @Override + public void initialize() { + logger.debug("Initializing Windcentrale handler '{}'", getThing().getUID()); + + Object param; + + param = getConfig().get(PROPERTY_MILL_ID); + int millId; + if (param instanceof BigDecimal) { + millId = ((BigDecimal) param).intValue(); + } else { + millId = 1; + } + + param = getConfig().get(PROPERTY_QTY_WINDDELEN); + if (param instanceof BigDecimal) { + wd = (BigDecimal) param; + } else { + wd = BigDecimal.ONE; + } + + int pollingPeriod = 30; + param = getConfig().get(PROPERTY_REFRESH_INTERVAL); + if (param instanceof BigDecimal) { + pollingPeriod = ((BigDecimal) param).intValue(); + } + + updateProperty(Thing.PROPERTY_VENDOR, "Windcentrale"); + updateProperty(Thing.PROPERTY_MODEL_ID, "Windmolen"); + updateProperty(Thing.PROPERTY_SERIAL_NUMBER, Integer.toString(millId)); + + String urlString = BASE_URL + millId + "/live?ignoreLoadingBar=true"; + try { + millUrl = new URL(urlString); + } catch (MalformedURLException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Constructed url '" + urlString + "' is not valid: " + e.getLocalizedMessage()); + return; + } + + pollingJob = scheduler.scheduleWithFixedDelay(this::updateData, 0, pollingPeriod, TimeUnit.SECONDS); + logger.debug("Polling job scheduled to run every {} sec. for '{}'", pollingPeriod, getThing().getUID()); + } + + @Override + public void dispose() { + logger.debug("Disposing Windcentrale handler '{}'", getThing().getUID()); + if (pollingJob != null) { + pollingJob.cancel(true); + pollingJob = null; + } + } + + private synchronized void updateData() { + logger.debug("Update windmill data '{}'", getThing().getUID()); + + try { + String getMillData = getMillData(); + JsonParser parser = new JsonParser(); + JsonObject millData = (JsonObject) parser.parse(getMillData); + + logger.trace("Retrieved updated mill data: {}", millData); + + updateState(CHANNEL_WIND_SPEED, new DecimalType(millData.get(CHANNEL_WIND_SPEED).getAsString())); + updateState(CHANNEL_WIND_DIRECTION, new StringType(millData.get(CHANNEL_WIND_DIRECTION).getAsString())); + updateState(CHANNEL_POWER_TOTAL, new DecimalType(millData.get(CHANNEL_POWER_TOTAL).getAsBigDecimal())); + updateState(CHANNEL_POWER_PER_WD, + new DecimalType(millData.get(CHANNEL_POWER_PER_WD).getAsBigDecimal().multiply(wd))); + updateState(CHANNEL_POWER_RELATIVE, + new DecimalType(millData.get(CHANNEL_POWER_RELATIVE).getAsBigDecimal())); + updateState(CHANNEL_ENERGY, new DecimalType(millData.get(CHANNEL_ENERGY).getAsBigDecimal())); + updateState(CHANNEL_ENERGY_FC, new DecimalType(millData.get(CHANNEL_ENERGY_FC).getAsBigDecimal())); + updateState(CHANNEL_RUNTIME, new DecimalType(millData.get(CHANNEL_RUNTIME).getAsBigDecimal())); + updateState(CHANNEL_RUNTIME_PER, new DecimalType(millData.get(CHANNEL_RUNTIME_PER).getAsBigDecimal())); + updateState(CHANNEL_LAST_UPDATE, new DateTimeType(millData.get(CHANNEL_LAST_UPDATE).getAsString())); + + if (!getThing().getStatus().equals(ThingStatus.ONLINE)) { + updateStatus(ThingStatus.ONLINE); + } + + } catch (Exception e) { + logger.debug("Failed to update windmill data", e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, e.getMessage()); + } + } + + private String getMillData() throws IOException { + try (InputStream connection = millUrl.openStream()) { + return IOUtils.toString(connection); + } + } +} diff --git a/addons/binding/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/internal/WindcentraleHandlerFactory.java b/addons/binding/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/internal/WindcentraleHandlerFactory.java new file mode 100644 index 0000000000000..f0012b413c184 --- /dev/null +++ b/addons/binding/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/internal/WindcentraleHandlerFactory.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2010-2017 by the respective copyright holders. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.binding.windcentrale.internal; + +import static org.openhab.binding.windcentrale.WindcentraleBindingConstants.*; + +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.openhab.binding.windcentrale.handler.WindcentraleHandler; + +/** + * The {@link WindcentraleHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Marcel Verpaalen - Initial contribution + */ +public class WindcentraleHandlerFactory extends BaseThingHandlerFactory { + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected ThingHandler createHandler(Thing thing) { + + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (thingTypeUID.equals(THING_TYPE_MILL)) { + return new WindcentraleHandler(thing); + } + + return null; + } + +} diff --git a/addons/binding/pom.xml b/addons/binding/pom.xml index 03fc7d923fca4..8bb27041e4929 100644 --- a/addons/binding/pom.xml +++ b/addons/binding/pom.xml @@ -76,6 +76,7 @@ org.openhab.binding.urtsi org.openhab.binding.vitotronic org.openhab.binding.wifiled + org.openhab.binding.windcentrale org.openhab.binding.yamahareceiver org.openhab.binding.zoneminder org.openhab.binding.zway diff --git a/features/openhab-addons/src/main/feature/feature.xml b/features/openhab-addons/src/main/feature/feature.xml index 868c7764c196f..acfbb068aae20 100644 --- a/features/openhab-addons/src/main/feature/feature.xml +++ b/features/openhab-addons/src/main/feature/feature.xml @@ -321,6 +321,11 @@ mvn:org.openhab.binding/org.openhab.binding.wifiled/${project.version} + + openhab-runtime-base + mvn:org.openhab.binding/org.openhab.binding.windcentrale/${project.version} + + openhab-runtime-base openhab-transport-upnp From 0ff32733b73931004594cd6c0ac50ea5b4a6a527 Mon Sep 17 00:00:00 2001 From: Marcel Verpaalen Date: Sat, 10 Jun 2017 14:44:20 +0200 Subject: [PATCH 2/3] [Windcentrale] Process comments Signed-off-by: Marcel Verpaalen --- .../META-INF/MANIFEST.MF | 2 + .../handler/WindcentraleHandler.java | 88 +++++++++---------- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/addons/binding/org.openhab.binding.windcentrale/META-INF/MANIFEST.MF b/addons/binding/org.openhab.binding.windcentrale/META-INF/MANIFEST.MF index 67d536f345946..d02d8a0f3e0fa 100644 --- a/addons/binding/org.openhab.binding.windcentrale/META-INF/MANIFEST.MF +++ b/addons/binding/org.openhab.binding.windcentrale/META-INF/MANIFEST.MF @@ -11,10 +11,12 @@ Import-Package: com.google.common.collect, org.apache.commons.io, org.eclipse.smarthome.config.core, org.eclipse.smarthome.config.discovery, + org.eclipse.smarthome.core.cache, org.eclipse.smarthome.core.library.types, org.eclipse.smarthome.core.thing, org.eclipse.smarthome.core.thing.binding, org.eclipse.smarthome.core.types, + org.eclipse.smarthome.io.net.http, org.openhab.binding.windcentrale, org.openhab.binding.windcentrale.handler, org.slf4j diff --git a/addons/binding/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/handler/WindcentraleHandler.java b/addons/binding/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/handler/WindcentraleHandler.java index 2c18a7c2ef591..3b39f527eb8ed 100644 --- a/addons/binding/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/handler/WindcentraleHandler.java +++ b/addons/binding/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/handler/WindcentraleHandler.java @@ -10,15 +10,11 @@ import static org.openhab.binding.windcentrale.WindcentraleBindingConstants.*; -import java.io.IOException; -import java.io.InputStream; import java.math.BigDecimal; -import java.net.MalformedURLException; -import java.net.URL; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import org.apache.commons.io.IOUtils; +import org.eclipse.smarthome.core.cache.ExpiringCache; import org.eclipse.smarthome.core.library.types.DateTimeType; import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.library.types.StringType; @@ -29,6 +25,7 @@ import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; +import org.eclipse.smarthome.io.net.http.HttpUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,12 +42,16 @@ public class WindcentraleHandler extends BaseThingHandler { private final Logger logger = LoggerFactory.getLogger(WindcentraleHandler.class); private static final String BASE_URL = "https://zep-api.windcentrale.nl/production/"; - private URL millUrl; private BigDecimal wd = BigDecimal.ONE; private ScheduledFuture pollingJob; + private JsonParser parser; + private final int CACHE_EXPIRY = 5 * 1000; // 5s + private ExpiringCache windcentraleCache; + public WindcentraleHandler(Thing thing) { super(thing); + parser = new JsonParser(); } @Override @@ -59,7 +60,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { logger.debug("Refreshing {}", channelUID); updateData(); } else { - logger.warn("This binding is a read-only binding and cannot handle commands"); + logger.debug("This binding is a read-only binding and cannot handle commands"); } } @@ -94,14 +95,16 @@ public void initialize() { updateProperty(Thing.PROPERTY_MODEL_ID, "Windmolen"); updateProperty(Thing.PROPERTY_SERIAL_NUMBER, Integer.toString(millId)); - String urlString = BASE_URL + millId + "/live?ignoreLoadingBar=true"; - try { - millUrl = new URL(urlString); - } catch (MalformedURLException e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Constructed url '" + urlString + "' is not valid: " + e.getLocalizedMessage()); - return; - } + String millUrl = BASE_URL + millId + "/live?ignoreLoadingBar=true"; + + windcentraleCache = new ExpiringCache(CACHE_EXPIRY, () -> { + try { + return HttpUtil.executeUrl("GET", millUrl, 5000); + } catch (Exception e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, e.getMessage()); + return null; + } + }); pollingJob = scheduler.scheduleWithFixedDelay(this::updateData, 0, pollingPeriod, TimeUnit.SECONDS); logger.debug("Polling job scheduled to run every {} sec. for '{}'", pollingPeriod, getThing().getUID()); @@ -120,38 +123,33 @@ private synchronized void updateData() { logger.debug("Update windmill data '{}'", getThing().getUID()); try { - String getMillData = getMillData(); - JsonParser parser = new JsonParser(); - JsonObject millData = (JsonObject) parser.parse(getMillData); - - logger.trace("Retrieved updated mill data: {}", millData); - - updateState(CHANNEL_WIND_SPEED, new DecimalType(millData.get(CHANNEL_WIND_SPEED).getAsString())); - updateState(CHANNEL_WIND_DIRECTION, new StringType(millData.get(CHANNEL_WIND_DIRECTION).getAsString())); - updateState(CHANNEL_POWER_TOTAL, new DecimalType(millData.get(CHANNEL_POWER_TOTAL).getAsBigDecimal())); - updateState(CHANNEL_POWER_PER_WD, - new DecimalType(millData.get(CHANNEL_POWER_PER_WD).getAsBigDecimal().multiply(wd))); - updateState(CHANNEL_POWER_RELATIVE, - new DecimalType(millData.get(CHANNEL_POWER_RELATIVE).getAsBigDecimal())); - updateState(CHANNEL_ENERGY, new DecimalType(millData.get(CHANNEL_ENERGY).getAsBigDecimal())); - updateState(CHANNEL_ENERGY_FC, new DecimalType(millData.get(CHANNEL_ENERGY_FC).getAsBigDecimal())); - updateState(CHANNEL_RUNTIME, new DecimalType(millData.get(CHANNEL_RUNTIME).getAsBigDecimal())); - updateState(CHANNEL_RUNTIME_PER, new DecimalType(millData.get(CHANNEL_RUNTIME_PER).getAsBigDecimal())); - updateState(CHANNEL_LAST_UPDATE, new DateTimeType(millData.get(CHANNEL_LAST_UPDATE).getAsString())); - - if (!getThing().getStatus().equals(ThingStatus.ONLINE)) { - updateStatus(ThingStatus.ONLINE); + String getMillData = windcentraleCache.getValue(); + if (getMillData != null) { + JsonObject millData = (JsonObject) parser.parse(getMillData); + + logger.trace("Retrieved updated mill data: {}", millData); + + updateState(CHANNEL_WIND_SPEED, new DecimalType(millData.get(CHANNEL_WIND_SPEED).getAsString())); + updateState(CHANNEL_WIND_DIRECTION, new StringType(millData.get(CHANNEL_WIND_DIRECTION).getAsString())); + updateState(CHANNEL_POWER_TOTAL, new DecimalType(millData.get(CHANNEL_POWER_TOTAL).getAsBigDecimal())); + updateState(CHANNEL_POWER_PER_WD, + new DecimalType(millData.get(CHANNEL_POWER_PER_WD).getAsBigDecimal().multiply(wd))); + updateState(CHANNEL_POWER_RELATIVE, + new DecimalType(millData.get(CHANNEL_POWER_RELATIVE).getAsBigDecimal())); + updateState(CHANNEL_ENERGY, new DecimalType(millData.get(CHANNEL_ENERGY).getAsBigDecimal())); + updateState(CHANNEL_ENERGY_FC, new DecimalType(millData.get(CHANNEL_ENERGY_FC).getAsBigDecimal())); + updateState(CHANNEL_RUNTIME, new DecimalType(millData.get(CHANNEL_RUNTIME).getAsBigDecimal())); + updateState(CHANNEL_RUNTIME_PER, new DecimalType(millData.get(CHANNEL_RUNTIME_PER).getAsBigDecimal())); + updateState(CHANNEL_LAST_UPDATE, new DateTimeType(millData.get(CHANNEL_LAST_UPDATE).getAsString())); + + if (!getThing().getStatus().equals(ThingStatus.ONLINE)) { + updateStatus(ThingStatus.ONLINE); + } } - } catch (Exception e) { - logger.debug("Failed to update windmill data", e); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, e.getMessage()); - } - } - - private String getMillData() throws IOException { - try (InputStream connection = millUrl.openStream()) { - return IOUtils.toString(connection); + logger.debug("Failed to process windmill data", e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, + "Failed to process mill data"); } } } From 2995b7c8dab8607bd033c8753a5275ee9c1b51ae Mon Sep 17 00:00:00 2001 From: Marcel Verpaalen Date: Sun, 11 Jun 2017 13:34:34 +0200 Subject: [PATCH 3/3] [windcentrale] more clean handling of the null response. Signed-off-by: Marcel Verpaalen --- .../handler/WindcentraleHandler.java | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/addons/binding/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/handler/WindcentraleHandler.java b/addons/binding/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/handler/WindcentraleHandler.java index 3b39f527eb8ed..8f2c070714a38 100644 --- a/addons/binding/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/handler/WindcentraleHandler.java +++ b/addons/binding/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/handler/WindcentraleHandler.java @@ -124,27 +124,27 @@ private synchronized void updateData() { try { String getMillData = windcentraleCache.getValue(); - if (getMillData != null) { - JsonObject millData = (JsonObject) parser.parse(getMillData); - - logger.trace("Retrieved updated mill data: {}", millData); - - updateState(CHANNEL_WIND_SPEED, new DecimalType(millData.get(CHANNEL_WIND_SPEED).getAsString())); - updateState(CHANNEL_WIND_DIRECTION, new StringType(millData.get(CHANNEL_WIND_DIRECTION).getAsString())); - updateState(CHANNEL_POWER_TOTAL, new DecimalType(millData.get(CHANNEL_POWER_TOTAL).getAsBigDecimal())); - updateState(CHANNEL_POWER_PER_WD, - new DecimalType(millData.get(CHANNEL_POWER_PER_WD).getAsBigDecimal().multiply(wd))); - updateState(CHANNEL_POWER_RELATIVE, - new DecimalType(millData.get(CHANNEL_POWER_RELATIVE).getAsBigDecimal())); - updateState(CHANNEL_ENERGY, new DecimalType(millData.get(CHANNEL_ENERGY).getAsBigDecimal())); - updateState(CHANNEL_ENERGY_FC, new DecimalType(millData.get(CHANNEL_ENERGY_FC).getAsBigDecimal())); - updateState(CHANNEL_RUNTIME, new DecimalType(millData.get(CHANNEL_RUNTIME).getAsBigDecimal())); - updateState(CHANNEL_RUNTIME_PER, new DecimalType(millData.get(CHANNEL_RUNTIME_PER).getAsBigDecimal())); - updateState(CHANNEL_LAST_UPDATE, new DateTimeType(millData.get(CHANNEL_LAST_UPDATE).getAsString())); - - if (!getThing().getStatus().equals(ThingStatus.ONLINE)) { - updateStatus(ThingStatus.ONLINE); - } + if (getMillData == null) { + return; + } + JsonObject millData = (JsonObject) parser.parse(getMillData); + logger.trace("Retrieved updated mill data: {}", millData); + + updateState(CHANNEL_WIND_SPEED, new DecimalType(millData.get(CHANNEL_WIND_SPEED).getAsString())); + updateState(CHANNEL_WIND_DIRECTION, new StringType(millData.get(CHANNEL_WIND_DIRECTION).getAsString())); + updateState(CHANNEL_POWER_TOTAL, new DecimalType(millData.get(CHANNEL_POWER_TOTAL).getAsBigDecimal())); + updateState(CHANNEL_POWER_PER_WD, + new DecimalType(millData.get(CHANNEL_POWER_PER_WD).getAsBigDecimal().multiply(wd))); + updateState(CHANNEL_POWER_RELATIVE, + new DecimalType(millData.get(CHANNEL_POWER_RELATIVE).getAsBigDecimal())); + updateState(CHANNEL_ENERGY, new DecimalType(millData.get(CHANNEL_ENERGY).getAsBigDecimal())); + updateState(CHANNEL_ENERGY_FC, new DecimalType(millData.get(CHANNEL_ENERGY_FC).getAsBigDecimal())); + updateState(CHANNEL_RUNTIME, new DecimalType(millData.get(CHANNEL_RUNTIME).getAsBigDecimal())); + updateState(CHANNEL_RUNTIME_PER, new DecimalType(millData.get(CHANNEL_RUNTIME_PER).getAsBigDecimal())); + updateState(CHANNEL_LAST_UPDATE, new DateTimeType(millData.get(CHANNEL_LAST_UPDATE).getAsString())); + + if (!getThing().getStatus().equals(ThingStatus.ONLINE)) { + updateStatus(ThingStatus.ONLINE); } } catch (Exception e) { logger.debug("Failed to process windmill data", e);