diff --git a/bundles/org.openhab.binding.tradfri/README.md b/bundles/org.openhab.binding.tradfri/README.md index af4c9fe0b3a9..87f7d76a6d43 100644 --- a/bundles/org.openhab.binding.tradfri/README.md +++ b/bundles/org.openhab.binding.tradfri/README.md @@ -22,18 +22,20 @@ These are: | Non-Colour Controller | 0x0820 | 0820 | | Non-Colour Scene Controller | 0x0830 | 0830 | | Control Outlet | 0x0010 | 0010 | +| Blind | 0x0999 | 0999 | The following matrix lists the capabilities (channels) for each of the supported lighting device types: -| Thing type | Brightness | Color | Color Temperature | Battery Level | Battery Low | Power | -|-------------|:----------:|:-----:|:-----------------:|:-------------:|:-----------:|:-----:| -| 0010 | | | | | | X | -| 0100 | X | | | | | | -| 0220 | X | | X | | | | -| 0210 | | X | X | | | | -| 0107 | | | | X | X | | -| 0820 | | | | X | X | | -| 0830 | | | | X | X | | +| Thing type | Brightness | Color | Color Temperature | Battery Level | Battery Low | Power | Position | +|-------------|:----------:|:-----:|:-----------------:|:-------------:|:-----------:|:-----:|:---------| +| 0010 | | | | | | X | | +| 0100 | X | | | | | | | +| 0220 | X | | X | | | | | +| 0210 | | X | X | | | | | +| 0107 | | | | X | X | | | +| 0820 | | | | X | X | | | +| 0830 | | | | X | X | | | +| 0999 | | | | X | X | | X | ## Thing Configuration @@ -60,14 +62,15 @@ The control outlet supports the `power` channel. Refer to the matrix above. -| Channel Type ID | Item Type | Description | -|-------------------|-----------|--------------------------------------------------| -| brightness | Dimmer | The brightness of the bulb in percent | -| color_temperature | Dimmer | color temperature from 0% = cold to 100% = warm | -| color | Color | full color | -| battery_level | Number | battery level (in %) | -| battery_low | Switch | battery low warning (<=10% = ON, >10% = OFF) | -| power | Switch | power switch | +| Channel Type ID | Item Type | Description | +|-------------------|---------------|--------------------------------------------------| +| brightness | Dimmer | The brightness of the bulb in percent | +| color_temperature | Dimmer | color temperature from 0% = cold to 100% = warm | +| color | Color | full color | +| battery_level | Number | battery level (in %) | +| battery_low | Switch | battery low warning (<=10% = ON, >10% = OFF) | +| power | Switch | power switch | +| position | Rollershutter | position of the blind in percent | ## Full Example diff --git a/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/TradfriBindingConstants.java b/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/TradfriBindingConstants.java index 44320be46472..4ad6b81951a5 100644 --- a/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/TradfriBindingConstants.java +++ b/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/TradfriBindingConstants.java @@ -25,6 +25,7 @@ * * @author Kai Kreuzer - Initial contribution * @author Christoph Weitkamp - Added support for remote controller and motion sensor devices (read-only battery level) + * @author Manuel Raffel - Added support for blinds */ public class TradfriBindingConstants { @@ -40,6 +41,7 @@ public class TradfriBindingConstants { public static final ThingTypeUID THING_TYPE_DIMMER = new ThingTypeUID(BINDING_ID, "0820"); public static final ThingTypeUID THING_TYPE_REMOTE_CONTROL = new ThingTypeUID(BINDING_ID, "0830"); public static final ThingTypeUID THING_TYPE_MOTION_SENSOR = new ThingTypeUID(BINDING_ID, "0107"); + public static final ThingTypeUID THING_TYPE_BLIND = new ThingTypeUID(BINDING_ID, "0999"); public static final Set SUPPORTED_LIGHT_TYPES_UIDS = Collections .unmodifiableSet(Stream.of(THING_TYPE_DIMMABLE_LIGHT, THING_TYPE_COLOR_TEMP_LIGHT, THING_TYPE_COLOR_LIGHT) @@ -48,6 +50,10 @@ public class TradfriBindingConstants { public static final Set SUPPORTED_PLUG_TYPES_UIDS = Collections .unmodifiableSet(Stream.of(THING_TYPE_ONOFF_PLUG).collect(Collectors.toSet())); + public static final Set SUPPORTED_BLIND_TYPES_UIDS = Collections + .unmodifiableSet(Stream.of(THING_TYPE_BLIND).collect(Collectors.toSet())); + + // List of all Gateway Configuration Properties public static final String GATEWAY_CONFIG_HOST = "host"; public static final String GATEWAY_CONFIG_PORT = "port"; @@ -64,12 +70,14 @@ public class TradfriBindingConstants { public static final String CHANNEL_BRIGHTNESS = "brightness"; public static final String CHANNEL_COLOR_TEMPERATURE = "color_temperature"; public static final String CHANNEL_COLOR = "color"; + public static final String CHANNEL_POSITION = "position"; public static final String CHANNEL_BATTERY_LEVEL = "battery_level"; public static final String CHANNEL_BATTERY_LOW = "battery_low"; // IPSO Objects public static final String DEVICES = "15001"; public static final String AUTH_PATH = "9063"; + public static final String BLIND = "15015"; public static final String CLIENT_IDENTITY_PROPOSED = "9090"; public static final String COLOR = "5706"; public static final String COLOR_X = "5709"; @@ -135,6 +143,7 @@ public class TradfriBindingConstants { public static final String OTA_UPDATE_STATE = "9054"; public static final String PLUG = "3312"; public static final String POWER_FACTOR = "5820"; + public static final String POSITION = "5536"; public static final String REACHABILITY_STATE = "9019"; public static final String REBOOT = "9030"; public static final String REPEAT_DAYS = "9041"; @@ -175,6 +184,7 @@ public class TradfriBindingConstants { public static final String TYPE_LIGHT = "2"; public static final String TYPE_PLUG = "3"; public static final String TYPE_SENSOR = "4"; + public static final String TYPE_BLIND = "7"; public static final String DEVICE_VENDOR = "0"; public static final String DEVICE_MODEL = "1"; public static final String DEVICE_FIRMWARE = "3"; diff --git a/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/TradfriHandlerFactory.java b/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/TradfriHandlerFactory.java index cec9b265aa9c..1821d8226646 100644 --- a/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/TradfriHandlerFactory.java +++ b/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/TradfriHandlerFactory.java @@ -35,6 +35,7 @@ import org.openhab.binding.tradfri.internal.handler.TradfriControllerHandler; import org.openhab.binding.tradfri.internal.handler.TradfriGatewayHandler; import org.openhab.binding.tradfri.internal.handler.TradfriLightHandler; +import org.openhab.binding.tradfri.internal.handler.TradfriBlindHandler; import org.openhab.binding.tradfri.internal.handler.TradfriPlugHandler; import org.openhab.binding.tradfri.internal.handler.TradfriSensorHandler; import org.osgi.framework.ServiceRegistration; @@ -45,6 +46,7 @@ * * @author Kai Kreuzer - Initial contribution * @author Christoph Weitkamp - Added support for remote controller and motion sensor devices (read-only battery level) + * @author Manuel Raffel - Added support for blinds */ @Component(service = ThingHandlerFactory.class, configurationPid = "binding.tradfri") @NonNullByDefault @@ -52,7 +54,7 @@ public class TradfriHandlerFactory extends BaseThingHandlerFactory { private static final Set SUPPORTED_THING_TYPES_UIDS = Stream .of(Stream.of(GATEWAY_TYPE_UID), SUPPORTED_LIGHT_TYPES_UIDS.stream(), - SUPPORTED_CONTROLLER_TYPES_UIDS.stream(), SUPPORTED_PLUG_TYPES_UIDS.stream()) + SUPPORTED_CONTROLLER_TYPES_UIDS.stream(), SUPPORTED_PLUG_TYPES_UIDS.stream(), SUPPORTED_BLIND_TYPES_UIDS.stream()) .reduce(Stream::concat).orElseGet(Stream::empty).collect(Collectors.toSet()); private final Map> discoveryServiceRegs = new HashMap<>(); @@ -74,6 +76,8 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { return new TradfriControllerHandler(thing); } else if (THING_TYPE_MOTION_SENSOR.equals(thingTypeUID)) { return new TradfriSensorHandler(thing); + } else if (THING_TYPE_BLIND.equals(thingTypeUID)) { + return new TradfriBlindHandler(thing); } else if (SUPPORTED_LIGHT_TYPES_UIDS.contains(thingTypeUID)) { return new TradfriLightHandler(thing); } else if (SUPPORTED_PLUG_TYPES_UIDS.contains(thingTypeUID)) { diff --git a/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/discovery/TradfriDiscoveryService.java b/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/discovery/TradfriDiscoveryService.java index cb1e613539e9..3e31c5a39287 100644 --- a/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/discovery/TradfriDiscoveryService.java +++ b/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/discovery/TradfriDiscoveryService.java @@ -43,6 +43,7 @@ * @author Kai Kreuzer - Initial contribution * @author Christoph Weitkamp - Added support for remote controller and motion sensor devices (read-only battery level) * @author Andre Fuechsel - fixed the results removal + * @author Manuel Raffel - Added support for blinds */ @NonNullByDefault public class TradfriDiscoveryService extends AbstractDiscoveryService implements DeviceUpdateListener { @@ -119,6 +120,9 @@ public void onUpdate(@Nullable String instanceId, @Nullable JsonObject data) { thingType = THING_TYPE_DIMMABLE_LIGHT; } thingId = new ThingUID(thingType, bridge, Integer.toString(id)); + } else if(TYPE_BLIND.equals(type) && data.has(BLIND)) { + ThingTypeUID thingType = THING_TYPE_BLIND; + thingId = new ThingUID(thingType, bridge, Integer.toString(id)); } else if (TYPE_PLUG.equals(type) && data.has(PLUG)) { // Smart plug ThingTypeUID thingType = THING_TYPE_ONOFF_PLUG; diff --git a/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/handler/TradfriBlindHandler.java b/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/handler/TradfriBlindHandler.java new file mode 100644 index 000000000000..7c9975bb03b1 --- /dev/null +++ b/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/handler/TradfriBlindHandler.java @@ -0,0 +1,133 @@ +/** + * Copyright (c) 2010-2019 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.tradfri.internal.handler; + +import static org.openhab.binding.tradfri.internal.TradfriBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.PercentType; +import org.eclipse.smarthome.core.library.types.StopMoveType; +import org.eclipse.smarthome.core.library.types.UpDownType; +import org.eclipse.smarthome.core.library.types.DecimalType; +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.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.tradfri.internal.model.TradfriBlindData; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonElement; + +/** + * The {@link TradfriBlindHandler} is responsible for handling commands for individual blinds. + * + * @author Manuel Raffel - Initial contribution + */ +@NonNullByDefault +public class TradfriBlindHandler extends TradfriThingHandler { + + private final Logger logger = LoggerFactory.getLogger(TradfriBlindHandler.class); + + // keeps track of the current state for handling of stop/move + private @Nullable TradfriBlindData state; + + public TradfriBlindHandler(Thing thing) { + super(thing); + } + + @Override + public void onUpdate(JsonElement data) { + if (active && !(data.isJsonNull())) { + TradfriBlindData state = new TradfriBlindData(data); + updateStatus(state.getReachabilityStatus() ? ThingStatus.ONLINE : ThingStatus.OFFLINE); + + PercentType position = state.getPosition(); + if (position != null) { + updateState(CHANNEL_POSITION, position); + } + + DecimalType batteryLevel = state.getBatteryLevel(); + if (batteryLevel != null) { + updateState(CHANNEL_BATTERY_LEVEL, batteryLevel); + } + + OnOffType batteryLow = state.getBatteryLow(); + if (batteryLow != null) { + updateState(CHANNEL_BATTERY_LOW, batteryLow); + } + + updateDeviceProperties(state); + + this.state = state; + + logger.debug( + "Updating thing for blindId {} to state {position: {}, firmwareVersion: {}, modelId: {}, vendor: {}}", + state.getDeviceId(), position, state.getFirmwareVersion(), state.getModelId(), + state.getVendor()); + } + } + + private void setPosition(PercentType percent) { + TradfriBlindData data = new TradfriBlindData(); + data.setPosition(percent); + set(data.getJsonString()); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (active) { + if (command instanceof RefreshType) { + logger.debug("Refreshing channel {}", channelUID); + coapClient.asyncGet(this); + return; + } + + switch (channelUID.getId()) { + case CHANNEL_POSITION: + handlePositionCommand(command); + break; + default: + logger.error("Unknown channel UID {}", channelUID); + } + } + } + + private void handlePositionCommand(Command command) { + if (command instanceof PercentType) { + setPosition((PercentType) command); + } else if (command instanceof StopMoveType) { + final TradfriBlindData state = this.state; + if (state != null && state.getPosition() != null) { + if(StopMoveType.STOP.equals(command)) { + // setPosition(state.getPosition()); + } else { + // (what) TODO (?) + } + } else { + logger.debug("Cannot handle stop/move as current state is not known."); + } + } else if (command instanceof UpDownType) { + if (UpDownType.UP.equals(command)) { + setPosition(PercentType.ZERO); + } else { + setPosition(PercentType.HUNDRED); + } + } else { + logger.debug("Cannot handle command {} for channel {}", command, CHANNEL_POSITION); + } + } +} diff --git a/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/model/TradfriBlindData.java b/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/model/TradfriBlindData.java new file mode 100644 index 000000000000..cfc1a6b82054 --- /dev/null +++ b/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/model/TradfriBlindData.java @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2010-2019 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.tradfri.internal.model; + +import static org.openhab.binding.tradfri.internal.TradfriBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.PercentType; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; + +/** + * The {@link TradfriBlindData} class is a Java wrapper for the raw JSON data about the blinds state. + * + * @author Manuel Raffel - Initial contribution + */ +@NonNullByDefault +public class TradfriBlindData extends TradfriWirelessDeviceData { + public TradfriBlindData() { + super(BLIND); + } + + public TradfriBlindData(JsonElement json) { + super(BLIND, json); + } + + public TradfriBlindData setPosition(PercentType position) { + attributes.add(POSITION, new JsonPrimitive(position.intValue())); + return this; + } + + public @Nullable PercentType getPosition() { + PercentType result = null; + + JsonElement position = attributes.get(POSITION); + if (position != null) { + result = new PercentType(position.getAsInt()); + } + + return result; + } + + public String getJsonString() { + return root.toString(); + } +} diff --git a/bundles/org.openhab.binding.tradfri/src/main/resources/ESH-INF/i18n/tradfri_de.properties b/bundles/org.openhab.binding.tradfri/src/main/resources/ESH-INF/i18n/tradfri_de.properties index 8ca916433634..574fdc4b0720 100644 --- a/bundles/org.openhab.binding.tradfri/src/main/resources/ESH-INF/i18n/tradfri_de.properties +++ b/bundles/org.openhab.binding.tradfri/src/main/resources/ESH-INF/i18n/tradfri_de.properties @@ -27,6 +27,8 @@ thing-type.tradfri.0820.label = Kabelloser Dimmer thing-type.tradfri.0820.description = Der Kabellose Dimmer liefert Daten wie z.B. die Batterieladung. thing-type.tradfri.0830.label = Fernbedienung thing-type.tradfri.0830.description = Die Fernbedienung liefert Daten wie z.B. die Batterieladung. +thing-type.tradfri.0999.label = Rollo +thing-type.tradfri.0999.description = Akkubetriebene Rollo mit einstellbarer Position. Liefert außerdem Daten wie z.B. die Akkuladung. # thing types config thing-type.config.tradfri.device.id.label = ID des Gerätes @@ -39,3 +41,5 @@ channel-type.tradfri.color_temperature.label = Farbtemperatur channel-type.tradfri.color_temperature.description = Ermöglicht die Steuerung der Farbtemperatur. Von Tageslichtweiß (0) bis Warmweiß (100). channel-type.tradfri.color.label = Farbe channel-type.tradfri.color.description = Ermöglicht die Steuerung der Farbe. +channel-type.tradfri.position.label = Position +channel-type.tradfri.position.description = Ermöglicht die Steuerung der Position von Offen (0) bis Geschlossen (100). diff --git a/bundles/org.openhab.binding.tradfri/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.tradfri/src/main/resources/ESH-INF/thing/thing-types.xml index f3676a93cd56..6f0164c72a48 100644 --- a/bundles/org.openhab.binding.tradfri/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.tradfri/src/main/resources/ESH-INF/thing/thing-types.xml @@ -137,6 +137,25 @@ + + + + + + + A blind that can be moved up and down. Also reports current battery level. + + + + + + + + id + + + + Dimmer @@ -147,6 +166,16 @@ + + Rollershutter + + Control the position of the blind in percent from 0 (open) to 100 (closed). + Rollershutter + + WindowCovering + + + Dimmer