Skip to content

Commit

Permalink
Merge pull request openhab#3 from lolodomo/matter_colortemperature
Browse files Browse the repository at this point in the history
New channel color temperature in mirek
  • Loading branch information
digitaldan authored Nov 15, 2024
2 parents ba4cda8 + 3529f9d commit f0e112e
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,118 +39,97 @@ public class MatterBindingConstants {

// This was borrowed from the zigbee binding as Matter uses the same cluster API model
// List of Channel UIDs
public static final String CHANNEL_NAME_ONOFF_ONOFF = "onoff";
public static final String CHANNEL_LABEL_ONOFF_ONOFF = "On Off";
public static final ChannelTypeUID CHANNEL_ONOFF_ONOFF = new ChannelTypeUID("matter:onoffcontrol-onoff");

public static final String CHANNEL_NAME_LEVEL_LEVEL = "level";
public static final String CHANNEL_LABEL_LEVEL_LEVEL = "Level Control";
public static final ChannelTypeUID CHANNEL_LEVEL_LEVEL = new ChannelTypeUID("matter:levelcontrol-level");

public static final String CHANNEL_NAME_COLOR_COLOR = "color";
public static final String CHANNEL_LABEL_COLOR_COLOR = "Color Control";
public static final ChannelTypeUID CHANNEL_COLOR_COLOR = new ChannelTypeUID("matter:colorcontrol-color");

public static final String CHANNEL_NAME_COLOR_TEMPERATURE = "colortemperature";
public static final String CHANNEL_LABEL_COLOR_TEMPERATURE = "Color Temperature";
public static final ChannelTypeUID CHANNEL_COLOR_TEMPERATURE = new ChannelTypeUID(
"matter:colorcontrol-temperature");

public static final String CHANNEL_NAME_POWER_BATTERYPERCENT = "powersourcebatpercentremaining";
public static final String CHANNEL_LABEL_COLOR_TEMPERATURE_ABS = "Color Temperature";
public static final ChannelTypeUID CHANNEL_COLOR_TEMPERATURE_ABS = new ChannelTypeUID(
"matter:colorcontrol-temperature-abs");

public static final String CHANNEL_LABEL_POWER_BATTERYPERCENT = "Battery Percent Remaining";
public static final ChannelTypeUID CHANNEL_POWER_BATTERYPERCENT = new ChannelTypeUID(
"matter:powersource-batpercentremaining");

public static final String CHANNEL_NAME_POWER_CHARGELEVEL = "powersourcechargelevel";
public static final String CHANNEL_LABEL_POWER_CHARGELEVEL = "Battery Charge Level";
public static final ChannelTypeUID CHANNEL_POWER_CHARGELEVEL = new ChannelTypeUID(
"matter:powersource-batchargelevel");

public static final String CHANNEL_NAME_THERMOSTAT_LOCALTEMPERATURE = "thermostatlocaltemperature";
public static final String CHANNEL_LABEL_THERMOSTAT_LOCALTEMPERATURE = "Local Temperature";
public static final ChannelTypeUID CHANNEL_THERMOSTAT_LOCALTEMPERATURE = new ChannelTypeUID(
"matter:thermostat-localtemperature");

public static final String CHANNEL_NAME_THERMOSTAT_OUTDOORTEMPERATURE = "thermostatoutdoortemperature";
public static final String CHANNEL_LABEL_THERMOSTAT_OUTDOORTEMPERATURE = "Outdoor Temperature";
public static final ChannelTypeUID CHANNEL_THERMOSTAT_OUTDOORTEMPERATURE = new ChannelTypeUID(
"matter:thermostat-outdoortemperature");

public static final String CHANNEL_NAME_THERMOSTAT_OCCUPIEDCOOLING = "thermostatoccupiedcooling";
public static final String CHANNEL_LABEL_THERMOSTAT_OCCUPIEDCOOLING = "Occupied Cooling Setpoint";
public static final ChannelTypeUID CHANNEL_THERMOSTAT_OCCUPIEDCOOLING = new ChannelTypeUID(
"matter:thermostat-occupiedcooling");

public static final String CHANNEL_NAME_THERMOSTAT_OCCUPIEDHEATING = "thermostatoccupiedheating";
public static final String CHANNEL_LABEL_THERMOSTAT_OCCUPIEDHEATING = "Occupied Heating Setpoint";
public static final ChannelTypeUID CHANNEL_THERMOSTAT_OCCUPIEDHEATING = new ChannelTypeUID(
"matter:thermostat-occupiedheating");

public static final String CHANNEL_NAME_THERMOSTAT_UNOCCUPIEDCOOLING = "thermostatunoccupiedcooling";
public static final String CHANNEL_LABEL_THERMOSTAT_UNOCCUPIEDCOOLING = "Unoccupied Cooling Setpoint";
public static final ChannelTypeUID CHANNEL_THERMOSTAT_UNOCCUPIEDCOOLING = new ChannelTypeUID(
"matter:thermostat-unoccupiedcooling");

public static final String CHANNEL_NAME_THERMOSTAT_UNOCCUPIEDHEATING = "thermostatunoccupiedheating";
public static final String CHANNEL_LABEL_THERMOSTAT_UNOCCUPIEDHEATING = "Unoccupied Heating Setpoint";
public static final ChannelTypeUID CHANNEL_THERMOSTAT_UNOCCUPIEDHEATING = new ChannelTypeUID(
"matter:thermostat-unoccupiedheating");

public static final String CHANNEL_NAME_THERMOSTAT_SYSTEMMODE = "thermostatsystemmode";
public static final String CHANNEL_LABEL_THERMOSTAT_SYSTEMMODE = "System Mode";
public static final ChannelTypeUID CHANNEL_THERMOSTAT_SYSTEMMODE = new ChannelTypeUID(
"matter:thermostat-systemmode");

public static final String CHANNEL_NAME_THERMOSTAT_RUNNINGMODE = "thermostatrunningmode";
public static final String CHANNEL_LABEL_THERMOSTAT_RUNNINGMODE = "Running Mode";
public static final ChannelTypeUID CHANNEL_THERMOSTAT_RUNNINGMODE = new ChannelTypeUID(
"matter:thermostat-runningmode");

public static final String CHANNEL_NAME_THERMOSTAT_HEATING_DEMAND = "thermostatheatingdemand";
public static final String CHANNEL_LABEL_THERMOSTAT_HEATING_DEMAND = "Heating Demand";
public static final ChannelTypeUID CHANNEL_THERMOSTAT_HEATING_DEMAND = new ChannelTypeUID(
"matter:thermostat-heatingdemand");

public static final String CHANNEL_NAME_THERMOSTAT_COOLING_DEMAND = "thermostatcoolingdemand";
public static final String CHANNEL_LABEL_THERMOSTAT_COOLING_DEMAND = "Cooling Demand";
public static final ChannelTypeUID CHANNEL_THERMOSTAT_COOLING_DEMAND = new ChannelTypeUID(
"matter:thermostat-coolingdemand");

public static final String CHANNEL_NAME_DOORLOCK_STATE = "doorlockstate";
public static final String CHANNEL_LABEL_DOORLOCK_STATE = "Door Lock State";
public static final ChannelTypeUID CHANNEL_DOORLOCK_STATE = new ChannelTypeUID("matter:door-state");

public static final String CHANNEL_NAME_WINDOWCOVERING_LIFT = "windowcoveringlift";
public static final String CHANNEL_LABEL_WINDOWCOVERING_LIFT = "Window Covering Lift";
public static final ChannelTypeUID CHANNEL_WINDOWCOVERING_LIFT = new ChannelTypeUID("matter:windowcovering-lift");

public static final String CHANNEL_NAME_FANCONTROL_PERCENT = "fancontrolpercent";
public static final String CHANNEL_LABEL_FANCONTROL_PERCENT = "Fan Control Percent";
public static final ChannelTypeUID CHANNEL_FANCONTROL_PERCENT = new ChannelTypeUID("matter:fancontrol-percent");

public static final String CHANNEL_NAME_FANCONTROL_MODE = "fancontrolmode";
public static final String CHANNEL_LABEL_FANCONTROL_MODE = "Fan Control Mode";
public static final ChannelTypeUID CHANNEL_FANCONTROL_MODE = new ChannelTypeUID("matter:fancontrol-mode");

public static final String CHANNEL_NAME_TEMPERATUREMEASURMENT_MEASUREDVALUE = "temperaturemeasurementmeasuredvalue";
public static final String CHANNEL_LABEL_TEMPERATUREMEASURMENT_MEASUREDVALUE = "Temperature";
public static final ChannelTypeUID CHANNEL_TEMPERATUREMEASURMENT_MEASUREDVALUE = new ChannelTypeUID(
"matter:temperaturemeasurement-measuredvalue");

public static final String CHANNEL_NAME_HUMIDITYMEASURMENT_MEASUREDVALUE = "relativehumiditymeasurementmeasuredvalue";
public static final String CHANNEL_LABEL_HUMIDITYMEASURMENT_MEASUREDVALUE = "Humidity";
public static final ChannelTypeUID CHANNEL_HUMIDITYMEASURMENT_MEASUREDVALUE = new ChannelTypeUID(
"matter:relativehumiditymeasurement-measuredvalue");

public static final String CHANNEL_NAME_OCCUPANCYSENSING_OCCUPIED = "occupancysensingoccupied";

public static final String CHANNEL_LABEL_OCCUPANCYSENSING_OCCUPIED = "Occupied";
public static final ChannelTypeUID CHANNEL_OCCUPANCYSENSING_OCCUPIED = new ChannelTypeUID(
"matter:occupancysensing-occupied");

public static final String CHANNEL_NAME_MODESELECT_MODE = "MODESELECT_MODE";
public static final ChannelTypeUID CHANNEL_MODESELECT_MODE = new ChannelTypeUID("matter:modeselect-mode");

public static final String CHANNEL_NAME_SWITCH_SWITCH = "SWITCH_SWITCH";
public static final String CHANNEL_LABEL_SWITCH_SWITCH = "Switch";
public static final ChannelTypeUID CHANNEL_SWITCH_SWITCH = new ChannelTypeUID("matter:switch-switch");
public static final ChannelTypeUID CHANNEL_SWITCH_SWITCHLATECHED = new ChannelTypeUID(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,25 @@
*/
package org.openhab.binding.matter.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;
Expand All @@ -31,6 +44,8 @@
@NonNullByDefault
public class MatterStateDescriptionOptionProvider extends BaseDynamicStateDescriptionProvider {

private final Map<ChannelUID, StateDescriptionFragment> stateDescriptionFragments = new ConcurrentHashMap<>();

@Activate
public MatterStateDescriptionOptionProvider(final @Reference EventPublisher eventPublisher, //
final @Reference ItemChannelLinkRegistry itemChannelLinkRegistry, //
Expand All @@ -39,4 +54,33 @@ public MatterStateDescriptionOptionProvider(final @Reference EventPublisher even
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);
}

public void setMinMax(ChannelUID channelUID, BigDecimal min, BigDecimal max, @Nullable BigDecimal step,
@Nullable String pattern) {
StateDescriptionFragment oldStateDescriptionFragment = stateDescriptionFragments.get(channelUID);
StateDescriptionFragmentBuilder builder = StateDescriptionFragmentBuilder.create().withMinimum(min)
.withMaximum(max);
if (step != null) {
builder = builder.withStep(step);
}
if (pattern != null) {
builder = builder.withPattern(pattern);
}
StateDescriptionFragment newStateDescriptionFragment = builder.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));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import static org.openhab.binding.matter.internal.MatterBindingConstants.*;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
Expand All @@ -36,12 +37,15 @@
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.types.QuantityType;
import org.openhab.core.library.unit.Units;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.ThingUID;
import org.openhab.core.thing.binding.builder.ChannelBuilder;
import org.openhab.core.types.Command;
import org.openhab.core.types.StateDescription;
import org.openhab.core.types.StateDescriptionFragmentBuilder;
import org.openhab.core.types.UnDefType;
import org.openhab.core.util.ColorUtil;
import org.slf4j.Logger;
Expand All @@ -50,7 +54,7 @@
/**
* @author Dan Cunningham - Initial contribution
* @author Chris Jackson - Original Zigbee binding color logic
*
*
*/
@NonNullByDefault
public class ColorControlConverter extends GenericConverter<ColorControlCluster> {
Expand Down Expand Up @@ -89,6 +93,22 @@ public ColorControlConverter(ColorControlCluster cluster, EndpointHandler handle
if (cluster.featureMap.colorTemperature) {
map.put(ChannelBuilder.create(new ChannelUID(thingUID, CHANNEL_COLOR_TEMPERATURE.getId()), ITEM_TYPE_DIMMER)
.withType(CHANNEL_COLOR_TEMPERATURE).withLabel(CHANNEL_LABEL_COLOR_TEMPERATURE).build(), null);

Optional.ofNullable(cluster.colorTempPhysicalMinMireds)
.ifPresent(temp -> colorTempPhysicalMinMireds = temp);
Optional.ofNullable(cluster.colorTempPhysicalMaxMireds)
.ifPresent(temp -> colorTempPhysicalMaxMireds = temp);
StateDescription stateDescription = null;
if (colorTempPhysicalMinMireds < colorTempPhysicalMaxMireds) {
stateDescription = StateDescriptionFragmentBuilder.create().withPattern("%.0f mirek")
.withMinimum(BigDecimal.valueOf(colorTempPhysicalMinMireds))
.withMaximum(BigDecimal.valueOf(colorTempPhysicalMaxMireds)).build().toStateDescription();
}
map.put(ChannelBuilder
.create(new ChannelUID(thingUID, CHANNEL_COLOR_TEMPERATURE_ABS.getId()),
ITEM_TYPE_NUMBER_TEMPERATURE)
.withType(CHANNEL_COLOR_TEMPERATURE_ABS).withLabel(CHANNEL_LABEL_COLOR_TEMPERATURE_ABS).build(),
stateDescription);
}
return map;
}
Expand Down Expand Up @@ -125,6 +145,19 @@ public void handleCommand(ChannelUID channelUID, Command command) {
optionsBitmap, optionsBitmap);
handler.sendClusterCommand(LevelControlCluster.CLUSTER_NAME, levelCommand);
}
} else if (channelUID.getId().equals(CHANNEL_COLOR_TEMPERATURE_ABS.getId())
&& command instanceof DecimalType decimal) {
ClusterCommand tempCommand = ColorControlCluster.moveToColorTemperature(decimal.intValue(), 0, optionsMask,
optionsMask);
handler.sendClusterCommand(ColorControlCluster.CLUSTER_NAME, tempCommand);
} else if (channelUID.getId().equals(CHANNEL_COLOR_TEMPERATURE_ABS.getId())
&& command instanceof QuantityType<?> quantity) {
quantity = quantity.toInvertibleUnit(Units.MIRED);
if (quantity != null) {
ClusterCommand tempCommand = ColorControlCluster.moveToColorTemperature(quantity.intValue(), 0,
optionsMask, optionsMask);
handler.sendClusterCommand(ColorControlCluster.CLUSTER_NAME, tempCommand);
}
}
}

Expand All @@ -151,6 +184,8 @@ public void onEvent(AttributeChangedMessage message) {
case "colorTemperatureMireds":
updateState(CHANNEL_COLOR_TEMPERATURE,
numberValue == 0 ? UnDefType.UNDEF : miredsToPercenType(numberValue));
updateState(CHANNEL_COLOR_TEMPERATURE_ABS, numberValue == 0 ? UnDefType.UNDEF
: QuantityType.valueOf(Double.valueOf(numberValue), Units.MIRED));
break;
case "enhancedCurrentHue":
break;
Expand Down Expand Up @@ -191,6 +226,8 @@ public void updateCluster(ColorControlCluster cluster) {
if (cluster.colorTemperatureMireds != null) {
updateState(CHANNEL_COLOR_TEMPERATURE, cluster.colorTemperatureMireds == 0 ? UnDefType.UNDEF
: miredsToPercenType(cluster.colorTemperatureMireds));
updateState(CHANNEL_COLOR_TEMPERATURE_ABS, cluster.colorTemperatureMireds == 0 ? UnDefType.UNDEF
: QuantityType.valueOf(Double.valueOf(cluster.colorTemperatureMireds), Units.MIRED));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;

import org.eclipse.jdt.annotation.NonNullByDefault;
Expand All @@ -40,7 +44,12 @@
import org.openhab.binding.matter.internal.devices.types.DeviceTypeRegistry;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.config.core.validation.ConfigValidationException;
import org.openhab.core.thing.*;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.ThingStatusInfo;
import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.thing.binding.BridgeHandler;
import org.openhab.core.thing.binding.ThingHandlerService;
Expand Down Expand Up @@ -250,6 +259,13 @@ public void updateEndpoint(Endpoint endpoint) {

Optional.ofNullable(stateDescription.getPattern())
.ifPresent(pattern -> stateDescriptionProvider.setStatePattern(channelUID, pattern));

BigDecimal min = stateDescription.getMinimum();
BigDecimal max = stateDescription.getMaximum();
if (min != null && max != null) {
stateDescriptionProvider.setMinMax(channelUID, min, max, stateDescription.getStep(),
stateDescription.getPattern());
}
}
});
this.deviceType = deviceType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@
light on and off.
</description>
<category>ColorLight</category>
<tags>
<tag>Control</tag>
<tag>Light</tag>
</tags>
<autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type>

Expand All @@ -79,6 +83,23 @@
<label>Color Temperature</label>
<description>Sets the color temperature of the light</description>
<category>ColorLight</category>
<tags>
<tag>Control</tag>
<tag>ColorTemperature</tag>
</tags>
<state pattern="%.0f %%" min="0" max="100"/>
</channel-type>

<channel-type id="colorcontrol-temperature-abs" advanced="true">
<item-type unitHint="mirek">Number:Temperature</item-type>
<label>Color Temperature</label>
<description>Sets the color temperature of the light in mirek</description>
<category>ColorLight</category>
<tags>
<tag>Control</tag>
<tag>ColorTemperature</tag>
</tags>
<state pattern="%.0f mirek" min="100" max="1000"/>
</channel-type>

<!-- Door Lock Channel -->
Expand Down Expand Up @@ -122,6 +143,10 @@
<label>Dimmer</label>
<description>Sets the level of the light</description>
<category>Light</category>
<tags>
<tag>Control</tag>
<tag>Light</tag>
</tags>
<autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type>

Expand Down

0 comments on commit f0e112e

Please sign in to comment.