diff --git a/bundles/org.openhab.binding.deconz/README.md b/bundles/org.openhab.binding.deconz/README.md index 01dbdfed0af46..6e2aa40bfd34b 100644 --- a/bundles/org.openhab.binding.deconz/README.md +++ b/bundles/org.openhab.binding.deconz/README.md @@ -160,7 +160,9 @@ Other devices support | brightness | Dimmer | R/W | Brightness of the light | `dimmablelight`, `colortemperaturelight` | | switch | Switch | R/W | State of a ON/OFF device | `onofflight` | | color | Color | R/W | Color of an multi-color light | `colorlight`, `extendedcolorlight`, `lightgroup`| -| color_temperature | Number | R/W | Color temperature in kelvin. The value range is determined by each individual light | `colortemperaturelight`, `extendedcolorlight`, `lightgroup` | +| color_temperature | Number | R/W | Color temperature in Kelvin. The value range is determined by each individual light | `colortemperaturelight`, `extendedcolorlight`, `lightgroup` | +| effect | String | R/W | Effect selection. Allowed commands are set dynamically | `colorlight` | +| effectSpeed | Number | R/W | Effect Speed | `colorlight` | | lock | Switch | R/W | Lock (ON) or unlock (OFF) the doorlock| `doorlock` | | position | Rollershutter | R/W | Position of the blind | `windowcovering` | | heatsetpoint | Number:Temperature | R/W | Target Temperature in °C | `thermostat` | @@ -174,6 +176,7 @@ Other devices support **NOTE:** For groups `color` and `color_temperature` are used for sending commands to the group. Their state represents the last command send to the group, not necessarily the actual state of the group. + ### Trigger Channels The dimmer switch additionally supports trigger channels. diff --git a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/BindingConstants.java b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/BindingConstants.java index 4dfc4f8ab0ff7..6c72389653581 100644 --- a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/BindingConstants.java +++ b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/BindingConstants.java @@ -15,6 +15,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.library.types.PercentType; import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.type.ChannelTypeUID; /** * The {@link BindingConstants} class defines common constants, which are @@ -112,6 +113,13 @@ public class BindingConstants { public static final String CHANNEL_ALL_ON = "all_on"; public static final String CHANNEL_ANY_ON = "any_on"; public static final String CHANNEL_LOCK = "lock"; + public static final String CHANNEL_EFFECT = "effect"; + public static final String CHANNEL_EFFECT_SPEED = "effectSpeed"; + + // channel uids + public static final ChannelTypeUID CHANNEL_EFFECT_TYPE_UID = new ChannelTypeUID(BINDING_ID, CHANNEL_EFFECT); + public static final ChannelTypeUID CHANNEL_EFFECT_SPEED_TYPE_UID = new ChannelTypeUID(BINDING_ID, + CHANNEL_EFFECT_SPEED); // Thing configuration public static final String CONFIG_HOST = "host"; diff --git a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/CommandDescriptionProvider.java b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/CommandDescriptionProvider.java new file mode 100644 index 0000000000000..1f808ac21897b --- /dev/null +++ b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/CommandDescriptionProvider.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.deconz.internal; + +import java.util.Locale; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.thing.Channel; +import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.ThingUID; +import org.openhab.core.thing.type.DynamicCommandDescriptionProvider; +import org.openhab.core.types.CommandDescription; +import org.osgi.service.component.annotations.Component; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Dynamic channel command description provider. + * Overrides the command description for the controls, which receive its configuration in the runtime. + * + * @author Jan N. Klug - Initial contribution + */ +@NonNullByDefault +@Component(service = { DynamicCommandDescriptionProvider.class, CommandDescriptionProvider.class }) +public class CommandDescriptionProvider implements DynamicCommandDescriptionProvider { + + private final Map descriptions = new ConcurrentHashMap<>(); + private final Logger logger = LoggerFactory.getLogger(CommandDescriptionProvider.class); + + /** + * Set a command description for a channel. This description will be used when preparing the channel command by + * the framework for presentation. A previous description, if existed, will be replaced. + * + * @param channelUID + * channel UID + * @param description + * state description for the channel + */ + public void setDescription(ChannelUID channelUID, CommandDescription description) { + logger.trace("adding command description for channel {}", channelUID); + descriptions.put(channelUID, description); + } + + /** + * remove all descriptions for a given thing + * + * @param thingUID the thing's UID + */ + public void removeDescriptionsForThing(ThingUID thingUID) { + logger.trace("removing state description for thing {}", thingUID); + descriptions.entrySet().removeIf(entry -> entry.getKey().getThingUID().equals(thingUID)); + } + + @Override + public @Nullable CommandDescription getCommandDescription(Channel channel, + @Nullable CommandDescription originalStateDescription, @Nullable Locale locale) { + if (descriptions.containsKey(channel.getUID())) { + logger.trace("returning new stateDescription for {}", channel.getUID()); + return descriptions.get(channel.getUID()); + } else { + return null; + } + } +} diff --git a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/DeconzHandlerFactory.java b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/DeconzHandlerFactory.java index 273e1b6389b3f..8e005d3adbfa4 100644 --- a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/DeconzHandlerFactory.java +++ b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/DeconzHandlerFactory.java @@ -55,14 +55,17 @@ public class DeconzHandlerFactory extends BaseThingHandlerFactory { private final WebSocketFactory webSocketFactory; private final HttpClientFactory httpClientFactory; private final StateDescriptionProvider stateDescriptionProvider; + private final CommandDescriptionProvider commandDescriptionProvider; @Activate public DeconzHandlerFactory(final @Reference WebSocketFactory webSocketFactory, final @Reference HttpClientFactory httpClientFactory, - final @Reference StateDescriptionProvider stateDescriptionProvider) { + final @Reference StateDescriptionProvider stateDescriptionProvider, + final @Reference CommandDescriptionProvider commandDescriptionProvider) { this.webSocketFactory = webSocketFactory; this.httpClientFactory = httpClientFactory; this.stateDescriptionProvider = stateDescriptionProvider; + this.commandDescriptionProvider = commandDescriptionProvider; GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(LightType.class, new LightTypeDeserializer()); @@ -85,7 +88,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { return new DeconzBridgeHandler((Bridge) thing, webSocketFactory, new AsyncHttpClient(httpClientFactory.getCommonHttpClient()), gson); } else if (LightThingHandler.SUPPORTED_THING_TYPE_UIDS.contains(thingTypeUID)) { - return new LightThingHandler(thing, gson, stateDescriptionProvider); + return new LightThingHandler(thing, gson, stateDescriptionProvider, commandDescriptionProvider); } else if (SensorThingHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) { return new SensorThingHandler(thing, gson); } else if (SensorThermostatThingHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) { diff --git a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/dto/LightState.java b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/dto/LightState.java index 2ac7ae6209a95..653a9b85fb0e2 100644 --- a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/dto/LightState.java +++ b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/dto/LightState.java @@ -35,6 +35,7 @@ public class LightState { public @Nullable String alert; public @Nullable String colormode; public @Nullable String effect; + public @Nullable Integer effectSpeed; // depending on the type of light public @Nullable Integer hue; @@ -66,6 +67,7 @@ public void clear() { alert = null; colormode = null; effect = null; + effectSpeed = null; hue = null; sat = null; @@ -81,8 +83,9 @@ private boolean equalsIgnoreNull(T o1, T o2) { @Override public String toString() { - return "LightState{reachable=" + reachable + ", on=" + on + ", bri=" + bri + ", alert='" + alert + '\'' - + ", colormode='" + colormode + '\'' + ", effect='" + effect + '\'' + ", hue=" + hue + ", sat=" + sat - + ", ct=" + ct + ", xy=" + Arrays.toString(xy) + ", transitiontime=" + transitiontime + '}'; + return "LightState{" + "reachable=" + reachable + ", on=" + on + ", bri=" + bri + ", alert='" + alert + '\'' + + ", colormode='" + colormode + '\'' + ", effect='" + effect + '\'' + ", effectSpeed=" + effectSpeed + + ", hue=" + hue + ", sat=" + sat + ", ct=" + ct + ", xy=" + Arrays.toString(xy) + ", transitiontime=" + + transitiontime + '}'; } } diff --git a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/DeconzBaseThingHandler.java b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/DeconzBaseThingHandler.java index 6e310ea8d372f..2a3ae3e34c910 100644 --- a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/DeconzBaseThingHandler.java +++ b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/DeconzBaseThingHandler.java @@ -129,6 +129,12 @@ public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { } } + /** + * parse the initial state response message + * + * @param r AsyncHttpClient.Result with the state response result + * @return a message of the correct type + */ protected abstract @Nullable T parseStateResponse(AsyncHttpClient.Result r); /** diff --git a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/DeconzBridgeHandler.java b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/DeconzBridgeHandler.java index 7955e11fed33f..60573e8382786 100644 --- a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/DeconzBridgeHandler.java +++ b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/DeconzBridgeHandler.java @@ -126,7 +126,7 @@ private void stopTimer() { private void parseAPIKeyResponse(AsyncHttpClient.Result r) { if (r.getResponseCode() == 403) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_PENDING, - "Allow authentification for 3rd party apps. Trying again in " + POLL_FREQUENCY_SEC + " seconds"); + "Allow authentication for 3rd party apps. Trying again in " + POLL_FREQUENCY_SEC + " seconds"); stopTimer(); scheduledFuture = scheduler.schedule(() -> requestApiKey(), POLL_FREQUENCY_SEC, TimeUnit.SECONDS); } else if (r.getResponseCode() == 200) { diff --git a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/LightThingHandler.java b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/LightThingHandler.java index 269a98ccaa42e..19ad0f71ba486 100644 --- a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/LightThingHandler.java +++ b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/LightThingHandler.java @@ -16,12 +16,12 @@ import static org.openhab.binding.deconz.internal.Util.*; import java.math.BigDecimal; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; +import java.util.*; +import java.util.stream.Collectors; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.deconz.internal.CommandDescriptionProvider; import org.openhab.binding.deconz.internal.StateDescriptionProvider; import org.openhab.binding.deconz.internal.Util; import org.openhab.binding.deconz.internal.dto.DeconzBaseMessage; @@ -35,11 +35,9 @@ import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.ThingTypeUID; -import org.openhab.core.types.Command; -import org.openhab.core.types.RefreshType; -import org.openhab.core.types.StateDescription; -import org.openhab.core.types.StateDescriptionFragmentBuilder; -import org.openhab.core.types.UnDefType; +import org.openhab.core.thing.binding.builder.ChannelBuilder; +import org.openhab.core.thing.binding.builder.ThingBuilder; +import org.openhab.core.types.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -71,6 +69,7 @@ public class LightThingHandler extends DeconzBaseThingHandler { private final Logger logger = LoggerFactory.getLogger(LightThingHandler.class); private final StateDescriptionProvider stateDescriptionProvider; + private final CommandDescriptionProvider commandDescriptionProvider; private long lastCommandExpireTimestamp = 0; private boolean needsPropertyUpdate = false; @@ -85,9 +84,11 @@ public class LightThingHandler extends DeconzBaseThingHandler { private int ctMax = ZCL_CT_MAX; private int ctMin = ZCL_CT_MIN; - public LightThingHandler(Thing thing, Gson gson, StateDescriptionProvider stateDescriptionProvider) { + public LightThingHandler(Thing thing, Gson gson, StateDescriptionProvider stateDescriptionProvider, + CommandDescriptionProvider commandDescriptionProvider) { super(thing, gson, ResourceType.LIGHTS); this.stateDescriptionProvider = stateDescriptionProvider; + this.commandDescriptionProvider = commandDescriptionProvider; } @Override @@ -136,6 +137,24 @@ public void handleCommand(ChannelUID channelUID, Command command) { } else { return; } + break; + case CHANNEL_EFFECT: + if (command instanceof StringType) { + // effect command only allowed for lights that are turned on + newLightState.on = true; + newLightState.effect = command.toString(); + } else { + return; + } + break; + case CHANNEL_EFFECT_SPEED: + if (command instanceof DecimalType) { + newLightState.on = true; + newLightState.effectSpeed = Util.constrainToRange(((DecimalType) command).intValue(), 0, 10); + } else { + return; + } + break; case CHANNEL_SWITCH: case CHANNEL_LOCK: if (command instanceof OnOffType) { @@ -161,7 +180,6 @@ public void handleCommand(ChannelUID channelUID, Command command) { } } else if (command instanceof HSBType) { HSBType hsbCommand = (HSBType) command; - if ("xy".equals(lightStateCache.colormode)) { PercentType[] xy = hsbCommand.toXY(); if (xy.length < 2) { @@ -249,7 +267,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { if (r.getResponseCode() == 403) { return null; } else if (r.getResponseCode() == 200) { - LightMessage lightMessage = gson.fromJson(r.getBody(), LightMessage.class); + LightMessage lightMessage = Objects.requireNonNull(gson.fromJson(r.getBody(), LightMessage.class)); if (needsPropertyUpdate) { // if we did not receive an ctmin/ctmax, then we probably don't need it needsPropertyUpdate = false; @@ -276,10 +294,72 @@ protected void processStateResponse(@Nullable LightMessage stateResponse) { if (stateResponse == null) { return; } - + if (stateResponse.state.effect != null) { + checkAndUpdateEffectChannels(stateResponse); + } messageReceived(config.id, stateResponse); } + private enum EffectLightModel { + LIDL_MELINARA, + TINT_MUELLER, + UNKNOWN; + } + + private void checkAndUpdateEffectChannels(LightMessage lightMessage) { + EffectLightModel model = EffectLightModel.UNKNOWN; + // try to determine which model we have + if (lightMessage.manufacturername.equals("_TZE200_s8gkrkxk")) { + // the LIDL Melinara string does not report a proper model name + model = EffectLightModel.LIDL_MELINARA; + } else if (lightMessage.manufacturername.equals("MLI")) { + model = EffectLightModel.TINT_MUELLER; + } else { + logger.info("Could not determine effect light type for thing {}, please request adding support on GitHub.", + thing.getUID()); + } + + ChannelUID effectChannelUID = new ChannelUID(thing.getUID(), CHANNEL_EFFECT); + ChannelUID effectSpeedChannelUID = new ChannelUID(thing.getUID(), CHANNEL_EFFECT_SPEED); + + if (thing.getChannel(CHANNEL_EFFECT) == null) { + ThingBuilder thingBuilder = editThing(); + thingBuilder.withChannel( + ChannelBuilder.create(effectChannelUID, "String").withType(CHANNEL_EFFECT_TYPE_UID).build()); + if (model == EffectLightModel.LIDL_MELINARA) { + // additional channels + thingBuilder.withChannel(ChannelBuilder.create(effectSpeedChannelUID, "Number") + .withType(CHANNEL_EFFECT_SPEED_TYPE_UID).build()); + } + updateThing(thingBuilder.build()); + } + + switch (model) { + case LIDL_MELINARA: + List options = List.of("none", "steady", "snow", "rainbow", "snake", "tinkle", "fireworks", + "flag", "waves", "updown", "vintage", "fading", "collide", "strobe", "sparkles", "carnival", + "glow"); + commandDescriptionProvider.setDescription(effectChannelUID, + CommandDescriptionBuilder.create().withCommandOptions(toCommandOptionList(options)).build()); + break; + case TINT_MUELLER: + options = List.of("none", "colorloop", "sunset", "party", "worklight", "campfire", "romance", + "nightlight"); + commandDescriptionProvider.setDescription(effectChannelUID, + CommandDescriptionBuilder.create().withCommandOptions(toCommandOptionList(options)).build()); + break; + default: + options = List.of("none", "colorloop"); + commandDescriptionProvider.setDescription(effectChannelUID, + CommandDescriptionBuilder.create().withCommandOptions(toCommandOptionList(options)).build()); + + } + } + + private List toCommandOptionList(List options) { + return options.stream().map(c -> new CommandOption(c, c)).collect(Collectors.toList()); + } + private void valueUpdated(String channelId, LightState newState) { Integer bri = newState.bri; Integer hue = newState.hue; @@ -327,6 +407,19 @@ private void valueUpdated(String channelId, LightState newState) { if (bri != null) { updateState(channelId, toPercentType(bri)); } + break; + case CHANNEL_EFFECT: + String effect = newState.effect; + if (effect != null) { + updateState(channelId, new StringType(effect)); + } + break; + case CHANNEL_EFFECT_SPEED: + Integer effectSpeed = newState.effectSpeed; + if (effectSpeed != null) { + updateState(channelId, new DecimalType(effectSpeed)); + } + break; default: } } diff --git a/bundles/org.openhab.binding.deconz/src/main/resources/OH-INF/thing/light-thing-types.xml b/bundles/org.openhab.binding.deconz/src/main/resources/OH-INF/thing/light-thing-types.xml index 745c2f108273b..7de5c8aca410e 100644 --- a/bundles/org.openhab.binding.deconz/src/main/resources/OH-INF/thing/light-thing-types.xml +++ b/bundles/org.openhab.binding.deconz/src/main/resources/OH-INF/thing/light-thing-types.xml @@ -177,6 +177,23 @@ + + String + + + Lighting + + + + + Number + + + Lighting + + + + Switch diff --git a/bundles/org.openhab.binding.deconz/src/test/java/org/openhab/binding/deconz/LightsTest.java b/bundles/org.openhab.binding.deconz/src/test/java/org/openhab/binding/deconz/LightsTest.java index 85df1150b4c95..d45686d8d9f68 100644 --- a/bundles/org.openhab.binding.deconz/src/test/java/org/openhab/binding/deconz/LightsTest.java +++ b/bundles/org.openhab.binding.deconz/src/test/java/org/openhab/binding/deconz/LightsTest.java @@ -28,6 +28,7 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; +import org.openhab.binding.deconz.internal.CommandDescriptionProvider; import org.openhab.binding.deconz.internal.StateDescriptionProvider; import org.openhab.binding.deconz.internal.dto.LightMessage; import org.openhab.binding.deconz.internal.handler.LightThingHandler; @@ -60,6 +61,7 @@ public class LightsTest { private @Mock @NonNullByDefault({}) ThingHandlerCallback thingHandlerCallback; private @Mock @NonNullByDefault({}) StateDescriptionProvider stateDescriptionProvider; + private @Mock @NonNullByDefault({}) CommandDescriptionProvider commandDescriptionProvider; @BeforeEach public void initialize() { @@ -81,7 +83,8 @@ public void colorTemperatureLightUpdateTest() throws IOException { Thing light = ThingBuilder.create(THING_TYPE_COLOR_TEMPERATURE_LIGHT, thingUID) .withChannel(ChannelBuilder.create(channelUID_bri, "Dimmer").build()) .withChannel(ChannelBuilder.create(channelUID_ct, "Number").build()).build(); - LightThingHandler lightThingHandler = new LightThingHandler(light, gson, stateDescriptionProvider); + LightThingHandler lightThingHandler = new LightThingHandler(light, gson, stateDescriptionProvider, + commandDescriptionProvider); lightThingHandler.setCallback(thingHandlerCallback); lightThingHandler.messageReceived("", lightMessage); @@ -102,7 +105,8 @@ public void colorTemperatureLightStateDescriptionProviderTest() { Thing light = ThingBuilder.create(THING_TYPE_COLOR_TEMPERATURE_LIGHT, thingUID).withProperties(properties) .withChannel(ChannelBuilder.create(channelUID_bri, "Dimmer").build()) .withChannel(ChannelBuilder.create(channelUID_ct, "Number").build()).build(); - LightThingHandler lightThingHandler = new LightThingHandler(light, gson, stateDescriptionProvider) { + LightThingHandler lightThingHandler = new LightThingHandler(light, gson, stateDescriptionProvider, + commandDescriptionProvider) { // avoid warning when initializing @Override public @Nullable Bridge getBridge() { @@ -125,7 +129,8 @@ public void dimmableLightUpdateTest() throws IOException { Thing light = ThingBuilder.create(THING_TYPE_DIMMABLE_LIGHT, thingUID) .withChannel(ChannelBuilder.create(channelUID_bri, "Dimmer").build()).build(); - LightThingHandler lightThingHandler = new LightThingHandler(light, gson, stateDescriptionProvider); + LightThingHandler lightThingHandler = new LightThingHandler(light, gson, stateDescriptionProvider, + commandDescriptionProvider); lightThingHandler.setCallback(thingHandlerCallback); lightThingHandler.messageReceived("", lightMessage); @@ -142,7 +147,8 @@ public void dimmableLightOverrangeUpdateTest() throws IOException { Thing light = ThingBuilder.create(THING_TYPE_DIMMABLE_LIGHT, thingUID) .withChannel(ChannelBuilder.create(channelUID_bri, "Dimmer").build()).build(); - LightThingHandler lightThingHandler = new LightThingHandler(light, gson, stateDescriptionProvider); + LightThingHandler lightThingHandler = new LightThingHandler(light, gson, stateDescriptionProvider, + commandDescriptionProvider); lightThingHandler.setCallback(thingHandlerCallback); lightThingHandler.messageReceived("", lightMessage); @@ -159,7 +165,8 @@ public void dimmableLightUnderrangeUpdateTest() throws IOException { Thing light = ThingBuilder.create(THING_TYPE_DIMMABLE_LIGHT, thingUID) .withChannel(ChannelBuilder.create(channelUID_bri, "Dimmer").build()).build(); - LightThingHandler lightThingHandler = new LightThingHandler(light, gson, stateDescriptionProvider); + LightThingHandler lightThingHandler = new LightThingHandler(light, gson, stateDescriptionProvider, + commandDescriptionProvider); lightThingHandler.setCallback(thingHandlerCallback); lightThingHandler.messageReceived("", lightMessage); @@ -176,7 +183,8 @@ public void windowCoveringUpdateTest() throws IOException { Thing light = ThingBuilder.create(THING_TYPE_WINDOW_COVERING, thingUID) .withChannel(ChannelBuilder.create(channelUID_pos, "Rollershutter").build()).build(); - LightThingHandler lightThingHandler = new LightThingHandler(light, gson, stateDescriptionProvider); + LightThingHandler lightThingHandler = new LightThingHandler(light, gson, stateDescriptionProvider, + commandDescriptionProvider); lightThingHandler.setCallback(thingHandlerCallback); lightThingHandler.messageReceived("", lightMessage);