diff --git a/bundles/org.openhab.binding.mystrom/README.md b/bundles/org.openhab.binding.mystrom/README.md index a0389947e..57ecf5c87 100644 --- a/bundles/org.openhab.binding.mystrom/README.md +++ b/bundles/org.openhab.binding.mystrom/README.md @@ -1,15 +1,17 @@ # myStrom Binding -This extension adds support for the myStrom devices. Currently only the smart plug is implemented. +This extension adds support for the myStrom devices. +As of today only the Smart Plug, Bulb and the Motionsensor are implemented. ## Supported Things This bundle adds the following thing types: -| Thing | ThingTypeID | Description | -| ------------------ | ----------- | -------------------------------------------------- | -| myStrom Smart Plug | mystromplug | A myStrom smart plug | -| myStrom Bulb | mystrombulb | A myStrom bulb | +| Thing | ThingTypeID | Description | +| ----------------------| ----------- | -------------------------------------------------- | +| myStrom Smart Plug | mystromplug | A myStrom smart plug | +| myStrom Bulb | mystrombulb | A myStrom bulb | +| myStrom Motion Sensor | mystrompir | A myStrom bulb | According to the myStrom API documentation all request specific to the myStrom Bulb are also work on the LED strip. @@ -26,6 +28,7 @@ The following parameters are valid for all thing types: | --------- | ------- | -------- | ------------------ | -------------------------------------------------------------------------- | | hostname | string | yes | localhost | The IP address or hostname of the myStrom smart plug | | refresh | integer | no | 10 | Poll interval in seconds. Increase this if you encounter connection errors | +| apiToken | string | no | | Specifies the API Token, if required. | ## Properties @@ -52,12 +55,14 @@ Disabling/enabling the thing can be used to update the properties. | ---------------- | -------------------- | --------- | --------------------------------------------------------------------- |-------------------------------------| | switch | Switch | false | Turn the device on or off | mystromplug, mystrombulb | | power | Number:Power | true | The currently delivered power | mystromplug, mystrombulb | -| temperature | Number:Temperature | true | The temperature at the plug | mystromplug | +| temperature | Number:Temperature | true | The temperature at the plug | mystromplug, mystrompir | | color | Color | false | The color we set the bulb to (mode 'hsv') | mystrombulb | | colorTemperature | Dimmer | false | The color temperature of the bulb in mode 'mono' (percentage) | mystrombulb | | brightness | Dimmer | false | The brightness of the bulb in mode 'mono' | mystrombulb | | ramp | Number:Time | false | Transition time from the light’s current state to the new state. [ms] | mystrombulb | | mode | String | false | The color mode we want the Bulb to set to (rgb, hsv or mono) | mystrombulb | +| light | Dimmer | true | The brightness of the Room. | mystrompir | +| motion | Switch | true | Motionstatus of the sensor | mystrompir | ## Full Example diff --git a/bundles/org.openhab.binding.mystrom/src/main/java/org/openhab/binding/mystrom/internal/AbstractMyStromHandler.java b/bundles/org.openhab.binding.mystrom/src/main/java/org/openhab/binding/mystrom/internal/AbstractMyStromHandler.java index 78186f24c..cdca5d2dc 100644 --- a/bundles/org.openhab.binding.mystrom/src/main/java/org/openhab/binding/mystrom/internal/AbstractMyStromHandler.java +++ b/bundles/org.openhab.binding.mystrom/src/main/java/org/openhab/binding/mystrom/internal/AbstractMyStromHandler.java @@ -12,17 +12,7 @@ */ package org.openhab.binding.mystrom.internal; -import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.PROPERTY_CONNECTED; -import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.PROPERTY_DNS; -import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.PROPERTY_GW; -import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.PROPERTY_IP; -import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.PROPERTY_LAST_REFRESH; -import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.PROPERTY_MAC; -import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.PROPERTY_MASK; -import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.PROPERTY_SSID; -import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.PROPERTY_STATIC; -import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.PROPERTY_TYPE; -import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.PROPERTY_VERSION; +import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.*; import java.text.DateFormat; import java.util.Calendar; @@ -61,10 +51,9 @@ import com.google.gson.JsonSyntaxException; @NonNullByDefault public abstract class AbstractMyStromHandler extends BaseThingHandler { protected static final String COMMUNICATION_ERROR = "Error while communicating to the myStrom plug: "; - protected static final String HTTP_REQUEST_URL_PREFIX = "http://"; + protected MyStromConfiguration config; protected final HttpClient httpClient; - protected String hostname = ""; protected String mac = ""; private final Logger logger = LoggerFactory.getLogger(AbstractMyStromHandler.class); @@ -73,14 +62,13 @@ public abstract class AbstractMyStromHandler extends BaseThingHandler { public AbstractMyStromHandler(Thing thing, HttpClient httpClient) { super(thing); + config = getConfigAs(MyStromConfiguration.class); this.httpClient = httpClient; } @Override public final void initialize() { - MyStromConfiguration config = getConfigAs(MyStromConfiguration.class); - this.hostname = HTTP_REQUEST_URL_PREFIX + config.hostname; - + config = getConfigAs(MyStromConfiguration.class); updateStatus(ThingStatus.UNKNOWN); scheduler.schedule(this::initializeInternal, 0, TimeUnit.SECONDS); } @@ -135,9 +123,12 @@ public abstract class AbstractMyStromHandler extends BaseThingHandler { */ protected final String sendHttpRequest(HttpMethod method, String path, @Nullable String requestData) throws MyStromException { - String url = hostname + path; + String url = config.getHostname() + path; try { Request request = httpClient.newRequest(url).timeout(10, TimeUnit.SECONDS).method(method); + if (!config.getApiToken().isEmpty()) { + request.getHeaders().add("Token", config.getApiToken()); + } if (requestData != null) { request = request.content(new StringContentProvider(requestData)).header(HttpHeader.CONTENT_TYPE, "application/x-www-form-urlencoded"); @@ -157,9 +148,7 @@ public abstract class AbstractMyStromHandler extends BaseThingHandler { try { updateProperties(); checkRequiredInfo(); - updateStatus(ThingStatus.ONLINE); - MyStromConfiguration config = getConfigAs(MyStromConfiguration.class); - pollingJob = scheduler.scheduleWithFixedDelay(this::pollDevice, 0, config.refresh, TimeUnit.SECONDS); + pollingJob = scheduler.scheduleWithFixedDelay(this::pollDevice, 0, config.getRefresh(), TimeUnit.SECONDS); } catch (MyStromException e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage()); } diff --git a/bundles/org.openhab.binding.mystrom/src/main/java/org/openhab/binding/mystrom/internal/MyStromBindingConstants.java b/bundles/org.openhab.binding.mystrom/src/main/java/org/openhab/binding/mystrom/internal/MyStromBindingConstants.java index d76daad88..9954caaaf 100644 --- a/bundles/org.openhab.binding.mystrom/src/main/java/org/openhab/binding/mystrom/internal/MyStromBindingConstants.java +++ b/bundles/org.openhab.binding.mystrom/src/main/java/org/openhab/binding/mystrom/internal/MyStromBindingConstants.java @@ -26,12 +26,14 @@ import org.openhab.core.thing.ThingTypeUID; public class MyStromBindingConstants { public static final int DEFAULT_REFRESH_RATE_SECONDS = 10; + public static final int DEFAULT_BACKOFF_TIME_SECONDS = 10; private static final String BINDING_ID = "mystrom"; // List of all Thing Type UIDs public static final ThingTypeUID THING_TYPE_PLUG = new ThingTypeUID(BINDING_ID, "mystromplug"); public static final ThingTypeUID THING_TYPE_BULB = new ThingTypeUID(BINDING_ID, "mystrombulb"); + public static final ThingTypeUID THING_TYPE_PIR = new ThingTypeUID(BINDING_ID, "mystrompir"); // List of all Channel ids public static final String CHANNEL_SWITCH = "switch"; @@ -42,6 +44,8 @@ public class MyStromBindingConstants { public static final String CHANNEL_MODE = "mode"; public static final String CHANNEL_COLOR_TEMPERATURE = "colorTemperature"; public static final String CHANNEL_BRIGHTNESS = "brightness"; + public static final String CHANNEL_MOTION = "motion"; + public static final String CHANNEL_LIGHT = "light"; // Config public static final String CONFIG_MAC = "mac"; diff --git a/bundles/org.openhab.binding.mystrom/src/main/java/org/openhab/binding/mystrom/internal/MyStromConfiguration.java b/bundles/org.openhab.binding.mystrom/src/main/java/org/openhab/binding/mystrom/internal/MyStromConfiguration.java index 3a7d7632c..19a15ce34 100644 --- a/bundles/org.openhab.binding.mystrom/src/main/java/org/openhab/binding/mystrom/internal/MyStromConfiguration.java +++ b/bundles/org.openhab.binding.mystrom/src/main/java/org/openhab/binding/mystrom/internal/MyStromConfiguration.java @@ -12,7 +12,7 @@ */ package org.openhab.binding.mystrom.internal; -import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.DEFAULT_REFRESH_RATE_SECONDS; +import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.*; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -20,16 +20,69 @@ import org.eclipse.jdt.annotation.NonNullByDefault; * The {@link MyStromConfiguration} class contains fields mapping thing configuration parameters. * * @author Paul Frank - Initial contribution + * @author Stefan Navratil - Added configuration for myStrom PIR */ @NonNullByDefault public class MyStromConfiguration { + private final String urlPrefix = "http://"; + + private String hostname = "localhost"; + + private String apiToken = ""; + + private int refresh = DEFAULT_REFRESH_RATE_SECONDS; + + private int backoffTime = DEFAULT_BACKOFF_TIME_SECONDS; + + private boolean ledEnable = true; + /** - * Hostname of the myStrom device. + * Returns the hostname with http prefix if missing. + * + * @return hostname */ - public String hostname = "localhost"; + public String getHostname() { + String prefix = ""; + if (!this.hostname.contains(urlPrefix)) { + prefix = urlPrefix; + } + return prefix + this.hostname; + } + /** - * Number of seconds in between refreshes from the myStrom device. + * returns API Token + * + * @return apiToken */ - public int refresh = DEFAULT_REFRESH_RATE_SECONDS; + public String getApiToken() { + return apiToken; + } + + /** + * Returns the refreshrate in SECONDS. + * + * @return refresh + */ + public int getRefresh() { + return refresh; + } + + /** + * Returns the Backoff time of the MotionSensor in SECONDS. + * + * @return backoff_time + */ + public int getBackoffTime() { + return backoffTime; + } + + /** + * Returns the Status LED Configuration. + * + * @return led_enable + */ + public boolean getLedEnable() { + return ledEnable; + } } diff --git a/bundles/org.openhab.binding.mystrom/src/main/java/org/openhab/binding/mystrom/internal/MyStromHandlerFactory.java b/bundles/org.openhab.binding.mystrom/src/main/java/org/openhab/binding/mystrom/internal/MyStromHandlerFactory.java index eb8955ffe..ce32a5713 100644 --- a/bundles/org.openhab.binding.mystrom/src/main/java/org/openhab/binding/mystrom/internal/MyStromHandlerFactory.java +++ b/bundles/org.openhab.binding.mystrom/src/main/java/org/openhab/binding/mystrom/internal/MyStromHandlerFactory.java @@ -12,8 +12,7 @@ */ package org.openhab.binding.mystrom.internal; -import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.THING_TYPE_BULB; -import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.THING_TYPE_PLUG; +import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.*; import java.util.Set; @@ -40,7 +39,8 @@ import org.osgi.service.component.annotations.Reference; @Component(configurationPid = "binding.mystrom", service = ThingHandlerFactory.class) public class MyStromHandlerFactory extends BaseThingHandlerFactory { - private static final Set SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_PLUG, THING_TYPE_BULB); + private static final Set SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_PLUG, THING_TYPE_BULB, + THING_TYPE_PIR); private final HttpClientFactory httpClientFactory; @@ -62,6 +62,8 @@ public class MyStromHandlerFactory extends BaseThingHandlerFactory { return new MyStromPlugHandler(thing, httpClientFactory.getCommonHttpClient()); } else if (THING_TYPE_BULB.equals(thingTypeUID)) { return new MyStromBulbHandler(thing, httpClientFactory.getCommonHttpClient()); + } else if (THING_TYPE_PIR.equals(thingTypeUID)) { + return new MyStromPIRHandler(thing, httpClientFactory.getCommonHttpClient()); } return null; diff --git a/bundles/org.openhab.binding.mystrom/src/main/java/org/openhab/binding/mystrom/internal/MyStromPIRHandler.java b/bundles/org.openhab.binding.mystrom/src/main/java/org/openhab/binding/mystrom/internal/MyStromPIRHandler.java new file mode 100644 index 000000000..16da560a4 --- /dev/null +++ b/bundles/org.openhab.binding.mystrom/src/main/java/org/openhab/binding/mystrom/internal/MyStromPIRHandler.java @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2010-2022 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.mystrom.internal; + +import static org.openhab.binding.mystrom.internal.MyStromBindingConstants.*; +import static org.openhab.core.library.unit.SIUnits.CELSIUS; +import static org.openhab.core.library.unit.Units.PERCENT; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.http.HttpMethod; +import org.openhab.core.library.types.OnOffType; +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.types.Command; + +import com.google.gson.JsonParseException; + +/** + * + * @author Stefan Navratil - Initial Contribution + * + */ + +@NonNullByDefault +public class MyStromPIRHandler extends AbstractMyStromHandler { + + private static class MyStromReport { + + public float light; + public boolean motion; + public float temperature; + } + + public MyStromPIRHandler(Thing thing, HttpClient httpClient) { + super(thing, httpClient); + try { + sendHttpRequest(HttpMethod.POST, "/api/v1/settings/pir", + "{\"backoff_time\":" + config.getBackoffTime() + ",\"led_enable\":" + config.getLedEnable() + "}"); + } catch (MyStromException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + } + + @Override + protected void pollDevice() { + MyStromReport report = getReport(); + if (report != null) { + updateState(CHANNEL_MOTION, OnOffType.from(report.motion)); + updateState(CHANNEL_TEMPERATURE, QuantityType.valueOf(report.temperature, CELSIUS)); + // The Default Light thresholds are from 30 to 300. + updateState(CHANNEL_LIGHT, QuantityType.valueOf(report.light / 3, PERCENT)); + } + } + + private @Nullable MyStromReport getReport() { + try { + String json = sendHttpRequest(HttpMethod.GET, "/api/v1/sensors", null); + MyStromReport report = gson.fromJson(json, MyStromReport.class); + updateStatus(ThingStatus.ONLINE); + return report; + } catch (MyStromException | JsonParseException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + return null; + } + } +} diff --git a/bundles/org.openhab.binding.mystrom/src/main/resources/OH-INF/i18n/mystrom.properties b/bundles/org.openhab.binding.mystrom/src/main/resources/OH-INF/i18n/mystrom.properties index 23f72e7cb..b5c44019d 100644 --- a/bundles/org.openhab.binding.mystrom/src/main/resources/OH-INF/i18n/mystrom.properties +++ b/bundles/org.openhab.binding.mystrom/src/main/resources/OH-INF/i18n/mystrom.properties @@ -7,17 +7,32 @@ binding.mystrom.description = This is the binding for myStrom devices. thing-type.mystrom.mystrombulb.label = myStrom Bulb thing-type.mystrom.mystrombulb.description = Controls the myStrom bulb +thing-type.mystrom.mystrompir.label = myStrom Motion Sensor thing-type.mystrom.mystromplug.label = myStrom Smart Plug thing-type.mystrom.mystromplug.description = Controls the myStrom smart plug # thing types config +thing-type.config.mystrom.mystrombulb.apiToken.label = API Token +thing-type.config.mystrom.mystrombulb.apiToken.description = Specifies the API token, if required (optional). thing-type.config.mystrom.mystrombulb.hostname.label = Hostname -thing-type.config.mystrom.mystrombulb.hostname.description = The host name or IP address of the myStrom bulb. +thing-type.config.mystrom.mystrombulb.hostname.description = The hostname or IP address of the myStrom bulb. thing-type.config.mystrom.mystrombulb.refresh.label = Refresh Interval thing-type.config.mystrom.mystrombulb.refresh.description = Specifies the refresh interval in seconds. +thing-type.config.mystrom.mystrompir.apiToken.label = API Token +thing-type.config.mystrom.mystrompir.apiToken.description = Specifies the API token, if required (optional). +thing-type.config.mystrom.mystrompir.backoffTime.label = Backoff Time +thing-type.config.mystrom.mystrompir.backoffTime.description = Specifies the minimum frequency between successive motion detections in seconds. +thing-type.config.mystrom.mystrompir.hostname.label = Hostname +thing-type.config.mystrom.mystrompir.hostname.description = The hostname or IP address of the myStrom sensor. +thing-type.config.mystrom.mystrompir.ledEnable.label = LED Enabled +thing-type.config.mystrom.mystrompir.ledEnable.description = Enables the status LED on the device. +thing-type.config.mystrom.mystrompir.refresh.label = Refresh Interval +thing-type.config.mystrom.mystrompir.refresh.description = Specifies the refresh interval in seconds. +thing-type.config.mystrom.mystromplug.apiToken.label = API Token +thing-type.config.mystrom.mystromplug.apiToken.description = Specifies the API token, if required (optional). thing-type.config.mystrom.mystromplug.hostname.label = Hostname -thing-type.config.mystrom.mystromplug.hostname.description = The host name or IP address of the myStrom plug. +thing-type.config.mystrom.mystromplug.hostname.description = The hostname or IP address of the myStrom plug. thing-type.config.mystrom.mystromplug.refresh.label = Refresh Interval thing-type.config.mystrom.mystromplug.refresh.description = Specifies the refresh interval in seconds. diff --git a/bundles/org.openhab.binding.mystrom/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.mystrom/src/main/resources/OH-INF/thing/thing-types.xml index b60710d94..92998051f 100644 --- a/bundles/org.openhab.binding.mystrom/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.mystrom/src/main/resources/OH-INF/thing/thing-types.xml @@ -32,7 +32,7 @@ - The host name or IP address of the myStrom plug. + The hostname or IP address of the myStrom plug. network-address localhost @@ -41,6 +41,10 @@ Specifies the refresh interval in seconds. 10 + + + Specifies the API token, if required (optional). + @@ -77,7 +81,7 @@ - The host name or IP address of the myStrom bulb. + The hostname or IP address of the myStrom bulb. network-address localhost @@ -86,10 +90,65 @@ Specifies the refresh interval in seconds. 10 + + + Specifies the API token, if required (optional). + + + + + + + + + + + + + + + + + + + + + + + mac + + + + + The hostname or IP address of the myStrom sensor. + network-address + localhost + + + + Specifies the refresh interval in seconds. + 10 + + + + Specifies the API token, if required (optional). + + + 10 + + Specifies the minimum frequency between successive motion detections in seconds. + + + true + + Enables the status LED on the device. + + + Number:Power