From c758013093f8e76c926265a256b898818f7a6ca0 Mon Sep 17 00:00:00 2001 From: Andrew Fiddian-Green Date: Sun, 24 Nov 2024 00:02:31 +0000 Subject: [PATCH] [tapocontrol] color temperature channel improvements (#17779) Signed-off-by: AndrewFG --- .../org.openhab.binding.tapocontrol/README.md | 2 +- .../internal/TapoControlHandlerFactory.java | 9 +- .../TapoStateDescriptionProvider.java | 83 +++++++++++++++++++ .../constants/TapoThingConstants.java | 1 + .../devices/wifi/bulb/TapoBulbHandler.java | 37 ++++++--- .../OH-INF/i18n/tapocontrol.properties | 2 - .../src/main/resources/OH-INF/thing/L530.xml | 5 ++ .../src/main/resources/OH-INF/thing/L630.xml | 5 ++ .../resources/OH-INF/thing/channelgroups.xml | 2 +- .../main/resources/OH-INF/thing/channels.xml | 9 -- .../resources/OH-INF/update/instructions.xml | 22 +++++ 11 files changed, 151 insertions(+), 26 deletions(-) create mode 100644 bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/TapoStateDescriptionProvider.java create mode 100644 bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/update/instructions.xml diff --git a/bundles/org.openhab.binding.tapocontrol/README.md b/bundles/org.openhab.binding.tapocontrol/README.md index 161db88c955..5c335bd77b6 100644 --- a/bundles/org.openhab.binding.tapocontrol/README.md +++ b/bundles/org.openhab.binding.tapocontrol/README.md @@ -96,7 +96,7 @@ All devices support some of the following channels: | | output2 | Switch | Power socket 2 on or off | P300 | | | output3 | Switch | Power socket 3 on or off | P300 | | | brightness | Dimmer | Brightness 0-100% | L510, L530, L610, L630, L900, L920 | -| | colorTemperature | Number | White-Color-Temp 2500-6500K | L510, L530, L610, L630, L900, L920 | +| | colorTemperature | Number:Temperature | Color Temperature in Kelvin | L530 (2500 K .. 6500 K), L630 (2200 K .. 6500 K) | | | color | Color | Color | L530, L630, L900, L920 | | sensor | isOpen | Switch | Contact (Door/Window) is Open | T110 | | | currentTemp | Number:Temperature | Current Temperature | T310, T315 | diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/TapoControlHandlerFactory.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/TapoControlHandlerFactory.java index fdb357bed38..8725f7a8b72 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/TapoControlHandlerFactory.java +++ b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/TapoControlHandlerFactory.java @@ -63,9 +63,12 @@ public class TapoControlHandlerFactory extends BaseThingHandlerFactory { private final Logger logger = LoggerFactory.getLogger(TapoControlHandlerFactory.class); private final Set accountHandlers = new HashSet<>(); private final HttpClient httpClient; + private final TapoStateDescriptionProvider stateDescriptionProvider; @Activate - public TapoControlHandlerFactory(final @Reference HttpClientFactory httpClientFactory) { + public TapoControlHandlerFactory(final @Reference HttpClientFactory httpClientFactory, + final @Reference TapoStateDescriptionProvider tapoStateDescriptionProvider) { + this.stateDescriptionProvider = tapoStateDescriptionProvider; // create new httpClient httpClient = httpClientFactory.createHttpClient(BINDING_ID, new SslContextFactory.Client()); httpClient.setFollowRedirects(false); @@ -118,9 +121,9 @@ public class TapoControlHandlerFactory extends BaseThingHandlerFactory { } else if (SUPPORTED_SOCKET_STRIP_UIDS.contains(thingTypeUID)) { return new TapoSocketStripHandler(thing); } else if (SUPPORTED_WHITE_BULB_UIDS.contains(thingTypeUID)) { - return new TapoBulbHandler(thing); + return new TapoBulbHandler(thing, stateDescriptionProvider); } else if (SUPPORTED_COLOR_BULB_UIDS.contains(thingTypeUID)) { - return new TapoBulbHandler(thing); + return new TapoBulbHandler(thing, stateDescriptionProvider); } else if (SUPPORTED_LIGHT_STRIP_UIDS.contains(thingTypeUID)) { return new TapoLightStripHandler(thing); } else if (SUPPORTED_SMART_CONTACTS.contains(thingTypeUID)) { diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/TapoStateDescriptionProvider.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/TapoStateDescriptionProvider.java new file mode 100644 index 00000000000..f1f403f3d8a --- /dev/null +++ b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/TapoStateDescriptionProvider.java @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2010-2024 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.tapocontrol.internal; + +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 TapoStateDescriptionProvider} provides state descriptions for different color temperature light models. + * + * @author Andrew Fiddian-Green - Initial contribution + * + */ +@NonNullByDefault +@Component(service = { DynamicStateDescriptionProvider.class, TapoStateDescriptionProvider.class }) +public class TapoStateDescriptionProvider extends BaseDynamicStateDescriptionProvider { + + private final Map stateDescriptionFragments = new ConcurrentHashMap<>(); + + @Activate + public TapoStateDescriptionProvider(final @Reference EventPublisher eventPublisher, + final @Reference ItemChannelLinkRegistry itemChannelLinkRegistry, + final @Reference ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) { + this.eventPublisher = eventPublisher; + 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.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoThingConstants.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoThingConstants.java index 9bc5e1288f6..73bf50bb22a 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoThingConstants.java +++ b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoThingConstants.java @@ -122,6 +122,7 @@ public class TapoThingConstants { public static final String CHILD_REPRESENTATION_PROPERTY = "serialNumber"; /*** DEVICE SETTINGS ***/ + public static final Integer BULB_MIN_COLORTEMP_EXT = 2200; public static final Integer BULB_MIN_COLORTEMP = 2500; public static final Integer BULB_MAX_COLORTEMP = 6500; diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/devices/wifi/bulb/TapoBulbHandler.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/devices/wifi/bulb/TapoBulbHandler.java index 9f1194ec164..e09427319a2 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/devices/wifi/bulb/TapoBulbHandler.java +++ b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/devices/wifi/bulb/TapoBulbHandler.java @@ -17,6 +17,7 @@ import static org.openhab.binding.tapocontrol.internal.constants.TapoThingConsta import static org.openhab.binding.tapocontrol.internal.helpers.utils.TypeUtils.*; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.tapocontrol.internal.TapoStateDescriptionProvider; import org.openhab.binding.tapocontrol.internal.devices.dto.TapoLightDynamicFx; import org.openhab.binding.tapocontrol.internal.devices.wifi.TapoBaseDeviceHandler; import org.openhab.binding.tapocontrol.internal.helpers.TapoErrorHandler; @@ -25,8 +26,10 @@ import org.openhab.core.library.types.HSBType; import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.PercentType; import org.openhab.core.library.unit.Units; +import org.openhab.core.thing.ChannelGroupUID; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.types.Command; import org.openhab.core.types.RefreshType; import org.slf4j.Logger; @@ -42,20 +45,34 @@ public class TapoBulbHandler extends TapoBaseDeviceHandler { private final Logger logger = LoggerFactory.getLogger(TapoBulbHandler.class); private TapoBulbData bulbData = new TapoBulbData(); private TapoBulbLastStates lastStates = new TapoBulbLastStates(); + private final TapoStateDescriptionProvider stateDescriptionProvider; /** * Constructor - * + * * @param thing Thing object representing device */ - public TapoBulbHandler(Thing thing) { + public TapoBulbHandler(Thing thing, TapoStateDescriptionProvider stateDescriptionProvider) { super(thing); + this.stateDescriptionProvider = stateDescriptionProvider; + } + + @Override + public void initialize() { + super.initialize(); + ThingTypeUID typeUID = thing.getThingTypeUID(); + if (SUPPORTED_COLOR_BULB_UIDS.contains(typeUID)) { + ChannelGroupUID groupUID = new ChannelGroupUID(getThingUID(), CHANNEL_GROUP_ACTUATOR); + ChannelUID channnelUID = new ChannelUID(groupUID, CHANNEL_COLOR_TEMP); + long minKelvin = L630_THING_TYPE.equals(typeUID) ? BULB_MIN_COLORTEMP_EXT : BULB_MIN_COLORTEMP; + stateDescriptionProvider.setMinMaxKelvin(channnelUID, minKelvin, BULB_MAX_COLORTEMP); + } } /** * Function called by {@link org.openhab.binding.tapocontrol.internal.api.TapoDeviceConnector} if new data were * received - * + * * @param queryCommand command where new data belong to */ @Override @@ -74,7 +91,7 @@ public class TapoBulbHandler extends TapoBaseDeviceHandler { /** * handle command sent to device - * + * * @param channelUID channelUID command is sent to * @param command command to be sent */ @@ -149,7 +166,7 @@ public class TapoBulbHandler extends TapoBaseDeviceHandler { /** * Switch device On or Off - * + * * @param on if true device will switch on. Otherwise switch off */ protected void switchOnOff(boolean on) { @@ -159,7 +176,7 @@ public class TapoBulbHandler extends TapoBaseDeviceHandler { /** * Set Britghtness of device - * + * * @param newBrightness percentage 0-100 of new brightness */ protected void setBrightness(Integer newBrightness) { @@ -175,7 +192,7 @@ public class TapoBulbHandler extends TapoBaseDeviceHandler { /** * Set Color of Device - * + * * @param command HSBType */ protected void setColor(HSBType command) { @@ -189,7 +206,7 @@ public class TapoBulbHandler extends TapoBaseDeviceHandler { /** * Set ColorTemp - * + * * @param colorTemp (Integer) in Kelvin */ protected void setColorTemp(Integer colorTemp) { @@ -201,7 +218,7 @@ public class TapoBulbHandler extends TapoBaseDeviceHandler { /** * Set light effect - * + * * @param fxId (String) id of LightEffect */ protected void setLightEffect(String fxId) { @@ -216,7 +233,7 @@ public class TapoBulbHandler extends TapoBaseDeviceHandler { /** * Set last state by mode - * + * * @param mode mode to set */ protected void setLastMode(TapoBulbModeEnum mode) { diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/i18n/tapocontrol.properties b/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/i18n/tapocontrol.properties index 7ca6c81a2ea..b18bbfdf5ad 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/i18n/tapocontrol.properties +++ b/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/i18n/tapocontrol.properties @@ -139,8 +139,6 @@ channel-type.tapocontrol.colorBulbMode.command.option.COLOR_LIGHT = Color channel-type.tapocontrol.colorBulbMode.command.option.LIGHT_FX = Effects channel-type.tapocontrol.colorChannel.label = Color channel-type.tapocontrol.colorChannel.description = Color -channel-type.tapocontrol.colorTemperature.label = Color Temperature -channel-type.tapocontrol.colorTemperature.description = This channel supports adjusting the color temperature from 2200K to 6500K. channel-type.tapocontrol.contactCloseEvent.label = Contact Closed channel-type.tapocontrol.contactCloseEvent.description = Event is fired if contact changes from open to closed channel-type.tapocontrol.contactOpenEvent.label = Contact Opened diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/L530.xml b/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/L530.xml index 73074332f6b..cd8948a6ac3 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/L530.xml +++ b/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/L530.xml @@ -17,6 +17,11 @@ + + + 1 + + macAddress diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/L630.xml b/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/L630.xml index 1108af0dd36..cbf8f9ecd6a 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/L630.xml +++ b/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/L630.xml @@ -16,6 +16,11 @@ + + + 1 + + macAddress diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/channelgroups.xml b/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/channelgroups.xml index 6a6c79a2e49..2fe48c2e8e6 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/channelgroups.xml +++ b/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/channelgroups.xml @@ -86,7 +86,7 @@ - + diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/channels.xml b/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/channels.xml index eb99925c062..45e274f1540 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/channels.xml @@ -59,15 +59,6 @@ - - - Number - - This channel supports adjusting the color temperature from 2200K to 6500K. - LightBulb - - - diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/update/instructions.xml b/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/update/instructions.xml new file mode 100644 index 00000000000..13ba4218439 --- /dev/null +++ b/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/update/instructions.xml @@ -0,0 +1,22 @@ + + + + + + + system:color-temperature-abs + + + + + + + + system:color-temperature-abs + + + + +