diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/Clip2StateDescriptionProvider.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/Clip2StateDescriptionProvider.java index 32523ffba93..6e7c9d51653 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/Clip2StateDescriptionProvider.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/Clip2StateDescriptionProvider.java @@ -12,19 +12,32 @@ */ package org.openhab.binding.hue.internal.handler; +import java.math.BigDecimal; +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.openhab.core.types.StateDescriptionFragmentBuilder; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; /** - * The {@link Clip2StateDescriptionProvider} provides dynamic state descriptions of scene channels whose list of options - * is determined at runtime. + * The {@link Clip2StateDescriptionProvider} provides dynamic state descriptions of alert, effect, scene, and colour + * temperature channels whose capabilities are dynamically determined at runtime. * * @author Andrew Fiddian-Green - Initial contribution * @@ -33,6 +46,8 @@ import org.osgi.service.component.annotations.Reference; @Component(service = { DynamicStateDescriptionProvider.class, Clip2StateDescriptionProvider.class }) public class Clip2StateDescriptionProvider extends BaseDynamicStateDescriptionProvider { + private final Map stateDescriptionFragments = new ConcurrentHashMap<>(); + @Activate public Clip2StateDescriptionProvider(final @Reference EventPublisher eventPublisher, final @Reference ItemChannelLinkRegistry itemChannelLinkRegistry, @@ -41,4 +56,29 @@ public class Clip2StateDescriptionProvider extends BaseDynamicStateDescriptionPr this.itemChannelLinkRegistry = itemChannelLinkRegistry; this.channelTypeI18nLocalizationService = channelTypeI18nLocalizationService; } + + @Override + public @Nullable StateDescription getStateDescription(Channel channel, @Nullable StateDescription original, + @Nullable Locale locale) { + StateDescriptionFragment stateDescriptionFragment = stateDescriptionFragments.get(channel.getUID()); + return stateDescriptionFragment != null ? stateDescriptionFragment.toStateDescription() + : super.getStateDescription(channel, original, locale); + } + + /** + * Set the state description minimum and maximum values and pattern in Kelvin for the given channel UID + */ + public void setMinMaxKelvin(ChannelUID channelUID, long minKelvin, long maxKelvin) { + StateDescriptionFragment oldStateDescriptionFragment = stateDescriptionFragments.get(channelUID); + StateDescriptionFragment newStateDescriptionFragment = StateDescriptionFragmentBuilder.create() + .withMinimum(BigDecimal.valueOf(minKelvin)).withMaximum(BigDecimal.valueOf(maxKelvin)) + .withStep(BigDecimal.valueOf(100)).withPattern("%.0f K").build(); + if (!newStateDescriptionFragment.equals(oldStateDescriptionFragment)) { + stateDescriptionFragments.put(channelUID, newStateDescriptionFragment); + ItemChannelLinkRegistry itemChannelLinkRegistry = this.itemChannelLinkRegistry; + postEvent(ThingEventFactory.createChannelDescriptionChangedEvent(channelUID, + itemChannelLinkRegistry != null ? itemChannelLinkRegistry.getLinkedItemNames(channelUID) : Set.of(), + newStateDescriptionFragment, oldStateDescriptionFragment)); + } + } } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/Clip2ThingHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/Clip2ThingHandler.java index ddbe824eaa1..15e2c8b484e 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/Clip2ThingHandler.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/Clip2ThingHandler.java @@ -38,6 +38,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.hue.internal.action.DynamicsActions; import org.openhab.binding.hue.internal.api.dto.clip2.Alerts; +import org.openhab.binding.hue.internal.api.dto.clip2.ColorTemperature; import org.openhab.binding.hue.internal.api.dto.clip2.ColorXy; import org.openhab.binding.hue.internal.api.dto.clip2.Dimming; import org.openhab.binding.hue.internal.api.dto.clip2.Effects; @@ -945,6 +946,7 @@ public class Clip2ThingHandler extends BaseThingHandler { case LIGHT: if (fullUpdate) { updateEffectChannel(resource); + updateColorTemperatureAbsoluteChannel(resource); } updateState(CHANNEL_2_COLOR_TEMP_PERCENT, resource.getColorTemperaturePercentState(), fullUpdate); updateState(CHANNEL_2_COLOR_TEMP_ABSOLUTE, resource.getColorTemperatureAbsoluteState(), fullUpdate); @@ -1114,6 +1116,24 @@ public class Clip2ThingHandler extends BaseThingHandler { } } + /** + * Process the incoming Resource to initialize the colour temperature absolute channel's state description based on + * the minimum and maximum values supported by the lamp's Mirek schema. + * + * @param resource a Resource possibly containing a color temperature element and respective Mirek schema element. + */ + private void updateColorTemperatureAbsoluteChannel(Resource resource) { + ColorTemperature colorTemperature = resource.getColorTemperature(); + if (colorTemperature != null) { + MirekSchema mirekSchema = colorTemperature.getMirekSchema(); + if (mirekSchema != null) { + stateDescriptionProvider.setMinMaxKelvin(new ChannelUID(thing.getUID(), CHANNEL_2_COLOR_TEMP_ABSOLUTE), + 1000000 / mirekSchema.getMirekMaximum(), 1000000 / mirekSchema.getMirekMinimum()); + logger.debug("{} -> updateColorTempAbsChannel() done", resource.getId()); + } + } + } + /** * Update the light properties. *