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 9d412c1a14ba3..86d32701c1062 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 @@ -112,6 +112,7 @@ protected void buildChannels() { .build(); } + boolean hasColorChannel = false; if (channelConfiguration.rgbStateTopic != null || channelConfiguration.rgbCommandTopic != null) { hasColorChannel = true; hiddenChannels.add(rgbChannel = buildChannel(RGB_CHANNEL_ID, ComponentChannelType.COLOR, @@ -167,7 +168,7 @@ protected void buildChannels() { if (localBrightnessChannel != null) { hiddenChannels.add(localBrightnessChannel); } - buildChannel(COLOR_CHANNEL_ID, ComponentChannelType.COLOR, colorValue, "Color", this) + colorChannel = buildChannel(COLOR_CHANNEL_ID, ComponentChannelType.COLOR, colorValue, "Color", this) .commandTopic(DUMMY_TOPIC, channelConfiguration.isRetain(), channelConfiguration.getQos()) .commandFilter(this::handleColorCommand).build(); } else if (localBrightnessChannel != null) { @@ -280,74 +281,76 @@ private boolean handleColorCommand(Command command) { @Override public void updateChannelState(ChannelUID channel, State state) { ChannelStateUpdateListener listener = this.channelStateUpdateListener; - switch (channel.getIdWithoutGroup()) { - case ON_OFF_CHANNEL_ID: - if (hasColorChannel) { - HSBType newOnState = colorValue.getChannelState() instanceof HSBType - ? (HSBType) colorValue.getChannelState() - : HSBType.WHITE; - if (state.equals(OnOffType.ON)) { - colorValue.update(newOnState); - } - - listener.updateChannelState(buildChannelUID(COLOR_CHANNEL_ID), - state.equals(OnOffType.ON) ? newOnState : HSBType.BLACK); - } else if (brightnessChannel != null) { - listener.updateChannelState(new ChannelUID(channel.getThingUID(), BRIGHTNESS_CHANNEL_ID), - state.equals(OnOffType.ON) ? brightnessValue.getChannelState() : PercentType.ZERO); - } else { - listener.updateChannelState(channel, state); - } - return; - case BRIGHTNESS_CHANNEL_ID: - onOffValue.update(Objects.requireNonNull(state.as(OnOffType.class))); - if (hasColorChannel) { - if (colorValue.getChannelState() instanceof HSBType) { - HSBType hsb = (HSBType) (colorValue.getChannelState()); - colorValue.update(new HSBType(hsb.getHue(), hsb.getSaturation(), - (PercentType) brightnessValue.getChannelState())); - } else { - colorValue.update(new HSBType(DecimalType.ZERO, PercentType.ZERO, - (PercentType) brightnessValue.getChannelState())); - } - listener.updateChannelState(buildChannelUID(COLOR_CHANNEL_ID), colorValue.getChannelState()); - } else { - listener.updateChannelState(channel, state); - } - return; - case COLOR_TEMP_CHANNEL_ID: - case EFFECT_CHANNEL_ID: - // Real channels; pass through - listener.updateChannelState(channel, state); - return; - case HS_CHANNEL_ID: - case XY_CHANNEL_ID: - if (brightnessValue.getChannelState() instanceof UnDefType) { - brightnessValue.update(PercentType.HUNDRED); - } - String[] split = state.toString().split(","); - if (split.length != 2) { - throw new IllegalArgumentException(state.toString() + " is not a valid string syntax"); + String id = channel.getIdWithoutGroup(); + ComponentChannel localBrightnessChannel = brightnessChannel; + ComponentChannel localColorChannel = colorChannel; + ChannelUID primaryChannelUID; + if (localColorChannel != null) { + primaryChannelUID = localColorChannel.getChannel().getUID(); + } else if (localBrightnessChannel != null) { + primaryChannelUID = localBrightnessChannel.getChannel().getUID(); + } else { + primaryChannelUID = onOffChannel.getChannel().getUID(); + } + // on_off, brightness, and color might exist as a sole channel, which means + // they got renamed. they need to be compared against the actual UID of the + // channel. all the rest we can just check against the basic ID + if (channel.equals(onOffChannel.getChannel().getUID())) { + if (localColorChannel != null) { + HSBType newOnState = colorValue.getChannelState() instanceof HSBType + ? (HSBType) colorValue.getChannelState() + : HSBType.WHITE; + if (state.equals(OnOffType.ON)) { + colorValue.update(newOnState); } - float x = Float.parseFloat(split[0]); - float y = Float.parseFloat(split[1]); - PercentType brightness = (PercentType) brightnessValue.getChannelState(); - if (channel.getIdWithoutGroup().equals(HS_CHANNEL_ID)) { - colorValue.update(new HSBType(new DecimalType(x), new PercentType(new BigDecimal(y)), brightness)); + + listener.updateChannelState(primaryChannelUID, state.equals(OnOffType.ON) ? newOnState : HSBType.BLACK); + } else if (brightnessChannel != null) { + listener.updateChannelState(primaryChannelUID, + state.equals(OnOffType.ON) ? brightnessValue.getChannelState() : PercentType.ZERO); + } else { + listener.updateChannelState(primaryChannelUID, state); + } + } else if (localBrightnessChannel != null && localBrightnessChannel.getChannel().getUID().equals(channel)) { + onOffValue.update(Objects.requireNonNull(state.as(OnOffType.class))); + if (localColorChannel != null) { + if (colorValue.getChannelState() instanceof HSBType) { + HSBType hsb = (HSBType) (colorValue.getChannelState()); + colorValue.update(new HSBType(hsb.getHue(), hsb.getSaturation(), + (PercentType) brightnessValue.getChannelState())); } else { - HSBType xyColor = HSBType.fromXY(x, y); - colorValue.update(new HSBType(xyColor.getHue(), xyColor.getSaturation(), brightness)); + colorValue.update(new HSBType(DecimalType.ZERO, PercentType.ZERO, + (PercentType) brightnessValue.getChannelState())); } - listener.updateChannelState(buildChannelUID(COLOR_CHANNEL_ID), colorValue.getChannelState()); - return; - case RGB_CHANNEL_ID: - colorValue.update((HSBType) state); - listener.updateChannelState(buildChannelUID(COLOR_CHANNEL_ID), colorValue.getChannelState()); - break; - case RGBW_CHANNEL_ID: - case RGBWW_CHANNEL_ID: - // TODO: update color value - break; + listener.updateChannelState(primaryChannelUID, colorValue.getChannelState()); + } else { + listener.updateChannelState(primaryChannelUID, state); + } + } else if (id.equals(COLOR_TEMP_CHANNEL_ID) || channel.getIdWithoutGroup().equals(EFFECT_CHANNEL_ID)) { + // Real channels; pass through + listener.updateChannelState(channel, state); + } else if (id.equals(HS_CHANNEL_ID) || id.equals(XY_CHANNEL_ID)) { + if (brightnessValue.getChannelState() instanceof UnDefType) { + brightnessValue.update(PercentType.HUNDRED); + } + String[] split = state.toString().split(","); + if (split.length != 2) { + throw new IllegalArgumentException(state.toString() + " is not a valid string syntax"); + } + float x = Float.parseFloat(split[0]); + float y = Float.parseFloat(split[1]); + PercentType brightness = (PercentType) brightnessValue.getChannelState(); + if (channel.getIdWithoutGroup().equals(HS_CHANNEL_ID)) { + colorValue.update(new HSBType(new DecimalType(x), new PercentType(new BigDecimal(y)), brightness)); + } else { + HSBType xyColor = HSBType.fromXY(x, y); + colorValue.update(new HSBType(xyColor.getHue(), xyColor.getSaturation(), brightness)); + } + listener.updateChannelState(primaryChannelUID, colorValue.getChannelState()); + } else if (id.equals(RGB_CHANNEL_ID)) { + colorValue.update((HSBType) state); + listener.updateChannelState(primaryChannelUID, colorValue.getChannelState()); } + // else rgbw channel, rgbww channel } } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Fan.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Fan.java index 539a0b43a2052..3c8ed4139aba0 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Fan.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Fan.java @@ -14,6 +14,7 @@ import java.math.BigDecimal; import java.util.List; +import java.util.Objects; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -118,6 +119,8 @@ static class ChannelConfiguration extends AbstractChannelConfiguration { private final PercentageValue speedValue; private State rawSpeedState; private final ComponentChannel onOffChannel; + private final @Nullable ComponentChannel speedChannel; + private final ComponentChannel primaryChannel; private final ChannelStateUpdateListener channelStateUpdateListener; public Fan(ComponentFactory.ComponentConfiguration componentConfiguration, boolean newStyleChannels) { @@ -144,11 +147,15 @@ public Fan(ComponentFactory.ComponentConfiguration componentConfiguration, boole if (channelConfiguration.percentageCommandTopic != null) { hiddenChannels.add(onOffChannel); - buildChannel(SPEED_CHANNEL_ID, ComponentChannelType.DIMMER, speedValue, "Speed", this) + primaryChannel = speedChannel = buildChannel(SPEED_CHANNEL_ID, ComponentChannelType.DIMMER, speedValue, + "Speed", this) .stateTopic(channelConfiguration.percentageStateTopic, channelConfiguration.percentageValueTemplate) .commandTopic(channelConfiguration.percentageCommandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos(), channelConfiguration.percentageCommandTemplate) .commandFilter(this::handlePercentageCommand).build(); + } else { + primaryChannel = onOffChannel; + speedChannel = null; } List presetModes = channelConfiguration.presetModes; @@ -198,7 +205,7 @@ private boolean handlePercentageCommand(Command command) { @Override public void updateChannelState(ChannelUID channel, State state) { - if (channel.getIdWithoutGroup().equals(SWITCH_CHANNEL_ID)) { + if (onOffChannel.getChannel().getUID().equals(channel)) { if (rawSpeedState instanceof UnDefType && state.equals(OnOffType.ON)) { // Assume full on if we don't yet know the actual speed state = PercentType.HUNDRED; @@ -207,7 +214,7 @@ public void updateChannelState(ChannelUID channel, State state) { } else { state = rawSpeedState; } - } else if (channel.getIdWithoutGroup().equals(SPEED_CHANNEL_ID)) { + } else if (Objects.requireNonNull(speedChannel).getChannel().getUID().equals(channel)) { rawSpeedState = state; if (onOffValue.getChannelState().equals(OnOffType.OFF)) { // Don't pass on percentage values while the fan is off @@ -215,7 +222,7 @@ public void updateChannelState(ChannelUID channel, State state) { } } speedValue.update(state); - channelStateUpdateListener.updateChannelState(buildChannelUID(SPEED_CHANNEL_ID), state); + channelStateUpdateListener.updateChannelState(primaryChannel.getChannel().getUID(), state); } @Override 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 ac218c337a86d..006031478c007 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 @@ -21,6 +21,7 @@ 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.ComponentChannel; import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannelType; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.HSBType; @@ -77,6 +78,7 @@ public JSONSchemaLight(ComponentFactory.ComponentConfiguration builder, boolean @Override protected void buildChannels() { + boolean hasColorChannel = false; List supportedColorModes = channelConfiguration.supportedColorModes; if (supportedColorModes != null) { if (LightColorMode.hasColorChannel(supportedColorModes)) { @@ -99,7 +101,7 @@ protected void buildChannels() { } if (hasColorChannel) { - buildChannel(COLOR_CHANNEL_ID, ComponentChannelType.COLOR, colorValue, "Color", this) + colorChannel = buildChannel(COLOR_CHANNEL_ID, ComponentChannelType.COLOR, colorValue, "Color", this) .commandTopic(DUMMY_TOPIC, true, 1).commandFilter(this::handleCommand).build(); } else if (channelConfiguration.brightness) { brightnessChannel = buildChannel(BRIGHTNESS_CHANNEL_ID, ComponentChannelType.DIMMER, brightnessValue, @@ -144,7 +146,7 @@ protected void publishState(HSBType state) { .divide(new BigDecimal(100), MathContext.DECIMAL128).intValue(); } - if (hasColorChannel) { + if (colorChannel != null) { json.color = new JSONState.Color(); if (channelConfiguration.supportedColorModes.contains(LightColorMode.COLOR_MODE_HS)) { json.color.h = state.getHue().toBigDecimal(); @@ -318,12 +320,15 @@ public void updateChannelState(ChannelUID channel, State state) { listener.updateChannelState(buildChannelUID(COLOR_MODE_CHANNEL_ID), colorModeValue.getChannelState()); - if (hasColorChannel) { - listener.updateChannelState(buildChannelUID(COLOR_CHANNEL_ID), colorValue.getChannelState()); - } else if (brightnessChannel != null) { - listener.updateChannelState(buildChannelUID(BRIGHTNESS_CHANNEL_ID), brightnessValue.getChannelState()); + ComponentChannel localBrightnessChannel = brightnessChannel; + ComponentChannel localColorChannel = colorChannel; + if (localColorChannel != null) { + listener.updateChannelState(localColorChannel.getChannel().getUID(), colorValue.getChannelState()); + } else if (localBrightnessChannel != null) { + listener.updateChannelState(localBrightnessChannel.getChannel().getUID(), + brightnessValue.getChannelState()); } else { - listener.updateChannelState(buildChannelUID(ON_OFF_CHANNEL_ID), onOffValue.getChannelState()); + listener.updateChannelState(onOffChannel.getChannel().getUID(), onOffValue.getChannelState()); } } } 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 554848e594d6b..46f26d530f757 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 @@ -228,10 +228,10 @@ static class ChannelConfiguration extends AbstractChannelConfiguration { } protected final boolean optimistic; - protected boolean hasColorChannel = false; protected @Nullable ComponentChannel onOffChannel; protected @Nullable ComponentChannel brightnessChannel; + protected @Nullable ComponentChannel colorChannel; // State has to be stored here, in order to mux multiple // MQTT sources into single OpenHAB channels diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/TemplateSchemaLight.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/TemplateSchemaLight.java index 89e46bd6295a9..3a056cb36f8a2 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/TemplateSchemaLight.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/TemplateSchemaLight.java @@ -23,6 +23,7 @@ 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.binding.mqtt.homeassistant.internal.ComponentChannelType; import org.openhab.binding.mqtt.homeassistant.internal.HomeAssistantChannelTransformation; import org.openhab.binding.mqtt.homeassistant.internal.exception.UnsupportedComponentException; @@ -85,8 +86,7 @@ protected void buildChannels() { if (channelConfiguration.redTemplate != null && channelConfiguration.greenTemplate != null && channelConfiguration.blueTemplate != null) { - hasColorChannel = true; - buildChannel(COLOR_CHANNEL_ID, ComponentChannelType.COLOR, colorValue, "Color", this) + colorChannel = buildChannel(COLOR_CHANNEL_ID, ComponentChannelType.COLOR, colorValue, "Color", this) .commandTopic(DUMMY_TOPIC, true, 1).commandFilter(command -> handleCommand(command)).build(); } else if (channelConfiguration.brightnessTemplate != null) { brightnessChannel = buildChannel(BRIGHTNESS_CHANNEL_ID, ComponentChannelType.DIMMER, brightnessValue, @@ -127,7 +127,7 @@ protected void publishState(HSBType state) { binding.put(TemplateVariables.BRIGHTNESS, state.getBrightness().toBigDecimal().multiply(factor).intValue()); } - if (hasColorChannel) { + if (colorChannel != null) { int[] rgb = ColorUtil.hsbToRgb(state); binding.put(TemplateVariables.RED, rgb[0]); binding.put(TemplateVariables.GREEN, rgb[1]); @@ -249,13 +249,15 @@ public void updateChannelState(ChannelUID channel, State state) { colorValue.update(HSBType.fromRGB(red, green, blue)); } } - - if (hasColorChannel) { - listener.updateChannelState(buildChannelUID(COLOR_CHANNEL_ID), colorValue.getChannelState()); - } else if (brightnessChannel != null) { - listener.updateChannelState(buildChannelUID(BRIGHTNESS_CHANNEL_ID), brightnessValue.getChannelState()); + ComponentChannel localBrightnessChannel = brightnessChannel; + ComponentChannel localColorChannel = colorChannel; + if (localColorChannel != null) { + listener.updateChannelState(localColorChannel.getChannel().getUID(), colorValue.getChannelState()); + } else if (localBrightnessChannel != null) { + listener.updateChannelState(localBrightnessChannel.getChannel().getUID(), + brightnessValue.getChannelState()); } else { - listener.updateChannelState(buildChannelUID(ON_OFF_CHANNEL_ID), onOffValue.getChannelState()); + listener.updateChannelState(onOffChannel.getChannel().getUID(), onOffValue.getChannelState()); } template = channelConfiguration.effectTemplate;