[tapocontrol] color temperature channel improvements (#17779)

Signed-off-by: AndrewFG <software@whitebear.ch>
This commit is contained in:
Andrew Fiddian-Green 2024-11-24 00:02:31 +00:00 committed by GitHub
parent ff103585da
commit c758013093
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 151 additions and 26 deletions

View File

@ -96,7 +96,7 @@ All devices support some of the following channels:
| | output2 | Switch | Power socket 2 on or off | P300 | | | output2 | Switch | Power socket 2 on or off | P300 |
| | output3 | Switch | Power socket 3 on or off | P300 | | | output3 | Switch | Power socket 3 on or off | P300 |
| | brightness | Dimmer | Brightness 0-100% | L510, L530, L610, L630, L900, L920 | | | 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 | | | color | Color | Color | L530, L630, L900, L920 |
| sensor | isOpen | Switch | Contact (Door/Window) is Open | T110 | | sensor | isOpen | Switch | Contact (Door/Window) is Open | T110 |
| | currentTemp | Number:Temperature | Current Temperature | T310, T315 | | | currentTemp | Number:Temperature | Current Temperature | T310, T315 |

View File

@ -63,9 +63,12 @@ public class TapoControlHandlerFactory extends BaseThingHandlerFactory {
private final Logger logger = LoggerFactory.getLogger(TapoControlHandlerFactory.class); private final Logger logger = LoggerFactory.getLogger(TapoControlHandlerFactory.class);
private final Set<TapoBridgeHandler> accountHandlers = new HashSet<>(); private final Set<TapoBridgeHandler> accountHandlers = new HashSet<>();
private final HttpClient httpClient; private final HttpClient httpClient;
private final TapoStateDescriptionProvider stateDescriptionProvider;
@Activate @Activate
public TapoControlHandlerFactory(final @Reference HttpClientFactory httpClientFactory) { public TapoControlHandlerFactory(final @Reference HttpClientFactory httpClientFactory,
final @Reference TapoStateDescriptionProvider tapoStateDescriptionProvider) {
this.stateDescriptionProvider = tapoStateDescriptionProvider;
// create new httpClient // create new httpClient
httpClient = httpClientFactory.createHttpClient(BINDING_ID, new SslContextFactory.Client()); httpClient = httpClientFactory.createHttpClient(BINDING_ID, new SslContextFactory.Client());
httpClient.setFollowRedirects(false); httpClient.setFollowRedirects(false);
@ -118,9 +121,9 @@ public class TapoControlHandlerFactory extends BaseThingHandlerFactory {
} else if (SUPPORTED_SOCKET_STRIP_UIDS.contains(thingTypeUID)) { } else if (SUPPORTED_SOCKET_STRIP_UIDS.contains(thingTypeUID)) {
return new TapoSocketStripHandler(thing); return new TapoSocketStripHandler(thing);
} else if (SUPPORTED_WHITE_BULB_UIDS.contains(thingTypeUID)) { } 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)) { } 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)) { } else if (SUPPORTED_LIGHT_STRIP_UIDS.contains(thingTypeUID)) {
return new TapoLightStripHandler(thing); return new TapoLightStripHandler(thing);
} else if (SUPPORTED_SMART_CONTACTS.contains(thingTypeUID)) { } else if (SUPPORTED_SMART_CONTACTS.contains(thingTypeUID)) {

View File

@ -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<ChannelUID, StateDescriptionFragment> 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));
}
}
}

View File

@ -122,6 +122,7 @@ public class TapoThingConstants {
public static final String CHILD_REPRESENTATION_PROPERTY = "serialNumber"; public static final String CHILD_REPRESENTATION_PROPERTY = "serialNumber";
/*** DEVICE SETTINGS ***/ /*** DEVICE SETTINGS ***/
public static final Integer BULB_MIN_COLORTEMP_EXT = 2200;
public static final Integer BULB_MIN_COLORTEMP = 2500; public static final Integer BULB_MIN_COLORTEMP = 2500;
public static final Integer BULB_MAX_COLORTEMP = 6500; public static final Integer BULB_MAX_COLORTEMP = 6500;

View File

@ -17,6 +17,7 @@ import static org.openhab.binding.tapocontrol.internal.constants.TapoThingConsta
import static org.openhab.binding.tapocontrol.internal.helpers.utils.TypeUtils.*; import static org.openhab.binding.tapocontrol.internal.helpers.utils.TypeUtils.*;
import org.eclipse.jdt.annotation.NonNullByDefault; 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.dto.TapoLightDynamicFx;
import org.openhab.binding.tapocontrol.internal.devices.wifi.TapoBaseDeviceHandler; import org.openhab.binding.tapocontrol.internal.devices.wifi.TapoBaseDeviceHandler;
import org.openhab.binding.tapocontrol.internal.helpers.TapoErrorHandler; 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.OnOffType;
import org.openhab.core.library.types.PercentType; import org.openhab.core.library.types.PercentType;
import org.openhab.core.library.unit.Units; import org.openhab.core.library.unit.Units;
import org.openhab.core.thing.ChannelGroupUID;
import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing; import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.types.Command; import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType; import org.openhab.core.types.RefreshType;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -42,20 +45,34 @@ public class TapoBulbHandler extends TapoBaseDeviceHandler {
private final Logger logger = LoggerFactory.getLogger(TapoBulbHandler.class); private final Logger logger = LoggerFactory.getLogger(TapoBulbHandler.class);
private TapoBulbData bulbData = new TapoBulbData(); private TapoBulbData bulbData = new TapoBulbData();
private TapoBulbLastStates lastStates = new TapoBulbLastStates(); private TapoBulbLastStates lastStates = new TapoBulbLastStates();
private final TapoStateDescriptionProvider stateDescriptionProvider;
/** /**
* Constructor * Constructor
* *
* @param thing Thing object representing device * @param thing Thing object representing device
*/ */
public TapoBulbHandler(Thing thing) { public TapoBulbHandler(Thing thing, TapoStateDescriptionProvider stateDescriptionProvider) {
super(thing); 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 * Function called by {@link org.openhab.binding.tapocontrol.internal.api.TapoDeviceConnector} if new data were
* received * received
* *
* @param queryCommand command where new data belong to * @param queryCommand command where new data belong to
*/ */
@Override @Override
@ -74,7 +91,7 @@ public class TapoBulbHandler extends TapoBaseDeviceHandler {
/** /**
* handle command sent to device * handle command sent to device
* *
* @param channelUID channelUID command is sent to * @param channelUID channelUID command is sent to
* @param command command to be sent * @param command command to be sent
*/ */
@ -149,7 +166,7 @@ public class TapoBulbHandler extends TapoBaseDeviceHandler {
/** /**
* Switch device On or Off * Switch device On or Off
* *
* @param on if true device will switch on. Otherwise switch off * @param on if true device will switch on. Otherwise switch off
*/ */
protected void switchOnOff(boolean on) { protected void switchOnOff(boolean on) {
@ -159,7 +176,7 @@ public class TapoBulbHandler extends TapoBaseDeviceHandler {
/** /**
* Set Britghtness of device * Set Britghtness of device
* *
* @param newBrightness percentage 0-100 of new brightness * @param newBrightness percentage 0-100 of new brightness
*/ */
protected void setBrightness(Integer newBrightness) { protected void setBrightness(Integer newBrightness) {
@ -175,7 +192,7 @@ public class TapoBulbHandler extends TapoBaseDeviceHandler {
/** /**
* Set Color of Device * Set Color of Device
* *
* @param command HSBType * @param command HSBType
*/ */
protected void setColor(HSBType command) { protected void setColor(HSBType command) {
@ -189,7 +206,7 @@ public class TapoBulbHandler extends TapoBaseDeviceHandler {
/** /**
* Set ColorTemp * Set ColorTemp
* *
* @param colorTemp (Integer) in Kelvin * @param colorTemp (Integer) in Kelvin
*/ */
protected void setColorTemp(Integer colorTemp) { protected void setColorTemp(Integer colorTemp) {
@ -201,7 +218,7 @@ public class TapoBulbHandler extends TapoBaseDeviceHandler {
/** /**
* Set light effect * Set light effect
* *
* @param fxId (String) id of LightEffect * @param fxId (String) id of LightEffect
*/ */
protected void setLightEffect(String fxId) { protected void setLightEffect(String fxId) {
@ -216,7 +233,7 @@ public class TapoBulbHandler extends TapoBaseDeviceHandler {
/** /**
* Set last state by mode * Set last state by mode
* *
* @param mode mode to set * @param mode mode to set
*/ */
protected void setLastMode(TapoBulbModeEnum mode) { protected void setLastMode(TapoBulbModeEnum mode) {

View File

@ -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.colorBulbMode.command.option.LIGHT_FX = Effects
channel-type.tapocontrol.colorChannel.label = Color channel-type.tapocontrol.colorChannel.label = Color
channel-type.tapocontrol.colorChannel.description = 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.label = Contact Closed
channel-type.tapocontrol.contactCloseEvent.description = Event is fired if contact changes from open to closed channel-type.tapocontrol.contactCloseEvent.description = Event is fired if contact changes from open to closed
channel-type.tapocontrol.contactOpenEvent.label = Contact Opened channel-type.tapocontrol.contactOpenEvent.label = Contact Opened

View File

@ -17,6 +17,11 @@
<channel-group id="effects" typeId="lightEffectL530"/> <channel-group id="effects" typeId="lightEffectL530"/>
<channel-group id="device" typeId="deviceState"/> <channel-group id="device" typeId="deviceState"/>
</channel-groups> </channel-groups>
<properties>
<property name="thingTypeVersion">1</property>
</properties>
<representation-property>macAddress</representation-property> <representation-property>macAddress</representation-property>
<config-description-ref uri="thing-type:tapo:device"/> <config-description-ref uri="thing-type:tapo:device"/>

View File

@ -16,6 +16,11 @@
<channel-group id="actuator" typeId="colorBulb"/> <channel-group id="actuator" typeId="colorBulb"/>
<channel-group id="device" typeId="deviceStateS"/> <channel-group id="device" typeId="deviceStateS"/>
</channel-groups> </channel-groups>
<properties>
<property name="thingTypeVersion">1</property>
</properties>
<representation-property>macAddress</representation-property> <representation-property>macAddress</representation-property>
<config-description-ref uri="thing-type:tapo:device"/> <config-description-ref uri="thing-type:tapo:device"/>

View File

@ -86,7 +86,7 @@
<channel id="mode" typeId="colorBulbMode"/> <channel id="mode" typeId="colorBulbMode"/>
<channel id="brightness" typeId="dimmerChannel"/> <channel id="brightness" typeId="dimmerChannel"/>
<channel id="color" typeId="colorChannel"/> <channel id="color" typeId="colorChannel"/>
<channel id="colorTemperature" typeId="colorTemperature"/> <channel id="colorTemperature" typeId="system.color-temperature-abs"/>
</channels> </channels>
</channel-group-type> </channel-group-type>

View File

@ -59,15 +59,6 @@
<state readOnly="false"/> <state readOnly="false"/>
</channel-type> </channel-type>
<!-- Color Temperature -->
<channel-type id="colorTemperature">
<item-type>Number</item-type>
<label>Color Temperature</label>
<description>This channel supports adjusting the color temperature from 2200K to 6500K.</description>
<category>LightBulb</category>
<state min="2200" max="6500" pattern="%d K"/>
</channel-type>
<!-- SENSOR CHANNEL TYPES --> <!-- SENSOR CHANNEL TYPES -->
<!-- SmartContact "isOpen" Channel Type --> <!-- SmartContact "isOpen" Channel Type -->
<channel-type id="isOpenChannel"> <channel-type id="isOpenChannel">

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<update:update-descriptions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:update="https://openhab.org/schemas/update-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/update-description/v1.0.0 https://openhab.org/schemas/update-description-1.0.0.xsd">
<thing-type uid="tapocontrol:L530">
<instruction-set targetVersion="1">
<update-channel id="colorTemperature">
<type>system:color-temperature-abs</type>
</update-channel>
</instruction-set>
</thing-type>
<thing-type uid="tapocontrol:L630">
<instruction-set targetVersion="1">
<update-channel id="colorTemperature">
<type>system:color-temperature-abs</type>
</update-channel>
</instruction-set>
</thing-type>
</update:update-descriptions>