[mqtt.espmilighthub] Use system channel types for color temp and brightness (#13801)

* [mqtt.espmilighthub] use system channel types for color temp and brightness

closes #10096

also add absolute color temp channel. and remove level channel when we
already have a color channel (you can link a DimmerItem to a color
channel if your light doesn't happen to have color or you want direct
control of brightness only for some reason)

---------

Signed-off-by: Cody Cutrer <cody@cutrer.us>
This commit is contained in:
Cody Cutrer 2023-12-16 01:49:35 -07:00 committed by GitHub
parent 71066837dc
commit de418fe42c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 200 additions and 64 deletions

View File

@ -118,9 +118,10 @@ Note that the group 0 (or ALL group) is not auto discovered as a thing and thus
| Channel | Type | Description |
|-|-|-|
| `level` | Dimmer | Level changes the brightness of the globe. |
| `level` | Dimmer | Level changes the brightness of the globe. Not present if the bulb supports the `colour` channel. |
| `colourTemperature` | Dimmer | Change from cool to warm white with this control. |
| `colour` | Color | Allows you to change the colour, brightness and saturation of the globe. |
| `colourTemperatureAbs` | Number:Temperature | Colour temperature in mireds. |
| `colour` | Color | Allows you to change the colour, brightness and saturation of the globe. Can also be linked directly with a Dimmer item if you happen to have a bulb that doesn't support colour, but is controlled by a remote that normally does support colour. |
| `discoMode` | String | Switch to a Disco mode directly from a drop down list. |
| `bulbMode` | String (read only) | Displays the mode the bulb is currently in so that rules can determine if the globe is white, a color, disco modes or night mode are selected. |
| `command` | String | Sends the raw commands that the buttons on a remote send. |
@ -192,8 +193,9 @@ Thing mqtt:rgb_cct:myBroker:0xE6C4 "Hallway" (mqtt:broker:myBroker) @ "MQTT"
*.items
```java
Dimmer Hallway_Level "Front Hall" {channel="mqtt:rgb_cct:myBroker:0xE6C4:level"}
Dimmer Hallway_Level "Front Hall" {channel="mqtt:rgb_cct:myBroker:0xE6C4:colour"}
Dimmer Hallway_ColourTemperature "White Color Temp" {channel="mqtt:rgb_cct:myBroker:0xE6C4:colourTemperature"}
Number:Temperature Hallway_ColourTemperatureK "White Color Temp [%d %unit%]" {channel="mqtt:rgb_cct:myBroker:0xE6C4:colourTemperatureAbs", unit="K"}
Color Hallway_Colour "Front Hall" ["Lighting"] {channel="mqtt:rgb_cct:myBroker:0xE6C4:colour"}
String Hallway_DiscoMode "Disco Mode" {channel="mqtt:rgb_cct:myBroker:0xE6C4:discoMode"}
String Hallway_BulbCommand "Send Command" {channel="mqtt:rgb_cct:myBroker:0xE6C4:command"}

View File

@ -33,6 +33,8 @@ public class EspMilightHubBindingConstants {
public static final String COMMANDS_BASE_TOPIC = "milight/commands/";
public static final String STATUS_TOPIC = "milight/status";
public static final BigDecimal BIG_DECIMAL_100 = new BigDecimal(100);
public static final BigDecimal BIG_DECIMAL_153 = new BigDecimal(153);
public static final BigDecimal BIG_DECIMAL_370 = new BigDecimal(370);
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_RGB_CCT = new ThingTypeUID(BINDING_ID, "rgb_cct");
public static final ThingTypeUID THING_TYPE_CCT = new ThingTypeUID(BINDING_ID, "cct");
@ -48,6 +50,7 @@ public class EspMilightHubBindingConstants {
public static final String CHANNEL_LEVEL = "level";
public static final String CHANNEL_COLOUR = "colour";
public static final String CHANNEL_COLOURTEMP = "colourTemperature";
public static final String CHANNEL_COLOURTEMP_ABS = "colourTemperatureAbs";
public static final String CHANNEL_DISCO_MODE = "discoMode";
public static final String CHANNEL_BULB_MODE = "bulbMode";
public static final String CHANNEL_COMMAND = "command";

View File

@ -0,0 +1,69 @@
/**
* Copyright (c) 2010-2023 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.mqtt.espmilighthub.internal;
import static org.openhab.binding.mqtt.espmilighthub.internal.EspMilightHubBindingConstants.*;
import java.math.BigDecimal;
import java.util.Locale;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ThingRegistry;
import org.openhab.core.thing.type.DynamicStateDescriptionProvider;
import org.openhab.core.types.StateDescription;
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;
import org.slf4j.LoggerFactory;
/**
* Provides custom state descriptions for system.color-temperature-absolute channels.
*
* @author Cody Cutrer - Initial contribution
*/
@Component(service = DynamicStateDescriptionProvider.class)
@NonNullByDefault
public class EspMilightStateDescriptionProvider implements DynamicStateDescriptionProvider {
private final ThingRegistry thingRegistry;
@Activate
public EspMilightStateDescriptionProvider(@Reference ThingRegistry thingRegistry) {
this.thingRegistry = thingRegistry;
}
@Override
public @Nullable StateDescription getStateDescription(Channel channel, @Nullable StateDescription original,
@Nullable Locale locale) {
var logger = LoggerFactory.getLogger(EspMilightStateDescriptionProvider.class);
var channelUID = channel.getUID();
var thing = thingRegistry.get(channelUID.getThingUID());
if (thing == null || !SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())
|| !channelUID.getId().equals(CHANNEL_COLOURTEMP_ABS)) {
return null;
}
StateDescriptionFragmentBuilder builder;
if (original != null) {
builder = StateDescriptionFragmentBuilder.create(original);
} else {
builder = StateDescriptionFragmentBuilder.create();
}
builder.withMinimum(BIG_DECIMAL_153).withMaximum(BIG_DECIMAL_370).withStep(BigDecimal.ONE)
.withPattern("%d mired");
return builder.build().toStateDescription();
}
}

View File

@ -35,7 +35,9 @@ import org.openhab.core.library.types.HSBType;
import org.openhab.core.library.types.IncreaseDecreaseType;
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.types.StringType;
import org.openhab.core.library.unit.Units;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
@ -97,7 +99,6 @@ public class EspMilightHubHandler extends BaseThingHandler implements MqttMessag
new BigDecimal("-0.5179722"), new BigDecimal("1.5317403"), new BigDecimal("-2.4243787"),
new BigDecimal("1.925865"), new BigDecimal("-0.471106") };
private static final BigDecimal BIG_DECIMAL_153 = new BigDecimal(153);
private static final BigDecimal BIG_DECIMAL_217 = new BigDecimal(217);
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@ -155,14 +156,21 @@ public class EspMilightHubHandler extends BaseThingHandler implements MqttMessag
String bulbLevel = Helper.resolveJSON(messageJSON, "\"level\":", 3);
if (!bulbLevel.isEmpty()) {
if ("0".equals(bulbLevel) || "OFF".equals(bulbState)) {
if (!hasRGB()) {
changeChannel(CHANNEL_LEVEL, OnOffType.OFF);
}
} else {
tempBulbLevel = new PercentType(Integer.valueOf(bulbLevel));
savedLevel = tempBulbLevel.toBigDecimal();
if (!hasRGB()) {
changeChannel(CHANNEL_LEVEL, tempBulbLevel);
}
}
} else if ("ON".equals(bulbState) || "OFF".equals(bulbState)) { // NOTE: Level is missing when this runs
if (!hasRGB()) {
changeChannel(CHANNEL_LEVEL, OnOffType.valueOf(bulbState));
}
}
bulbMode = Helper.resolveJSON(messageJSON, "\"bulb_mode\":\"", 5);
switch (bulbMode) {
case "white":
@ -174,6 +182,7 @@ public class EspMilightHubHandler extends BaseThingHandler implements MqttMessag
if (!bulbCTempS.isEmpty()) {
var bulbCTemp = Integer.valueOf(bulbCTempS);
changeChannel(CHANNEL_COLOURTEMP, scaleMireds(bulbCTemp));
changeChannel(CHANNEL_COLOURTEMP_ABS, new QuantityType(bulbCTemp, Units.MIRED));
if (hasRGB()) {
changeChannel(CHANNEL_COLOUR, calculateHSBFromColorTemp(bulbCTemp, tempBulbLevel));
}
@ -198,7 +207,9 @@ public class EspMilightHubHandler extends BaseThingHandler implements MqttMessag
new PercentType(Integer.valueOf(bulbSaturation)), tempBulbLevel);
changeChannel(CHANNEL_COLOUR, hsb);
if (hasCCT()) {
changeChannel(CHANNEL_COLOURTEMP, scaleMireds(calculateColorTempFromHSB(hsb)));
int mireds = calculateColorTempFromHSB(hsb);
changeChannel(CHANNEL_COLOURTEMP, scaleMireds(mireds));
changeChannel(CHANNEL_COLOURTEMP_ABS, new QuantityType(mireds, Units.MIRED));
}
}
break;
@ -214,9 +225,6 @@ public class EspMilightHubHandler extends BaseThingHandler implements MqttMessag
case "night":
if (hasRGB()) {
changeChannel(CHANNEL_BULB_MODE, new StringType("night"));
if (config.oneTriggersNightMode) {
changeChannel(CHANNEL_LEVEL, new PercentType("1"));
}
}
break;
}
@ -430,6 +438,17 @@ public class EspMilightHubHandler extends BaseThingHandler implements MqttMessag
int scaledCommand = (int) Math.round((370 - (2.17 * Float.valueOf(command.toString()))));
sendMQTT("{\"state\":\"ON\",\"level\":" + savedLevel + ",\"color_temp\":" + scaledCommand + "}");
break;
case CHANNEL_COLOURTEMP_ABS:
int mireds;
QuantityType<?> miredsQt;
if (command instanceof QuantityType
&& (miredsQt = ((QuantityType<?>) command).toInvertibleUnit(Units.MIRED)) != null) {
mireds = miredsQt.intValue();
} else {
mireds = Integer.valueOf(command.toString());
}
sendMQTT("{\"state\":\"ON\",\"level\":" + savedLevel + ",\"color_temp\":" + mireds + "}");
break;
case CHANNEL_COMMAND:
sendMQTT("{\"command\":\"" + command + "\"}");
break;

View File

@ -56,10 +56,6 @@ channel-type.mqtt.bulbMode.state.option.white = white
channel-type.mqtt.bulbMode.state.option.color = color
channel-type.mqtt.bulbMode.state.option.scene = scene
channel-type.mqtt.bulbMode.state.option.night = night
channel-type.mqtt.colour.label = Colour
channel-type.mqtt.colour.description = Allows you to change the colour, brightness and saturation of the globe.
channel-type.mqtt.colourTemperature.label = Colour Temperature
channel-type.mqtt.colourTemperature.description = Change from cool to warm white with this control.
channel-type.mqtt.command.label = Command
channel-type.mqtt.command.description = Send a raw command to the globe/s.
channel-type.mqtt.command.state.option.next_mode = Next Mode
@ -83,5 +79,3 @@ channel-type.mqtt.discoMode.state.option.5 = Disco 5
channel-type.mqtt.discoMode.state.option.6 = Disco 6
channel-type.mqtt.discoMode.state.option.7 = Disco 7
channel-type.mqtt.discoMode.state.option.8 = Disco 8
channel-type.mqtt.level.label = Level
channel-type.mqtt.level.description = Level changes the brightness of the globe.

View File

@ -12,9 +12,9 @@
<description>LED globe with full Colour, and both cool and warm whites.</description>
<category>Lightbulb</category>
<channels>
<channel id="level" typeId="level"/>
<channel id="colourTemperature" typeId="colourTemperature"/>
<channel id="colour" typeId="colour"/>
<channel id="colourTemperature" typeId="system.color-temperature"/>
<channel id="colourTemperatureAbs" typeId="system.color-temperature-abs"/>
<channel id="colour" typeId="system.color"/>
<channel id="discoMode" typeId="discoMode"/>
<channel id="bulbMode" typeId="bulbMode"/>
<channel id="command" typeId="command"/>
@ -30,9 +30,9 @@
<description>Use this when your remote is the newer 8 group type called FUT089 and your globes are rgb_cct</description>
<category>Lightbulb</category>
<channels>
<channel id="level" typeId="level"/>
<channel id="colourTemperature" typeId="colourTemperature"/>
<channel id="colour" typeId="colour"/>
<channel id="colourTemperature" typeId="system.color-temperature"/>
<channel id="colourTemperatureAbs" typeId="system.color-temperature-abs"/>
<channel id="colour" typeId="system.color"/>
<channel id="discoMode" typeId="discoMode"/>
<channel id="bulbMode" typeId="bulbMode"/>
<channel id="command" typeId="command"/>
@ -48,8 +48,9 @@
<description>Use this when your remote is the newer fut091 and your globes are cct</description>
<category>Lightbulb</category>
<channels>
<channel id="level" typeId="level"/>
<channel id="colourTemperature" typeId="colourTemperature"/>
<channel id="level" typeId="system.brightness"/>
<channel id="colourTemperature" typeId="system.color-temperature"/>
<channel id="colourTemperatureAbs" typeId="system.color-temperature-abs"/>
<channel id="command" typeId="command"/>
</channels>
<config-description-ref uri="thing-type:mqtt:cct"/>
@ -63,8 +64,9 @@
<description>LED globe with both cool and warm white controls</description>
<category>Lightbulb</category>
<channels>
<channel id="level" typeId="level"/>
<channel id="colourTemperature" typeId="colourTemperature"/>
<channel id="level" typeId="system.brightness"/>
<channel id="colourTemperature" typeId="system.color-temperature"/>
<channel id="colourTemperatureAbs" typeId="system.color-temperature-abs"/>
<channel id="command" typeId="command"/>
</channels>
<config-description-ref uri="thing-type:mqtt:cct"/>
@ -78,8 +80,7 @@
<description>RGB Globe with a fixed white</description>
<category>Lightbulb</category>
<channels>
<channel id="level" typeId="level"/>
<channel id="colour" typeId="colour"/>
<channel id="colour" typeId="system.color"/>
<channel id="discoMode" typeId="discoMode"/>
<channel id="bulbMode" typeId="bulbMode"/>
<channel id="command" typeId="command"/>
@ -95,8 +96,7 @@
<description>RGB Globe with no white</description>
<category>Lightbulb</category>
<channels>
<channel id="level" typeId="level"/>
<channel id="colour" typeId="colour"/>
<channel id="colour" typeId="system.color"/>
<channel id="discoMode" typeId="discoMode"/>
<channel id="bulbMode" typeId="bulbMode"/>
<channel id="command" typeId="command"/>
@ -104,39 +104,6 @@
<config-description-ref uri="thing-type:mqtt:rgb"/>
</thing-type>
<channel-type id="level">
<item-type>Dimmer</item-type>
<label>Level</label>
<description>Level changes the brightness of the globe.</description>
<category>Slider</category>
<tags>
<tag>Control</tag>
<tag>Light</tag>
</tags>
</channel-type>
<channel-type id="colourTemperature">
<item-type>Dimmer</item-type>
<label>Colour Temperature</label>
<description>Change from cool to warm white with this control.</description>
<category>Slider</category>
<tags>
<tag>Control</tag>
<tag>ColorTemperature</tag>
</tags>
</channel-type>
<channel-type id="colour">
<item-type>Color</item-type>
<label>Colour</label>
<description>Allows you to change the colour, brightness and saturation of the globe.</description>
<category>ColorLight</category>
<tags>
<tag>Control</tag>
<tag>Light</tag>
</tags>
</channel-type>
<channel-type id="command" advanced="true">
<item-type>String</item-type>
<label>Command</label>

View File

@ -0,0 +1,82 @@
<?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="mqtt:rgb_cct">
<instruction-set targetVersion="1">
<remove-channel id="level"/>
<update-channel id="colorTemperature">
<type>system:color-temperature</type>
</update-channel>
<add-channel id="colourTemperatureAbs">
<type>system:color-temperature-abs</type>
</add-channel>
<update-channel id="colour">
<type>system:color</type>
</update-channel>
</instruction-set>
</thing-type>
<thing-type uid="mqtt:fut089">
<instruction-set targetVersion="1">
<remove-channel id="level"/>
<update-channel id="colorTemperature">
<type>system:color-temperature</type>
</update-channel>
<add-channel id="colourTemperatureAbs">
<type>system:color-temperature-abs</type>
</add-channel>
<update-channel id="colour">
<type>system:color</type>
</update-channel>
</instruction-set>
</thing-type>
<thing-type uid="mqtt:fut091">
<instruction-set targetVersion="1">
<update-channel id="level">
<type>system:brightness</type>
</update-channel>
<update-channel id="colorTemperature">
<type>system:color-temperature</type>
</update-channel>
<add-channel id="colourTemperatureAbs">
<type>system:color-temperature-abs</type>
</add-channel>
</instruction-set>
</thing-type>
<thing-type uid="mqtt:cct">
<instruction-set targetVersion="1">
<update-channel id="level">
<type>system:brightness</type>
</update-channel>
<update-channel id="colorTemperature">
<type>system:color-temperature</type>
</update-channel>
<add-channel id="colourTemperatureAbs">
<type>system:color-temperature-abs</type>
</add-channel>
</instruction-set>
</thing-type>
<thing-type uid="mqtt:rgbw">
<instruction-set targetVersion="1">
<remove-channel id="level"/>
<update-channel id="colour">
<type>system:color</type>
</update-channel>
</instruction-set>
</thing-type>
<thing-type uid="mqtt:rgb">
<instruction-set targetVersion="1">
<remove-channel id="level"/>
<update-channel id="colour">
<type>system:color</type>
</update-channel>
</instruction-set>
</thing-type>
</update:update-descriptions>