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 8644676a7..fb13efd35 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 3ee5fc01e..c4baa76fe 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 efa228f2f..ac887ded8 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 fd727666b..33c90e794 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/HueStateDescriptionProvider.java similarity index 53% rename from bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueStateDescriptionOptionProvider.java rename to bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueStateDescriptionProvider.java index 4801c59d6..3948970fc 100644 --- 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/HueStateDescriptionProvider.java @@ -14,16 +14,21 @@ 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; @@ -34,27 +39,36 @@ import org.osgi.service.component.annotations.Reference; * * @author Hengrui Jiang - Initial contribution */ -@Component(service = { DynamicStateDescriptionProvider.class, HueStateDescriptionOptionProvider.class }) +@Component(service = { DynamicStateDescriptionProvider.class, HueStateDescriptionProvider.class }) @NonNullByDefault -public class HueStateDescriptionOptionProvider extends BaseDynamicStateDescriptionProvider { +public class HueStateDescriptionProvider extends BaseDynamicStateDescriptionProvider { - private final Map descriptions = new ConcurrentHashMap<>(); + private final Map stateDescriptionFragments = new ConcurrentHashMap<>(); @Activate - public HueStateDescriptionOptionProvider( + 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 setDescription(ChannelUID channelUID, StateDescription description) { - descriptions.put(channelUID, description); + 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) { - StateDescription stateDescription = descriptions.get(channel.getUID()); - return stateDescription != null ? stateDescription + 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 7f2398af4..bfdd8cc1c 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;