From: Cody Cutrer Date: Sun, 19 Nov 2023 16:52:51 +0000 (-0700) Subject: [mqtt.homeassistant] implement effect channel for light (#15914) X-Git-Url: https://git.basschouten.com/?a=commitdiff_plain;h=44e32d3fbb5ab9e9a286c1b99acec185d225af57;p=openhab-addons.git [mqtt.homeassistant] implement effect channel for light (#15914) Signed-off-by: Cody Cutrer --- diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DefaultSchemaLight.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DefaultSchemaLight.java index 8b90631d3a..676d6ddd2c 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DefaultSchemaLight.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DefaultSchemaLight.java @@ -98,8 +98,9 @@ public class DefaultSchemaLight extends Light { .build(); } - if (channelConfiguration.effectStateTopic != null || channelConfiguration.effectCommandTopic != null) { - buildChannel(EFFECT_CHANNEL_ID, effectValue, "Lighting effect", this) + if (effectValue != null + && (channelConfiguration.effectStateTopic != null || channelConfiguration.effectCommandTopic != null)) { + buildChannel(EFFECT_CHANNEL_ID, Objects.requireNonNull(effectValue), "Lighting Effect", this) .stateTopic(channelConfiguration.effectStateTopic, channelConfiguration.effectValueTemplate) .commandTopic(channelConfiguration.effectCommandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/JSONSchemaLight.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/JSONSchemaLight.java index 8a270d01e0..93dcd606a6 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/JSONSchemaLight.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/JSONSchemaLight.java @@ -114,6 +114,22 @@ public class JSONSchemaLight extends AbstractRawSchemaLight { onOffChannel = buildChannel(ON_OFF_CHANNEL_ID, onOffValue, "On/Off State", this) .commandTopic(DUMMY_TOPIC, true, 1).commandFilter(this::handleCommand).build(); } + + if (effectValue != null) { + buildChannel(EFFECT_CHANNEL_ID, Objects.requireNonNull(effectValue), "Lighting Effect", this) + .commandTopic(DUMMY_TOPIC, true, 1).commandFilter(command -> handleEffectCommand(command)).build(); + + } + } + + private boolean handleEffectCommand(Command command) { + if (command instanceof StringType) { + JSONState json = new JSONState(); + json.state = "ON"; + json.effect = command.toString(); + publishState(json); + } + return false; } @Override @@ -151,6 +167,10 @@ public class JSONSchemaLight extends AbstractRawSchemaLight { } } + publishState(json); + } + + private void publishState(JSONState json) { String command = getGson().toJson(json); logger.debug("Publishing new state '{}' of light {} to MQTT.", command, getName()); rawChannel.getState().publishValue(new StringType(command)); @@ -224,6 +244,15 @@ public class JSONSchemaLight extends AbstractRawSchemaLight { return; } + if (effectValue != null) { + if (jsonState.effect != null) { + effectValue.update(new StringType(jsonState.effect)); + listener.updateChannelState(buildChannelUID(EFFECT_CHANNEL_ID), effectValue.getChannelState()); + } else { + listener.updateChannelState(buildChannelUID(EFFECT_CHANNEL_ID), UnDefType.NULL); + } + } + if (jsonState.state != null) { onOffValue.update(onOffValue.parseCommand(new StringType(jsonState.state))); if (brightnessValue.getChannelState() instanceof UnDefType) { diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Light.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Light.java index 782268cdab..c0c41ef34a 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Light.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Light.java @@ -47,7 +47,7 @@ import com.google.gson.annotations.SerializedName; * three different schemas. * * As of now, only on/off, brightness, and RGB are fully implemented and tested. - * HS and XY are implemented, but not tested. Color temp and effect are only + * HS and XY are implemented, but not tested. Color temp is only * implemented (but not tested) for the default schema. * * @author David Graeff - Initial contribution @@ -246,7 +246,7 @@ public abstract class Light extends AbstractComponent hiddenChannels = new ArrayList<>(); @@ -281,6 +281,13 @@ public abstract class Light extends AbstractComponent effectList = channelConfiguration.effectList; + if (effectList != null) { + effectValue = new TextValue(effectList.toArray(new String[0])); + } else { + effectValue = null; + } + @Nullable BigDecimal min = null, max = null; if (channelConfiguration.minMireds != null) { min = new BigDecimal(channelConfiguration.minMireds); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/DefaultSchemaLightTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/DefaultSchemaLightTests.java index a5b092b01e..150d9e4f15 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/DefaultSchemaLightTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/DefaultSchemaLightTests.java @@ -27,11 +27,13 @@ import org.junit.jupiter.api.Test; import org.openhab.binding.mqtt.generic.values.ColorValue; import org.openhab.binding.mqtt.generic.values.OnOffValue; import org.openhab.binding.mqtt.generic.values.PercentageValue; +import org.openhab.binding.mqtt.generic.values.TextValue; import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannel; import org.openhab.core.library.types.DecimalType; 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.StringType; /** * Tests for {@link Light} confirming to the default schema @@ -285,6 +287,40 @@ public class DefaultSchemaLightTests extends AbstractComponentTests { assertPublished("zigbee2mqtt/light/set/state", "OFF_"); } + @Test + public void testOnOffWithEffect() throws InterruptedException { + // @formatter:off + var component = (Light) discoverComponent(configTopicToMqtt(CONFIG_TOPIC), + "{ " + + " \"name\": \"light\", " + + " \"state_topic\": \"zigbee2mqtt/light/state\", " + + " \"command_topic\": \"zigbee2mqtt/light/set/state\", " + + " \"effect_command_topic\": \"zigbee2mqtt/light/set/effect\", " + + " \"state_value_template\": \"{{ value_json.power }}\", " + + " \"effect_list\": [\"party\", \"rainbow\"]," + + " \"effect_state_topic\": \"zigbee2mqtt/light/effect\"" + + "}"); + // @formatter:on + + assertThat(component.channels.size(), is(2)); + assertThat(component.getName(), is("light")); + + assertChannel(component, Light.ON_OFF_CHANNEL_ID, "zigbee2mqtt/light/state", "zigbee2mqtt/light/set/state", + "On/Off State", OnOffValue.class); + assertChannel(component, Light.EFFECT_CHANNEL_ID, "zigbee2mqtt/light/effect", "zigbee2mqtt/light/set/effect", + "Lighting Effect", TextValue.class); + + publishMessage("zigbee2mqtt/light/state", "{\"power\": \"ON\"}"); + assertState(component, Light.ON_OFF_CHANNEL_ID, OnOffType.ON); + publishMessage("zigbee2mqtt/light/effect", "party"); + assertState(component, Light.EFFECT_CHANNEL_ID, new StringType("party")); + publishMessage("zigbee2mqtt/light/state", "{\"power\": \"OFF\"}"); + assertState(component, Light.ON_OFF_CHANNEL_ID, OnOffType.OFF); + + sendCommand(component, Light.EFFECT_CHANNEL_ID, new StringType("rainbow")); + assertPublished("zigbee2mqtt/light/set/effect", "rainbow"); + } + @Override protected Set getConfigTopics() { return Set.of(CONFIG_TOPIC);