* Added API Token to configuration.
* Added motionsensor to myStrom binding.
* Added SPDX Header.
* fix: removed unnecessary updateStatus().
Signed-off-by: Stefan Navratil <stefan@navratil.ch>
# 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.
| --------- | ------- | -------- | ------------------ | -------------------------------------------------------------------------- |
| 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
| ---------------- | -------------------- | --------- | --------------------------------------------------------------------- |-------------------------------------|
| 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
*/
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;
@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);
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);
}
*/
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");
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());
}
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";
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";
*/
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;
* 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;
+
+ /**
+ * Returns the hostname with http prefix if missing.
+ *
+ * @return hostname
+ */
+ public String getHostname() {
+ String prefix = "";
+ if (!this.hostname.contains(urlPrefix)) {
+ prefix = urlPrefix;
+ }
+ return prefix + this.hostname;
+ }
+
+ /**
+ * returns API Token
+ *
+ * @return apiToken
+ */
+ public String getApiToken() {
+ return apiToken;
+ }
+
/**
- * Hostname of the myStrom device.
+ * Returns the refreshrate in SECONDS.
+ *
+ * @return refresh
*/
- public String hostname = "localhost";
+ public int getRefresh() {
+ return refresh;
+ }
+
+ /**
+ * Returns the Backoff time of the MotionSensor in SECONDS.
+ *
+ * @return backoff_time
+ */
+ public int getBackoffTime() {
+ return backoffTime;
+ }
+
/**
- * Number of seconds in between refreshes from the myStrom device.
+ * Returns the Status LED Configuration.
+ *
+ * @return led_enable
*/
- public int refresh = DEFAULT_REFRESH_RATE_SECONDS;
+ public boolean getLedEnable() {
+ return ledEnable;
+ }
}
*/
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;
@Component(configurationPid = "binding.mystrom", service = ThingHandlerFactory.class)
public class MyStromHandlerFactory extends BaseThingHandlerFactory {
- private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_PLUG, THING_TYPE_BULB);
+ private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_PLUG, THING_TYPE_BULB,
+ THING_TYPE_PIR);
private final HttpClientFactory httpClientFactory;
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;
--- /dev/null
+/**
+ * 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;
+ }
+ }
+}
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.
<config-description>
<parameter name="hostname" type="text">
<label>Hostname</label>
- <description>The host name or IP address of the myStrom plug.</description>
+ <description>The hostname or IP address of the myStrom plug.</description>
<context>network-address</context>
<default>localhost</default>
</parameter>
<description>Specifies the refresh interval in seconds.</description>
<default>10</default>
</parameter>
+ <parameter name="apiToken" type="text">
+ <label>API Token</label>
+ <description>Specifies the API token, if required (optional).</description>
+ </parameter>
</config-description>
</thing-type>
<config-description>
<parameter name="hostname" type="text" required="true">
<label>Hostname</label>
- <description>The host name or IP address of the myStrom bulb.</description>
+ <description>The hostname or IP address of the myStrom bulb.</description>
<context>network-address</context>
<default>localhost</default>
</parameter>
<description>Specifies the refresh interval in seconds.</description>
<default>10</default>
</parameter>
+ <parameter name="apiToken" type="text">
+ <label>API Token</label>
+ <description>Specifies the API token, if required (optional).</description>
+ </parameter>
</config-description>
</thing-type>
+ <thing-type id="mystrompir">
+
+ <label>myStrom Motion Sensor</label>
+ <channels>
+ <channel id="motion" typeId="system.motion"/>
+ <channel id="temperature" typeId="system.indoor-temperature"></channel>
+ <channel id="light" typeId="system.brightness"></channel>
+ </channels>
+ <properties>
+ <property name="mac"/>
+ <property name="version"/>
+ <property name="type"/>
+ <property name="ssid"/>
+ <property name="ip"/>
+ <property name="mask"/>
+ <property name="gw"/>
+ <property name="dns"/>
+ <property name="static"/>
+ <property name="connected"/>
+ </properties>
+
+ <representation-property>mac</representation-property>
+
+ <config-description>
+ <parameter name="hostname" type="text">
+ <label>Hostname</label>
+ <description>The hostname or IP address of the myStrom sensor.</description>
+ <context>network-address</context>
+ <default>localhost</default>
+ </parameter>
+ <parameter name="refresh" type="integer" unit="s" min="1">
+ <label>Refresh Interval</label>
+ <description>Specifies the refresh interval in seconds.</description>
+ <default>10</default>
+ </parameter>
+ <parameter name="apiToken" type="text">
+ <label>API Token</label>
+ <description>Specifies the API token, if required (optional).</description>
+ </parameter>
+ <parameter name="backoffTime" type="integer" unit="s" min="1">
+ <default>10</default>
+ <label>Backoff Time</label>
+ <description>Specifies the minimum frequency between successive motion detections in seconds.</description>
+ </parameter>
+ <parameter name="ledEnable" type="boolean">
+ <default>true</default>
+ <label>LED Enabled</label>
+ <description>Enables the status LED on the device.</description>
+ </parameter>
+ </config-description>
+ </thing-type>
<channel-type id="power-channel">
<item-type>Number:Power</item-type>