From: Christoph Weitkamp Date: Thu, 24 Jun 2021 10:15:49 +0000 (+0200) Subject: [hue] Added support for publishing ChannelDescriptionChangedEvents (#10718) X-Git-Url: https://git.basschouten.com/?a=commitdiff_plain;h=c5c2cab0a7d735628437df5b600aca8343857936;p=openhab-addons.git [hue] Added support for publishing ChannelDescriptionChangedEvents (#10718) * Added service references to DynamicStateDescriptionProvider to support publishing ChannelDescriptionChangedEvent Signed-off-by: Christoph Weitkamp --- diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/HueThingHandlerFactory.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/HueThingHandlerFactory.java index 8644676a73..fb13efd351 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/HueThingHandlerFactory.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/HueThingHandlerFactory.java @@ -24,7 +24,7 @@ import org.eclipse.jdt.annotation.Nullable; 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; @@ -67,11 +67,11 @@ public class HueThingHandlerFactory extends BaseThingHandlerFactory { 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 @@ -142,9 +142,9 @@ public class HueThingHandlerFactory extends BaseThingHandlerFactory { @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())) { @@ -160,7 +160,7 @@ public class HueThingHandlerFactory extends BaseThingHandlerFactory { } 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; } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java index 3ee5fc01eb..c4baa76feb 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java @@ -97,7 +97,7 @@ public class HueBridgeHandler extends ConfigStatusBridgeHandler implements HueCl 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 lastLightStates = new ConcurrentHashMap<>(); private final Map lastSensorStates = new ConcurrentHashMap<>(); @@ -403,7 +403,7 @@ public class HueBridgeHandler extends ConfigStatusBridgeHandler implements HueCl private List consoleScenesList = new ArrayList<>(); - public HueBridgeHandler(Bridge bridge, HueStateDescriptionOptionProvider stateDescriptionOptionProvider) { + public HueBridgeHandler(Bridge bridge, HueStateDescriptionProvider stateDescriptionOptionProvider) { super(bridge); this.stateDescriptionOptionProvider = stateDescriptionOptionProvider; } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueGroupHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueGroupHandler.java index efa228f2fe..ac887ded8f 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueGroupHandler.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueGroupHandler.java @@ -62,7 +62,7 @@ public class HueGroupHandler extends BaseThingHandler implements GroupStatusList 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; @@ -79,7 +79,7 @@ public class HueGroupHandler extends BaseThingHandler implements GroupStatusList private List consoleScenesList = List.of(); - public HueGroupHandler(Thing thing, HueStateDescriptionOptionProvider stateDescriptionOptionProvider) { + public HueGroupHandler(Thing thing, HueStateDescriptionProvider stateDescriptionOptionProvider) { super(thing); this.stateDescriptionOptionProvider = stateDescriptionOptionProvider; } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueLightHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueLightHandler.java index fd727666b7..33c90e7946 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueLightHandler.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueLightHandler.java @@ -49,7 +49,7 @@ import org.openhab.core.thing.binding.BaseThingHandler; 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; @@ -83,7 +83,7 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList private final Logger logger = LoggerFactory.getLogger(HueLightHandler.class); - private final HueStateDescriptionOptionProvider stateDescriptionOptionProvider; + private final HueStateDescriptionProvider stateDescriptionProvider; private @NonNullByDefault({}) String lightId; @@ -105,9 +105,9 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList 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 @@ -185,18 +185,14 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList 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; diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueStateDescriptionOptionProvider.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueStateDescriptionOptionProvider.java deleted file mode 100644 index 4801c59d60..0000000000 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueStateDescriptionOptionProvider.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * 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 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); - } -} diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueStateDescriptionProvider.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueStateDescriptionProvider.java new file mode 100644 index 0000000000..3948970fcc --- /dev/null +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueStateDescriptionProvider.java @@ -0,0 +1,74 @@ +/** + * 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 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); + } +} diff --git a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/handler/HueLightHandlerTest.java b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/handler/HueLightHandlerTest.java index 7f2398af4b..bfdd8cc1c2 100644 --- a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/handler/HueLightHandlerTest.java +++ b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/handler/HueLightHandlerTest.java @@ -39,7 +39,6 @@ import org.openhab.core.thing.Thing; 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; @@ -385,6 +384,7 @@ public class HueLightHandlerTest { 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); @@ -400,8 +400,7 @@ public class HueLightHandlerTest { 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;