[deconz] add support for effects on color lights (#9238)

* add support for effects
* add tags
* remove unnecessary constants
* fix state update

Signed-off-by: Jan N. Klug <jan.n.klug@rub.de>
This commit is contained in:
J-N-K 2020-12-09 23:44:09 +01:00 committed by GitHub
parent 6fe75cb288
commit 27a8455cda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 243 additions and 25 deletions

View File

@ -160,7 +160,9 @@ Other devices support
| brightness | Dimmer | R/W | Brightness of the light | `dimmablelight`, `colortemperaturelight` | | brightness | Dimmer | R/W | Brightness of the light | `dimmablelight`, `colortemperaturelight` |
| switch | Switch | R/W | State of a ON/OFF device | `onofflight` | | 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 | 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` | | lock | Switch | R/W | Lock (ON) or unlock (OFF) the doorlock| `doorlock` |
| position | Rollershutter | R/W | Position of the blind | `windowcovering` | | position | Rollershutter | R/W | Position of the blind | `windowcovering` |
| heatsetpoint | Number:Temperature | R/W | Target Temperature in °C | `thermostat` | | 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. **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. Their state represents the last command send to the group, not necessarily the actual state of the group.
### Trigger Channels ### Trigger Channels
The dimmer switch additionally supports trigger channels. The dimmer switch additionally supports trigger channels.

View File

@ -15,6 +15,7 @@ package org.openhab.binding.deconz.internal;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.library.types.PercentType; import org.openhab.core.library.types.PercentType;
import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.type.ChannelTypeUID;
/** /**
* The {@link BindingConstants} class defines common constants, which are * 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_ALL_ON = "all_on";
public static final String CHANNEL_ANY_ON = "any_on"; public static final String CHANNEL_ANY_ON = "any_on";
public static final String CHANNEL_LOCK = "lock"; 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 // Thing configuration
public static final String CONFIG_HOST = "host"; public static final String CONFIG_HOST = "host";

View File

@ -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<ChannelUID, CommandDescription> 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;
}
}
}

View File

@ -55,14 +55,17 @@ public class DeconzHandlerFactory extends BaseThingHandlerFactory {
private final WebSocketFactory webSocketFactory; private final WebSocketFactory webSocketFactory;
private final HttpClientFactory httpClientFactory; private final HttpClientFactory httpClientFactory;
private final StateDescriptionProvider stateDescriptionProvider; private final StateDescriptionProvider stateDescriptionProvider;
private final CommandDescriptionProvider commandDescriptionProvider;
@Activate @Activate
public DeconzHandlerFactory(final @Reference WebSocketFactory webSocketFactory, public DeconzHandlerFactory(final @Reference WebSocketFactory webSocketFactory,
final @Reference HttpClientFactory httpClientFactory, final @Reference HttpClientFactory httpClientFactory,
final @Reference StateDescriptionProvider stateDescriptionProvider) { final @Reference StateDescriptionProvider stateDescriptionProvider,
final @Reference CommandDescriptionProvider commandDescriptionProvider) {
this.webSocketFactory = webSocketFactory; this.webSocketFactory = webSocketFactory;
this.httpClientFactory = httpClientFactory; this.httpClientFactory = httpClientFactory;
this.stateDescriptionProvider = stateDescriptionProvider; this.stateDescriptionProvider = stateDescriptionProvider;
this.commandDescriptionProvider = commandDescriptionProvider;
GsonBuilder gsonBuilder = new GsonBuilder(); GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(LightType.class, new LightTypeDeserializer()); gsonBuilder.registerTypeAdapter(LightType.class, new LightTypeDeserializer());
@ -85,7 +88,7 @@ public class DeconzHandlerFactory extends BaseThingHandlerFactory {
return new DeconzBridgeHandler((Bridge) thing, webSocketFactory, return new DeconzBridgeHandler((Bridge) thing, webSocketFactory,
new AsyncHttpClient(httpClientFactory.getCommonHttpClient()), gson); new AsyncHttpClient(httpClientFactory.getCommonHttpClient()), gson);
} else if (LightThingHandler.SUPPORTED_THING_TYPE_UIDS.contains(thingTypeUID)) { } 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)) { } else if (SensorThingHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
return new SensorThingHandler(thing, gson); return new SensorThingHandler(thing, gson);
} else if (SensorThermostatThingHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) { } else if (SensorThermostatThingHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {

View File

@ -35,6 +35,7 @@ public class LightState {
public @Nullable String alert; public @Nullable String alert;
public @Nullable String colormode; public @Nullable String colormode;
public @Nullable String effect; public @Nullable String effect;
public @Nullable Integer effectSpeed;
// depending on the type of light // depending on the type of light
public @Nullable Integer hue; public @Nullable Integer hue;
@ -66,6 +67,7 @@ public class LightState {
alert = null; alert = null;
colormode = null; colormode = null;
effect = null; effect = null;
effectSpeed = null;
hue = null; hue = null;
sat = null; sat = null;
@ -81,8 +83,9 @@ public class LightState {
@Override @Override
public String toString() { public String toString() {
return "LightState{reachable=" + reachable + ", on=" + on + ", bri=" + bri + ", alert='" + alert + '\'' return "LightState{" + "reachable=" + reachable + ", on=" + on + ", bri=" + bri + ", alert='" + alert + '\''
+ ", colormode='" + colormode + '\'' + ", effect='" + effect + '\'' + ", hue=" + hue + ", sat=" + sat + ", colormode='" + colormode + '\'' + ", effect='" + effect + '\'' + ", effectSpeed=" + effectSpeed
+ ", ct=" + ct + ", xy=" + Arrays.toString(xy) + ", transitiontime=" + transitiontime + '}'; + ", hue=" + hue + ", sat=" + sat + ", ct=" + ct + ", xy=" + Arrays.toString(xy) + ", transitiontime="
+ transitiontime + '}';
} }
} }

View File

@ -129,6 +129,12 @@ public abstract class DeconzBaseThingHandler<T extends DeconzBaseMessage> extend
} }
} }
/**
* 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); protected abstract @Nullable T parseStateResponse(AsyncHttpClient.Result r);
/** /**

View File

@ -126,7 +126,7 @@ public class DeconzBridgeHandler extends BaseBridgeHandler implements WebSocketC
private void parseAPIKeyResponse(AsyncHttpClient.Result r) { private void parseAPIKeyResponse(AsyncHttpClient.Result r) {
if (r.getResponseCode() == 403) { if (r.getResponseCode() == 403) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_PENDING, 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(); stopTimer();
scheduledFuture = scheduler.schedule(() -> requestApiKey(), POLL_FREQUENCY_SEC, TimeUnit.SECONDS); scheduledFuture = scheduler.schedule(() -> requestApiKey(), POLL_FREQUENCY_SEC, TimeUnit.SECONDS);
} else if (r.getResponseCode() == 200) { } else if (r.getResponseCode() == 200) {

View File

@ -16,12 +16,12 @@ import static org.openhab.binding.deconz.internal.BindingConstants.*;
import static org.openhab.binding.deconz.internal.Util.*; import static org.openhab.binding.deconz.internal.Util.*;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.HashMap; import java.util.*;
import java.util.Map; import java.util.stream.Collectors;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; 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.StateDescriptionProvider;
import org.openhab.binding.deconz.internal.Util; import org.openhab.binding.deconz.internal.Util;
import org.openhab.binding.deconz.internal.dto.DeconzBaseMessage; import org.openhab.binding.deconz.internal.dto.DeconzBaseMessage;
@ -35,11 +35,9 @@ import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.types.Command; import org.openhab.core.thing.binding.builder.ChannelBuilder;
import org.openhab.core.types.RefreshType; import org.openhab.core.thing.binding.builder.ThingBuilder;
import org.openhab.core.types.StateDescription; import org.openhab.core.types.*;
import org.openhab.core.types.StateDescriptionFragmentBuilder;
import org.openhab.core.types.UnDefType;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -71,6 +69,7 @@ public class LightThingHandler extends DeconzBaseThingHandler<LightMessage> {
private final Logger logger = LoggerFactory.getLogger(LightThingHandler.class); private final Logger logger = LoggerFactory.getLogger(LightThingHandler.class);
private final StateDescriptionProvider stateDescriptionProvider; private final StateDescriptionProvider stateDescriptionProvider;
private final CommandDescriptionProvider commandDescriptionProvider;
private long lastCommandExpireTimestamp = 0; private long lastCommandExpireTimestamp = 0;
private boolean needsPropertyUpdate = false; private boolean needsPropertyUpdate = false;
@ -85,9 +84,11 @@ public class LightThingHandler extends DeconzBaseThingHandler<LightMessage> {
private int ctMax = ZCL_CT_MAX; private int ctMax = ZCL_CT_MAX;
private int ctMin = ZCL_CT_MIN; 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); super(thing, gson, ResourceType.LIGHTS);
this.stateDescriptionProvider = stateDescriptionProvider; this.stateDescriptionProvider = stateDescriptionProvider;
this.commandDescriptionProvider = commandDescriptionProvider;
} }
@Override @Override
@ -136,6 +137,24 @@ public class LightThingHandler extends DeconzBaseThingHandler<LightMessage> {
} else { } else {
return; 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_SWITCH:
case CHANNEL_LOCK: case CHANNEL_LOCK:
if (command instanceof OnOffType) { if (command instanceof OnOffType) {
@ -161,7 +180,6 @@ public class LightThingHandler extends DeconzBaseThingHandler<LightMessage> {
} }
} else if (command instanceof HSBType) { } else if (command instanceof HSBType) {
HSBType hsbCommand = (HSBType) command; HSBType hsbCommand = (HSBType) command;
if ("xy".equals(lightStateCache.colormode)) { if ("xy".equals(lightStateCache.colormode)) {
PercentType[] xy = hsbCommand.toXY(); PercentType[] xy = hsbCommand.toXY();
if (xy.length < 2) { if (xy.length < 2) {
@ -249,7 +267,7 @@ public class LightThingHandler extends DeconzBaseThingHandler<LightMessage> {
if (r.getResponseCode() == 403) { if (r.getResponseCode() == 403) {
return null; return null;
} else if (r.getResponseCode() == 200) { } 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 (needsPropertyUpdate) {
// if we did not receive an ctmin/ctmax, then we probably don't need it // if we did not receive an ctmin/ctmax, then we probably don't need it
needsPropertyUpdate = false; needsPropertyUpdate = false;
@ -276,10 +294,72 @@ public class LightThingHandler extends DeconzBaseThingHandler<LightMessage> {
if (stateResponse == null) { if (stateResponse == null) {
return; return;
} }
if (stateResponse.state.effect != null) {
checkAndUpdateEffectChannels(stateResponse);
}
messageReceived(config.id, 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<String> 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<CommandOption> toCommandOptionList(List<String> options) {
return options.stream().map(c -> new CommandOption(c, c)).collect(Collectors.toList());
}
private void valueUpdated(String channelId, LightState newState) { private void valueUpdated(String channelId, LightState newState) {
Integer bri = newState.bri; Integer bri = newState.bri;
Integer hue = newState.hue; Integer hue = newState.hue;
@ -327,6 +407,19 @@ public class LightThingHandler extends DeconzBaseThingHandler<LightMessage> {
if (bri != null) { if (bri != null) {
updateState(channelId, toPercentType(bri)); 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: default:
} }
} }

View File

@ -177,6 +177,23 @@
<state pattern="%d K" min="15" max="100000" step="100"/> <state pattern="%d K" min="15" max="100000" step="100"/>
</channel-type> </channel-type>
<channel-type id="effect">
<item-type>String</item-type>
<label>Effect Channel</label>
<tags>
<tag>Lighting</tag>
</tags>
</channel-type>
<channel-type id="effectSpeed">
<item-type>Number</item-type>
<label>Effect Speed Channel</label>
<tags>
<tag>Lighting</tag>
</tags>
<state min="0" max="10" step="1"/>
</channel-type>
<channel-type id="alert"> <channel-type id="alert">
<item-type>Switch</item-type> <item-type>Switch</item-type>
<label>Alert</label> <label>Alert</label>

View File

@ -28,6 +28,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension; 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.StateDescriptionProvider;
import org.openhab.binding.deconz.internal.dto.LightMessage; import org.openhab.binding.deconz.internal.dto.LightMessage;
import org.openhab.binding.deconz.internal.handler.LightThingHandler; import org.openhab.binding.deconz.internal.handler.LightThingHandler;
@ -60,6 +61,7 @@ public class LightsTest {
private @Mock @NonNullByDefault({}) ThingHandlerCallback thingHandlerCallback; private @Mock @NonNullByDefault({}) ThingHandlerCallback thingHandlerCallback;
private @Mock @NonNullByDefault({}) StateDescriptionProvider stateDescriptionProvider; private @Mock @NonNullByDefault({}) StateDescriptionProvider stateDescriptionProvider;
private @Mock @NonNullByDefault({}) CommandDescriptionProvider commandDescriptionProvider;
@BeforeEach @BeforeEach
public void initialize() { public void initialize() {
@ -81,7 +83,8 @@ public class LightsTest {
Thing light = ThingBuilder.create(THING_TYPE_COLOR_TEMPERATURE_LIGHT, thingUID) Thing light = ThingBuilder.create(THING_TYPE_COLOR_TEMPERATURE_LIGHT, thingUID)
.withChannel(ChannelBuilder.create(channelUID_bri, "Dimmer").build()) .withChannel(ChannelBuilder.create(channelUID_bri, "Dimmer").build())
.withChannel(ChannelBuilder.create(channelUID_ct, "Number").build()).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.setCallback(thingHandlerCallback);
lightThingHandler.messageReceived("", lightMessage); lightThingHandler.messageReceived("", lightMessage);
@ -102,7 +105,8 @@ public class LightsTest {
Thing light = ThingBuilder.create(THING_TYPE_COLOR_TEMPERATURE_LIGHT, thingUID).withProperties(properties) Thing light = ThingBuilder.create(THING_TYPE_COLOR_TEMPERATURE_LIGHT, thingUID).withProperties(properties)
.withChannel(ChannelBuilder.create(channelUID_bri, "Dimmer").build()) .withChannel(ChannelBuilder.create(channelUID_bri, "Dimmer").build())
.withChannel(ChannelBuilder.create(channelUID_ct, "Number").build()).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 // avoid warning when initializing
@Override @Override
public @Nullable Bridge getBridge() { public @Nullable Bridge getBridge() {
@ -125,7 +129,8 @@ public class LightsTest {
Thing light = ThingBuilder.create(THING_TYPE_DIMMABLE_LIGHT, thingUID) Thing light = ThingBuilder.create(THING_TYPE_DIMMABLE_LIGHT, thingUID)
.withChannel(ChannelBuilder.create(channelUID_bri, "Dimmer").build()).build(); .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.setCallback(thingHandlerCallback);
lightThingHandler.messageReceived("", lightMessage); lightThingHandler.messageReceived("", lightMessage);
@ -142,7 +147,8 @@ public class LightsTest {
Thing light = ThingBuilder.create(THING_TYPE_DIMMABLE_LIGHT, thingUID) Thing light = ThingBuilder.create(THING_TYPE_DIMMABLE_LIGHT, thingUID)
.withChannel(ChannelBuilder.create(channelUID_bri, "Dimmer").build()).build(); .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.setCallback(thingHandlerCallback);
lightThingHandler.messageReceived("", lightMessage); lightThingHandler.messageReceived("", lightMessage);
@ -159,7 +165,8 @@ public class LightsTest {
Thing light = ThingBuilder.create(THING_TYPE_DIMMABLE_LIGHT, thingUID) Thing light = ThingBuilder.create(THING_TYPE_DIMMABLE_LIGHT, thingUID)
.withChannel(ChannelBuilder.create(channelUID_bri, "Dimmer").build()).build(); .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.setCallback(thingHandlerCallback);
lightThingHandler.messageReceived("", lightMessage); lightThingHandler.messageReceived("", lightMessage);
@ -176,7 +183,8 @@ public class LightsTest {
Thing light = ThingBuilder.create(THING_TYPE_WINDOW_COVERING, thingUID) Thing light = ThingBuilder.create(THING_TYPE_WINDOW_COVERING, thingUID)
.withChannel(ChannelBuilder.create(channelUID_pos, "Rollershutter").build()).build(); .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.setCallback(thingHandlerCallback);
lightThingHandler.messageReceived("", lightMessage); lightThingHandler.messageReceived("", lightMessage);