[mqtt.homeassistant] Fix color lights that don't specify color_mode: true (#17240)

* [mqtt.homeassistant] Fix color lights that don't specify color_mode: true

See https://github.com/home-assistant/core/pull/111676

Signed-off-by: Cody Cutrer <cody@cutrer.us>
Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
Cody Cutrer 2024-08-13 15:22:31 -06:00 committed by Ciprian Pascu
parent 4a3b0a976a
commit 795f797ab7
3 changed files with 66 additions and 16 deletions

View File

@ -22,7 +22,6 @@ import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.mqtt.generic.ChannelStateUpdateListener;
import org.openhab.binding.mqtt.generic.values.TextValue;
import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannelType;
import org.openhab.binding.mqtt.homeassistant.internal.exception.UnsupportedComponentException;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.HSBType;
import org.openhab.core.library.types.OnOffType;
@ -82,19 +81,7 @@ public class JSONSchemaLight extends AbstractRawSchemaLight {
@Override
protected void buildChannels() {
List<LightColorMode> supportedColorModes = channelConfiguration.supportedColorModes;
if (supportedColorModes != null && supportedColorModes.contains(LightColorMode.COLOR_MODE_COLOR_TEMP)) {
colorModeValue = new TextValue(
supportedColorModes.stream().map(LightColorMode::serializedName).toArray(String[]::new));
buildChannel(COLOR_MODE_CHANNEL_ID, ComponentChannelType.STRING, colorModeValue, "Color Mode", this)
.isAdvanced(true).build();
}
if (channelConfiguration.colorMode) {
if (supportedColorModes == null || channelConfiguration.supportedColorModes.isEmpty()) {
throw new UnsupportedComponentException("JSON schema light with color modes '" + getHaID()
+ "' does not define supported_color_modes!");
}
if (supportedColorModes != null) {
if (LightColorMode.hasColorChannel(supportedColorModes)) {
hasColorChannel = true;
}
@ -103,6 +90,14 @@ public class JSONSchemaLight extends AbstractRawSchemaLight {
buildChannel(COLOR_TEMP_CHANNEL_ID, ComponentChannelType.NUMBER, colorTempValue, "Color Temperature",
this).commandTopic(DUMMY_TOPIC, true, 1)
.commandFilter(command -> handleColorTempCommand(command)).build();
if (hasColorChannel) {
colorModeValue = new TextValue(
supportedColorModes.stream().map(LightColorMode::serializedName).toArray(String[]::new));
buildChannel(COLOR_MODE_CHANNEL_ID, ComponentChannelType.STRING, colorModeValue, "Color Mode", this)
.isAdvanced(true).build();
}
}
}

View File

@ -83,8 +83,6 @@ public abstract class Light extends AbstractComponent<Light.ChannelConfiguration
protected String schema = DEFAULT_SCHEMA;
protected @Nullable Boolean optimistic; // All schemas
protected boolean brightness = false; // JSON schema only
@SerializedName("color_mode")
protected boolean colorMode = false; // JSON schema only
@SerializedName("supported_color_modes")
protected @Nullable List<LightColorMode> supportedColorModes; // JSON schema only
// Defines when on the payload_on is sent. Using last (the default) will send

View File

@ -95,6 +95,63 @@ public class JSONSchemaLightTests extends AbstractComponentTests {
assertPublished("zigbee2mqtt/light/set/state", "{\"state\":\"ON\",\"brightness\":127}");
}
@Test
public void testRgbNewStyle() throws InterruptedException {
// @formatter:off
var component = (Light) discoverComponent(configTopicToMqtt(CONFIG_TOPIC),
"""
{ \
"availability": [ \
{ \
"topic": "zigbee2mqtt/bridge/state" \
} \
], \
"device": { \
"identifiers": [ \
"zigbee2mqtt_0x0000000000000000" \
], \
"manufacturer": "Lights inc", \
"model": "light v1", \
"name": "Light", \
"sw_version": "Zigbee2MQTT 1.18.2" \
}, \
"name": "light", \
"schema": "json", \
"state_topic": "zigbee2mqtt/light/state", \
"command_topic": "zigbee2mqtt/light/set/state", \
"brightness": true, \
"supported_color_modes": ["rgb"]\
}\
""");
// @formatter:on
assertThat(component.channels.size(), is(1));
assertThat(component.getName(), is("light"));
assertChannel(component, Light.COLOR_CHANNEL_ID, "", "dummy", "Color", ColorValue.class);
publishMessage("zigbee2mqtt/light/state", "{ \"state\": \"ON\" }");
assertState(component, Light.COLOR_CHANNEL_ID, HSBType.WHITE);
publishMessage("zigbee2mqtt/light/state", "{ \"color\": {\"r\": 10, \"g\": 20, \"b\": 30 } }");
assertState(component, Light.COLOR_CHANNEL_ID, HSBType.fromRGB(10, 20, 30));
publishMessage("zigbee2mqtt/light/state", "{ \"brightness\": 255 }");
assertState(component, Light.COLOR_CHANNEL_ID, new HSBType("210,67,100"));
sendCommand(component, Light.COLOR_CHANNEL_ID, HSBType.BLUE);
assertPublished("zigbee2mqtt/light/set/state",
"{\"state\":\"ON\",\"brightness\":255,\"color\":{\"r\":0,\"g\":0,\"b\":255}}");
// OnOff commands should route to the correct topic
sendCommand(component, Light.COLOR_CHANNEL_ID, OnOffType.OFF);
assertPublished("zigbee2mqtt/light/set/state", "{\"state\":\"OFF\"}");
sendCommand(component, Light.COLOR_CHANNEL_ID, OnOffType.ON);
assertPublished("zigbee2mqtt/light/set/state", "{\"state\":\"ON\"}");
sendCommand(component, Light.COLOR_CHANNEL_ID, new PercentType(50));
assertPublished("zigbee2mqtt/light/set/state", "{\"state\":\"ON\",\"brightness\":127}");
}
@Test
public void testBrightnessAndOnOff() throws InterruptedException {
// @formatter:off