* Added service references to DynamicStateDescriptionProvider to support publishing ChannelDescriptionChangedEvent
Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
import org.openhab.binding.hue.internal.handler.HueBridgeHandler;
import org.openhab.binding.hue.internal.handler.HueGroupHandler;
import org.openhab.binding.hue.internal.handler.HueLightHandler;
-import org.openhab.binding.hue.internal.handler.HueStateDescriptionOptionProvider;
+import org.openhab.binding.hue.internal.handler.HueStateDescriptionProvider;
import org.openhab.binding.hue.internal.handler.sensors.ClipHandler;
import org.openhab.binding.hue.internal.handler.sensors.DimmerSwitchHandler;
import org.openhab.binding.hue.internal.handler.sensors.GeofencePresenceHandler;
ClipHandler.SUPPORTED_THING_TYPES.stream(), HueGroupHandler.SUPPORTED_THING_TYPES.stream())
.flatMap(i -> i).collect(Collectors.toSet()));
- private final HueStateDescriptionOptionProvider stateOptionProvider;
+ private final HueStateDescriptionProvider stateDescriptionProvider;
@Activate
- public HueThingHandlerFactory(final @Reference HueStateDescriptionOptionProvider stateOptionProvider) {
- this.stateOptionProvider = stateOptionProvider;
+ public HueThingHandlerFactory(final @Reference HueStateDescriptionProvider stateDescriptionProvider) {
+ this.stateDescriptionProvider = stateDescriptionProvider;
}
@Override
@Override
protected @Nullable ThingHandler createHandler(Thing thing) {
if (HueBridgeHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
- return new HueBridgeHandler((Bridge) thing, stateOptionProvider);
+ return new HueBridgeHandler((Bridge) thing, stateDescriptionProvider);
} else if (HueLightHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
- return new HueLightHandler(thing, stateOptionProvider);
+ return new HueLightHandler(thing, stateDescriptionProvider);
} else if (DimmerSwitchHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
return new DimmerSwitchHandler(thing);
} else if (TapSwitchHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
} else if (ClipHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
return new ClipHandler(thing);
} else if (HueGroupHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
- return new HueGroupHandler(thing, stateOptionProvider);
+ return new HueGroupHandler(thing, stateDescriptionProvider);
} else {
return null;
}
private static final long SCENE_POLLING_INTERVAL = TimeUnit.SECONDS.convert(10, TimeUnit.MINUTES);
private final Logger logger = LoggerFactory.getLogger(HueBridgeHandler.class);
- private final HueStateDescriptionOptionProvider stateDescriptionOptionProvider;
+ private final HueStateDescriptionProvider stateDescriptionOptionProvider;
private final Map<String, FullLight> lastLightStates = new ConcurrentHashMap<>();
private final Map<String, FullSensor> lastSensorStates = new ConcurrentHashMap<>();
private List<String> consoleScenesList = new ArrayList<>();
- public HueBridgeHandler(Bridge bridge, HueStateDescriptionOptionProvider stateDescriptionOptionProvider) {
+ public HueBridgeHandler(Bridge bridge, HueStateDescriptionProvider stateDescriptionOptionProvider) {
super(bridge);
this.stateDescriptionOptionProvider = stateDescriptionOptionProvider;
}
public static final String PROPERTY_MEMBERS = "members";
private final Logger logger = LoggerFactory.getLogger(HueGroupHandler.class);
- private final HueStateDescriptionOptionProvider stateDescriptionOptionProvider;
+ private final HueStateDescriptionProvider stateDescriptionOptionProvider;
private @NonNullByDefault({}) String groupId;
private List<String> consoleScenesList = List.of();
- public HueGroupHandler(Thing thing, HueStateDescriptionOptionProvider stateDescriptionOptionProvider) {
+ public HueGroupHandler(Thing thing, HueStateDescriptionProvider stateDescriptionOptionProvider) {
super(thing);
this.stateDescriptionOptionProvider = stateDescriptionOptionProvider;
}
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerService;
import org.openhab.core.types.Command;
-import org.openhab.core.types.StateDescription;
+import org.openhab.core.types.StateDescriptionFragment;
import org.openhab.core.types.StateDescriptionFragmentBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final Logger logger = LoggerFactory.getLogger(HueLightHandler.class);
- private final HueStateDescriptionOptionProvider stateDescriptionOptionProvider;
+ private final HueStateDescriptionProvider stateDescriptionProvider;
private @NonNullByDefault({}) String lightId;
private @Nullable ScheduledFuture<?> scheduledFuture;
- public HueLightHandler(Thing hueLight, HueStateDescriptionOptionProvider stateDescriptionOptionProvider) {
+ public HueLightHandler(Thing hueLight, HueStateDescriptionProvider stateDescriptionProvider) {
super(hueLight);
- this.stateDescriptionOptionProvider = stateDescriptionOptionProvider;
+ this.stateDescriptionProvider = stateDescriptionProvider;
}
@Override
colorTemperatureCapabilties = ct;
// minimum and maximum are inverted due to mired/Kelvin conversion!
- StateDescription stateDescription = StateDescriptionFragmentBuilder.create()
+ StateDescriptionFragment stateDescriptionFragment = StateDescriptionFragmentBuilder.create()
.withMinimum(new BigDecimal(LightStateConverter.miredToKelvin(ct.max))) //
.withMaximum(new BigDecimal(LightStateConverter.miredToKelvin(ct.min))) //
.withStep(new BigDecimal(100)) //
.withPattern("%.0f K") //
- .build().toStateDescription();
- if (stateDescription != null) {
- stateDescriptionOptionProvider.setDescription(
- new ChannelUID(thing.getUID(), CHANNEL_COLORTEMPERATURE_ABS), stateDescription);
- } else {
- logger.warn("Failed to create state description in thing {}", thing.getUID());
- }
+ .build();
+ stateDescriptionProvider.setStateDescriptionFragment(
+ new ChannelUID(thing.getUID(), CHANNEL_COLORTEMPERATURE_ABS), stateDescriptionFragment);
}
}
capabilitiesInitializedSuccessfully = true;
+++ /dev/null
-/**
- * Copyright (c) 2010-2021 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.hue.internal.handler;
-
-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.binding.BaseDynamicStateDescriptionProvider;
-import org.openhab.core.thing.i18n.ChannelTypeI18nLocalizationService;
-import org.openhab.core.thing.type.DynamicStateDescriptionProvider;
-import org.openhab.core.types.StateDescription;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Reference;
-
-/**
- * Dynamic provider of state options for {@link HueBridgeHandler} while leaving other state description fields as
- * original.
- *
- * @author Hengrui Jiang - Initial contribution
- */
-@Component(service = { DynamicStateDescriptionProvider.class, HueStateDescriptionOptionProvider.class })
-@NonNullByDefault
-public class HueStateDescriptionOptionProvider extends BaseDynamicStateDescriptionProvider {
-
- private final Map<ChannelUID, StateDescription> descriptions = new ConcurrentHashMap<>();
-
- @Activate
- public HueStateDescriptionOptionProvider(
- final @Reference ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) {
- this.channelTypeI18nLocalizationService = channelTypeI18nLocalizationService;
- }
-
- public void setDescription(ChannelUID channelUID, StateDescription description) {
- descriptions.put(channelUID, description);
- }
-
- @Override
- public @Nullable StateDescription getStateDescription(Channel channel,
- @Nullable StateDescription originalStateDescription, @Nullable Locale locale) {
- StateDescription stateDescription = descriptions.get(channel.getUID());
- return stateDescription != null ? stateDescription
- : super.getStateDescription(channel, originalStateDescription, locale);
- }
-}
--- /dev/null
+/**
+ * Copyright (c) 2010-2021 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.hue.internal.handler;
+
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.core.events.EventPublisher;
+import org.openhab.core.thing.Channel;
+import org.openhab.core.thing.ChannelUID;
+import org.openhab.core.thing.binding.BaseDynamicStateDescriptionProvider;
+import org.openhab.core.thing.events.ThingEventFactory;
+import org.openhab.core.thing.i18n.ChannelTypeI18nLocalizationService;
+import org.openhab.core.thing.link.ItemChannelLinkRegistry;
+import org.openhab.core.thing.type.DynamicStateDescriptionProvider;
+import org.openhab.core.types.StateDescription;
+import org.openhab.core.types.StateDescriptionFragment;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * Dynamic provider of state options for {@link HueBridgeHandler} while leaving other state description fields as
+ * original.
+ *
+ * @author Hengrui Jiang - Initial contribution
+ */
+@Component(service = { DynamicStateDescriptionProvider.class, HueStateDescriptionProvider.class })
+@NonNullByDefault
+public class HueStateDescriptionProvider extends BaseDynamicStateDescriptionProvider {
+
+ private final Map<ChannelUID, StateDescriptionFragment> stateDescriptionFragments = new ConcurrentHashMap<>();
+
+ @Activate
+ public HueStateDescriptionProvider(final @Reference EventPublisher eventPublisher, //
+ final @Reference ItemChannelLinkRegistry itemChannelLinkRegistry, //
+ final @Reference ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) {
+ this.eventPublisher = eventPublisher;
+ this.itemChannelLinkRegistry = itemChannelLinkRegistry;
+ this.channelTypeI18nLocalizationService = channelTypeI18nLocalizationService;
+ }
+
+ public void setStateDescriptionFragment(ChannelUID channelUID, StateDescriptionFragment stateDescriptionFragment) {
+ StateDescriptionFragment oldStateDescriptionFragment = stateDescriptionFragments.get(channelUID);
+ if (!stateDescriptionFragment.equals(oldStateDescriptionFragment)) {
+ stateDescriptionFragments.put(channelUID, stateDescriptionFragment);
+ postEvent(ThingEventFactory.createChannelDescriptionChangedEvent(channelUID,
+ itemChannelLinkRegistry != null ? itemChannelLinkRegistry.getLinkedItemNames(channelUID) : Set.of(),
+ stateDescriptionFragment, oldStateDescriptionFragment));
+ }
+ }
+
+ @Override
+ public @Nullable StateDescription getStateDescription(Channel channel,
+ @Nullable StateDescription originalStateDescription, @Nullable Locale locale) {
+ StateDescriptionFragment stateDescriptionFragment = stateDescriptionFragments.get(channel.getUID());
+ return stateDescriptionFragment != null ? stateDescriptionFragment.toStateDescription()
+ : super.getStateDescription(channel, originalStateDescription, locale);
+ }
+}
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingUID;
import org.openhab.core.thing.binding.ThingHandlerCallback;
-import org.openhab.core.thing.i18n.ChannelTypeI18nLocalizationService;
import org.openhab.core.types.Command;
import com.google.gson.Gson;
assertSendCommand(channel, command, currentState, expectedReply, "LCT001", "Philips");
}
+ @SuppressWarnings("null")
private void assertSendCommand(String channel, Command command, HueLightState currentState, String expectedReply,
String expectedModel, String expectedVendor) {
FullLight light = gson.fromJson(currentState.toString(), FullConfig.class).getLights().get(0);
long fadeTime = 400;
- HueLightHandler hueLightHandler = new HueLightHandler(mockThing,
- new HueStateDescriptionOptionProvider(mock(ChannelTypeI18nLocalizationService.class))) {
+ HueLightHandler hueLightHandler = new HueLightHandler(mockThing, mock(HueStateDescriptionProvider.class)) {
@Override
protected synchronized HueClient getHueClient() {
return mockClient;