From 1c0bdcb596cd64a5f56a9a81fcc49556c4571bd2 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Thu, 28 Dec 2023 16:37:22 -0700 Subject: [PATCH 01/11] [mqtt.homeassistant] don't dynamically generate channel types Instead, use state descriptions for the varying parts, which means that there is not an explosion of channel types for every single Home Assistant channel, which can cause performance issues if you have a lot of devices/channels Signed-off-by: Cody Cutrer --- .../internal/MqttBindingConstants.java | 11 +- .../internal/MqttThingHandlerFactory.java | 42 +++----- .../internal/ComponentChannel.java | 75 +++++++------ .../internal/component/AbstractComponent.java | 36 +++++-- .../component/AbstractRawSchemaLight.java | 8 +- .../internal/component/AlarmControlPanel.java | 13 ++- .../internal/component/BinarySensor.java | 4 +- .../internal/component/Button.java | 4 +- .../internal/component/Camera.java | 5 +- .../internal/component/Climate.java | 52 +++++---- .../internal/component/Cover.java | 20 ++-- .../component/DefaultSchemaLight.java | 47 ++++---- .../internal/component/DeviceTrigger.java | 4 +- .../homeassistant/internal/component/Fan.java | 4 +- .../internal/component/JSONSchemaLight.java | 28 ++--- .../internal/component/Lock.java | 7 +- .../internal/component/Number.java | 4 +- .../internal/component/Scene.java | 4 +- .../internal/component/Select.java | 4 +- .../internal/component/Sensor.java | 8 +- .../internal/component/Switch.java | 4 +- .../internal/component/Update.java | 7 +- .../internal/component/Vacuum.java | 59 +++++----- .../handler/HomeAssistantThingHandler.java | 15 ++- .../config/homeassistant-channel-config.xml | 8 +- .../resources/OH-INF/i18n/mqtt.properties | 33 ++++++ .../OH-INF/thing/homeassistant-channels.xml | 102 ++++++++++++++++++ .../internal/AbstractHomeAssistantTests.java | 6 ++ .../component/AbstractComponentTests.java | 10 +- .../HomeAssistantThingHandlerTests.java | 15 +-- 30 files changed, 439 insertions(+), 200 deletions(-) create mode 100644 bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/OH-INF/thing/homeassistant-channels.xml diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/generic/internal/MqttBindingConstants.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/generic/internal/MqttBindingConstants.java index bd5c0ddcfc12c..b31a4222ca401 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/generic/internal/MqttBindingConstants.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/generic/internal/MqttBindingConstants.java @@ -14,6 +14,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.type.ChannelTypeUID; /** * The {@link MqttBindingConstants} class defines common constants, which are @@ -29,5 +30,13 @@ public class MqttBindingConstants { // List of all Thing Type UIDs public static final ThingTypeUID HOMEASSISTANT_MQTT_THING = new ThingTypeUID(BINDING_ID, "homeassistant"); - public static final String CONFIG_HA_CHANNEL = "channel-type:mqtt:ha-channel"; + public static final ChannelTypeUID CHANNEL_TYPE_UID_COLOR = new ChannelTypeUID(BINDING_ID, "ha-color"); + public static final ChannelTypeUID CHANNEL_TYPE_UID_DIMMER = new ChannelTypeUID(BINDING_ID, "ha-dimmer"); + public static final ChannelTypeUID CHANNEL_TYPE_UID_IMAGE = new ChannelTypeUID(BINDING_ID, "ha-image"); + public static final ChannelTypeUID CHANNEL_TYPE_UID_NUMBER = new ChannelTypeUID(BINDING_ID, "ha-number"); + public static final ChannelTypeUID CHANNEL_TYPE_UID_ROLLERSHUTTER = new ChannelTypeUID(BINDING_ID, + "ha-rollershutter"); + public static final ChannelTypeUID CHANNEL_TYPE_UID_STRING = new ChannelTypeUID(BINDING_ID, "ha-string"); + public static final ChannelTypeUID CHANNEL_TYPE_UID_SWITCH = new ChannelTypeUID(BINDING_ID, "ha-switch"); + public static final ChannelTypeUID CHANNEL_TYPE_UID_TRIGGER = new ChannelTypeUID(BINDING_ID, "ha-trigger"); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/generic/internal/MqttThingHandlerFactory.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/generic/internal/MqttThingHandlerFactory.java index 44e6295669676..b28fadcab1bcd 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/generic/internal/MqttThingHandlerFactory.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/generic/internal/MqttThingHandlerFactory.java @@ -18,6 +18,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.mqtt.generic.MqttChannelStateDescriptionProvider; import org.openhab.binding.mqtt.generic.MqttChannelTypeProvider; import org.openhab.binding.mqtt.generic.TransformationServiceProvider; import org.openhab.binding.mqtt.homeassistant.internal.handler.HomeAssistantThingHandler; @@ -26,12 +27,11 @@ import org.openhab.core.thing.binding.BaseThingHandlerFactory; import org.openhab.core.thing.binding.ThingHandler; import org.openhab.core.thing.binding.ThingHandlerFactory; +import org.openhab.core.thing.type.ChannelTypeRegistry; import org.openhab.core.transform.TransformationHelper; import org.openhab.core.transform.TransformationService; -import org.osgi.service.component.ComponentContext; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; -import org.osgi.service.component.annotations.Deactivate; import org.osgi.service.component.annotations.Reference; /** @@ -43,10 +43,22 @@ @Component(service = ThingHandlerFactory.class) @NonNullByDefault public class MqttThingHandlerFactory extends BaseThingHandlerFactory implements TransformationServiceProvider { - private @NonNullByDefault({}) MqttChannelTypeProvider typeProvider; + private final MqttChannelTypeProvider typeProvider; + private final MqttChannelStateDescriptionProvider stateDescriptionProvider; + private final ChannelTypeRegistry channelTypeRegistry; + private static final Set SUPPORTED_THING_TYPES_UIDS = Stream .of(MqttBindingConstants.HOMEASSISTANT_MQTT_THING).collect(Collectors.toSet()); + @Activate + public MqttThingHandlerFactory(final @Reference MqttChannelTypeProvider typeProvider, + final @Reference MqttChannelStateDescriptionProvider stateDescriptionProvider, + final @Reference ChannelTypeRegistry channelTypeRegistry) { + this.typeProvider = typeProvider; + this.stateDescriptionProvider = stateDescriptionProvider; + this.channelTypeRegistry = channelTypeRegistry; + } + @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID) || isHomeassistantDynamicType(thingTypeUID); @@ -57,33 +69,13 @@ private boolean isHomeassistantDynamicType(ThingTypeUID thingTypeUID) { && thingTypeUID.getId().startsWith(MqttBindingConstants.HOMEASSISTANT_MQTT_THING.getId()); } - @Activate - @Override - protected void activate(ComponentContext componentContext) { - super.activate(componentContext); - } - - @Deactivate - @Override - protected void deactivate(ComponentContext componentContext) { - super.deactivate(componentContext); - } - - @Reference - protected void setChannelProvider(MqttChannelTypeProvider provider) { - this.typeProvider = provider; - } - - protected void unsetChannelProvider(MqttChannelTypeProvider provider) { - this.typeProvider = null; - } - @Override protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (supportsThingType(thingTypeUID)) { - return new HomeAssistantThingHandler(thing, typeProvider, this, 10000, 2000); + return new HomeAssistantThingHandler(thing, typeProvider, stateDescriptionProvider, channelTypeRegistry, + this, 10000, 2000); } return null; } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentChannel.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentChannel.java index 41f66df011ea0..9ac5a12bf21c8 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentChannel.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentChannel.java @@ -12,7 +12,6 @@ */ package org.openhab.binding.mqtt.homeassistant.internal; -import java.net.URI; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ScheduledExecutorService; import java.util.function.Predicate; @@ -23,10 +22,8 @@ import org.openhab.binding.mqtt.generic.ChannelState; import org.openhab.binding.mqtt.generic.ChannelStateTransformation; import org.openhab.binding.mqtt.generic.ChannelStateUpdateListener; -import org.openhab.binding.mqtt.generic.MqttChannelTypeProvider; import org.openhab.binding.mqtt.generic.TransformationServiceProvider; import org.openhab.binding.mqtt.generic.values.Value; -import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.component.AbstractComponent; import org.openhab.core.config.core.Configuration; import org.openhab.core.io.transport.mqtt.MqttBrokerConnection; @@ -36,12 +33,12 @@ import org.openhab.core.thing.type.AutoUpdatePolicy; import org.openhab.core.thing.type.ChannelDefinition; import org.openhab.core.thing.type.ChannelDefinitionBuilder; +import org.openhab.core.thing.type.ChannelKind; import org.openhab.core.thing.type.ChannelType; -import org.openhab.core.thing.type.ChannelTypeBuilder; import org.openhab.core.thing.type.ChannelTypeUID; import org.openhab.core.types.Command; import org.openhab.core.types.CommandDescription; -import org.openhab.core.types.StateDescriptionFragment; +import org.openhab.core.types.StateDescription; /** * An {@link AbstractComponent}s derived class consists of one or multiple channels. @@ -65,18 +62,21 @@ public class ComponentChannel { private final ChannelUID channelUID; private final ChannelState channelState; private final Channel channel; - private final ChannelType type; private final ChannelTypeUID channelTypeUID; + private final @Nullable StateDescription stateDescription; + private final @Nullable CommandDescription commandDescription; private final ChannelStateUpdateListener channelStateUpdateListener; - private ComponentChannel(ChannelUID channelUID, ChannelState channelState, Channel channel, ChannelType type, - ChannelTypeUID channelTypeUID, ChannelStateUpdateListener channelStateUpdateListener) { + private ComponentChannel(ChannelUID channelUID, ChannelState channelState, Channel channel, + ChannelTypeUID channelTypeUID, @Nullable StateDescription stateDescription, + @Nullable CommandDescription commandDescription, ChannelStateUpdateListener channelStateUpdateListener) { super(); this.channelUID = channelUID; this.channelState = channelState; this.channel = channel; - this.type = type; this.channelTypeUID = channelTypeUID; + this.stateDescription = stateDescription; + this.commandDescription = commandDescription; this.channelStateUpdateListener = channelStateUpdateListener; } @@ -88,10 +88,22 @@ public Channel getChannel() { return channel; } + public ChannelTypeUID getChannelTypeUID() { + return channelTypeUID; + } + public ChannelState getState() { return channelState; } + public @Nullable StateDescription getStateDescription() { + return stateDescription; + } + + public @Nullable CommandDescription getCommandDescription() { + return commandDescription; + } + public CompletableFuture<@Nullable Void> stop() { return channelState.stop(); } @@ -104,15 +116,7 @@ public ChannelState getState() { return channelState.start(connection, scheduler, timeout); } - public void addChannelTypes(MqttChannelTypeProvider channelTypeProvider) { - channelTypeProvider.setChannelType(channelTypeUID, type); - } - - public void removeChannelTypes(MqttChannelTypeProvider channelTypeProvider) { - channelTypeProvider.removeChannelType(channelTypeUID); - } - - public ChannelDefinition type() { + public ChannelDefinition channelDefinition() { return new ChannelDefinitionBuilder(channelUID.getId(), channelTypeUID).build(); } @@ -123,6 +127,7 @@ public void resetState() { public static class Builder { private final AbstractComponent component; private final String channelID; + private ChannelTypeUID channelTypeUID; private final Value valueState; private final String label; private final ChannelStateUpdateListener channelStateUpdateListener; @@ -141,10 +146,11 @@ public static class Builder { private String format = "%s"; - public Builder(AbstractComponent component, String channelID, Value valueState, String label, - ChannelStateUpdateListener channelStateUpdateListener) { + public Builder(AbstractComponent component, String channelID, ChannelTypeUID channelTypeUID, + Value valueState, String label, ChannelStateUpdateListener channelStateUpdateListener) { this.component = component; this.channelID = channelID; + this.channelTypeUID = channelTypeUID; this.valueState = valueState; this.label = label; this.isAdvanced = false; @@ -230,11 +236,8 @@ public ComponentChannel build(boolean addToComponent) { ChannelState channelState; Channel channel; ChannelType type; - ChannelTypeUID channelTypeUID; channelUID = component.buildChannelUID(channelID); - channelTypeUID = new ChannelTypeUID(MqttBindingConstants.BINDING_ID, - channelUID.getGroupId() + "_" + channelID); channelState = new HomeAssistantChannelState( ChannelConfigBuilder.create().withRetain(retain).withQos(qos).withStateTopic(stateTopic) .withCommandTopic(commandTopic).makeTrigger(trigger).withFormatter(format).build(), @@ -244,30 +247,32 @@ public ComponentChannel build(boolean addToComponent) { if (!component.isEnabledByDefault()) { isAdvanced = true; } + if (isAdvanced) { + channelTypeUID = new ChannelTypeUID(channelTypeUID.getBindingId(), + channelTypeUID.getId() + "-advanced"); + } - ChannelTypeBuilder typeBuilder; + ChannelKind kind; + StateDescription stateDescription = null; + CommandDescription commandDescription = null; if (this.trigger) { - typeBuilder = ChannelTypeBuilder.trigger(channelTypeUID, label); + kind = ChannelKind.TRIGGER; } else { - StateDescriptionFragment stateDescription = valueState.createStateDescription(commandTopic == null) - .build(); - CommandDescription commandDescription = valueState.createCommandDescription().build(); - typeBuilder = ChannelTypeBuilder.state(channelTypeUID, label, channelState.getItemType()) - .withStateDescriptionFragment(stateDescription).withCommandDescription(commandDescription); + kind = ChannelKind.STATE; + stateDescription = valueState.createStateDescription(commandTopic == null).build().toStateDescription(); + commandDescription = valueState.createCommandDescription().build(); } - type = typeBuilder.withConfigDescriptionURI(URI.create(MqttBindingConstants.CONFIG_HA_CHANNEL)) - .isAdvanced(isAdvanced).build(); Configuration configuration = new Configuration(); configuration.put("config", component.getChannelConfigurationJson()); component.getHaID().toConfig(configuration); channel = ChannelBuilder.create(channelUID, channelState.getItemType()).withType(channelTypeUID) - .withKind(type.getKind()).withLabel(label).withConfiguration(configuration) + .withKind(kind).withLabel(label).withConfiguration(configuration) .withAutoUpdatePolicy(autoUpdatePolicy).build(); - ComponentChannel result = new ComponentChannel(channelUID, channelState, channel, type, channelTypeUID, - channelStateUpdateListener); + ComponentChannel result = new ComponentChannel(channelUID, channelState, channel, channelTypeUID, + stateDescription, commandDescription, channelStateUpdateListener); TransformationServiceProvider transformationProvider = component.getTransformationServiceProvider(); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java index ca901bcba9590..db8647c2b8f97 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java @@ -26,6 +26,7 @@ import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.AvailabilityTracker; import org.openhab.binding.mqtt.generic.ChannelStateUpdateListener; +import org.openhab.binding.mqtt.generic.MqttChannelStateDescriptionProvider; import org.openhab.binding.mqtt.generic.MqttChannelTypeProvider; import org.openhab.binding.mqtt.generic.TransformationServiceProvider; import org.openhab.binding.mqtt.generic.values.Value; @@ -45,6 +46,9 @@ import org.openhab.core.thing.type.ChannelGroupType; import org.openhab.core.thing.type.ChannelGroupTypeBuilder; import org.openhab.core.thing.type.ChannelGroupTypeUID; +import org.openhab.core.thing.type.ChannelTypeUID; +import org.openhab.core.types.CommandDescription; +import org.openhab.core.types.StateDescription; import com.google.gson.Gson; @@ -138,9 +142,10 @@ public AbstractComponent(ComponentFactory.ComponentConfiguration componentConfig } } - protected ComponentChannel.Builder buildChannel(String channelID, Value valueState, String label, - ChannelStateUpdateListener channelStateUpdateListener) { - return new ComponentChannel.Builder(this, channelID, valueState, label, channelStateUpdateListener); + protected ComponentChannel.Builder buildChannel(String channelID, ChannelTypeUID channelTypeUID, Value valueState, + String label, ChannelStateUpdateListener channelStateUpdateListener) { + return new ComponentChannel.Builder(this, channelID, channelTypeUID, valueState, label, + channelStateUpdateListener); } public void setConfigSeen() { @@ -181,12 +186,22 @@ public void setConfigSeen() { * * @param channelTypeProvider The channel type provider */ - public void addChannelTypes(MqttChannelTypeProvider channelTypeProvider) { + public void addChannelTypes(MqttChannelTypeProvider channelTypeProvider, + MqttChannelStateDescriptionProvider stateDescriptionProvider) { ChannelGroupTypeUID groupTypeUID = channelGroupTypeUID; if (groupTypeUID != null) { channelTypeProvider.setChannelGroupType(groupTypeUID, Objects.requireNonNull(getType())); } - channels.values().forEach(v -> v.addChannelTypes(channelTypeProvider)); + channels.values().forEach(channel -> { + StateDescription stateDescription = channel.getStateDescription(); + if (stateDescription != null) { + stateDescriptionProvider.setDescription(channel.getChannelUID(), stateDescription); + } + CommandDescription commandDescription = channel.getCommandDescription(); + if (commandDescription != null) { + stateDescriptionProvider.setDescription(channel.getChannelUID(), commandDescription); + } + }); } /** @@ -195,12 +210,13 @@ public void addChannelTypes(MqttChannelTypeProvider channelTypeProvider) { * * @param channelTypeProvider The channel type provider */ - public void removeChannelTypes(MqttChannelTypeProvider channelTypeProvider) { - channels.values().forEach(v -> v.removeChannelTypes(channelTypeProvider)); + public void removeChannelTypes(MqttChannelTypeProvider channelTypeProvider, + MqttChannelStateDescriptionProvider stateDescriptionProvider) { ChannelGroupTypeUID groupTypeUID = channelGroupTypeUID; if (groupTypeUID != null) { channelTypeProvider.removeChannelGroupType(groupTypeUID); } + channels.values().forEach(v -> stateDescriptionProvider.remove(v.getChannelUID())); } public ChannelUID buildChannelUID(String channelID) { @@ -275,14 +291,14 @@ public int getConfigHash() { if (groupTypeUID == null) { return null; } - final List channelDefinitions = channels.values().stream().map(ComponentChannel::type) - .collect(Collectors.toList()); + final List channelDefinitions = channels.values().stream() + .map(ComponentChannel::channelDefinition).collect(Collectors.toList()); return ChannelGroupTypeBuilder.instance(groupTypeUID, getName()).withChannelDefinitions(channelDefinitions) .build(); } public List getChannels() { - return channels.values().stream().map(ComponentChannel::type).collect(Collectors.toList()); + return channels.values().stream().map(ComponentChannel::channelDefinition).collect(Collectors.toList()); } /** diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractRawSchemaLight.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractRawSchemaLight.java index 2cce0c4ce8c96..8b3f6ee9ad2e8 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractRawSchemaLight.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractRawSchemaLight.java @@ -14,6 +14,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.mqtt.generic.values.TextValue; +import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannel; import org.openhab.core.library.types.HSBType; import org.openhab.core.library.types.OnOffType; @@ -33,9 +34,10 @@ abstract class AbstractRawSchemaLight extends Light { public AbstractRawSchemaLight(ComponentFactory.ComponentConfiguration builder) { super(builder); - hiddenChannels.add(rawChannel = buildChannel(RAW_CHANNEL_ID, new TextValue(), "Raw state", this) - .stateTopic(channelConfiguration.stateTopic).commandTopic(channelConfiguration.commandTopic, - channelConfiguration.isRetain(), channelConfiguration.getQos()) + hiddenChannels.add(rawChannel = buildChannel(RAW_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + new TextValue(), "Raw state", this).stateTopic(channelConfiguration.stateTopic) + .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), + channelConfiguration.getQos()) .build(false)); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AlarmControlPanel.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AlarmControlPanel.java index 961d4ee3e1e4e..8ddd56c3c8fbe 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AlarmControlPanel.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AlarmControlPanel.java @@ -15,6 +15,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.values.TextValue; +import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import com.google.gson.annotations.SerializedName; @@ -74,22 +75,24 @@ public AlarmControlPanel(ComponentFactory.ComponentConfiguration componentConfig final String[] stateEnum = { channelConfiguration.stateDisarmed, channelConfiguration.stateArmedHome, channelConfiguration.stateArmedAway, channelConfiguration.statePending, channelConfiguration.stateTriggered }; - buildChannel(STATE_CHANNEL_ID, new TextValue(stateEnum), getName(), componentConfiguration.getUpdateListener()) + buildChannel(STATE_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, new TextValue(stateEnum), + getName(), componentConfiguration.getUpdateListener()) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate())// .build(); String commandTopic = channelConfiguration.commandTopic; if (commandTopic != null) { - buildChannel(SWITCH_DISARM_CHANNEL_ID, new TextValue(new String[] { channelConfiguration.payloadDisarm }), - getName(), componentConfiguration.getUpdateListener()) + buildChannel(SWITCH_DISARM_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + new TextValue(new String[] { channelConfiguration.payloadDisarm }), getName(), + componentConfiguration.getUpdateListener()) .commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()).build(); - buildChannel(SWITCH_ARM_HOME_CHANNEL_ID, + buildChannel(SWITCH_ARM_HOME_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, new TextValue(new String[] { channelConfiguration.payloadArmHome }), getName(), componentConfiguration.getUpdateListener()) .commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()).build(); - buildChannel(SWITCH_ARM_AWAY_CHANNEL_ID, + buildChannel(SWITCH_ARM_AWAY_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, new TextValue(new String[] { channelConfiguration.payloadArmAway }), getName(), componentConfiguration.getUpdateListener()) .commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()).build(); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensor.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensor.java index 2d636e95254f5..e808ee42a2cc1 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensor.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensor.java @@ -19,6 +19,7 @@ import org.openhab.binding.mqtt.generic.ChannelStateUpdateListener; import org.openhab.binding.mqtt.generic.values.OnOffValue; import org.openhab.binding.mqtt.generic.values.Value; +import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.binding.mqtt.homeassistant.internal.listener.ExpireUpdateStateListener; import org.openhab.binding.mqtt.homeassistant.internal.listener.OffDelayUpdateStateListener; @@ -72,7 +73,8 @@ public BinarySensor(ComponentFactory.ComponentConfiguration componentConfigurati OnOffValue value = new OnOffValue(channelConfiguration.payloadOn, channelConfiguration.payloadOff); - buildChannel(SENSOR_CHANNEL_ID, value, "value", getListener(componentConfiguration, value)) + buildChannel(SENSOR_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, value, "value", + getListener(componentConfiguration, value)) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()) .withAutoUpdatePolicy(AutoUpdatePolicy.VETO).build(); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Button.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Button.java index c54fcd48b5606..7e461ebf5cbac 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Button.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Button.java @@ -15,6 +15,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.values.TextValue; +import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.core.thing.type.AutoUpdatePolicy; @@ -51,7 +52,8 @@ public Button(ComponentFactory.ComponentConfiguration componentConfiguration) { TextValue value = new TextValue(new String[] { channelConfiguration.payloadPress }); - buildChannel(BUTTON_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener()) + buildChannel(BUTTON_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, value, getName(), + componentConfiguration.getUpdateListener()) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) .withAutoUpdatePolicy(AutoUpdatePolicy.VETO).build(); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Camera.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Camera.java index 97fddc02dffc0..30a3f78beda16 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Camera.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Camera.java @@ -14,6 +14,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.mqtt.generic.values.ImageValue; +import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; /** @@ -43,7 +44,7 @@ public Camera(ComponentFactory.ComponentConfiguration componentConfiguration) { ImageValue value = new ImageValue(); - buildChannel(CAMERA_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener()) - .stateTopic(channelConfiguration.topic).build(); + buildChannel(CAMERA_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_IMAGE, value, getName(), + componentConfiguration.getUpdateListener()).stateTopic(channelConfiguration.topic).build(); } } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Climate.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Climate.java index 2b8cc8ad97fa0..0215ed73b5245 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Climate.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Climate.java @@ -27,11 +27,13 @@ import org.openhab.binding.mqtt.generic.values.OnOffValue; import org.openhab.binding.mqtt.generic.values.TextValue; import org.openhab.binding.mqtt.generic.values.Value; +import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannel; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.core.library.types.StringType; import org.openhab.core.library.unit.ImperialUnits; import org.openhab.core.library.unit.SIUnits; +import org.openhab.core.thing.type.ChannelTypeUID; import org.openhab.core.types.Command; import org.openhab.core.types.State; @@ -218,75 +220,81 @@ public Climate(ComponentFactory.ComponentConfiguration componentConfiguration) { final ChannelStateUpdateListener updateListener = componentConfiguration.getUpdateListener(); ComponentChannel actionChannel = buildOptionalChannel(ACTION_CH_ID, - new TextValue(ACTION_MODES.toArray(new String[0])), updateListener, null, null, - channelConfiguration.actionTemplate, channelConfiguration.actionTopic, null); + MqttBindingConstants.CHANNEL_TYPE_UID_STRING, new TextValue(ACTION_MODES.toArray(new String[0])), + updateListener, null, null, channelConfiguration.actionTemplate, channelConfiguration.actionTopic, + null); final Predicate commandFilter = channelConfiguration.sendIfOff ? null : getCommandFilter(actionChannel); - buildOptionalChannel(AUX_CH_ID, new OnOffValue(), updateListener, null, channelConfiguration.auxCommandTopic, - channelConfiguration.auxStateTemplate, channelConfiguration.auxStateTopic, commandFilter); + buildOptionalChannel(AUX_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, new OnOffValue(), updateListener, + null, channelConfiguration.auxCommandTopic, channelConfiguration.auxStateTemplate, + channelConfiguration.auxStateTopic, commandFilter); - buildOptionalChannel(AWAY_MODE_CH_ID, new OnOffValue(), updateListener, null, - channelConfiguration.awayModeCommandTopic, channelConfiguration.awayModeStateTemplate, - channelConfiguration.awayModeStateTopic, commandFilter); + buildOptionalChannel(AWAY_MODE_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, new OnOffValue(), + updateListener, null, channelConfiguration.awayModeCommandTopic, + channelConfiguration.awayModeStateTemplate, channelConfiguration.awayModeStateTopic, commandFilter); - buildOptionalChannel(CURRENT_TEMPERATURE_CH_ID, + buildOptionalChannel(CURRENT_TEMPERATURE_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_NUMBER, new NumberValue(null, null, precision, channelConfiguration.temperatureUnit.getUnit()), updateListener, null, null, channelConfiguration.currentTemperatureTemplate, channelConfiguration.currentTemperatureTopic, commandFilter); - buildOptionalChannel(FAN_MODE_CH_ID, new TextValue(channelConfiguration.fanModes.toArray(new String[0])), - updateListener, channelConfiguration.fanModeCommandTemplate, channelConfiguration.fanModeCommandTopic, + buildOptionalChannel(FAN_MODE_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + new TextValue(channelConfiguration.fanModes.toArray(new String[0])), updateListener, + channelConfiguration.fanModeCommandTemplate, channelConfiguration.fanModeCommandTopic, channelConfiguration.fanModeStateTemplate, channelConfiguration.fanModeStateTopic, commandFilter); List holdModes = channelConfiguration.holdModes; if (holdModes != null && !holdModes.isEmpty()) { - buildOptionalChannel(HOLD_CH_ID, new TextValue(holdModes.toArray(new String[0])), updateListener, + buildOptionalChannel(HOLD_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + new TextValue(holdModes.toArray(new String[0])), updateListener, channelConfiguration.holdCommandTemplate, channelConfiguration.holdCommandTopic, channelConfiguration.holdStateTemplate, channelConfiguration.holdStateTopic, commandFilter); } - buildOptionalChannel(MODE_CH_ID, new TextValue(channelConfiguration.modes.toArray(new String[0])), - updateListener, channelConfiguration.modeCommandTemplate, channelConfiguration.modeCommandTopic, + buildOptionalChannel(MODE_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + new TextValue(channelConfiguration.modes.toArray(new String[0])), updateListener, + channelConfiguration.modeCommandTemplate, channelConfiguration.modeCommandTopic, channelConfiguration.modeStateTemplate, channelConfiguration.modeStateTopic, commandFilter); - buildOptionalChannel(SWING_CH_ID, new TextValue(channelConfiguration.swingModes.toArray(new String[0])), - updateListener, channelConfiguration.swingCommandTemplate, channelConfiguration.swingCommandTopic, + buildOptionalChannel(SWING_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + new TextValue(channelConfiguration.swingModes.toArray(new String[0])), updateListener, + channelConfiguration.swingCommandTemplate, channelConfiguration.swingCommandTopic, channelConfiguration.swingStateTemplate, channelConfiguration.swingStateTopic, commandFilter); - buildOptionalChannel(TEMPERATURE_CH_ID, + buildOptionalChannel(TEMPERATURE_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_NUMBER, new NumberValue(channelConfiguration.minTemp, channelConfiguration.maxTemp, channelConfiguration.tempStep, channelConfiguration.temperatureUnit.getUnit()), updateListener, channelConfiguration.temperatureCommandTemplate, channelConfiguration.temperatureCommandTopic, channelConfiguration.temperatureStateTemplate, channelConfiguration.temperatureStateTopic, commandFilter); - buildOptionalChannel(TEMPERATURE_HIGH_CH_ID, + buildOptionalChannel(TEMPERATURE_HIGH_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_NUMBER, new NumberValue(channelConfiguration.minTemp, channelConfiguration.maxTemp, channelConfiguration.tempStep, channelConfiguration.temperatureUnit.getUnit()), updateListener, channelConfiguration.temperatureHighCommandTemplate, channelConfiguration.temperatureHighCommandTopic, channelConfiguration.temperatureHighStateTemplate, channelConfiguration.temperatureHighStateTopic, commandFilter); - buildOptionalChannel(TEMPERATURE_LOW_CH_ID, + buildOptionalChannel(TEMPERATURE_LOW_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_NUMBER, new NumberValue(channelConfiguration.minTemp, channelConfiguration.maxTemp, channelConfiguration.tempStep, channelConfiguration.temperatureUnit.getUnit()), updateListener, channelConfiguration.temperatureLowCommandTemplate, channelConfiguration.temperatureLowCommandTopic, channelConfiguration.temperatureLowStateTemplate, channelConfiguration.temperatureLowStateTopic, commandFilter); - buildOptionalChannel(POWER_CH_ID, new OnOffValue(), updateListener, null, - channelConfiguration.powerCommandTopic, null, null, null); + buildOptionalChannel(POWER_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, new OnOffValue(), + updateListener, null, channelConfiguration.powerCommandTopic, null, null, null); } @Nullable - private ComponentChannel buildOptionalChannel(String channelId, Value valueState, + private ComponentChannel buildOptionalChannel(String channelId, ChannelTypeUID channelTypeUID, Value valueState, ChannelStateUpdateListener channelStateUpdateListener, @Nullable String commandTemplate, @Nullable String commandTopic, @Nullable String stateTemplate, @Nullable String stateTopic, @Nullable Predicate commandFilter) { if ((commandTopic != null && !commandTopic.isBlank()) || (stateTopic != null && !stateTopic.isBlank())) { - return buildChannel(channelId, valueState, getName(), channelStateUpdateListener) + return buildChannel(channelId, channelTypeUID, valueState, getName(), channelStateUpdateListener) .stateTopic(stateTopic, stateTemplate, channelConfiguration.getValueTemplate()) .commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos(), commandTemplate) diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Cover.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Cover.java index 55f5b632705f6..21dfcf9febb7f 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Cover.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Cover.java @@ -16,6 +16,7 @@ import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.values.RollershutterValue; import org.openhab.binding.mqtt.generic.values.TextValue; +import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannel; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.core.library.types.StopMoveType; @@ -95,16 +96,17 @@ public Cover(ComponentFactory.ComponentConfiguration componentConfiguration) { TextValue value = new TextValue(new String[] { channelConfiguration.stateClosed, channelConfiguration.stateClosing, channelConfiguration.stateOpen, channelConfiguration.stateOpening, channelConfiguration.stateStopped }); - buildChannel(STATE_CHANNEL_ID, value, "State", componentConfiguration.getUpdateListener()) - .stateTopic(stateTopic).isAdvanced(true).build(); + buildChannel(STATE_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, value, "State", + componentConfiguration.getUpdateListener()).stateTopic(stateTopic).isAdvanced(true).build(); } if (channelConfiguration.commandTopic != null) { - hiddenChannels.add(stateChannel = buildChannel(STATE_CHANNEL_ID, new TextValue(), "State", - componentConfiguration.getUpdateListener()) - .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), - channelConfiguration.getQos()) - .build(false)); + hiddenChannels + .add(stateChannel = buildChannel(STATE_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + new TextValue(), "State", componentConfiguration.getUpdateListener()) + .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), + channelConfiguration.getQos()) + .build(false)); } else { // no command topic. we need to make sure we send // integers for open and close @@ -132,8 +134,8 @@ public Cover(ComponentFactory.ComponentConfiguration componentConfiguration) { channelConfiguration.payloadClose, channelConfiguration.payloadStop, channelConfiguration.stateOpen, channelConfiguration.stateClosed, inverted, channelConfiguration.setPositionTopic == null); - buildChannel(COVER_CHANNEL_ID, value, "Cover", componentConfiguration.getUpdateListener()) - .stateTopic(rollershutterStateTopic, stateTemplate) + buildChannel(COVER_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_ROLLERSHUTTER, value, "Cover", + componentConfiguration.getUpdateListener()).stateTopic(rollershutterStateTopic, stateTemplate) .commandTopic(rollershutterCommandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) .commandFilter(command -> { if (stateChannel == null) { 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 3db47a4051dbd..573b3efec82fa 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 @@ -21,6 +21,7 @@ import org.openhab.binding.mqtt.generic.mapping.ColorMode; import org.openhab.binding.mqtt.generic.values.ColorValue; import org.openhab.binding.mqtt.generic.values.TextValue; +import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannel; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.HSBType; @@ -60,7 +61,8 @@ public DefaultSchemaLight(ComponentFactory.ComponentConfiguration builder) { @Override protected void buildChannels() { ComponentChannel localOnOffChannel; - localOnOffChannel = onOffChannel = buildChannel(ON_OFF_CHANNEL_ID, onOffValue, "On/Off State", this) + localOnOffChannel = onOffChannel = buildChannel(ON_OFF_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, + onOffValue, "On/Off State", this) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.stateValueTemplate) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) @@ -69,8 +71,8 @@ protected void buildChannels() { @Nullable ComponentChannel localBrightnessChannel = null; if (channelConfiguration.brightnessStateTopic != null || channelConfiguration.brightnessCommandTopic != null) { - localBrightnessChannel = brightnessChannel = buildChannel(BRIGHTNESS_CHANNEL_ID, brightnessValue, - "Brightness", this) + localBrightnessChannel = brightnessChannel = buildChannel(BRIGHTNESS_CHANNEL_ID, + MqttBindingConstants.CHANNEL_TYPE_UID_DIMMER, brightnessValue, "Brightness", this) .stateTopic(channelConfiguration.brightnessStateTopic, channelConfiguration.brightnessValueTemplate) .commandTopic(channelConfiguration.brightnessCommandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) @@ -78,20 +80,23 @@ protected void buildChannels() { } if (channelConfiguration.whiteCommandTopic != null) { - buildChannel(WHITE_CHANNEL_ID, brightnessValue, "Go directly to white of a specific brightness", this) + buildChannel(WHITE_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_DIMMER, brightnessValue, + "Go directly to white of a specific brightness", this) .commandTopic(channelConfiguration.whiteCommandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) .isAdvanced(true).build(); } if (channelConfiguration.colorModeStateTopic != null) { - buildChannel(COLOR_MODE_CHANNEL_ID, new TextValue(), "Current color mode", this) + buildChannel(COLOR_MODE_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, new TextValue(), + "Current color mode", this) .stateTopic(channelConfiguration.colorModeStateTopic, channelConfiguration.colorModeValueTemplate) .build(); } if (channelConfiguration.colorTempStateTopic != null || channelConfiguration.colorTempCommandTopic != null) { - buildChannel(COLOR_TEMP_CHANNEL_ID, colorTempValue, "Color Temperature", this) + buildChannel(COLOR_TEMP_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_NUMBER, colorTempValue, + "Color Temperature", this) .stateTopic(channelConfiguration.colorTempStateTopic, channelConfiguration.colorTempValueTemplate) .commandTopic(channelConfiguration.colorTempCommandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) @@ -100,7 +105,8 @@ protected void buildChannels() { if (effectValue != null && (channelConfiguration.effectStateTopic != null || channelConfiguration.effectCommandTopic != null)) { - buildChannel(EFFECT_CHANNEL_ID, Objects.requireNonNull(effectValue), "Lighting Effect", this) + buildChannel(EFFECT_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + Objects.requireNonNull(effectValue), "Lighting Effect", this) .stateTopic(channelConfiguration.effectStateTopic, channelConfiguration.effectValueTemplate) .commandTopic(channelConfiguration.effectCommandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) @@ -109,8 +115,8 @@ protected void buildChannels() { if (channelConfiguration.rgbStateTopic != null || channelConfiguration.rgbCommandTopic != null) { hasColorChannel = true; - hiddenChannels.add(rgbChannel = buildChannel(RGB_CHANNEL_ID, new ColorValue(ColorMode.RGB, null, null, 100), - "RGB state", this) + hiddenChannels.add(rgbChannel = buildChannel(RGB_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_COLOR, + new ColorValue(ColorMode.RGB, null, null, 100), "RGB state", this) .stateTopic(channelConfiguration.rgbStateTopic, channelConfiguration.rgbValueTemplate) .commandTopic(channelConfiguration.rgbCommandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) @@ -119,7 +125,8 @@ protected void buildChannels() { if (channelConfiguration.rgbwStateTopic != null || channelConfiguration.rgbwCommandTopic != null) { hasColorChannel = true; - hiddenChannels.add(buildChannel(RGBW_CHANNEL_ID, new TextValue(), "RGBW state", this) + hiddenChannels.add(buildChannel(RGBW_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + new TextValue(), "RGBW state", this) .stateTopic(channelConfiguration.rgbwStateTopic, channelConfiguration.rgbwValueTemplate) .commandTopic(channelConfiguration.rgbwCommandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) @@ -128,7 +135,8 @@ protected void buildChannels() { if (channelConfiguration.rgbwwStateTopic != null || channelConfiguration.rgbwwCommandTopic != null) { hasColorChannel = true; - hiddenChannels.add(buildChannel(RGBWW_CHANNEL_ID, new TextValue(), "RGBWW state", this) + hiddenChannels.add(buildChannel(RGBWW_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + new TextValue(), "RGBWW state", this) .stateTopic(channelConfiguration.rgbwwStateTopic, channelConfiguration.rgbwwValueTemplate) .commandTopic(channelConfiguration.rgbwwCommandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) @@ -137,17 +145,18 @@ protected void buildChannels() { if (channelConfiguration.xyStateTopic != null || channelConfiguration.xyCommandTopic != null) { hasColorChannel = true; - hiddenChannels.add( - xyChannel = buildChannel(XY_CHANNEL_ID, new ColorValue(ColorMode.XYY, null, null, 100), "XY State", - this).stateTopic(channelConfiguration.xyStateTopic, channelConfiguration.xyValueTemplate) - .commandTopic(channelConfiguration.xyCommandTopic, channelConfiguration.isRetain(), - channelConfiguration.getQos()) - .build(false)); + hiddenChannels.add(xyChannel = buildChannel(XY_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_COLOR, + new ColorValue(ColorMode.XYY, null, null, 100), "XY State", this) + .stateTopic(channelConfiguration.xyStateTopic, channelConfiguration.xyValueTemplate) + .commandTopic(channelConfiguration.xyCommandTopic, channelConfiguration.isRetain(), + channelConfiguration.getQos()) + .build(false)); } if (channelConfiguration.hsStateTopic != null || channelConfiguration.hsCommandTopic != null) { hasColorChannel = true; - hiddenChannels.add(this.hsChannel = buildChannel(HS_CHANNEL_ID, new TextValue(), "Hue and Saturation", this) + hiddenChannels.add(this.hsChannel = buildChannel(HS_CHANNEL_ID, + MqttBindingConstants.CHANNEL_TYPE_UID_STRING, new TextValue(), "Hue and Saturation", this) .stateTopic(channelConfiguration.hsStateTopic, channelConfiguration.hsValueTemplate) .commandTopic(channelConfiguration.hsCommandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) @@ -159,7 +168,7 @@ protected void buildChannels() { if (localBrightnessChannel != null) { hiddenChannels.add(localBrightnessChannel); } - buildChannel(COLOR_CHANNEL_ID, colorValue, "Color", this) + buildChannel(COLOR_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_COLOR, colorValue, "Color", this) .commandTopic(DUMMY_TOPIC, channelConfiguration.isRetain(), channelConfiguration.getQos()) .commandFilter(this::handleColorCommand).build(); } else if (localBrightnessChannel != null) { diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DeviceTrigger.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DeviceTrigger.java index 0ff48e027381c..74a20f9768026 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DeviceTrigger.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DeviceTrigger.java @@ -15,6 +15,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.values.TextValue; +import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.binding.mqtt.homeassistant.internal.exception.ConfigurationException; @@ -65,7 +66,8 @@ public DeviceTrigger(ComponentFactory.ComponentConfiguration componentConfigurat value = new TextValue(); } - buildChannel(channelConfiguration.type, value, getName(), componentConfiguration.getUpdateListener()) + buildChannel(channelConfiguration.type, MqttBindingConstants.CHANNEL_TYPE_UID_TRIGGER, value, getName(), + componentConfiguration.getUpdateListener()) .stateTopic(channelConfiguration.topic, channelConfiguration.getValueTemplate()).trigger(true).build(); } } 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 4a0a041d11004..ea022092a0373 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 @@ -15,6 +15,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.values.OnOffValue; +import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import com.google.gson.annotations.SerializedName; @@ -54,7 +55,8 @@ public Fan(ComponentFactory.ComponentConfiguration componentConfiguration) { super(componentConfiguration, ChannelConfiguration.class); OnOffValue value = new OnOffValue(channelConfiguration.payloadOn, channelConfiguration.payloadOff); - buildChannel(SWITCH_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener()) + buildChannel(SWITCH_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, value, getName(), + componentConfiguration.getUpdateListener()) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos(), channelConfiguration.commandTemplate) 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 b678d3830eaf0..1f68b4eb6f38f 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.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.exception.UnsupportedComponentException; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.HSBType; @@ -84,7 +85,8 @@ protected void buildChannels() { 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, colorModeValue, "Color Mode", this).isAdvanced(true).build(); + buildChannel(COLOR_MODE_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, colorModeValue, + "Color Mode", this).isAdvanced(true).build(); } if (channelConfiguration.colorMode) { @@ -98,26 +100,28 @@ protected void buildChannels() { } if (supportedColorModes.contains(LightColorMode.COLOR_MODE_COLOR_TEMP)) { - buildChannel(COLOR_TEMP_CHANNEL_ID, colorTempValue, "Color Temperature", this) - .commandTopic(DUMMY_TOPIC, true, 1).commandFilter(command -> handleColorTempCommand(command)) - .build(); + buildChannel(COLOR_TEMP_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_NUMBER, colorTempValue, + "Color Temperature", this).commandTopic(DUMMY_TOPIC, true, 1) + .commandFilter(command -> handleColorTempCommand(command)).build(); } } if (hasColorChannel) { - buildChannel(COLOR_CHANNEL_ID, colorValue, "Color", this).commandTopic(DUMMY_TOPIC, true, 1) - .commandFilter(this::handleCommand).build(); - } else if (channelConfiguration.brightness) { - brightnessChannel = buildChannel(BRIGHTNESS_CHANNEL_ID, brightnessValue, "Brightness", this) + buildChannel(COLOR_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_COLOR, colorValue, "Color", this) .commandTopic(DUMMY_TOPIC, true, 1).commandFilter(this::handleCommand).build(); + } else if (channelConfiguration.brightness) { + brightnessChannel = buildChannel(BRIGHTNESS_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_DIMMER, + brightnessValue, "Brightness", this).commandTopic(DUMMY_TOPIC, true, 1) + .commandFilter(this::handleCommand).build(); } else { - onOffChannel = buildChannel(ON_OFF_CHANNEL_ID, onOffValue, "On/Off State", this) - .commandTopic(DUMMY_TOPIC, true, 1).commandFilter(this::handleCommand).build(); + onOffChannel = buildChannel(ON_OFF_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, 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(); + buildChannel(EFFECT_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + Objects.requireNonNull(effectValue), "Lighting Effect", this).commandTopic(DUMMY_TOPIC, true, 1) + .commandFilter(command -> handleEffectCommand(command)).build(); } } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Lock.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Lock.java index eab24ceffc7d6..ee865e7fd34f2 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Lock.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Lock.java @@ -17,6 +17,7 @@ import org.openhab.binding.mqtt.generic.ChannelStateUpdateListener; import org.openhab.binding.mqtt.generic.values.OnOffValue; import org.openhab.binding.mqtt.generic.values.TextValue; +import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.StringType; @@ -82,7 +83,8 @@ public Lock(ComponentFactory.ComponentConfiguration componentConfiguration) { channelConfiguration.stateUnlocking, channelConfiguration.stateJammed }, channelConfiguration.payloadLock, channelConfiguration.payloadUnlock); - buildChannel(LOCK_CHANNEL_ID, lockValue, "Lock", componentConfiguration.getUpdateListener()) + buildChannel(LOCK_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, lockValue, "Lock", + componentConfiguration.getUpdateListener()) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) @@ -103,7 +105,8 @@ public Lock(ComponentFactory.ComponentConfiguration componentConfiguration) { stateValue = new TextValue(new String[] { channelConfiguration.stateJammed, channelConfiguration.stateLocked, channelConfiguration.stateLocking, channelConfiguration.stateUnlocked, channelConfiguration.stateUnlocking }, commands); - buildChannel(STATE_CHANNEL_ID, stateValue, "State", componentConfiguration.getUpdateListener()) + buildChannel(STATE_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, stateValue, "State", + componentConfiguration.getUpdateListener()) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Number.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Number.java index 73635d99c6ed2..c3d6a3a003957 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Number.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Number.java @@ -17,6 +17,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.values.NumberValue; +import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.binding.mqtt.homeassistant.internal.exception.ConfigurationException; import org.openhab.core.types.util.UnitUtils; @@ -82,7 +83,8 @@ public Number(ComponentFactory.ComponentConfiguration componentConfiguration) { NumberValue value = new NumberValue(channelConfiguration.min, channelConfiguration.max, channelConfiguration.step, UnitUtils.parseUnit(channelConfiguration.unitOfMeasurement)); - buildChannel(NUMBER_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener()) + buildChannel(NUMBER_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_NUMBER, value, getName(), + componentConfiguration.getUpdateListener()) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos(), channelConfiguration.commandTemplate) diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Scene.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Scene.java index 85df85b4796a0..ed0707ccd4aac 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Scene.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Scene.java @@ -15,6 +15,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.values.TextValue; +import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.core.thing.type.AutoUpdatePolicy; @@ -49,7 +50,8 @@ public Scene(ComponentFactory.ComponentConfiguration componentConfiguration) { TextValue value = new TextValue(new String[] { channelConfiguration.payloadOn }); - buildChannel(SCENE_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener()) + buildChannel(SCENE_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, value, getName(), + componentConfiguration.getUpdateListener()) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) .withAutoUpdatePolicy(AutoUpdatePolicy.VETO).build(); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Select.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Select.java index 0d54c4ca15783..ce1b3be3364c8 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Select.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Select.java @@ -15,6 +15,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.values.TextValue; +import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.binding.mqtt.homeassistant.internal.exception.ConfigurationException; @@ -66,7 +67,8 @@ public Select(ComponentFactory.ComponentConfiguration componentConfiguration) { TextValue value = new TextValue(channelConfiguration.options); - buildChannel(SELECT_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener()) + buildChannel(SELECT_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, value, getName(), + componentConfiguration.getUpdateListener()) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos(), channelConfiguration.commandTemplate) diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Sensor.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Sensor.java index 26b6c704d6ae8..cdd308d4f9000 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Sensor.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Sensor.java @@ -21,8 +21,10 @@ import org.openhab.binding.mqtt.generic.values.NumberValue; import org.openhab.binding.mqtt.generic.values.TextValue; import org.openhab.binding.mqtt.generic.values.Value; +import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.binding.mqtt.homeassistant.internal.listener.ExpireUpdateStateListener; +import org.openhab.core.thing.type.ChannelTypeUID; import org.openhab.core.types.util.UnitUtils; import com.google.gson.annotations.SerializedName; @@ -73,22 +75,26 @@ public Sensor(ComponentFactory.ComponentConfiguration componentConfiguration) { Value value; String uom = channelConfiguration.unitOfMeasurement; String sc = channelConfiguration.stateClass; + ChannelTypeUID type; if (uom != null && !uom.isBlank()) { value = new NumberValue(null, null, null, UnitUtils.parseUnit(uom)); + type = MqttBindingConstants.CHANNEL_TYPE_UID_NUMBER; } else if (sc != null && !sc.isBlank()) { // see state_class at https://developers.home-assistant.io/docs/core/entity/sensor#properties // > If not None, the sensor is assumed to be numerical value = new NumberValue(null, null, null, null); + type = MqttBindingConstants.CHANNEL_TYPE_UID_NUMBER; } else { value = new TextValue(); + type = MqttBindingConstants.CHANNEL_TYPE_UID_STRING; } String icon = channelConfiguration.getIcon(); boolean trigger = TRIGGER_ICONS.matcher(icon).matches(); - buildChannel(SENSOR_CHANNEL_ID, value, getName(), getListener(componentConfiguration, value)) + buildChannel(SENSOR_CHANNEL_ID, type, value, getName(), getListener(componentConfiguration, value)) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate())// .trigger(trigger).build(); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Switch.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Switch.java index 83521651f8d79..a3b4d95c6ef7e 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Switch.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Switch.java @@ -15,6 +15,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.values.OnOffValue; +import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.binding.mqtt.homeassistant.internal.exception.ConfigurationException; @@ -72,7 +73,8 @@ public Switch(ComponentFactory.ComponentConfiguration componentConfiguration) { OnOffValue value = new OnOffValue(channelConfiguration.stateOn, channelConfiguration.stateOff, channelConfiguration.payloadOn, channelConfiguration.payloadOff); - buildChannel(SWITCH_CHANNEL_ID, value, "state", componentConfiguration.getUpdateListener()) + buildChannel(SWITCH_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, value, "state", + componentConfiguration.getUpdateListener()) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Update.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Update.java index 035ecd832e694..dbb048d328148 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Update.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Update.java @@ -20,6 +20,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.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannel; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.core.io.transport.mqtt.MqttBrokerConnection; @@ -149,7 +150,8 @@ public Update(ComponentFactory.ComponentConfiguration componentConfiguration) { String commandTopic = channelConfiguration.commandTopic; String payloadInstall = channelConfiguration.payloadInstall; - var builder = buildChannel(UPDATE_CHANNEL_ID, value, getName(), this); + var builder = buildChannel(UPDATE_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, value, getName(), + this); if (channelConfiguration.stateTopic != null) { builder.stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()); } @@ -162,7 +164,8 @@ public Update(ComponentFactory.ComponentConfiguration componentConfiguration) { if (channelConfiguration.latestVersionTopic != null) { value = new TextValue(); - latestVersionChannel = buildChannel(LATEST_VERSION_CHANNEL_ID, value, getName(), this) + latestVersionChannel = buildChannel(LATEST_VERSION_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + value, getName(), this) .stateTopic(channelConfiguration.latestVersionTopic, channelConfiguration.latestVersionTemplate) .build(false); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Vacuum.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Vacuum.java index 964c24b3a9e7d..b48988ab7b270 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Vacuum.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Vacuum.java @@ -26,8 +26,10 @@ import org.openhab.binding.mqtt.generic.values.PercentageValue; import org.openhab.binding.mqtt.generic.values.TextValue; import org.openhab.binding.mqtt.generic.values.Value; +import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannel; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; +import org.openhab.core.thing.type.ChannelTypeUID; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -226,8 +228,9 @@ public Vacuum(ComponentFactory.ComponentConfiguration componentConfiguration) { addPayloadToList(deviceSupportedFeatures, FEATURE_START, channelConfiguration.payloadStart, commands); } - buildOptionalChannel(COMMAND_CH_ID, new TextValue(commands.toArray(new String[0])), updateListener, null, - channelConfiguration.commandTopic, null, null); + buildOptionalChannel(COMMAND_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + new TextValue(commands.toArray(new String[0])), updateListener, null, channelConfiguration.commandTopic, + null, null); final var fanSpeedList = channelConfiguration.fanSpeedList; if (deviceSupportedFeatures.contains(FEATURE_FAN_SPEED) && fanSpeedList != null && !fanSpeedList.isEmpty()) { @@ -236,48 +239,51 @@ public Vacuum(ComponentFactory.ComponentConfiguration componentConfiguration) { } var fanSpeedValue = new TextValue(fanSpeedList.toArray(new String[0])); if (channelConfiguration.schema == Schema.LEGACY) { - buildOptionalChannel(FAN_SPEED_CH_ID, fanSpeedValue, updateListener, null, - channelConfiguration.setFanSpeedTopic, channelConfiguration.fanSpeedTemplate, - channelConfiguration.fanSpeedTopic); + buildOptionalChannel(FAN_SPEED_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, fanSpeedValue, + updateListener, null, channelConfiguration.setFanSpeedTopic, + channelConfiguration.fanSpeedTemplate, channelConfiguration.fanSpeedTopic); } else if (deviceSupportedFeatures.contains(FEATURE_STATUS)) { - buildOptionalChannel(FAN_SPEED_CH_ID, fanSpeedValue, updateListener, null, - channelConfiguration.setFanSpeedTopic, "{{ value_json.fan_speed }}", + buildOptionalChannel(FAN_SPEED_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, fanSpeedValue, + updateListener, null, channelConfiguration.setFanSpeedTopic, "{{ value_json.fan_speed }}", channelConfiguration.stateTopic); } else { LOGGER.info("Status feature is disabled, unable to get fan speed."); - buildOptionalChannel(FAN_SPEED_CH_ID, fanSpeedValue, updateListener, null, - channelConfiguration.setFanSpeedTopic, null, null); + buildOptionalChannel(FAN_SPEED_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, fanSpeedValue, + updateListener, null, channelConfiguration.setFanSpeedTopic, null, null); } } if (deviceSupportedFeatures.contains(FEATURE_SEND_COMMAND)) { - buildOptionalChannel(CUSTOM_COMMAND_CH_ID, new TextValue(), updateListener, null, - channelConfiguration.sendCommandTopic, null, null); + buildOptionalChannel(CUSTOM_COMMAND_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, new TextValue(), + updateListener, null, channelConfiguration.sendCommandTopic, null, null); } if (channelConfiguration.schema == Schema.LEGACY) { // I assume, that if these topics defined in config, then we don't need to check features - buildOptionalChannel(BATTERY_LEVEL_CH_ID, + buildOptionalChannel(BATTERY_LEVEL_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_DIMMER, new PercentageValue(BigDecimal.ZERO, BigDecimal.valueOf(100), BigDecimal.ONE, null, null), updateListener, null, null, channelConfiguration.batteryLevelTemplate, channelConfiguration.batteryLevelTopic); - buildOptionalChannel(CHARGING_CH_ID, new OnOffValue(TRUE, FALSE), updateListener, null, null, - channelConfiguration.chargingTemplate, channelConfiguration.chargingTopic); - buildOptionalChannel(CLEANING_CH_ID, new OnOffValue(TRUE, FALSE), updateListener, null, null, - channelConfiguration.cleaningTemplate, channelConfiguration.cleaningTopic); - buildOptionalChannel(DOCKED_CH_ID, new OnOffValue(TRUE, FALSE), updateListener, null, null, - channelConfiguration.dockedTemplate, channelConfiguration.dockedTopic); - buildOptionalChannel(ERROR_CH_ID, new TextValue(), updateListener, null, null, - channelConfiguration.errorTemplate, channelConfiguration.errorTopic); + buildOptionalChannel(CHARGING_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, + new OnOffValue(TRUE, FALSE), updateListener, null, null, channelConfiguration.chargingTemplate, + channelConfiguration.chargingTopic); + buildOptionalChannel(CLEANING_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, + new OnOffValue(TRUE, FALSE), updateListener, null, null, channelConfiguration.cleaningTemplate, + channelConfiguration.cleaningTopic); + buildOptionalChannel(DOCKED_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, + new OnOffValue(TRUE, FALSE), updateListener, null, null, channelConfiguration.dockedTemplate, + channelConfiguration.dockedTopic); + buildOptionalChannel(ERROR_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, new TextValue(), + updateListener, null, null, channelConfiguration.errorTemplate, channelConfiguration.errorTopic); } else { if (deviceSupportedFeatures.contains(FEATURE_STATUS)) { // state key is mandatory - buildOptionalChannel(STATE_CH_ID, + buildOptionalChannel(STATE_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, new TextValue(new String[] { STATE_CLEANING, STATE_DOCKED, STATE_PAUSED, STATE_IDLE, STATE_RETURNING, STATE_ERROR }), updateListener, null, null, "{{ value_json.state }}", channelConfiguration.stateTopic); if (deviceSupportedFeatures.contains(FEATURE_BATTERY)) { - buildOptionalChannel(BATTERY_LEVEL_CH_ID, + buildOptionalChannel(BATTERY_LEVEL_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_DIMMER, new PercentageValue(BigDecimal.ZERO, BigDecimal.valueOf(100), BigDecimal.ONE, null, null), updateListener, null, null, "{{ value_json.battery_level }}", channelConfiguration.stateTopic); @@ -285,16 +291,17 @@ public Vacuum(ComponentFactory.ComponentConfiguration componentConfiguration) { } } - buildOptionalChannel(JSON_ATTRIBUTES_CH_ID, new TextValue(), updateListener, null, null, - channelConfiguration.jsonAttributesTemplate, channelConfiguration.jsonAttributesTopic); + buildOptionalChannel(JSON_ATTRIBUTES_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, new TextValue(), + updateListener, null, null, channelConfiguration.jsonAttributesTemplate, + channelConfiguration.jsonAttributesTopic); } @Nullable - private ComponentChannel buildOptionalChannel(String channelId, Value valueState, + private ComponentChannel buildOptionalChannel(String channelId, ChannelTypeUID channelTypeUID, Value valueState, ChannelStateUpdateListener channelStateUpdateListener, @Nullable String commandTemplate, @Nullable String commandTopic, @Nullable String stateTemplate, @Nullable String stateTopic) { if ((commandTopic != null && !commandTopic.isBlank()) || (stateTopic != null && !stateTopic.isBlank())) { - return buildChannel(channelId, valueState, getName(), channelStateUpdateListener) + return buildChannel(channelId, channelTypeUID, valueState, getName(), channelStateUpdateListener) .stateTopic(stateTopic, stateTemplate, channelConfiguration.getValueTemplate()) .commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos(), commandTemplate) diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java index eb6aa2f0d7f40..51129bc9f479b 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java @@ -30,6 +30,7 @@ import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.AbstractMQTTThingHandler; import org.openhab.binding.mqtt.generic.ChannelState; +import org.openhab.binding.mqtt.generic.MqttChannelStateDescriptionProvider; import org.openhab.binding.mqtt.generic.MqttChannelTypeProvider; import org.openhab.binding.mqtt.generic.TransformationServiceProvider; import org.openhab.binding.mqtt.generic.tools.DelayedBatchProcessing; @@ -58,6 +59,7 @@ import org.openhab.core.thing.binding.builder.ThingBuilder; import org.openhab.core.thing.type.ChannelDefinition; import org.openhab.core.thing.type.ChannelGroupDefinition; +import org.openhab.core.thing.type.ChannelTypeRegistry; import org.openhab.core.thing.type.ThingType; import org.openhab.core.thing.util.ThingHelper; import org.slf4j.Logger; @@ -93,6 +95,8 @@ public class HomeAssistantThingHandler extends AbstractMQTTThingHandler private final Logger logger = LoggerFactory.getLogger(HomeAssistantThingHandler.class); protected final MqttChannelTypeProvider channelTypeProvider; + protected final MqttChannelStateDescriptionProvider stateDescriptionProvider; + protected final ChannelTypeRegistry channelTypeRegistry; public final int attributeReceiveTimeout; protected final DelayedBatchProcessing> delayedProcessing; protected final DiscoverComponents discoverComponents; @@ -118,11 +122,14 @@ public class HomeAssistantThingHandler extends AbstractMQTTThingHandler * @param attributeReceiveTimeout The timeout per attribute field subscription. In milliseconds. */ public HomeAssistantThingHandler(Thing thing, MqttChannelTypeProvider channelTypeProvider, + MqttChannelStateDescriptionProvider stateDescriptionProvider, ChannelTypeRegistry channelTypeRegistry, TransformationServiceProvider transformationServiceProvider, int subscribeTimeout, int attributeReceiveTimeout) { super(thing, subscribeTimeout); this.gson = new GsonBuilder().registerTypeAdapterFactory(new ChannelConfigurationTypeAdapterFactory()).create(); this.channelTypeProvider = channelTypeProvider; + this.stateDescriptionProvider = stateDescriptionProvider; + this.channelTypeRegistry = channelTypeRegistry; this.transformationServiceProvider = transformationServiceProvider; this.attributeReceiveTimeout = attributeReceiveTimeout; this.delayedProcessing = new DelayedBatchProcessing<>(attributeReceiveTimeout, this, scheduler); @@ -148,7 +155,7 @@ public void initialize() { AbstractComponent component = haComponents.get(groupID); if (component != null) { // the types may have been removed in dispose() so we need to add them again - component.addChannelTypes(channelTypeProvider); + component.addChannelTypes(channelTypeProvider, stateDescriptionProvider); continue; } @@ -168,7 +175,7 @@ public void initialize() { id = groupUID.getId(); } haComponents.put(id, component); - component.addChannelTypes(channelTypeProvider); + component.addChannelTypes(channelTypeProvider, stateDescriptionProvider); } catch (ConfigurationException e) { logger.error("Cannot not restore component {}: {}", thing, e.getMessage()); } @@ -183,7 +190,7 @@ public void initialize() { public void dispose() { // super.dispose() calls stop() super.dispose(); - haComponents.values().forEach(c -> c.removeChannelTypes(channelTypeProvider)); + haComponents.values().forEach(c -> c.removeChannelTypes(channelTypeProvider, stateDescriptionProvider)); } @Override @@ -289,7 +296,7 @@ public void accept(List> discoveredComponentsList) { } // Add channel and group types to the types registry - discovered.addChannelTypes(channelTypeProvider); + discovered.addChannelTypes(channelTypeProvider, stateDescriptionProvider); // Add component to the component map haComponents.put(id, discovered); // Start component / Subscribe to channel topics diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/OH-INF/config/homeassistant-channel-config.xml b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/OH-INF/config/homeassistant-channel-config.xml index 64cbf21ea2977..d84743bc7331d 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/OH-INF/config/homeassistant-channel-config.xml +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/OH-INF/config/homeassistant-channel-config.xml @@ -7,7 +7,7 @@ - HomeAssistant component type (e.g. binary_sensor, switch, light) + Home Assistant component type (e.g. binary_sensor, switch, light) @@ -17,12 +17,12 @@ - Object id of the component + Object ID of the component - - The json configuration string received by the component via MQTT. + + The JSON configuration string received by the component via MQTT. diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/OH-INF/i18n/mqtt.properties b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/OH-INF/i18n/mqtt.properties index 408ba3982639b..22cb9fb44fb43 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/OH-INF/i18n/mqtt.properties +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/OH-INF/i18n/mqtt.properties @@ -9,6 +9,39 @@ thing-type.config.mqtt.homeassistant.basetopic.label = MQTT Base Prefix thing-type.config.mqtt.homeassistant.basetopic.description = MQTT base prefix thing-type.config.mqtt.homeassistant.topics.label = MQTT Config Topic thing-type.config.mqtt.homeassistant.topics.description = List of Home Assistant configuration topics (e.g. button/my-device/restart) + +# channel types + +channel-type.mqtt.ha-color-advanced.label = Color +channel-type.mqtt.ha-color.label = Color +channel-type.mqtt.ha-dimmer-advanced.label = Dimmer +channel-type.mqtt.ha-dimmer.label = Dimmer +channel-type.mqtt.ha-image-advanced.label = Image +channel-type.mqtt.ha-image.label = Image +channel-type.mqtt.ha-number-advanced.label = Number +channel-type.mqtt.ha-number.label = Number +channel-type.mqtt.ha-rollershutter-advanced.label = Rollershutter +channel-type.mqtt.ha-rollershutter.label = Rollershutter +channel-type.mqtt.ha-string-advanced.label = String +channel-type.mqtt.ha-string.label = String +channel-type.mqtt.ha-switch-advanced.label = Switch +channel-type.mqtt.ha-switch.label = Switch +channel-type.mqtt.ha-trigger-advanced.label = Trigger +channel-type.mqtt.ha-trigger.label = Trigger + +# channel types config + +channel-type.config.mqtt.ha-channel.component.label = Component +channel-type.config.mqtt.ha-channel.component.description = Home Assistant component type (e.g. binary_sensor, switch, light) +channel-type.config.mqtt.ha-channel.config.label = JSON Configuration +channel-type.config.mqtt.ha-channel.config.description = The JSON configuration string received by the component via MQTT. +channel-type.config.mqtt.ha-channel.nodeid.label = Node ID +channel-type.config.mqtt.ha-channel.nodeid.description = Optional node name of the component +channel-type.config.mqtt.ha-channel.objectid.label = Object ID +channel-type.config.mqtt.ha-channel.objectid.description = Object ID of the component + +# thing types config + thing-type.config.mqtt.homeassistant-updatable.basetopic.label = MQTT Base Prefix thing-type.config.mqtt.homeassistant-updatable.basetopic.description = MQTT base prefix thing-type.config.mqtt.homeassistant-updatable.topics.label = MQTT Config Topic diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/OH-INF/thing/homeassistant-channels.xml b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/OH-INF/thing/homeassistant-channels.xml new file mode 100644 index 0000000000000..cd4679398b1dc --- /dev/null +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/OH-INF/thing/homeassistant-channels.xml @@ -0,0 +1,102 @@ + + + + + Color + + + + + + Dimmer + + + + + + Image + + + + + + Number + + + + + + Rollershutter + + + + + + String + + + + + + Switch + + + + + + trigger + + + + + + Color + + + + + + Dimmer + + + + + + Image + + + + + + Number + + + + + + Rollershutter + + + + + + String + + + + + + Switch + + + + + + trigger + + + + diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/AbstractHomeAssistantTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/AbstractHomeAssistantTests.java index dbf052b2f47d3..e03f7f18b1571 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/AbstractHomeAssistantTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/AbstractHomeAssistantTests.java @@ -35,6 +35,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.quality.Strictness; +import org.openhab.binding.mqtt.generic.MqttChannelStateDescriptionProvider; import org.openhab.binding.mqtt.generic.MqttChannelTypeProvider; import org.openhab.binding.mqtt.generic.TransformationServiceProvider; import org.openhab.binding.mqtt.handler.BrokerHandler; @@ -50,6 +51,7 @@ import org.openhab.core.thing.ThingUID; import org.openhab.core.thing.binding.builder.BridgeBuilder; import org.openhab.core.thing.binding.builder.ThingBuilder; +import org.openhab.core.thing.type.ChannelTypeRegistry; import org.openhab.core.thing.type.ThingTypeBuilder; import org.openhab.core.thing.type.ThingTypeRegistry; import org.openhab.transform.jinja.internal.JinjaTransformationService; @@ -83,6 +85,8 @@ public abstract class AbstractHomeAssistantTests extends JavaTest { protected @Mock @NonNullByDefault({}) TransformationServiceProvider transformationServiceProvider; protected @NonNullByDefault({}) MqttChannelTypeProvider channelTypeProvider; + protected @NonNullByDefault({}) MqttChannelStateDescriptionProvider stateDescriptionProvider; + protected @NonNullByDefault({}) ChannelTypeRegistry channelTypeRegistry; protected final Bridge bridgeThing = BridgeBuilder.create(BRIDGE_TYPE_UID, BRIDGE_UID).build(); protected final BrokerHandler bridgeHandler = spy(new BrokerHandler(bridgeThing)); @@ -102,6 +106,8 @@ public void beforeEachAbstractHomeAssistantTests() { .thenReturn(jinjaTransformationService); channelTypeProvider = spy(new MqttChannelTypeProvider(thingTypeRegistry)); + stateDescriptionProvider = spy(new MqttChannelStateDescriptionProvider()); + channelTypeRegistry = spy(new ChannelTypeRegistry()); setupConnection(); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponentTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponentTests.java index 4c089f72e1845..7985d25db4aa3 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponentTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponentTests.java @@ -32,6 +32,7 @@ import org.junit.jupiter.api.BeforeEach; import org.mockito.ArgumentMatchers; import org.mockito.Mock; +import org.openhab.binding.mqtt.generic.MqttChannelStateDescriptionProvider; import org.openhab.binding.mqtt.generic.MqttChannelTypeProvider; import org.openhab.binding.mqtt.generic.TransformationServiceProvider; import org.openhab.binding.mqtt.generic.values.Value; @@ -45,6 +46,7 @@ import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatusInfo; import org.openhab.core.thing.binding.ThingHandlerCallback; +import org.openhab.core.thing.type.ChannelTypeRegistry; import org.openhab.core.types.Command; import org.openhab.core.types.State; @@ -76,8 +78,8 @@ public void setupThingHandler() { when(callbackMock.getBridge(eq(BRIDGE_UID))).thenReturn(bridgeThing); - thingHandler = new LatchThingHandler(haThing, channelTypeProvider, transformationServiceProvider, - SUBSCRIBE_TIMEOUT, ATTRIBUTE_RECEIVE_TIMEOUT); + thingHandler = new LatchThingHandler(haThing, channelTypeProvider, stateDescriptionProvider, + channelTypeRegistry, transformationServiceProvider, SUBSCRIBE_TIMEOUT, ATTRIBUTE_RECEIVE_TIMEOUT); thingHandler.setConnection(bridgeConnection); thingHandler.setCallback(callbackMock); thingHandler = spy(thingHandler); @@ -285,9 +287,11 @@ protected static class LatchThingHandler extends HomeAssistantThingHandler { private @Nullable AbstractComponent<@NonNull ? extends AbstractChannelConfiguration> discoveredComponent; public LatchThingHandler(Thing thing, MqttChannelTypeProvider channelTypeProvider, + MqttChannelStateDescriptionProvider stateDescriptionProvider, ChannelTypeRegistry channelTypeRegistry, TransformationServiceProvider transformationServiceProvider, int subscribeTimeout, int attributeReceiveTimeout) { - super(thing, channelTypeProvider, transformationServiceProvider, subscribeTimeout, attributeReceiveTimeout); + super(thing, channelTypeProvider, stateDescriptionProvider, channelTypeRegistry, + transformationServiceProvider, subscribeTimeout, attributeReceiveTimeout); } @Override diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandlerTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandlerTests.java index 33e2f6e284776..7da7b0f1ef3c0 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandlerTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandlerTests.java @@ -37,6 +37,7 @@ import org.openhab.binding.mqtt.homeassistant.internal.component.Switch; import org.openhab.core.thing.Channel; import org.openhab.core.thing.binding.ThingHandlerCallback; +import org.openhab.core.types.StateDescription; /** * Tests for {@link HomeAssistantThingHandler} @@ -73,8 +74,8 @@ public void setup() { when(callbackMock.getBridge(eq(BRIDGE_UID))).thenReturn(bridgeThing); - thingHandler = new HomeAssistantThingHandler(haThing, channelTypeProvider, transformationServiceProvider, - SUBSCRIBE_TIMEOUT, ATTRIBUTE_RECEIVE_TIMEOUT); + thingHandler = new HomeAssistantThingHandler(haThing, channelTypeProvider, stateDescriptionProvider, + channelTypeRegistry, transformationServiceProvider, SUBSCRIBE_TIMEOUT, ATTRIBUTE_RECEIVE_TIMEOUT); thingHandler.setConnection(bridgeConnection); thingHandler.setCallback(callbackMock); nonSpyThingHandler = thingHandler; @@ -106,7 +107,7 @@ public void testInitialize() { thingHandler.delayedProcessing.forceProcessNow(); assertThat(haThing.getChannels().size(), CoreMatchers.is(6)); - verify(channelTypeProvider, times(6)).setChannelType(any(), any()); + verify(stateDescriptionProvider, times(6)).setDescription(any(), any(StateDescription.class)); verify(channelTypeProvider, times(1)).setChannelGroupType(any(), any()); configTopic = "homeassistant/switch/0x847127fffe11dd6a_auto_lock_zigbee2mqtt/config"; @@ -117,7 +118,7 @@ public void testInitialize() { thingHandler.delayedProcessing.forceProcessNow(); assertThat(haThing.getChannels().size(), CoreMatchers.is(7)); - verify(channelTypeProvider, times(7)).setChannelType(any(), any()); + verify(stateDescriptionProvider, times(7)).setDescription(any(), any(StateDescription.class)); verify(channelTypeProvider, times(2)).setChannelGroupType(any(), any()); } @@ -240,7 +241,7 @@ public void testDispose() { getResourceAsByteArray("component/configTS0601AutoLock.json")); thingHandler.delayedProcessing.forceProcessNow(); assertThat(haThing.getChannels().size(), CoreMatchers.is(7)); - verify(channelTypeProvider, times(7)).setChannelType(any(), any()); + verify(stateDescriptionProvider, times(7)).setDescription(any(), any(StateDescription.class)); // When dispose thingHandler.dispose(); @@ -250,8 +251,8 @@ public void testDispose() { verify(bridgeConnection, timeout(SUBSCRIBE_TIMEOUT)).unsubscribe(eq(t), any()); }); - // Expect channel types removed, 6 for climate and 1 for switch - verify(channelTypeProvider, times(7)).removeChannelType(any()); + // Expect channel descriptions removed, 6 for climate and 1 for switch + verify(stateDescriptionProvider, times(7)).remove(any()); // Expect channel group types removed, 1 for each component verify(channelTypeProvider, times(2)).removeChannelGroupType(any()); } From b3e4feb6897fa50e6b099e1018862785dd86c8e9 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Fri, 29 Dec 2023 15:11:48 -0700 Subject: [PATCH 02/11] [mqtt.homeassistant] dynamically change thing type after creation This has two important impacts, and one not-as-important-but-still- beneficial impact: * ThingTypes are not created for Things that are never actually created, but only discovered, reducing bloat. * Avoids warnings about things types not being in the registry * Thing IDs end up like mqtt:homeassistant:broker:mydevice instead of mqtt:homeassistant_mydevice:broker:mydevice Note that already-created things will maintain their original ID, and it's only new things created from auto-discovery that will have the new, shorter thing IDs. Signed-off-by: Cody Cutrer --- .../internal/component/AbstractComponent.java | 4 ++ .../discovery/HomeAssistantDiscovery.java | 12 +---- .../handler/HomeAssistantThingHandler.java | 46 ++++++++++++++----- 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java index db8647c2b8f97..1dd1f4a41f443 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java @@ -340,4 +340,8 @@ public boolean isEnabledByDefault() { public Gson getGson() { return componentConfiguration.getGson(); } + + public C getChannelConfiguration() { + return channelConfiguration; + } } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscovery.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscovery.java index 4626a9860468f..9b10da58db3af 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscovery.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscovery.java @@ -51,7 +51,6 @@ import org.openhab.core.io.transport.mqtt.MqttBrokerConnection; import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.thing.ThingUID; -import org.openhab.core.thing.type.ThingType; import org.osgi.framework.Constants; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; @@ -206,11 +205,8 @@ public void receivedMessage(ThingUID connectionBridge, MqttBrokerConnection conn .fromString(new String(payload, StandardCharsets.UTF_8), gson); final String thingID = config.getThingId(haID.objectID); - - final ThingTypeUID typeID = new ThingTypeUID(MqttBindingConstants.BINDING_ID, - MqttBindingConstants.HOMEASSISTANT_MQTT_THING.getId() + "_" + thingID); - - final ThingUID thingUID = new ThingUID(typeID, connectionBridge, thingID); + final ThingUID thingUID = new ThingUID(MqttBindingConstants.HOMEASSISTANT_MQTT_THING, connectionBridge, + thingID); thingIDPerTopic.put(topic, thingUID); @@ -282,10 +278,6 @@ protected void publishResults() { results.clear(); componentsPerThingID.clear(); for (DiscoveryResult result : localResults) { - final ThingTypeUID typeID = result.getThingTypeUID(); - ThingType type = typeProvider.derive(typeID, MqttBindingConstants.HOMEASSISTANT_MQTT_THING).build(); - typeProvider.setThingTypeIfAbsent(typeID, type); - thingDiscovered(result); } } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java index 51129bc9f479b..f4da894363a52 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java @@ -60,7 +60,6 @@ import org.openhab.core.thing.type.ChannelDefinition; import org.openhab.core.thing.type.ChannelGroupDefinition; import org.openhab.core.thing.type.ChannelTypeRegistry; -import org.openhab.core.thing.type.ThingType; import org.openhab.core.thing.util.ThingHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -148,6 +147,7 @@ public void initialize() { } discoveryHomeAssistantIDs.addAll(HaID.fromConfig(config)); + ThingTypeUID typeID = getThing().getThingTypeUID(); for (Channel channel : thing.getChannels()) { final String groupID = channel.getUID().getGroupId(); // Already restored component? @@ -169,6 +169,10 @@ public void initialize() { try { component = ComponentFactory.createComponent(thingUID, haID, channelConfigurationJSON, this, this, scheduler, gson, transformationServiceProvider); + if (typeID.equals(MqttBindingConstants.HOMEASSISTANT_MQTT_THING)) { + typeID = calculateThingTypeUID(component); + } + final ChannelGroupUID groupUID = component.getGroupUID(); String id = null; if (groupUID != null) { @@ -181,9 +185,9 @@ public void initialize() { } } } - updateThingType(); - - super.initialize(); + if (updateThingType(typeID)) { + super.initialize(); + } } @Override @@ -276,7 +280,11 @@ public void accept(List> discoveredComponentsList) { } synchronized (haComponents) { // sync whenever discoverComponents is started + ThingTypeUID typeID = getThing().getThingTypeUID(); for (AbstractComponent discovered : discoveredComponentsList) { + if (typeID.equals(MqttBindingConstants.HOMEASSISTANT_MQTT_THING)) { + typeID = calculateThingTypeUID(discovered); + } final ChannelGroupUID groupUID = discovered.getGroupUID(); String id = null; if (groupUID != null) { @@ -326,7 +334,7 @@ public void accept(List> discoveredComponentsList) { discoveredChannels.sort(CHANNEL_COMPARATOR_BY_UID); ThingHelper.addChannelsToThing(thing, discoveredChannels); } - updateThingType(); + updateThingType(typeID); } } @@ -379,10 +387,22 @@ public void handleConfigurationUpdate(Map configurationParameter super.handleConfigurationUpdate(configurationParameters); } - private void updateThingType() { + private boolean updateThingType(ThingTypeUID typeID) { // if this is a dynamic type, then we update the type - ThingTypeUID typeID = thing.getThingTypeUID(); if (!MqttBindingConstants.HOMEASSISTANT_MQTT_THING.equals(typeID)) { + var builder = channelTypeProvider.derive(typeID, MqttBindingConstants.HOMEASSISTANT_MQTT_THING); + + if (getThing().getThingTypeUID().equals(MqttBindingConstants.HOMEASSISTANT_MQTT_THING)) { + logger.debug("Migrating Home Assistant thing {} from generic type to dynamic type {}", + getThing().getUID(), typeID); + + // just create an empty thing type for now; channel configurations won't follow over + // to the re-created Thing, so we need to re-discover them all anyway + channelTypeProvider.setThingType(typeID, builder.build()); + changeThingType(typeID, getConfig()); + return false; + } + List groupDefs; List channelDefs; synchronized (haComponents) { // sync whenever discoverComponents is started @@ -391,16 +411,20 @@ private void updateThingType() { channelDefs = haComponents.values().stream().map(AbstractComponent::getChannels).flatMap(List::stream) .collect(Collectors.toList()); } - var builder = channelTypeProvider.derive(typeID, MqttBindingConstants.HOMEASSISTANT_MQTT_THING) - .withChannelDefinitions(channelDefs).withChannelGroupDefinitions(groupDefs); + builder.withChannelDefinitions(channelDefs).withChannelGroupDefinitions(groupDefs); Update updateComponent = this.updateComponent; if (updateComponent != null && updateComponent.isUpdatable()) { builder.withConfigDescriptionURI(UPDATABLE_CONFIG_DESCRIPTION_URI); } - ThingType thingType = builder.build(); - channelTypeProvider.setThingType(typeID, thingType); + channelTypeProvider.setThingType(typeID, builder.build()); } + return true; + } + + private ThingTypeUID calculateThingTypeUID(AbstractComponent component) { + return new ThingTypeUID(MqttBindingConstants.BINDING_ID, MqttBindingConstants.HOMEASSISTANT_MQTT_THING.getId() + + "_" + component.getChannelConfiguration().getThingId(component.getHaID().objectID)); } private void releaseStateUpdated(Update.ReleaseState state) { From bbdfdc31e536b66da5f22202947355be6245b1a4 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Fri, 29 Dec 2023 16:32:05 -0700 Subject: [PATCH 03/11] [mqtt.homeassistant] simplify channel ids for newly discovered things This is triggered by a property only set by discovery, so will only apply to newly created things. Channel groups are now named after simply the component type and object_id, if possible, and without additional encoding, instead off encoding the unique_id. Most devices will encode the component type and device identifiers into the unique_id, and of arbitrary format, so it is far more complicated than necessary, when a channel group is already only within the scope of the thing/device. Many component types that can only ever have one channel (button, switch, sensor, select, scene, etc.) will not be in a channel group anymore. In this case their channel id is what their group id would have been, without the repetitiveness of "sensor_#sensor". Signed-off-by: Cody Cutrer --- .../internal/DiscoverComponents.java | 6 ++- .../mqtt/homeassistant/internal/HaID.java | 12 +++++- .../internal/component/AbstractComponent.java | 33 ++++++++++++++--- .../component/AbstractRawSchemaLight.java | 4 +- .../internal/component/AlarmControlPanel.java | 4 +- .../internal/component/BinarySensor.java | 6 +-- .../internal/component/Button.java | 4 +- .../internal/component/Camera.java | 4 +- .../internal/component/Climate.java | 4 +- .../internal/component/ComponentFactory.java | 37 ++++++++++--------- .../internal/component/Cover.java | 4 +- .../component/DefaultSchemaLight.java | 4 +- .../internal/component/DeviceTrigger.java | 4 +- .../homeassistant/internal/component/Fan.java | 4 +- .../internal/component/JSONSchemaLight.java | 4 +- .../internal/component/Light.java | 11 +++--- .../internal/component/Lock.java | 4 +- .../internal/component/Number.java | 4 +- .../internal/component/Scene.java | 4 +- .../internal/component/Select.java | 4 +- .../internal/component/Sensor.java | 4 +- .../internal/component/Switch.java | 6 +-- .../internal/component/Update.java | 4 +- .../internal/component/Vacuum.java | 4 +- .../discovery/HomeAssistantDiscovery.java | 1 + .../handler/HomeAssistantThingHandler.java | 9 ++++- .../internal/component/BinarySensorTests.java | 2 +- .../internal/component/SwitchTests.java | 8 ++-- 28 files changed, 121 insertions(+), 78 deletions(-) diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/DiscoverComponents.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/DiscoverComponents.java index 96724530bc8ef..1907e80077523 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/DiscoverComponents.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/DiscoverComponents.java @@ -53,6 +53,7 @@ public class DiscoverComponents implements MqttMessageSubscriber { private final ChannelStateUpdateListener updateListener; private final AvailabilityTracker tracker; private final TransformationServiceProvider transformationServiceProvider; + private final boolean newStyleChannels; protected final CompletableFuture<@Nullable Void> discoverFinishedFuture = new CompletableFuture<>(); private final Gson gson; @@ -79,13 +80,14 @@ public static interface ComponentDiscovered { */ public DiscoverComponents(ThingUID thingUID, ScheduledExecutorService scheduler, ChannelStateUpdateListener channelStateUpdateListener, AvailabilityTracker tracker, Gson gson, - TransformationServiceProvider transformationServiceProvider) { + TransformationServiceProvider transformationServiceProvider, boolean newStyleChannels) { this.thingUID = thingUID; this.scheduler = scheduler; this.updateListener = channelStateUpdateListener; this.gson = gson; this.tracker = tracker; this.transformationServiceProvider = transformationServiceProvider; + this.newStyleChannels = newStyleChannels; } @Override @@ -101,7 +103,7 @@ public void processMessage(String topic, byte[] payload) { if (config.length() > 0) { try { component = ComponentFactory.createComponent(thingUID, haID, config, updateListener, tracker, scheduler, - gson, transformationServiceProvider); + gson, transformationServiceProvider, newStyleChannels); component.setConfigSeen(); logger.trace("Found HomeAssistant component {}", haID); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/HaID.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/HaID.java index 7a2ca110c9e0c..b810f48b4f3dd 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/HaID.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/HaID.java @@ -187,9 +187,19 @@ public String toShortTopic() { * * @return group id */ - public String getGroupId(@Nullable final String uniqueId) { + public String getGroupId(@Nullable final String uniqueId, boolean newStyleChannels) { String result = uniqueId; + // newStyleChannels are auto-discovered things with openHAB >= 4.2.0 + // assuming the topic has both a node ID and an object ID, simply use + // the component type and object ID - without encoding(!) + // since the only character allowed in object IDs but not allowed in UID + // is `-`. It also doesn't need to be reversible, so it's okay to just + // collapse `-` to `_`. + if (!nodeID.isBlank() && newStyleChannels) { + return component + "_" + objectID.replace('-', '_'); + } + // the null test is only here so the compile knows, result is not null afterwards if (result == null || result.isBlank()) { StringBuilder str = new StringBuilder(); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java index 1dd1f4a41f443..7269c2dee3078 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java @@ -80,15 +80,29 @@ public abstract class AbstractComponent protected final C channelConfiguration; protected boolean configSeen; + protected final boolean newStyleChannels; + protected final boolean singleChannelComponent; + protected final String groupId; + + public AbstractComponent(ComponentFactory.ComponentConfiguration componentConfiguration, Class clazz, + boolean newStyleChannels) { + this(componentConfiguration, clazz, newStyleChannels, false); + } /** * Creates component based on generic configuration and component configuration type. * * @param componentConfiguration generic componentConfiguration with not parsed JSON config * @param clazz target configuration type + * @param newStyleChannels if new style channels should be used + * @param singleChannelComponent if this component only ever has one channel, so should never be in a group + * (only if newStyleChannels is true) */ - public AbstractComponent(ComponentFactory.ComponentConfiguration componentConfiguration, Class clazz) { + public AbstractComponent(ComponentFactory.ComponentConfiguration componentConfiguration, Class clazz, + boolean newStyleChannels, boolean singleChannelComponent) { this.componentConfiguration = componentConfiguration; + this.newStyleChannels = newStyleChannels; + this.singleChannelComponent = newStyleChannels ? singleChannelComponent : false; this.channelConfigurationJson = componentConfiguration.getConfigJSON(); this.channelConfiguration = componentConfiguration.getConfig(clazz); @@ -98,11 +112,17 @@ public AbstractComponent(ComponentFactory.ComponentConfiguration componentConfig String name = channelConfiguration.getName(); if (name != null && !name.isEmpty()) { - String groupId = this.haID.getGroupId(channelConfiguration.getUniqueId()); - - this.channelGroupTypeUID = new ChannelGroupTypeUID(MqttBindingConstants.BINDING_ID, groupId); - this.channelGroupUID = new ChannelGroupUID(componentConfiguration.getThingUID(), groupId); + groupId = this.haID.getGroupId(channelConfiguration.getUniqueId(), newStyleChannels); + + if (this.singleChannelComponent) { + this.channelGroupTypeUID = null; + this.channelGroupUID = null; + } else { + this.channelGroupTypeUID = new ChannelGroupTypeUID(MqttBindingConstants.BINDING_ID, groupId); + this.channelGroupUID = new ChannelGroupUID(componentConfiguration.getThingUID(), groupId); + } } else { + groupId = ""; this.channelGroupTypeUID = null; this.channelGroupUID = null; } @@ -144,6 +164,9 @@ public AbstractComponent(ComponentFactory.ComponentConfiguration componentConfig protected ComponentChannel.Builder buildChannel(String channelID, ChannelTypeUID channelTypeUID, Value valueState, String label, ChannelStateUpdateListener channelStateUpdateListener) { + if (singleChannelComponent) { + channelID = groupId; + } return new ComponentChannel.Builder(this, channelID, channelTypeUID, valueState, label, channelStateUpdateListener); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractRawSchemaLight.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractRawSchemaLight.java index 8b3f6ee9ad2e8..be48d1c897e19 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractRawSchemaLight.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractRawSchemaLight.java @@ -32,8 +32,8 @@ abstract class AbstractRawSchemaLight extends Light { protected ComponentChannel rawChannel; - public AbstractRawSchemaLight(ComponentFactory.ComponentConfiguration builder) { - super(builder); + public AbstractRawSchemaLight(ComponentFactory.ComponentConfiguration builder, boolean newStyleChannels) { + super(builder, newStyleChannels); hiddenChannels.add(rawChannel = buildChannel(RAW_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, new TextValue(), "Raw state", this).stateTopic(channelConfiguration.stateTopic) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AlarmControlPanel.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AlarmControlPanel.java index 8ddd56c3c8fbe..da079596c8de7 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AlarmControlPanel.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AlarmControlPanel.java @@ -69,8 +69,8 @@ static class ChannelConfiguration extends AbstractChannelConfiguration { protected String payloadArmAway = "ARM_AWAY"; } - public AlarmControlPanel(ComponentFactory.ComponentConfiguration componentConfiguration) { - super(componentConfiguration, ChannelConfiguration.class); + public AlarmControlPanel(ComponentFactory.ComponentConfiguration componentConfiguration, boolean newStyleChannels) { + super(componentConfiguration, ChannelConfiguration.class, newStyleChannels); final String[] stateEnum = { channelConfiguration.stateDisarmed, channelConfiguration.stateArmedHome, channelConfiguration.stateArmedAway, channelConfiguration.statePending, diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensor.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensor.java index e808ee42a2cc1..f5a79c2bff87b 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensor.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensor.java @@ -68,12 +68,12 @@ static class ChannelConfiguration extends AbstractChannelConfiguration { protected @Nullable List jsonAttributes; } - public BinarySensor(ComponentFactory.ComponentConfiguration componentConfiguration) { - super(componentConfiguration, ChannelConfiguration.class); + public BinarySensor(ComponentFactory.ComponentConfiguration componentConfiguration, boolean newStyleChannels) { + super(componentConfiguration, ChannelConfiguration.class, newStyleChannels, true); OnOffValue value = new OnOffValue(channelConfiguration.payloadOn, channelConfiguration.payloadOff); - buildChannel(SENSOR_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, value, "value", + buildChannel(SENSOR_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, value, getName(), getListener(componentConfiguration, value)) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()) .withAutoUpdatePolicy(AutoUpdatePolicy.VETO).build(); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Button.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Button.java index 7e461ebf5cbac..febb156a5eb5a 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Button.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Button.java @@ -47,8 +47,8 @@ static class ChannelConfiguration extends AbstractChannelConfiguration { protected String payloadPress = "PRESS"; } - public Button(ComponentFactory.ComponentConfiguration componentConfiguration) { - super(componentConfiguration, ChannelConfiguration.class); + public Button(ComponentFactory.ComponentConfiguration componentConfiguration, boolean newStyleChannels) { + super(componentConfiguration, ChannelConfiguration.class, newStyleChannels, true); TextValue value = new TextValue(new String[] { channelConfiguration.payloadPress }); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Camera.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Camera.java index 30a3f78beda16..5fe21017c0a93 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Camera.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Camera.java @@ -39,8 +39,8 @@ static class ChannelConfiguration extends AbstractChannelConfiguration { protected String topic = ""; } - public Camera(ComponentFactory.ComponentConfiguration componentConfiguration) { - super(componentConfiguration, ChannelConfiguration.class); + public Camera(ComponentFactory.ComponentConfiguration componentConfiguration, boolean newStyleChannels) { + super(componentConfiguration, ChannelConfiguration.class, newStyleChannels); ImageValue value = new ImageValue(); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Climate.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Climate.java index 0215ed73b5245..3e3317f2725d2 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Climate.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Climate.java @@ -212,8 +212,8 @@ static class ChannelConfiguration extends AbstractChannelConfiguration { protected Boolean sendIfOff = true; } - public Climate(ComponentFactory.ComponentConfiguration componentConfiguration) { - super(componentConfiguration, ChannelConfiguration.class); + public Climate(ComponentFactory.ComponentConfiguration componentConfiguration, boolean newStyleChannels) { + super(componentConfiguration, ChannelConfiguration.class, newStyleChannels); BigDecimal precision = channelConfiguration.precision != null ? channelConfiguration.precision : channelConfiguration.temperatureUnit.getDefaultPrecision(); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/ComponentFactory.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/ComponentFactory.java index 367f666e48d1e..0c48a72805a91 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/ComponentFactory.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/ComponentFactory.java @@ -48,45 +48,46 @@ public class ComponentFactory { */ public static AbstractComponent createComponent(ThingUID thingUID, HaID haID, String channelConfigurationJSON, ChannelStateUpdateListener updateListener, AvailabilityTracker tracker, ScheduledExecutorService scheduler, - Gson gson, TransformationServiceProvider transformationServiceProvider) throws ConfigurationException { + Gson gson, TransformationServiceProvider transformationServiceProvider, boolean newStyleChannels) + throws ConfigurationException { ComponentConfiguration componentConfiguration = new ComponentConfiguration(thingUID, haID, channelConfigurationJSON, gson, updateListener, tracker, scheduler) .transformationProvider(transformationServiceProvider); switch (haID.component) { case "alarm_control_panel": - return new AlarmControlPanel(componentConfiguration); + return new AlarmControlPanel(componentConfiguration, newStyleChannels); case "binary_sensor": - return new BinarySensor(componentConfiguration); + return new BinarySensor(componentConfiguration, newStyleChannels); case "button": - return new Button(componentConfiguration); + return new Button(componentConfiguration, newStyleChannels); case "camera": - return new Camera(componentConfiguration); + return new Camera(componentConfiguration, newStyleChannels); case "cover": - return new Cover(componentConfiguration); + return new Cover(componentConfiguration, newStyleChannels); case "fan": - return new Fan(componentConfiguration); + return new Fan(componentConfiguration, newStyleChannels); case "climate": - return new Climate(componentConfiguration); + return new Climate(componentConfiguration, newStyleChannels); case "device_automation": - return new DeviceTrigger(componentConfiguration); + return new DeviceTrigger(componentConfiguration, newStyleChannels); case "light": - return Light.create(componentConfiguration); + return Light.create(componentConfiguration, newStyleChannels); case "lock": - return new Lock(componentConfiguration); + return new Lock(componentConfiguration, newStyleChannels); case "number": - return new Number(componentConfiguration); + return new Number(componentConfiguration, newStyleChannels); case "scene": - return new Scene(componentConfiguration); + return new Scene(componentConfiguration, newStyleChannels); case "select": - return new Select(componentConfiguration); + return new Select(componentConfiguration, newStyleChannels); case "sensor": - return new Sensor(componentConfiguration); + return new Sensor(componentConfiguration, newStyleChannels); case "switch": - return new Switch(componentConfiguration); + return new Switch(componentConfiguration, newStyleChannels); case "update": - return new Update(componentConfiguration); + return new Update(componentConfiguration, newStyleChannels); case "vacuum": - return new Vacuum(componentConfiguration); + return new Vacuum(componentConfiguration, newStyleChannels); default: throw new UnsupportedComponentException("Component '" + haID + "' is unsupported!"); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Cover.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Cover.java index 21dfcf9febb7f..0264555094da4 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Cover.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Cover.java @@ -85,8 +85,8 @@ static class ChannelConfiguration extends AbstractChannelConfiguration { @Nullable ComponentChannel stateChannel = null; - public Cover(ComponentFactory.ComponentConfiguration componentConfiguration) { - super(componentConfiguration, ChannelConfiguration.class); + public Cover(ComponentFactory.ComponentConfiguration componentConfiguration, boolean newStyleChannels) { + super(componentConfiguration, ChannelConfiguration.class, newStyleChannels); String stateTopic = channelConfiguration.stateTopic; 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 573b3efec82fa..9487616913a10 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 @@ -54,8 +54,8 @@ public class DefaultSchemaLight extends Light { protected @Nullable ComponentChannel rgbChannel; protected @Nullable ComponentChannel xyChannel; - public DefaultSchemaLight(ComponentFactory.ComponentConfiguration builder) { - super(builder); + public DefaultSchemaLight(ComponentFactory.ComponentConfiguration builder, boolean newStyleChannels) { + super(builder, newStyleChannels); } @Override diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DeviceTrigger.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DeviceTrigger.java index 74a20f9768026..96af915a099a5 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DeviceTrigger.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DeviceTrigger.java @@ -45,8 +45,8 @@ static class ChannelConfiguration extends AbstractChannelConfiguration { protected @Nullable String payload; } - public DeviceTrigger(ComponentFactory.ComponentConfiguration componentConfiguration) { - super(componentConfiguration, ChannelConfiguration.class); + public DeviceTrigger(ComponentFactory.ComponentConfiguration componentConfiguration, boolean newStyleChannels) { + super(componentConfiguration, ChannelConfiguration.class, newStyleChannels, true); if (!"trigger".equals(channelConfiguration.automationType)) { throw new ConfigurationException("Component:DeviceTrigger must have automation_type 'trigger'"); 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 ea022092a0373..e69701ac6992a 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 @@ -51,8 +51,8 @@ static class ChannelConfiguration extends AbstractChannelConfiguration { protected String payloadOff = "OFF"; } - public Fan(ComponentFactory.ComponentConfiguration componentConfiguration) { - super(componentConfiguration, ChannelConfiguration.class); + public Fan(ComponentFactory.ComponentConfiguration componentConfiguration, boolean newStyleChannels) { + super(componentConfiguration, ChannelConfiguration.class, newStyleChannels); OnOffValue value = new OnOffValue(channelConfiguration.payloadOn, channelConfiguration.payloadOff); buildChannel(SWITCH_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, value, getName(), 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 1f68b4eb6f38f..9782ceca70d45 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 @@ -74,8 +74,8 @@ protected static class Color { TextValue colorModeValue; - public JSONSchemaLight(ComponentFactory.ComponentConfiguration builder) { - super(builder); + public JSONSchemaLight(ComponentFactory.ComponentConfiguration builder, boolean newStyleChannels) { + super(builder, newStyleChannels); colorModeValue = new TextValue(); } 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 ad1c82d6988ff..db6baee7ba164 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 @@ -245,21 +245,22 @@ static class ChannelConfiguration extends AbstractChannelConfiguration { protected final ChannelStateUpdateListener channelStateUpdateListener; - public static Light create(ComponentFactory.ComponentConfiguration builder) throws UnsupportedComponentException { + public static Light create(ComponentFactory.ComponentConfiguration builder, boolean newStyleChannels) + throws UnsupportedComponentException { String schema = builder.getConfig(ChannelConfiguration.class).schema; switch (schema) { case DEFAULT_SCHEMA: - return new DefaultSchemaLight(builder); + return new DefaultSchemaLight(builder, newStyleChannels); case JSON_SCHEMA: - return new JSONSchemaLight(builder); + return new JSONSchemaLight(builder, newStyleChannels); default: throw new UnsupportedComponentException( "Component '" + builder.getHaID() + "' of schema '" + schema + "' is not supported!"); } } - protected Light(ComponentFactory.ComponentConfiguration builder) { - super(builder, ChannelConfiguration.class); + protected Light(ComponentFactory.ComponentConfiguration builder, boolean newStyleChannels) { + super(builder, ChannelConfiguration.class, newStyleChannels); this.channelStateUpdateListener = builder.getUpdateListener(); @Nullable diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Lock.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Lock.java index ee865e7fd34f2..4dc077689ae41 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Lock.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Lock.java @@ -73,8 +73,8 @@ static class ChannelConfiguration extends AbstractChannelConfiguration { private OnOffValue lockValue; private TextValue stateValue; - public Lock(ComponentFactory.ComponentConfiguration componentConfiguration) { - super(componentConfiguration, ChannelConfiguration.class); + public Lock(ComponentFactory.ComponentConfiguration componentConfiguration, boolean newStyleChannels) { + super(componentConfiguration, ChannelConfiguration.class, newStyleChannels); this.optimistic = channelConfiguration.optimistic || channelConfiguration.stateTopic.isBlank(); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Number.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Number.java index c3d6a3a003957..c5316c69a1f3f 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Number.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Number.java @@ -70,8 +70,8 @@ static class ChannelConfiguration extends AbstractChannelConfiguration { protected @Nullable String jsonAttributesTemplate; } - public Number(ComponentFactory.ComponentConfiguration componentConfiguration) { - super(componentConfiguration, ChannelConfiguration.class); + public Number(ComponentFactory.ComponentConfiguration componentConfiguration, boolean newStyleChannels) { + super(componentConfiguration, ChannelConfiguration.class, newStyleChannels, true); boolean optimistic = channelConfiguration.optimistic != null ? channelConfiguration.optimistic : channelConfiguration.stateTopic.isBlank(); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Scene.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Scene.java index ed0707ccd4aac..8fc649553ac93 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Scene.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Scene.java @@ -45,8 +45,8 @@ static class ChannelConfiguration extends AbstractChannelConfiguration { protected String payloadOn = "ON"; } - public Scene(ComponentFactory.ComponentConfiguration componentConfiguration) { - super(componentConfiguration, ChannelConfiguration.class); + public Scene(ComponentFactory.ComponentConfiguration componentConfiguration, boolean newStyleChannels) { + super(componentConfiguration, ChannelConfiguration.class, newStyleChannels, true); TextValue value = new TextValue(new String[] { channelConfiguration.payloadOn }); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Select.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Select.java index ce1b3be3364c8..f2db9b43f86fc 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Select.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Select.java @@ -55,8 +55,8 @@ static class ChannelConfiguration extends AbstractChannelConfiguration { protected @Nullable String jsonAttributesTemplate; } - public Select(ComponentFactory.ComponentConfiguration componentConfiguration) { - super(componentConfiguration, ChannelConfiguration.class); + public Select(ComponentFactory.ComponentConfiguration componentConfiguration, boolean newStyleChannels) { + super(componentConfiguration, ChannelConfiguration.class, newStyleChannels, true); boolean optimistic = channelConfiguration.optimistic != null ? channelConfiguration.optimistic : channelConfiguration.stateTopic.isBlank(); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Sensor.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Sensor.java index cdd308d4f9000..e8809da07f427 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Sensor.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Sensor.java @@ -69,8 +69,8 @@ static class ChannelConfiguration extends AbstractChannelConfiguration { protected @Nullable List jsonAttributes; } - public Sensor(ComponentFactory.ComponentConfiguration componentConfiguration) { - super(componentConfiguration, ChannelConfiguration.class); + public Sensor(ComponentFactory.ComponentConfiguration componentConfiguration, boolean newStyleChannels) { + super(componentConfiguration, ChannelConfiguration.class, newStyleChannels, true); Value value; String uom = channelConfiguration.unitOfMeasurement; diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Switch.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Switch.java index a3b4d95c6ef7e..3e81741041e9a 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Switch.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Switch.java @@ -60,8 +60,8 @@ static class ChannelConfiguration extends AbstractChannelConfiguration { protected @Nullable String jsonAttributesTemplate; } - public Switch(ComponentFactory.ComponentConfiguration componentConfiguration) { - super(componentConfiguration, ChannelConfiguration.class); + public Switch(ComponentFactory.ComponentConfiguration componentConfiguration, boolean newStyleChannels) { + super(componentConfiguration, ChannelConfiguration.class, newStyleChannels, true); boolean optimistic = channelConfiguration.optimistic != null ? channelConfiguration.optimistic : channelConfiguration.stateTopic.isBlank(); @@ -73,7 +73,7 @@ public Switch(ComponentFactory.ComponentConfiguration componentConfiguration) { OnOffValue value = new OnOffValue(channelConfiguration.stateOn, channelConfiguration.stateOff, channelConfiguration.payloadOn, channelConfiguration.payloadOff); - buildChannel(SWITCH_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, value, "state", + buildChannel(SWITCH_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, value, getName(), componentConfiguration.getUpdateListener()) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Update.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Update.java index dbb048d328148..6dbd3030fc32d 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Update.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Update.java @@ -143,8 +143,8 @@ public interface ReleaseStateListener { private ReleaseState state = new ReleaseState(); private @Nullable ReleaseStateListener listener = null; - public Update(ComponentFactory.ComponentConfiguration componentConfiguration) { - super(componentConfiguration, ChannelConfiguration.class); + public Update(ComponentFactory.ComponentConfiguration componentConfiguration, boolean newStyleChannels) { + super(componentConfiguration, ChannelConfiguration.class, newStyleChannels); TextValue value = new TextValue(); String commandTopic = channelConfiguration.commandTopic; diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Vacuum.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Vacuum.java index b48988ab7b270..a133a3bc77fe3 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Vacuum.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Vacuum.java @@ -190,8 +190,8 @@ static class ChannelConfiguration extends AbstractChannelConfiguration { * * @param componentConfiguration generic componentConfiguration with not parsed JSON config */ - public Vacuum(ComponentFactory.ComponentConfiguration componentConfiguration) { - super(componentConfiguration, ChannelConfiguration.class); + public Vacuum(ComponentFactory.ComponentConfiguration componentConfiguration, boolean newStyleChannels) { + super(componentConfiguration, ChannelConfiguration.class, newStyleChannels); final ChannelStateUpdateListener updateListener = componentConfiguration.getUpdateListener(); final var allowedSupportedFeatures = channelConfiguration.schema == Schema.LEGACY ? LEGACY_SUPPORTED_FEATURES diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscovery.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscovery.java index 9b10da58db3af..b89f0944aba50 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscovery.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscovery.java @@ -237,6 +237,7 @@ public void receivedMessage(ThingUID connectionBridge, MqttBrokerConnection conn properties = handlerConfig.appendToProperties(properties); properties = config.appendToProperties(properties); properties.put("deviceId", thingID); + properties.put("newStyleChannels", "true"); // Because we need the new properties map with the updated "components" list results.put(thingUID.getAsString(), diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java index f4da894363a52..0f4f5eefbbd31 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java @@ -109,6 +109,7 @@ public class HomeAssistantThingHandler extends AbstractMQTTThingHandler protected final TransformationServiceProvider transformationServiceProvider; private boolean started; + private boolean newStyleChannels; private @Nullable Update updateComponent; /** @@ -132,8 +133,12 @@ public HomeAssistantThingHandler(Thing thing, MqttChannelTypeProvider channelTyp this.transformationServiceProvider = transformationServiceProvider; this.attributeReceiveTimeout = attributeReceiveTimeout; this.delayedProcessing = new DelayedBatchProcessing<>(attributeReceiveTimeout, this, scheduler); + + Map properties = getThing().getProperties(); + newStyleChannels = "true".equals(thing.getProperties().get("newStyleChannels")); + this.discoverComponents = new DiscoverComponents(thing.getUID(), scheduler, this, this, gson, - this.transformationServiceProvider); + this.transformationServiceProvider, newStyleChannels); } @Override @@ -168,7 +173,7 @@ public void initialize() { } else { try { component = ComponentFactory.createComponent(thingUID, haID, channelConfigurationJSON, this, this, - scheduler, gson, transformationServiceProvider); + scheduler, gson, transformationServiceProvider, newStyleChannels); if (typeID.equals(MqttBindingConstants.HOMEASSISTANT_MQTT_THING)) { typeID = calculateThingTypeUID(component); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensorTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensorTests.java index 9f4d9bc52e0b8..e8c150df40889 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensorTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensorTests.java @@ -67,7 +67,7 @@ public void test() throws InterruptedException { assertThat(component.getName(), is("onoffsensor")); assertThat(component.getGroupUID().getId(), is("sn1")); - assertChannel(component, BinarySensor.SENSOR_CHANNEL_ID, "zigbee2mqtt/sensor/state", "", "value", + assertChannel(component, BinarySensor.SENSOR_CHANNEL_ID, "zigbee2mqtt/sensor/state", "", "onoffsensor", OnOffValue.class); publishMessage("zigbee2mqtt/sensor/state", "{ \"state\": \"ON_\" }"); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/SwitchTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/SwitchTests.java index 881294f36bd00..48b02abb6e6a7 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/SwitchTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/SwitchTests.java @@ -66,8 +66,8 @@ public void testSwitchWithStateAndCommand() { assertThat(component.channels.size(), is(1)); assertThat(component.getName(), is("th1 auto lock")); - assertChannel(component, Switch.SWITCH_CHANNEL_ID, "zigbee2mqtt/th1", "zigbee2mqtt/th1/set/auto_lock", "state", - OnOffValue.class); + assertChannel(component, Switch.SWITCH_CHANNEL_ID, "zigbee2mqtt/th1", "zigbee2mqtt/th1/set/auto_lock", + "th1 auto lock", OnOffValue.class); publishMessage("zigbee2mqtt/th1", "{\"auto_lock\": \"MANUAL\"}"); assertState(component, Switch.SWITCH_CHANNEL_ID, OnOffType.OFF); @@ -111,7 +111,7 @@ public void testSwitchWithState() { assertThat(component.channels.size(), is(1)); assertThat(component.getName(), is("th1 auto lock")); - assertChannel(component, Switch.SWITCH_CHANNEL_ID, "zigbee2mqtt/th1", "", "state", OnOffValue.class); + assertChannel(component, Switch.SWITCH_CHANNEL_ID, "zigbee2mqtt/th1", "", "th1 auto lock", OnOffValue.class); publishMessage("zigbee2mqtt/th1", "{\"auto_lock\": \"MANUAL\"}"); assertState(component, Switch.SWITCH_CHANNEL_ID, OnOffType.OFF); @@ -151,7 +151,7 @@ public void testSwitchWithCommand() { assertThat(component.channels.size(), is(1)); assertThat(component.getName(), is("th1 auto lock")); - assertChannel(component, Switch.SWITCH_CHANNEL_ID, "", "zigbee2mqtt/th1/set/auto_lock", "state", + assertChannel(component, Switch.SWITCH_CHANNEL_ID, "", "zigbee2mqtt/th1/set/auto_lock", "th1 auto lock", OnOffValue.class); component.getChannel(Switch.SWITCH_CHANNEL_ID).getState().publishValue(OnOffType.OFF); From 2e86a4e996c604d62ae5551c5fc950d045ad2c6d Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Mon, 13 Nov 2023 19:08:14 -0700 Subject: [PATCH 04/11] [mqtt] Use AbstractStorageBasedTypeProvider Includes both homie and homeassistant dynamic things. It also fixes all ordering issues in both bindings in order to be consistent in how types are persisted: * For Homie, Nodes (channel groups) and Properties (channels) are ordered in the way they are defined in $nodes and $properties * For Home Assistant, Components are ordered by label. This includes both single channel components that are not in a channel group, as well as channel groups. We also ensure that on the Thing itself non-grouped channels consistently sort before grouped channels. Signed-off-by: Cody Cutrer --- .../mqtt/generic/MqttChannelTypeProvider.java | 113 +++++--------- .../binding/mqtt/generic/tools/ChildMap.java | 25 +++ .../internal/ComponentChannel.java | 23 +-- .../internal/component/AbstractComponent.java | 105 ++++++------- .../discovery/HomeAssistantDiscovery.java | 3 +- .../handler/HomeAssistantThingHandler.java | 144 ++++++++---------- .../internal/AbstractHomeAssistantTests.java | 17 ++- .../component/AbstractComponentTests.java | 4 +- .../internal/component/BinarySensorTests.java | 2 +- .../internal/component/SensorTests.java | 2 +- .../HomeAssistantThingHandlerTests.java | 44 ++++-- .../internal/handler/HomieThingHandler.java | 42 +++-- .../mqtt/homie/internal/homie300/Node.java | 36 ++++- .../handler/HomieThingHandlerTests.java | 4 +- .../HomeAssistantMQTTImplementationTest.java | 9 +- 15 files changed, 290 insertions(+), 283 deletions(-) diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/MqttChannelTypeProvider.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/MqttChannelTypeProvider.java index 1991d003f7a68..8ffe385717f97 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/MqttChannelTypeProvider.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/MqttChannelTypeProvider.java @@ -14,22 +14,19 @@ import java.net.URI; import java.util.Collection; -import java.util.Locale; -import java.util.Map; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.internal.MqttThingHandlerFactory; +import org.openhab.core.storage.StorageService; import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.binding.AbstractStorageBasedTypeProvider; import org.openhab.core.thing.binding.ThingTypeProvider; import org.openhab.core.thing.type.ChannelGroupType; import org.openhab.core.thing.type.ChannelGroupTypeProvider; import org.openhab.core.thing.type.ChannelGroupTypeUID; -import org.openhab.core.thing.type.ChannelType; import org.openhab.core.thing.type.ChannelTypeProvider; -import org.openhab.core.thing.type.ChannelTypeUID; import org.openhab.core.thing.type.ThingType; import org.openhab.core.thing.type.ThingTypeBuilder; import org.openhab.core.thing.type.ThingTypeRegistry; @@ -45,89 +42,30 @@ * This provider is started on-demand only, as soon as {@link MqttThingHandlerFactory} or an extension requires it. * * @author David Graeff - Initial contribution + * @author Cody Cutrer - Use AbstractStorageBasedTypeProvider * */ @NonNullByDefault @Component(immediate = false, service = { ThingTypeProvider.class, ChannelTypeProvider.class, ChannelGroupTypeProvider.class, MqttChannelTypeProvider.class }) -public class MqttChannelTypeProvider implements ThingTypeProvider, ChannelGroupTypeProvider, ChannelTypeProvider { - private final ThingTypeRegistry typeRegistry; - - private final Map types = new ConcurrentHashMap<>(); - private final Map groups = new ConcurrentHashMap<>(); - private final Map things = new ConcurrentHashMap<>(); +public class MqttChannelTypeProvider extends AbstractStorageBasedTypeProvider { + private final ThingTypeRegistry thingTypeRegistry; @Activate - public MqttChannelTypeProvider(@Reference ThingTypeRegistry typeRegistry) { - super(); - this.typeRegistry = typeRegistry; - } - - @Override - public Collection getChannelTypes(@Nullable Locale locale) { - return types.values(); - } - - @Override - public @Nullable ChannelType getChannelType(ChannelTypeUID channelTypeUID, @Nullable Locale locale) { - return types.get(channelTypeUID); - } - - @Override - public @Nullable ChannelGroupType getChannelGroupType(ChannelGroupTypeUID channelGroupTypeUID, - @Nullable Locale locale) { - return groups.get(channelGroupTypeUID); - } - - @Override - public Collection getChannelGroupTypes(@Nullable Locale locale) { - return groups.values(); - } - - @Override - public Collection getThingTypes(@Nullable Locale locale) { - return things.values(); - } - - public Set getThingTypeUIDs() { - return things.keySet(); - } - - @Override - public @Nullable ThingType getThingType(ThingTypeUID thingTypeUID, @Nullable Locale locale) { - return things.get(thingTypeUID); - } - - public void removeChannelType(ChannelTypeUID uid) { - types.remove(uid); - } - - public void removeChannelGroupType(ChannelGroupTypeUID uid) { - groups.remove(uid); - } - - public void setChannelGroupType(ChannelGroupTypeUID uid, ChannelGroupType type) { - groups.put(uid, type); - } - - public void setChannelType(ChannelTypeUID uid, ChannelType type) { - types.put(uid, type); - } - - public void removeThingType(ThingTypeUID uid) { - things.remove(uid); - } - - public void setThingType(ThingTypeUID uid, ThingType type) { - things.put(uid, type); + public MqttChannelTypeProvider(@Reference ThingTypeRegistry thingTypeRegistry, + @Reference StorageService storageService) { + super(storageService); + this.thingTypeRegistry = thingTypeRegistry; } - public void setThingTypeIfAbsent(ThingTypeUID uid, ThingType type) { - things.putIfAbsent(uid, type); + public void putThingTypeIfAbsent(ThingTypeUID uid, ThingType type) { + if (getThingType(uid, null) == null) { + putThingType(type); + } } public ThingTypeBuilder derive(ThingTypeUID newTypeId, ThingTypeUID baseTypeId) { - ThingType baseType = typeRegistry.getThingType(baseTypeId); + ThingType baseType = thingTypeRegistry.getThingType(baseTypeId); ThingTypeBuilder result = ThingTypeBuilder.instance(newTypeId, baseType.getLabel()) .withChannelGroupDefinitions(baseType.getChannelGroupDefinitions()) @@ -155,4 +93,25 @@ public ThingTypeBuilder derive(ThingTypeUID newTypeId, ThingTypeUID baseTypeId) return result; } + + public void updateChannelGroupTypesForPrefix(String prefix, Collection types) { + Collection oldCgts = channelGroupTypesForPrefix(prefix); + + Set oldUids = oldCgts.stream().map(ChannelGroupType::getUID).collect(Collectors.toSet()); + Collection uids = types.stream().map(ChannelGroupType::getUID).toList(); + + oldUids.removeAll(uids); + // oldUids now contains only UIDs that no longer exist. so remove them + oldUids.stream().forEach(uid -> removeChannelGroupType(uid)); + types.stream().forEach(t -> putChannelGroupType(t)); + } + + public void removeChannelGroupTypesForPrefix(String prefix) { + channelGroupTypesForPrefix(prefix).stream().forEach(cgt -> removeChannelGroupType(cgt.getUID())); + } + + private Collection channelGroupTypesForPrefix(String prefix) { + return getChannelGroupTypes(null).stream().filter(cgt -> cgt.getUID().getId().startsWith(prefix + "_")) + .toList(); + } } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/tools/ChildMap.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/tools/ChildMap.java index 03d095059ee47..952da6e39fea6 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/tools/ChildMap.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/tools/ChildMap.java @@ -12,7 +12,10 @@ */ package org.openhab.binding.mqtt.generic.tools; +import java.util.Collection; +import java.util.HashSet; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.CompletableFuture; @@ -64,6 +67,24 @@ public Stream stream() { return map.values().stream(); } + /** + * Streams the objects in this map in the order of the given keys. + * + * Extraneous keys are ignored, and missing keys are included at the end in unspecified order. + * + * @param order The keys in the order they should be streamed + */ + public Stream stream(Collection order) { + // need to make a copy to avoid editing `map` itself + Set missingKeys = new HashSet<>(map.keySet()); + missingKeys.removeAll(order); + Stream result = order.stream().map(k -> map.get(k)).filter(Objects::nonNull).map(Objects::requireNonNull); + if (!missingKeys.isEmpty()) { + result = Stream.concat(result, missingKeys.stream().map(k -> map.get(k)).map(Objects::requireNonNull)); + } + return result; + } + /** * Modifies the map in way that it matches the entries of the given childIDs. * @@ -134,4 +155,8 @@ public void clear() { public void put(String key, T value) { map.put(key, value); } + + public Set keySet() { + return map.keySet(); + } } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentChannel.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentChannel.java index 9ac5a12bf21c8..21f836fc4f9b1 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentChannel.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentChannel.java @@ -12,6 +12,7 @@ */ package org.openhab.binding.mqtt.homeassistant.internal; +import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ScheduledExecutorService; import java.util.function.Predicate; @@ -59,39 +60,26 @@ public class ComponentChannel { private static final String JINJA = "JINJA"; - private final ChannelUID channelUID; private final ChannelState channelState; private final Channel channel; - private final ChannelTypeUID channelTypeUID; private final @Nullable StateDescription stateDescription; private final @Nullable CommandDescription commandDescription; private final ChannelStateUpdateListener channelStateUpdateListener; - private ComponentChannel(ChannelUID channelUID, ChannelState channelState, Channel channel, - ChannelTypeUID channelTypeUID, @Nullable StateDescription stateDescription, + private ComponentChannel(ChannelState channelState, Channel channel, @Nullable StateDescription stateDescription, @Nullable CommandDescription commandDescription, ChannelStateUpdateListener channelStateUpdateListener) { super(); - this.channelUID = channelUID; this.channelState = channelState; this.channel = channel; - this.channelTypeUID = channelTypeUID; this.stateDescription = stateDescription; this.commandDescription = commandDescription; this.channelStateUpdateListener = channelStateUpdateListener; } - public ChannelUID getChannelUID() { - return channelUID; - } - public Channel getChannel() { return channel; } - public ChannelTypeUID getChannelTypeUID() { - return channelTypeUID; - } - public ChannelState getState() { return channelState; } @@ -117,7 +105,8 @@ public ChannelState getState() { } public ChannelDefinition channelDefinition() { - return new ChannelDefinitionBuilder(channelUID.getId(), channelTypeUID).build(); + return new ChannelDefinitionBuilder(channel.getUID().getId(), + Objects.requireNonNull(channel.getChannelTypeUID())).withLabel(channel.getLabel()).build(); } public void resetState() { @@ -271,8 +260,8 @@ public ComponentChannel build(boolean addToComponent) { .withKind(kind).withLabel(label).withConfiguration(configuration) .withAutoUpdatePolicy(autoUpdatePolicy).build(); - ComponentChannel result = new ComponentChannel(channelUID, channelState, channel, channelTypeUID, - stateDescription, commandDescription, channelStateUpdateListener); + ComponentChannel result = new ComponentChannel(channelState, channel, stateDescription, commandDescription, + channelStateUpdateListener); TransformationServiceProvider transformationProvider = component.getTransformationServiceProvider(); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java index 7269c2dee3078..c178a2ba07d1e 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java @@ -19,7 +19,6 @@ import java.util.TreeMap; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ScheduledExecutorService; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -27,7 +26,6 @@ import org.openhab.binding.mqtt.generic.AvailabilityTracker; import org.openhab.binding.mqtt.generic.ChannelStateUpdateListener; import org.openhab.binding.mqtt.generic.MqttChannelStateDescriptionProvider; -import org.openhab.binding.mqtt.generic.MqttChannelTypeProvider; import org.openhab.binding.mqtt.generic.TransformationServiceProvider; import org.openhab.binding.mqtt.generic.values.Value; import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; @@ -39,6 +37,7 @@ import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AvailabilityMode; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.Device; import org.openhab.core.io.transport.mqtt.MqttBrokerConnection; +import org.openhab.core.thing.Channel; import org.openhab.core.thing.ChannelGroupUID; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.type.ChannelDefinition; @@ -49,6 +48,8 @@ import org.openhab.core.thing.type.ChannelTypeUID; import org.openhab.core.types.CommandDescription; import org.openhab.core.types.StateDescription; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.gson.Gson; @@ -63,9 +64,10 @@ public abstract class AbstractComponent { private static final String JINJA_PREFIX = "JINJA:"; + private final Logger logger = LoggerFactory.getLogger(AbstractComponent.class); + // Component location fields protected final ComponentConfiguration componentConfiguration; - protected final @Nullable ChannelGroupTypeUID channelGroupTypeUID; protected final @Nullable ChannelGroupUID channelGroupUID; protected final HaID haID; @@ -83,6 +85,7 @@ public abstract class AbstractComponent protected final boolean newStyleChannels; protected final boolean singleChannelComponent; protected final String groupId; + protected final String uniqueId; public AbstractComponent(ComponentFactory.ComponentConfiguration componentConfiguration, Class clazz, boolean newStyleChannels) { @@ -115,17 +118,20 @@ public AbstractComponent(ComponentFactory.ComponentConfiguration componentConfig groupId = this.haID.getGroupId(channelConfiguration.getUniqueId(), newStyleChannels); if (this.singleChannelComponent) { - this.channelGroupTypeUID = null; this.channelGroupUID = null; } else { - this.channelGroupTypeUID = new ChannelGroupTypeUID(MqttBindingConstants.BINDING_ID, groupId); + this.channelGroupUID = new ChannelGroupUID(componentConfiguration.getThingUID(), groupId); } } else { - groupId = ""; - this.channelGroupTypeUID = null; + if (newStyleChannels && this.singleChannelComponent) { + groupId = haID.component; + } else { + groupId = ""; + } this.channelGroupUID = null; } + uniqueId = this.haID.getGroupId(channelConfiguration.getUniqueId(), false); this.configSeen = false; @@ -205,43 +211,23 @@ public void setConfigSeen() { } /** - * Add all channel types to the channel type provider. + * Add all state and command descriptions to the state description provider. * - * @param channelTypeProvider The channel type provider + * @param stateDescriptionProvider The state description provider */ - public void addChannelTypes(MqttChannelTypeProvider channelTypeProvider, - MqttChannelStateDescriptionProvider stateDescriptionProvider) { - ChannelGroupTypeUID groupTypeUID = channelGroupTypeUID; - if (groupTypeUID != null) { - channelTypeProvider.setChannelGroupType(groupTypeUID, Objects.requireNonNull(getType())); - } + public void addStateDescriptions(MqttChannelStateDescriptionProvider stateDescriptionProvider) { channels.values().forEach(channel -> { StateDescription stateDescription = channel.getStateDescription(); if (stateDescription != null) { - stateDescriptionProvider.setDescription(channel.getChannelUID(), stateDescription); + stateDescriptionProvider.setDescription(channel.getChannel().getUID(), stateDescription); } CommandDescription commandDescription = channel.getCommandDescription(); if (commandDescription != null) { - stateDescriptionProvider.setDescription(channel.getChannelUID(), commandDescription); + stateDescriptionProvider.setDescription(channel.getChannel().getUID(), commandDescription); } }); } - /** - * Removes all channels from the channel type provider. - * Call this if the corresponding Thing handler gets disposed. - * - * @param channelTypeProvider The channel type provider - */ - public void removeChannelTypes(MqttChannelTypeProvider channelTypeProvider, - MqttChannelStateDescriptionProvider stateDescriptionProvider) { - ChannelGroupTypeUID groupTypeUID = channelGroupTypeUID; - if (groupTypeUID != null) { - channelTypeProvider.removeChannelGroupType(groupTypeUID); - } - channels.values().forEach(v -> stateDescriptionProvider.remove(v.getChannelUID())); - } - public ChannelUID buildChannelUID(String channelID) { final ChannelGroupUID groupUID = channelGroupUID; if (groupUID != null) { @@ -250,18 +236,8 @@ public ChannelUID buildChannelUID(String channelID) { return new ChannelUID(componentConfiguration.getThingUID(), channelID); } - /** - * Each HomeAssistant component corresponds to a Channel Group Type. - */ - public @Nullable ChannelGroupTypeUID getGroupTypeUID() { - return channelGroupTypeUID; - } - - /** - * The unique id of this component. - */ - public @Nullable ChannelGroupUID getGroupUID() { - return channelGroupUID; + public String getGroupId() { + return groupId; } /** @@ -309,19 +285,27 @@ public int getConfigHash() { /** * Return the channel group type. */ - public @Nullable ChannelGroupType getType() { - ChannelGroupTypeUID groupTypeUID = channelGroupTypeUID; - if (groupTypeUID == null) { + public @Nullable ChannelGroupType getChannelGroupType(String prefix) { + if (channelGroupUID == null) { return null; } - final List channelDefinitions = channels.values().stream() - .map(ComponentChannel::channelDefinition).collect(Collectors.toList()); - return ChannelGroupTypeBuilder.instance(groupTypeUID, getName()).withChannelDefinitions(channelDefinitions) - .build(); + return ChannelGroupTypeBuilder.instance(getChannelGroupTypeUID(prefix), getName()) + .withChannelDefinitions(getAllChannelDefinitions()).build(); + } + + public List getChannelDefinitions() { + if (channelGroupUID != null) { + return List.of(); + } + return getAllChannelDefinitions(); } - public List getChannels() { - return channels.values().stream().map(ComponentChannel::channelDefinition).collect(Collectors.toList()); + private List getAllChannelDefinitions() { + return channels.values().stream().map(ComponentChannel::channelDefinition).toList(); + } + + public List getChannels() { + return channels.values().stream().map(ComponentChannel::getChannel).toList(); } /** @@ -335,12 +319,15 @@ public void resetState() { /** * Return the channel group definition for this component. */ - public @Nullable ChannelGroupDefinition getGroupDefinition() { - ChannelGroupTypeUID groupTypeUID = channelGroupTypeUID; - if (groupTypeUID == null) { + public @Nullable ChannelGroupDefinition getGroupDefinition(String prefix) { + if (channelGroupUID == null) { return null; } - return new ChannelGroupDefinition(channelGroupUID.getId(), groupTypeUID, getName(), null); + return new ChannelGroupDefinition(channelGroupUID.getId(), getChannelGroupTypeUID(prefix), getName(), null); + } + + public boolean hasGroup() { + return channelGroupUID != null; } public HaID getHaID() { @@ -367,4 +354,8 @@ public Gson getGson() { public C getChannelConfiguration() { return channelConfiguration; } + + private ChannelGroupTypeUID getChannelGroupTypeUID(String prefix) { + return new ChannelGroupTypeUID(MqttBindingConstants.BINDING_ID, prefix + "_" + uniqueId); + } } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscovery.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscovery.java index b89f0944aba50..ca675d346f8a1 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscovery.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscovery.java @@ -51,6 +51,7 @@ import org.openhab.core.io.transport.mqtt.MqttBrokerConnection; import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.thing.ThingUID; +import org.openhab.core.thing.type.ThingType; import org.osgi.framework.Constants; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; @@ -144,7 +145,7 @@ protected void unsetTypeProvider(MqttChannelTypeProvider provider) { @Override public Set getSupportedThingTypes() { - return typeProvider.getThingTypeUIDs(); + return typeProvider.getThingTypes(null).stream().map(ThingType::getUID).collect(Collectors.toSet()); } /** diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java index 0f4f5eefbbd31..0aec229aabb56 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java @@ -13,7 +13,6 @@ package org.openhab.binding.mqtt.homeassistant.internal.handler; import java.net.URI; -import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; @@ -24,7 +23,6 @@ import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; -import java.util.stream.Collectors; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -49,7 +47,6 @@ import org.openhab.core.config.core.validation.ConfigValidationException; import org.openhab.core.io.transport.mqtt.MqttBrokerConnection; import org.openhab.core.thing.Channel; -import org.openhab.core.thing.ChannelGroupUID; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; @@ -57,10 +54,7 @@ import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.thing.ThingUID; import org.openhab.core.thing.binding.builder.ThingBuilder; -import org.openhab.core.thing.type.ChannelDefinition; -import org.openhab.core.thing.type.ChannelGroupDefinition; import org.openhab.core.thing.type.ChannelTypeRegistry; -import org.openhab.core.thing.util.ThingHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -87,8 +81,9 @@ public class HomeAssistantThingHandler extends AbstractMQTTThingHandler implements ComponentDiscovered, Consumer>> { public static final String AVAILABILITY_CHANNEL = "availability"; - private static final Comparator CHANNEL_COMPARATOR_BY_UID = Comparator - .comparing(channel -> channel.getUID().toString()); + private static final Comparator> COMPONENT_COMPARATOR = Comparator + .comparing((AbstractComponent component) -> component.hasGroup()) + .thenComparing(AbstractComponent::getName); private static final URI UPDATABLE_CONFIG_DESCRIPTION_URI = URI.create("thing-type:mqtt:homeassistant-updatable"); private final Logger logger = LoggerFactory.getLogger(HomeAssistantThingHandler.class); @@ -158,11 +153,6 @@ public void initialize() { // Already restored component? @Nullable AbstractComponent component = haComponents.get(groupID); - if (component != null) { - // the types may have been removed in dispose() so we need to add them again - component.addChannelTypes(channelTypeProvider, stateDescriptionProvider); - continue; - } HaID haID = HaID.fromConfig(config.basetopic, channel.getConfiguration()); discoveryHomeAssistantIDs.add(haID); @@ -178,15 +168,9 @@ public void initialize() { typeID = calculateThingTypeUID(component); } - final ChannelGroupUID groupUID = component.getGroupUID(); - String id = null; - if (groupUID != null) { - id = groupUID.getId(); - } - haComponents.put(id, component); - component.addChannelTypes(channelTypeProvider, stateDescriptionProvider); + haComponents.put(component.getGroupId(), component); } catch (ConfigurationException e) { - logger.error("Cannot not restore component {}: {}", thing, e.getMessage()); + logger.error("Cannot restore component {}: {}", thing, e.getMessage()); } } } @@ -197,9 +181,9 @@ public void initialize() { @Override public void dispose() { + removeStateDescriptions(); // super.dispose() calls stop() super.dispose(); - haComponents.values().forEach(c -> c.removeChannelTypes(channelTypeProvider, stateDescriptionProvider)); } @Override @@ -250,13 +234,21 @@ protected void stop() { @Override public @Nullable ChannelState getChannelState(ChannelUID channelUID) { - String groupID = channelUID.getGroupId(); + String componentId; + if (channelUID.isInGroup()) { + componentId = channelUID.getGroupId(); + } else { + componentId = channelUID.getId(); + } AbstractComponent component; synchronized (haComponents) { // sync whenever discoverComponents is started - component = haComponents.get(groupID); + component = haComponents.get(componentId); } if (component == null) { - return null; + component = haComponents.get(""); + if (component == null) { + return null; + } } ComponentChannel componentChannel = component.getChannel(channelUID.getIdWithoutGroup()); if (componentChannel == null) { @@ -290,11 +282,7 @@ public void accept(List> discoveredComponentsList) { if (typeID.equals(MqttBindingConstants.HOMEASSISTANT_MQTT_THING)) { typeID = calculateThingTypeUID(discovered); } - final ChannelGroupUID groupUID = discovered.getGroupUID(); - String id = null; - if (groupUID != null) { - id = groupUID.getId(); - } + String id = discovered.getGroupId(); AbstractComponent known = haComponents.get(id); // Is component already known? if (known != null) { @@ -308,8 +296,6 @@ public void accept(List> discoveredComponentsList) { } } - // Add channel and group types to the types registry - discovered.addChannelTypes(channelTypeProvider, stateDescriptionProvider); // Add component to the component map haComponents.put(id, discovered); // Start component / Subscribe to channel topics @@ -322,47 +308,11 @@ public void accept(List> discoveredComponentsList) { updateComponent = (Update) discovered; updateComponent.setReleaseStateUpdateListener(this::releaseStateUpdated); } - - List discoveredChannels = discovered.getChannelMap().values().stream() - .map(ComponentChannel::getChannel).collect(Collectors.toList()); - if (known != null) { - // We had previously known component with different config hash - // We remove all conflicting old channels, they will be re-added below based on the new discovery - logger.debug( - "Received component {} with slightly different config. Making sure we re-create conflicting channels...", - discovered.getHaID()); - removeJustRediscoveredChannels(discoveredChannels); - } - - // Add newly discovered channels. We sort the channels - // for (mostly) consistent jsondb serialization - discoveredChannels.sort(CHANNEL_COMPARATOR_BY_UID); - ThingHelper.addChannelsToThing(thing, discoveredChannels); } updateThingType(typeID); } } - private void removeJustRediscoveredChannels(List discoveredChannels) { - ArrayList mutableChannels = new ArrayList<>(getThing().getChannels()); - Set newChannelUIDs = discoveredChannels.stream().map(Channel::getUID).collect(Collectors.toSet()); - // Take current channels but remove those channels that were just re-discovered - List existingChannelsWithNewlyDiscoveredChannelsRemoved = mutableChannels.stream() - .filter(existingChannel -> !newChannelUIDs.contains(existingChannel.getUID())) - .collect(Collectors.toList()); - if (existingChannelsWithNewlyDiscoveredChannelsRemoved.size() < mutableChannels.size()) { - // We sort the channels for (mostly) consistent jsondb serialization - existingChannelsWithNewlyDiscoveredChannelsRemoved.sort(CHANNEL_COMPARATOR_BY_UID); - updateThingChannels(existingChannelsWithNewlyDiscoveredChannelsRemoved); - } - } - - private void updateThingChannels(List channelList) { - ThingBuilder thingBuilder = editThing(); - thingBuilder.withChannels(channelList); - updateThing(thingBuilder.build()); - } - @Override protected void updateThingStatus(boolean messageReceived, Optional availabilityTopicsSeen) { if (availabilityTopicsSeen.orElse(messageReceived)) { @@ -395,7 +345,7 @@ public void handleConfigurationUpdate(Map configurationParameter private boolean updateThingType(ThingTypeUID typeID) { // if this is a dynamic type, then we update the type if (!MqttBindingConstants.HOMEASSISTANT_MQTT_THING.equals(typeID)) { - var builder = channelTypeProvider.derive(typeID, MqttBindingConstants.HOMEASSISTANT_MQTT_THING); + var thingTypeBuilder = channelTypeProvider.derive(typeID, MqttBindingConstants.HOMEASSISTANT_MQTT_THING); if (getThing().getThingTypeUID().equals(MqttBindingConstants.HOMEASSISTANT_MQTT_THING)) { logger.debug("Migrating Home Assistant thing {} from generic type to dynamic type {}", @@ -403,26 +353,40 @@ private boolean updateThingType(ThingTypeUID typeID) { // just create an empty thing type for now; channel configurations won't follow over // to the re-created Thing, so we need to re-discover them all anyway - channelTypeProvider.setThingType(typeID, builder.build()); + channelTypeProvider.putThingType(thingTypeBuilder.build()); changeThingType(typeID, getConfig()); return false; } - List groupDefs; - List channelDefs; synchronized (haComponents) { // sync whenever discoverComponents is started - groupDefs = haComponents.values().stream().map(AbstractComponent::getGroupDefinition) - .filter(Objects::nonNull).map(Objects::requireNonNull).collect(Collectors.toList()); - channelDefs = haComponents.values().stream().map(AbstractComponent::getChannels).flatMap(List::stream) - .collect(Collectors.toList()); - } - builder.withChannelDefinitions(channelDefs).withChannelGroupDefinitions(groupDefs); - Update updateComponent = this.updateComponent; - if (updateComponent != null && updateComponent.isUpdatable()) { - builder.withConfigDescriptionURI(UPDATABLE_CONFIG_DESCRIPTION_URI); - } + var sortedComponents = haComponents.values().stream().sorted(COMPONENT_COMPARATOR).toList(); + + var channelGroupTypes = sortedComponents.stream().map(c -> c.getChannelGroupType(typeID.getId())) + .filter(Objects::nonNull).map(Objects::requireNonNull).toList(); + channelTypeProvider.updateChannelGroupTypesForPrefix(typeID.getId(), channelGroupTypes); + + var groupDefs = sortedComponents.stream().map(c -> c.getGroupDefinition(typeID.getId())) + .filter(Objects::nonNull).map(Objects::requireNonNull).toList(); + var channelDefs = sortedComponents.stream().map(AbstractComponent::getChannelDefinitions) + .flatMap(List::stream).toList(); + thingTypeBuilder.withChannelDefinitions(channelDefs).withChannelGroupDefinitions(groupDefs); + Update updateComponent = this.updateComponent; + if (updateComponent != null && updateComponent.isUpdatable()) { + thingTypeBuilder.withConfigDescriptionURI(UPDATABLE_CONFIG_DESCRIPTION_URI); + } + + channelTypeProvider.putThingType(thingTypeBuilder.build()); + + removeStateDescriptions(); + sortedComponents.stream().forEach(c -> c.addStateDescriptions(stateDescriptionProvider)); + + ThingBuilder thingBuilder = editThing().withChannels(); - channelTypeProvider.setThingType(typeID, builder.build()); + sortedComponents.stream().map(AbstractComponent::getChannels).flatMap(List::stream) + .forEach(c -> thingBuilder.withChannel(c)); + + updateThing(thingBuilder.build()); + } } return true; } @@ -432,6 +396,20 @@ private ThingTypeUID calculateThingTypeUID(AbstractComponent component) { + "_" + component.getChannelConfiguration().getThingId(component.getHaID().objectID)); } + @Override + public void handleRemoval() { + synchronized (haComponents) { + channelTypeProvider.removeThingType(thing.getThingTypeUID()); + channelTypeProvider.removeChannelGroupTypesForPrefix(thing.getThingTypeUID().getId()); + removeStateDescriptions(); + } + super.handleRemoval(); + } + + private void removeStateDescriptions() { + thing.getChannels().stream().forEach(c -> stateDescriptionProvider.remove(c.getUID())); + } + private void releaseStateUpdated(Update.ReleaseState state) { Map properties = editProperties(); properties = state.appendToProperties(properties); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/AbstractHomeAssistantTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/AbstractHomeAssistantTests.java index e03f7f18b1571..7c2d33c7b67a6 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/AbstractHomeAssistantTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/AbstractHomeAssistantTests.java @@ -39,9 +39,11 @@ import org.openhab.binding.mqtt.generic.MqttChannelTypeProvider; import org.openhab.binding.mqtt.generic.TransformationServiceProvider; import org.openhab.binding.mqtt.handler.BrokerHandler; +import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.core.io.transport.mqtt.MqttBrokerConnection; import org.openhab.core.io.transport.mqtt.MqttMessageSubscriber; import org.openhab.core.test.java.JavaTest; +import org.openhab.core.test.storage.VolatileStorageService; import org.openhab.core.thing.Bridge; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; @@ -52,6 +54,7 @@ import org.openhab.core.thing.binding.builder.BridgeBuilder; import org.openhab.core.thing.binding.builder.ThingBuilder; import org.openhab.core.thing.type.ChannelTypeRegistry; +import org.openhab.core.thing.type.ThingType; import org.openhab.core.thing.type.ThingTypeBuilder; import org.openhab.core.thing.type.ThingTypeRegistry; import org.openhab.transform.jinja.internal.JinjaTransformationService; @@ -74,11 +77,12 @@ public abstract class AbstractHomeAssistantTests extends JavaTest { public static final String BRIDGE_ID = UUID.randomUUID().toString(); public static final ThingUID BRIDGE_UID = new ThingUID(BRIDGE_TYPE_UID, BRIDGE_ID); - public static final String HA_TYPE_ID = "homeassistant"; - public static final String HA_TYPE_LABEL = "Homeassistant"; - public static final ThingTypeUID HA_TYPE_UID = new ThingTypeUID(BINDING_ID, HA_TYPE_ID); + public static final String HA_TYPE_LABEL = "Home Assistant Thing"; + public static final ThingTypeUID HA_TYPE_UID = new ThingTypeUID(BINDING_ID, "homeassistant_dynamic_type"); public static final String HA_ID = UUID.randomUUID().toString(); - public static final ThingUID HA_UID = new ThingUID(HA_TYPE_UID, HA_ID); + public static final ThingUID HA_UID = new ThingUID(MqttBindingConstants.HOMEASSISTANT_MQTT_THING, HA_ID); + public static final ThingType HA_THING_TYPE = ThingTypeBuilder + .instance(MqttBindingConstants.HOMEASSISTANT_MQTT_THING, HA_TYPE_LABEL).build(); protected @Mock @NonNullByDefault({}) MqttBrokerConnection bridgeConnection; protected @Mock @NonNullByDefault({}) ThingTypeRegistry thingTypeRegistry; @@ -99,13 +103,12 @@ public abstract class AbstractHomeAssistantTests extends JavaTest { public void beforeEachAbstractHomeAssistantTests() { when(thingTypeRegistry.getThingType(BRIDGE_TYPE_UID)) .thenReturn(ThingTypeBuilder.instance(BRIDGE_TYPE_UID, BRIDGE_TYPE_LABEL).build()); - when(thingTypeRegistry.getThingType(HA_TYPE_UID)) - .thenReturn(ThingTypeBuilder.instance(HA_TYPE_UID, HA_TYPE_LABEL).build()); + when(thingTypeRegistry.getThingType(MqttBindingConstants.HOMEASSISTANT_MQTT_THING)).thenReturn(HA_THING_TYPE); when(transformationServiceProvider .getTransformationService(JinjaTransformationProfile.PROFILE_TYPE_UID.getId())) .thenReturn(jinjaTransformationService); - channelTypeProvider = spy(new MqttChannelTypeProvider(thingTypeRegistry)); + channelTypeProvider = spy(new MqttChannelTypeProvider(thingTypeRegistry, new VolatileStorageService())); stateDescriptionProvider = spy(new MqttChannelStateDescriptionProvider()); channelTypeRegistry = spy(new ChannelTypeRegistry()); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponentTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponentTests.java index 7985d25db4aa3..2910c9523b1a3 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponentTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponentTests.java @@ -195,7 +195,7 @@ protected void spyOnChannelUpdates(AbstractComponent<@NonNull ? extends Abstract */ protected void assertTriggered(AbstractComponent<@NonNull ? extends AbstractChannelConfiguration> component, String channelId, String trigger) { - verify(thingHandler).triggerChannel(eq(component.getChannel(channelId).getChannelUID()), eq(trigger)); + verify(thingHandler).triggerChannel(eq(component.getChannel(channelId).getChannel().getUID()), eq(trigger)); } /** @@ -279,7 +279,7 @@ protected boolean publishMessage(String mqttTopic, byte[] payload) { protected void sendCommand(AbstractComponent<@NonNull ? extends AbstractChannelConfiguration> component, String channelId, Command command) { var channel = Objects.requireNonNull(component.getChannel(channelId)); - thingHandler.handleCommand(channel.getChannelUID(), command); + thingHandler.handleCommand(channel.getChannel().getUID(), command); } protected static class LatchThingHandler extends HomeAssistantThingHandler { diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensorTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensorTests.java index e8c150df40889..6c875e74b0cb7 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensorTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensorTests.java @@ -65,7 +65,7 @@ public void test() throws InterruptedException { assertThat(component.channels.size(), is(1)); assertThat(component.getName(), is("onoffsensor")); - assertThat(component.getGroupUID().getId(), is("sn1")); + assertThat(component.getGroupId(), is("sn1")); assertChannel(component, BinarySensor.SENSOR_CHANNEL_ID, "zigbee2mqtt/sensor/state", "", "onoffsensor", OnOffValue.class); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/SensorTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/SensorTests.java index 78549ef16a7e5..c2abf74b39c07 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/SensorTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/SensorTests.java @@ -65,7 +65,7 @@ public void test() throws InterruptedException { assertThat(component.channels.size(), is(1)); assertThat(component.getName(), is("sensor1")); - assertThat(component.getGroupUID().getId(), is("sn1")); + assertThat(component.getGroupId(), is("sn1")); assertChannel(component, Sensor.SENSOR_CHANNEL_ID, "zigbee2mqtt/sensor/state", "", "sensor1", NumberValue.class); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandlerTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandlerTests.java index 7da7b0f1ef3c0..15df43128a7f9 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandlerTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandlerTests.java @@ -106,9 +106,9 @@ public void testInitialize() { verify(thingHandler, times(1)).componentDiscovered(eq(new HaID(configTopic)), any(Climate.class)); thingHandler.delayedProcessing.forceProcessNow(); - assertThat(haThing.getChannels().size(), CoreMatchers.is(6)); + assertThat(nonSpyThingHandler.getThing().getChannels().size(), CoreMatchers.is(6)); verify(stateDescriptionProvider, times(6)).setDescription(any(), any(StateDescription.class)); - verify(channelTypeProvider, times(1)).setChannelGroupType(any(), any()); + verify(channelTypeProvider, times(1)).putChannelGroupType(any()); configTopic = "homeassistant/switch/0x847127fffe11dd6a_auto_lock_zigbee2mqtt/config"; thingHandler.discoverComponents.processMessage(configTopic, @@ -117,9 +117,9 @@ public void testInitialize() { verify(thingHandler, times(1)).componentDiscovered(eq(new HaID(configTopic)), any(Switch.class)); thingHandler.delayedProcessing.forceProcessNow(); - assertThat(haThing.getChannels().size(), CoreMatchers.is(7)); - verify(stateDescriptionProvider, times(7)).setDescription(any(), any(StateDescription.class)); - verify(channelTypeProvider, times(2)).setChannelGroupType(any(), any()); + assertThat(nonSpyThingHandler.getThing().getChannels().size(), CoreMatchers.is(7)); + verify(stateDescriptionProvider, atLeast(7)).setDescription(any(), any(StateDescription.class)); + verify(channelTypeProvider, times(3)).putChannelGroupType(any()); } /** @@ -171,7 +171,7 @@ public void testDuplicateComponentPublish() throws InterruptedException { verify(thingHandler, times(1)).componentDiscovered(eq(new HaID(configTopicTempCorridor)), any(Sensor.class)); thingHandler.delayedProcessing.forceProcessNow(); waitForAssert(() -> { - assertThat("1 channel created", thingHandler.getThing().getChannels().size() == 1); + assertThat("1 channel created", nonSpyThingHandler.getThing().getChannels().size() == 1); }); // @@ -187,7 +187,7 @@ public void testDuplicateComponentPublish() throws InterruptedException { thingHandler.delayedProcessing.forceProcessNow(); verify(thingHandler, times(1)).componentDiscovered(eq(new HaID(configTopicTempOutside)), any(Sensor.class)); waitForAssert(() -> { - assertThat("2 channel created", thingHandler.getThing().getChannels().size() == 2); + assertThat("2 channel created", nonSpyThingHandler.getThing().getChannels().size() == 2); }); // @@ -202,7 +202,7 @@ public void testDuplicateComponentPublish() throws InterruptedException { thingHandler.delayedProcessing.forceProcessNow(); waitForAssert(() -> { - assertThat("2 channel created", thingHandler.getThing().getChannels().size() == 2); + assertThat("2 channel created", nonSpyThingHandler.getThing().getChannels().size() == 2); }); // @@ -220,7 +220,7 @@ public void testDuplicateComponentPublish() throws InterruptedException { verify(thingHandler, times(2)).componentDiscovered(eq(new HaID(configTopicTempCorridor)), any(Sensor.class)); waitForAssert(() -> { - assertThat("2 channel created", thingHandler.getThing().getChannels().size() == 2); + assertThat("2 channel created", nonSpyThingHandler.getThing().getChannels().size() == 2); }); } @@ -240,8 +240,8 @@ public void testDispose() { "homeassistant/switch/0x847127fffe11dd6a_auto_lock_zigbee2mqtt/config", getResourceAsByteArray("component/configTS0601AutoLock.json")); thingHandler.delayedProcessing.forceProcessNow(); - assertThat(haThing.getChannels().size(), CoreMatchers.is(7)); - verify(stateDescriptionProvider, times(7)).setDescription(any(), any(StateDescription.class)); + assertThat(nonSpyThingHandler.getThing().getChannels().size(), CoreMatchers.is(7)); + verify(stateDescriptionProvider, atLeast(7)).setDescription(any(), any(StateDescription.class)); // When dispose thingHandler.dispose(); @@ -250,6 +250,28 @@ public void testDispose() { MQTT_TOPICS.forEach(t -> { verify(bridgeConnection, timeout(SUBSCRIBE_TIMEOUT)).unsubscribe(eq(t), any()); }); + } + + @Test + public void testRemoveThing() { + thingHandler.initialize(); + + // Expect subscription on each topic from config + CONFIG_TOPICS.forEach(t -> { + var fullTopic = HandlerConfiguration.DEFAULT_BASETOPIC + "/" + t + "/config"; + verify(bridgeConnection, timeout(SUBSCRIBE_TIMEOUT)).subscribe(eq(fullTopic), any()); + }); + thingHandler.discoverComponents.processMessage( + "homeassistant/climate/0x847127fffe11dd6a_climate_zigbee2mqtt/config", + getResourceAsByteArray("component/configTS0601ClimateThermostat.json")); + thingHandler.discoverComponents.processMessage( + "homeassistant/switch/0x847127fffe11dd6a_auto_lock_zigbee2mqtt/config", + getResourceAsByteArray("component/configTS0601AutoLock.json")); + thingHandler.delayedProcessing.forceProcessNow(); + assertThat(nonSpyThingHandler.getThing().getChannels().size(), CoreMatchers.is(7)); + + // When dispose + nonSpyThingHandler.handleRemoval(); // Expect channel descriptions removed, 6 for climate and 1 for switch verify(stateDescriptionProvider, times(7)).remove(any()); diff --git a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/handler/HomieThingHandler.java b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/handler/HomieThingHandler.java index cb305be7841f8..5eea5f2444f18 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/handler/HomieThingHandler.java +++ b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/handler/HomieThingHandler.java @@ -12,6 +12,7 @@ */ package org.openhab.binding.mqtt.homie.internal.handler; +import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -19,6 +20,7 @@ import java.util.concurrent.ScheduledFuture; import java.util.function.Consumer; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -58,6 +60,8 @@ */ @NonNullByDefault public class HomieThingHandler extends AbstractMQTTThingHandler implements DeviceCallback, Consumer> { + private static final String[] EMPTY_ARRAY = new String[] {}; + private final Logger logger = LoggerFactory.getLogger(HomieThingHandler.class); protected Device device; protected final MqttChannelTypeProvider channelTypeProvider; @@ -140,6 +144,8 @@ public void handleRemoval() { if (config.removetopics) { this.removeRetainedTopics(); } + channelTypeProvider.removeThingType(thing.getThingTypeUID()); + channelTypeProvider.removeChannelGroupTypesForPrefix(thing.getThingTypeUID().getId()); super.handleRemoval(); } @@ -169,7 +175,6 @@ protected void stop() { } delayedProcessing.join(); device.stop(); - channelTypeProvider.removeThingType(device.thingTypeUID); super.stop(); } @@ -216,7 +221,6 @@ public void readyStateChanged(ReadyState state) { @Override public void nodeRemoved(Node node) { - channelTypeProvider.removeChannelGroupType(node.channelGroupTypeUID); delayedProcessing.accept(node); } @@ -228,7 +232,6 @@ public void propertyRemoved(Property property) { @Override public void nodeAddedOrChanged(Node node) { - channelTypeProvider.setChannelGroupType(node.channelGroupTypeUID, node.type()); delayedProcessing.accept(node); } @@ -288,27 +291,42 @@ protected void updateThingStatus(boolean messageReceived, Optional avai private void updateThingType() { // Make sure any dynamic channel types exist (i.e. ones created for a number channel with a specific dimension) device.nodes.stream().flatMap(n -> n.properties.stream()).map(Property::getChannelType).filter(Objects::nonNull) - .forEach(ct -> channelTypeProvider.setChannelType(ct.getUID(), ct)); + .forEach(ct -> channelTypeProvider.putChannelType(Objects.requireNonNull(ct))); // if this is a dynamic type, then we update the type ThingTypeUID typeID = device.thingTypeUID; if (!MqttBindingConstants.HOMIE300_MQTT_THING.equals(typeID)) { - device.nodes.stream() - .forEach(n -> channelTypeProvider.setChannelGroupType(n.channelGroupTypeUID, n.type())); + channelTypeProvider.updateChannelGroupTypesForPrefix(thing.getThingTypeUID().getId(), device.nodes.stream() + .map(n -> n.type(thing.getThingTypeUID().getId(), channelTypeProvider)).toList()); - List groupDefs = device.nodes().stream().map(Node::getChannelGroupDefinition) - .collect(Collectors.toList()); + List groupDefs = device.nodes.stream(nodeOrder()) + .map(n -> n.getChannelGroupDefinition(thing.getThingTypeUID().getId())).toList(); var builder = channelTypeProvider.derive(typeID, MqttBindingConstants.HOMIE300_MQTT_THING) .withChannelGroupDefinitions(groupDefs); - ThingType thingType = builder.build(); - channelTypeProvider.setThingType(typeID, thingType); + channelTypeProvider.putThingType(builder.build()); } } private void updateChannels() { - List channels = device.nodes().stream().flatMap(n -> n.properties.stream()) - .map(p -> p.getChannel(channelTypeRegistry)).collect(Collectors.toList()); + List channels = device.nodes.stream(nodeOrder()) + .flatMap(node -> node.properties + .stream(node.propertyOrder(thing.getThingTypeUID().getId(), channelTypeProvider)) + .map(p -> p.getChannel(channelTypeRegistry))) + .toList(); updateThing(editThing().withChannels(channels).build()); } + + private Collection nodeOrder() { + String[] nodes = device.attributes.nodes; + if (nodes != null) { + return Stream.of(nodes).toList(); + } + ThingType thingType = channelTypeProvider.getThingType(thing.getThingTypeUID(), null); + if (thingType != null) { + return thingType.getChannelGroupDefinitions().stream().map(ChannelGroupDefinition::getId).toList(); + } + + return device.nodes.keySet(); + } } diff --git a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Node.java b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Node.java index d9d9592250e4a..30715f3f8b91f 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Node.java +++ b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Node.java @@ -13,6 +13,7 @@ package org.openhab.binding.mqtt.homie.internal.homie300; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.concurrent.CompletableFuture; @@ -22,6 +23,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.mqtt.generic.MqttChannelTypeProvider; import org.openhab.binding.mqtt.generic.mapping.AbstractMqttAttributeClass; import org.openhab.binding.mqtt.generic.tools.ChildMap; import org.openhab.binding.mqtt.homie.generic.internal.MqttBindingConstants; @@ -47,6 +49,8 @@ */ @NonNullByDefault public class Node implements AbstractMqttAttributeClass.AttributeChanged { + private static final String[] EMPTY_ARRAY = new String[] {}; + private final Logger logger = LoggerFactory.getLogger(Node.class); // Homie public final String nodeID; @@ -55,7 +59,6 @@ public class Node implements AbstractMqttAttributeClass.AttributeChanged { // Runtime public final DeviceCallback callback; protected final ChannelGroupUID channelGroupUID; - public final ChannelGroupTypeUID channelGroupTypeUID; private final String topic; private boolean initialized = false; @@ -72,7 +75,6 @@ public Node(String topic, String nodeID, ThingUID thingUID, DeviceCallback callb this.topic = topic + "/" + nodeID; this.nodeID = nodeID; this.callback = callback; - channelGroupTypeUID = new ChannelGroupTypeUID(MqttBindingConstants.BINDING_ID, UIDUtils.encode(this.topic)); channelGroupUID = new ChannelGroupUID(thingUID, UIDUtils.encode(nodeID)); properties = new ChildMap<>(); } @@ -117,15 +119,16 @@ public void nodeRestoredFromConfig() { /** * Return the channel group type for this Node. */ - public ChannelGroupType type() { - final List channelDefinitions = properties.stream() - .map(p -> Objects.requireNonNull(p.getChannelDefinition())).collect(Collectors.toList()); - return ChannelGroupTypeBuilder.instance(channelGroupTypeUID, attributes.name) + public ChannelGroupType type(String prefix, MqttChannelTypeProvider channelTypeProvider) { + final List channelDefinitions = properties.stream(propertyOrder(prefix, channelTypeProvider)) + .map(p -> Objects.requireNonNull(p.getChannelDefinition())).toList(); + return ChannelGroupTypeBuilder.instance(getChannelGroupTypeUID(prefix), attributes.name) .withChannelDefinitions(channelDefinitions).build(); } - public ChannelGroupDefinition getChannelGroupDefinition() { - return new ChannelGroupDefinition(channelGroupUID.getId(), channelGroupTypeUID, attributes.name, null); + public ChannelGroupDefinition getChannelGroupDefinition(String prefix) { + return new ChannelGroupDefinition(channelGroupUID.getId(), getChannelGroupTypeUID(prefix), attributes.name, + null); } /** @@ -220,4 +223,21 @@ public List getRetainedTopics() { return topics; } + + public Collection propertyOrder(String prefix, MqttChannelTypeProvider channelTypeProvider) { + String[] properties = attributes.properties; + if (properties != null) { + return Stream.of(properties).toList(); + } + ChannelGroupType channelGroupType = channelTypeProvider.getChannelGroupType(getChannelGroupTypeUID(prefix), + null); + if (channelGroupType != null) { + return channelGroupType.getChannelDefinitions().stream().map(ChannelDefinition::getId).toList(); + } + return this.properties.keySet(); + } + + private ChannelGroupTypeUID getChannelGroupTypeUID(String prefix) { + return new ChannelGroupTypeUID(MqttBindingConstants.BINDING_ID, prefix + "_" + UIDUtils.encode(this.topic)); + } } diff --git a/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/internal/handler/HomieThingHandlerTests.java b/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/internal/handler/HomieThingHandlerTests.java index 09d09c6a2b2d2..4e5eeedee2580 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/internal/handler/HomieThingHandlerTests.java +++ b/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/internal/handler/HomieThingHandlerTests.java @@ -62,6 +62,7 @@ import org.openhab.core.config.core.Configuration; import org.openhab.core.io.transport.mqtt.MqttBrokerConnection; import org.openhab.core.library.types.StringType; +import org.openhab.core.test.storage.VolatileStorageService; import org.openhab.core.thing.Channel; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; @@ -99,7 +100,8 @@ public class HomieThingHandlerTests { private @NonNullByDefault({}) Thing thing; private @NonNullByDefault({}) HomieThingHandler thingHandler; - private final MqttChannelTypeProvider channelTypeProvider = spy(new MqttChannelTypeProvider(thingTypeRegistryMock)); + private final MqttChannelTypeProvider channelTypeProvider = spy( + new MqttChannelTypeProvider(thingTypeRegistryMock, new VolatileStorageService())); private final MqttChannelStateDescriptionProvider stateDescriptionProvider = new MqttChannelStateDescriptionProvider(); private final String deviceID = ThingChannelConstants.TEST_HOMIE_THING.getId(); diff --git a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java index 916ea59231d01..3bb3ef162c5a1 100644 --- a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java +++ b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java @@ -161,8 +161,7 @@ public void parseHATree() throws Exception { ComponentDiscovered cd = (haID, c) -> { haComponents.put(c.getGroupUID().getId(), c); c.addChannelTypes(channelTypeProvider); - channelTypeProvider.setChannelGroupType(Objects.requireNonNull(c.getGroupTypeUID()), - Objects.requireNonNull(c.getType())); + channelTypeProvider.putChannelGroupType(Objects.requireNonNull(c.getGroupTypeUID()), Objects.requireNonNull(c.getType())); latch.countDown(); }; @@ -182,9 +181,9 @@ public void parseHATree() throws Exception { assertThat(haComponents.size(), is(1)); // For the switch component we should have one channel group type and one channel type - // setChannelGroupType is called once above - verify(channelTypeProvider, times(2)).setChannelGroupType(any(), any()); - verify(channelTypeProvider, times(1)).setChannelType(any(), any()); + // putChannelGroupType is called once above + verify(channelTypeProvider, times(2)).putChannelGroupType(any(), any()); + verify(channelTypeProvider, times(1)).putChannelType(any(), any()); String channelGroupId = UIDUtils .encode("node_" + ThingChannelConstants.TEST_HOME_ASSISTANT_THING.getId() + "_switch"); From c377dcd9b13668e2435fcb23b61b66ab831fffb1 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Mon, 1 Apr 2024 10:37:44 -0600 Subject: [PATCH 05/11] fix spotless warning Signed-off-by: Cody Cutrer --- .../homeassistant/HomeAssistantMQTTImplementationTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java index 3bb3ef162c5a1..7a6ae0fbb6207 100644 --- a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java +++ b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java @@ -161,7 +161,8 @@ public void parseHATree() throws Exception { ComponentDiscovered cd = (haID, c) -> { haComponents.put(c.getGroupUID().getId(), c); c.addChannelTypes(channelTypeProvider); - channelTypeProvider.putChannelGroupType(Objects.requireNonNull(c.getGroupTypeUID()), Objects.requireNonNull(c.getType())); + channelTypeProvider.putChannelGroupType(Objects.requireNonNull(c.getGroupTypeUID()), + Objects.requireNonNull(c.getType())); latch.countDown(); }; From cb2a0ec3d5c9e298700f10f0cfd969692a4e3e50 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Mon, 1 Apr 2024 12:23:53 -0600 Subject: [PATCH 06/11] address itests compilation errors Signed-off-by: Cody Cutrer --- .../mqtt/homeassistant/DiscoverComponentsTest.java | 2 +- .../HomeAssistantMQTTImplementationTest.java | 13 ++----------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/DiscoverComponentsTest.java b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/DiscoverComponentsTest.java index 417f79e4a8e6d..cc35c25ed397a 100644 --- a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/DiscoverComponentsTest.java +++ b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/DiscoverComponentsTest.java @@ -84,7 +84,7 @@ public void discoveryTimeTest() throws InterruptedException, ExecutionException, Gson gson = new GsonBuilder().registerTypeAdapterFactory(new ChannelConfigurationTypeAdapterFactory()).create(); DiscoverComponents discover = spy(new DiscoverComponents(ThingChannelConstants.TEST_HOME_ASSISTANT_THING, - scheduler, channelStateUpdateListener, availabilityTracker, gson, transformationServiceProvider)); + scheduler, channelStateUpdateListener, availabilityTracker, gson, transformationServiceProvider, true)); HandlerConfiguration config = new HandlerConfiguration("homeassistant", List.of("switch/object")); diff --git a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java index 7a6ae0fbb6207..c665c477e4be1 100644 --- a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java +++ b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java @@ -22,7 +22,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; @@ -152,17 +151,14 @@ public void parseHATree() throws Exception { ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(4); DiscoverComponents discover = spy(new DiscoverComponents(ThingChannelConstants.TEST_HOME_ASSISTANT_THING, - scheduler, channelStateUpdateListener, availabilityTracker, gson, transformationServiceProvider)); + scheduler, channelStateUpdateListener, availabilityTracker, gson, transformationServiceProvider, true)); // The DiscoverComponents object calls ComponentDiscovered callbacks. // In the following implementation we add the found component to the `haComponents` map // and add the types to the channelTypeProvider, like in the real Thing handler. final CountDownLatch latch = new CountDownLatch(1); ComponentDiscovered cd = (haID, c) -> { - haComponents.put(c.getGroupUID().getId(), c); - c.addChannelTypes(channelTypeProvider); - channelTypeProvider.putChannelGroupType(Objects.requireNonNull(c.getGroupTypeUID()), - Objects.requireNonNull(c.getType())); + haComponents.put(c.getGroupId(), c); latch.countDown(); }; @@ -181,11 +177,6 @@ public void parseHATree() throws Exception { assertNull(failure); assertThat(haComponents.size(), is(1)); - // For the switch component we should have one channel group type and one channel type - // putChannelGroupType is called once above - verify(channelTypeProvider, times(2)).putChannelGroupType(any(), any()); - verify(channelTypeProvider, times(1)).putChannelType(any(), any()); - String channelGroupId = UIDUtils .encode("node_" + ThingChannelConstants.TEST_HOME_ASSISTANT_THING.getId() + "_switch"); From 9c1f7f01354a74a7733fa5cb24ad22414ce05bda Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Thu, 18 Apr 2024 15:56:18 -0600 Subject: [PATCH 07/11] address review comments Signed-off-by: Cody Cutrer --- .../mqtt/generic/MqttChannelTypeProvider.java | 12 +++------- .../internal/component/AbstractComponent.java | 23 ++++--------------- .../internal/handler/HomieThingHandler.java | 2 -- .../mqtt/homie/internal/homie300/Node.java | 2 -- 4 files changed, 8 insertions(+), 31 deletions(-) diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/MqttChannelTypeProvider.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/MqttChannelTypeProvider.java index 8ffe385717f97..322497df4b743 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/MqttChannelTypeProvider.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/MqttChannelTypeProvider.java @@ -58,12 +58,6 @@ public MqttChannelTypeProvider(@Reference ThingTypeRegistry thingTypeRegistry, this.thingTypeRegistry = thingTypeRegistry; } - public void putThingTypeIfAbsent(ThingTypeUID uid, ThingType type) { - if (getThingType(uid, null) == null) { - putThingType(type); - } - } - public ThingTypeBuilder derive(ThingTypeUID newTypeId, ThingTypeUID baseTypeId) { ThingType baseType = thingTypeRegistry.getThingType(baseTypeId); @@ -102,12 +96,12 @@ public void updateChannelGroupTypesForPrefix(String prefix, Collection removeChannelGroupType(uid)); - types.stream().forEach(t -> putChannelGroupType(t)); + oldUids.forEach(this::removeChannelGroupType); + types.forEach(this::putChannelGroupType); } public void removeChannelGroupTypesForPrefix(String prefix) { - channelGroupTypesForPrefix(prefix).stream().forEach(cgt -> removeChannelGroupType(cgt.getUID())); + channelGroupTypesForPrefix(prefix).forEach(cgt -> removeChannelGroupType(cgt.getUID())); } private Collection channelGroupTypesForPrefix(String prefix) { diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java index c178a2ba07d1e..1ae9ad0992db1 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java @@ -48,8 +48,6 @@ import org.openhab.core.thing.type.ChannelTypeUID; import org.openhab.core.types.CommandDescription; import org.openhab.core.types.StateDescription; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.google.gson.Gson; @@ -64,8 +62,6 @@ public abstract class AbstractComponent { private static final String JINJA_PREFIX = "JINJA:"; - private final Logger logger = LoggerFactory.getLogger(AbstractComponent.class); - // Component location fields protected final ComponentConfiguration componentConfiguration; protected final @Nullable ChannelGroupUID channelGroupUID; @@ -82,7 +78,6 @@ public abstract class AbstractComponent protected final C channelConfiguration; protected boolean configSeen; - protected final boolean newStyleChannels; protected final boolean singleChannelComponent; protected final String groupId; protected final String uniqueId; @@ -104,8 +99,7 @@ public AbstractComponent(ComponentFactory.ComponentConfiguration componentConfig public AbstractComponent(ComponentFactory.ComponentConfiguration componentConfiguration, Class clazz, boolean newStyleChannels, boolean singleChannelComponent) { this.componentConfiguration = componentConfiguration; - this.newStyleChannels = newStyleChannels; - this.singleChannelComponent = newStyleChannels ? singleChannelComponent : false; + this.singleChannelComponent = newStyleChannels && singleChannelComponent; this.channelConfigurationJson = componentConfiguration.getConfigJSON(); this.channelConfiguration = componentConfiguration.getConfig(clazz); @@ -117,18 +111,11 @@ public AbstractComponent(ComponentFactory.ComponentConfiguration componentConfig if (name != null && !name.isEmpty()) { groupId = this.haID.getGroupId(channelConfiguration.getUniqueId(), newStyleChannels); - if (this.singleChannelComponent) { - this.channelGroupUID = null; - } else { - - this.channelGroupUID = new ChannelGroupUID(componentConfiguration.getThingUID(), groupId); - } + this.channelGroupUID = this.singleChannelComponent + ? new ChannelGroupUID(componentConfiguration.getThingUID(), groupId) + : null; } else { - if (newStyleChannels && this.singleChannelComponent) { - groupId = haID.component; - } else { - groupId = ""; - } + this.groupId = this.singleChannelComponent ? haID.component : ""; this.channelGroupUID = null; } uniqueId = this.haID.getGroupId(channelConfiguration.getUniqueId(), false); diff --git a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/handler/HomieThingHandler.java b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/handler/HomieThingHandler.java index 5eea5f2444f18..f4e1899b65529 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/handler/HomieThingHandler.java +++ b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/handler/HomieThingHandler.java @@ -60,8 +60,6 @@ */ @NonNullByDefault public class HomieThingHandler extends AbstractMQTTThingHandler implements DeviceCallback, Consumer> { - private static final String[] EMPTY_ARRAY = new String[] {}; - private final Logger logger = LoggerFactory.getLogger(HomieThingHandler.class); protected Device device; protected final MqttChannelTypeProvider channelTypeProvider; diff --git a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Node.java b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Node.java index 30715f3f8b91f..1d42536975f57 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Node.java +++ b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Node.java @@ -49,8 +49,6 @@ */ @NonNullByDefault public class Node implements AbstractMqttAttributeClass.AttributeChanged { - private static final String[] EMPTY_ARRAY = new String[] {}; - private final Logger logger = LoggerFactory.getLogger(Node.class); // Homie public final String nodeID; From c8357430470e74a2dc57adfb2fbbeb57e64002a2 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Fri, 26 Jul 2024 13:08:43 -0600 Subject: [PATCH 08/11] fix errors introduced by last commit the ternary accidentally got swapped Signed-off-by: Cody Cutrer --- .../homeassistant/internal/component/AbstractComponent.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java index 1ae9ad0992db1..1f0e0d64cd651 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java @@ -111,9 +111,8 @@ public AbstractComponent(ComponentFactory.ComponentConfiguration componentConfig if (name != null && !name.isEmpty()) { groupId = this.haID.getGroupId(channelConfiguration.getUniqueId(), newStyleChannels); - this.channelGroupUID = this.singleChannelComponent - ? new ChannelGroupUID(componentConfiguration.getThingUID(), groupId) - : null; + this.channelGroupUID = this.singleChannelComponent ? null + : new ChannelGroupUID(componentConfiguration.getThingUID(), groupId); } else { this.groupId = this.singleChannelComponent ? haID.component : ""; this.channelGroupUID = null; From d2685f2f016f14f01ae4d72a98b7457c08eeb392 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Fri, 26 Jul 2024 14:02:09 -0600 Subject: [PATCH 09/11] fix itest for new channel names Signed-off-by: Cody Cutrer --- .../binding/mqtt/homeassistant/internal/HaID.java | 2 +- .../HomeAssistantMQTTImplementationTest.java | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/HaID.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/HaID.java index b810f48b4f3dd..829cbb54fe509 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/HaID.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/HaID.java @@ -190,7 +190,7 @@ public String toShortTopic() { public String getGroupId(@Nullable final String uniqueId, boolean newStyleChannels) { String result = uniqueId; - // newStyleChannels are auto-discovered things with openHAB >= 4.2.0 + // newStyleChannels are auto-discovered things with openHAB >= 4.3.0 // assuming the topic has both a node ID and an object ID, simply use // the component type and object ID - without encoding(!) // since the only character allowed in object IDs but not allowed in UID diff --git a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java index c665c477e4be1..72a41d4f6456a 100644 --- a/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java +++ b/itests/org.openhab.binding.mqtt.homeassistant.tests/src/main/java/org/openhab/binding/mqtt/homeassistant/HomeAssistantMQTTImplementationTest.java @@ -55,7 +55,6 @@ import org.openhab.core.library.types.OnOffType; import org.openhab.core.types.State; import org.openhab.core.types.UnDefType; -import org.openhab.core.util.UIDUtils; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -177,10 +176,10 @@ public void parseHATree() throws Exception { assertNull(failure); assertThat(haComponents.size(), is(1)); - String channelGroupId = UIDUtils - .encode("node_" + ThingChannelConstants.TEST_HOME_ASSISTANT_THING.getId() + "_switch"); + String channelGroupId = "switch_" + ThingChannelConstants.TEST_HOME_ASSISTANT_THING.getId(); + String channelId = Switch.SWITCH_CHANNEL_ID; - State value = haComponents.get(channelGroupId).getChannel(Switch.SWITCH_CHANNEL_ID).getState().getCache() + State value = haComponents.get(channelGroupId).getChannel(channelGroupId).getState().getCache() .getChannelState(); assertThat(value, is(UnDefType.UNDEF)); @@ -194,8 +193,7 @@ public void parseHATree() throws Exception { verify(channelStateUpdateListener, timeout(4000).times(1)).updateChannelState(any(), any()); // Value should be ON now. - value = haComponents.get(channelGroupId).getChannel(Switch.SWITCH_CHANNEL_ID).getState().getCache() - .getChannelState(); + value = haComponents.get(channelGroupId).getChannel(channelGroupId).getState().getCache().getChannelState(); assertThat(value, is(OnOffType.ON)); } } From a88d40b4b2fa5d215b97e03dea31430b573f5321 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Mon, 12 Aug 2024 10:59:40 -0600 Subject: [PATCH 10/11] Use ChannelType ID constants, not strings Signed-off-by: Cody Cutrer Co-Authored-By: Anton Kharuzhy --- .../internal/MqttBindingConstants.java | 11 ---- .../internal/ComponentChannelType.java | 44 ++++++++++++++ .../internal/component/AbstractComponent.java | 8 +-- .../component/AbstractRawSchemaLight.java | 6 +- .../internal/component/AlarmControlPanel.java | 12 ++-- .../internal/component/BinarySensor.java | 4 +- .../internal/component/Button.java | 4 +- .../internal/component/Camera.java | 4 +- .../internal/component/Climate.java | 44 +++++++------- .../internal/component/Cover.java | 17 +++--- .../component/DefaultSchemaLight.java | 55 +++++++++--------- .../internal/component/DeviceTrigger.java | 4 +- .../homeassistant/internal/component/Fan.java | 4 +- .../internal/component/JSONSchemaLight.java | 25 ++++---- .../internal/component/Lock.java | 6 +- .../internal/component/Number.java | 4 +- .../internal/component/Scene.java | 4 +- .../internal/component/Select.java | 4 +- .../internal/component/Sensor.java | 11 ++-- .../internal/component/Switch.java | 4 +- .../internal/component/Update.java | 9 ++- .../internal/component/Vacuum.java | 58 +++++++++---------- 22 files changed, 182 insertions(+), 160 deletions(-) create mode 100644 bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentChannelType.java diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/generic/internal/MqttBindingConstants.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/generic/internal/MqttBindingConstants.java index b31a4222ca401..7de63cc519b7c 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/generic/internal/MqttBindingConstants.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/generic/internal/MqttBindingConstants.java @@ -14,7 +14,6 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.thing.ThingTypeUID; -import org.openhab.core.thing.type.ChannelTypeUID; /** * The {@link MqttBindingConstants} class defines common constants, which are @@ -29,14 +28,4 @@ public class MqttBindingConstants { // List of all Thing Type UIDs public static final ThingTypeUID HOMEASSISTANT_MQTT_THING = new ThingTypeUID(BINDING_ID, "homeassistant"); - - public static final ChannelTypeUID CHANNEL_TYPE_UID_COLOR = new ChannelTypeUID(BINDING_ID, "ha-color"); - public static final ChannelTypeUID CHANNEL_TYPE_UID_DIMMER = new ChannelTypeUID(BINDING_ID, "ha-dimmer"); - public static final ChannelTypeUID CHANNEL_TYPE_UID_IMAGE = new ChannelTypeUID(BINDING_ID, "ha-image"); - public static final ChannelTypeUID CHANNEL_TYPE_UID_NUMBER = new ChannelTypeUID(BINDING_ID, "ha-number"); - public static final ChannelTypeUID CHANNEL_TYPE_UID_ROLLERSHUTTER = new ChannelTypeUID(BINDING_ID, - "ha-rollershutter"); - public static final ChannelTypeUID CHANNEL_TYPE_UID_STRING = new ChannelTypeUID(BINDING_ID, "ha-string"); - public static final ChannelTypeUID CHANNEL_TYPE_UID_SWITCH = new ChannelTypeUID(BINDING_ID, "ha-switch"); - public static final ChannelTypeUID CHANNEL_TYPE_UID_TRIGGER = new ChannelTypeUID(BINDING_ID, "ha-trigger"); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentChannelType.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentChannelType.java new file mode 100644 index 0000000000000..b99f8683ec115 --- /dev/null +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentChannelType.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2010-2024 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.homeassistant.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; +import org.openhab.core.thing.type.ChannelTypeUID; + +/** + * The types of HomeAssistant channels components. + * + * @author Cody Cutrer - Initial contribution + */ +@NonNullByDefault +public enum ComponentChannelType { + COLOR("ha-color"), + DIMMER("ha-dimmer"), + IMAGE("ha-image"), + NUMBER("ha-number"), + ROLLERSHUTTER("ha-rollershutter"), + STRING("ha-string"), + SWITCH("ha-switch"), + TRIGGER("ha-trigger"); + + final ChannelTypeUID channelTypeUID; + + ComponentChannelType(String id) { + channelTypeUID = new ChannelTypeUID(MqttBindingConstants.BINDING_ID, id); + } + + public ChannelTypeUID getChannelTypeUID() { + return channelTypeUID; + } +} diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java index 1f0e0d64cd651..befc19a5c7d87 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponent.java @@ -30,6 +30,7 @@ import org.openhab.binding.mqtt.generic.values.Value; import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannel; +import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannelType; import org.openhab.binding.mqtt.homeassistant.internal.HaID; import org.openhab.binding.mqtt.homeassistant.internal.component.ComponentFactory.ComponentConfiguration; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; @@ -45,7 +46,6 @@ import org.openhab.core.thing.type.ChannelGroupType; import org.openhab.core.thing.type.ChannelGroupTypeBuilder; import org.openhab.core.thing.type.ChannelGroupTypeUID; -import org.openhab.core.thing.type.ChannelTypeUID; import org.openhab.core.types.CommandDescription; import org.openhab.core.types.StateDescription; @@ -154,12 +154,12 @@ public AbstractComponent(ComponentFactory.ComponentConfiguration componentConfig } } - protected ComponentChannel.Builder buildChannel(String channelID, ChannelTypeUID channelTypeUID, Value valueState, - String label, ChannelStateUpdateListener channelStateUpdateListener) { + protected ComponentChannel.Builder buildChannel(String channelID, ComponentChannelType channelType, + Value valueState, String label, ChannelStateUpdateListener channelStateUpdateListener) { if (singleChannelComponent) { channelID = groupId; } - return new ComponentChannel.Builder(this, channelID, channelTypeUID, valueState, label, + return new ComponentChannel.Builder(this, channelID, channelType.getChannelTypeUID(), valueState, label, channelStateUpdateListener); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractRawSchemaLight.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractRawSchemaLight.java index be48d1c897e19..c7a43e57bbd8c 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractRawSchemaLight.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractRawSchemaLight.java @@ -14,8 +14,8 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.mqtt.generic.values.TextValue; -import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannel; +import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannelType; import org.openhab.core.library.types.HSBType; import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.PercentType; @@ -34,8 +34,8 @@ abstract class AbstractRawSchemaLight extends Light { public AbstractRawSchemaLight(ComponentFactory.ComponentConfiguration builder, boolean newStyleChannels) { super(builder, newStyleChannels); - hiddenChannels.add(rawChannel = buildChannel(RAW_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, - new TextValue(), "Raw state", this).stateTopic(channelConfiguration.stateTopic) + hiddenChannels.add(rawChannel = buildChannel(RAW_CHANNEL_ID, ComponentChannelType.STRING, new TextValue(), + "Raw state", this).stateTopic(channelConfiguration.stateTopic) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) .build(false)); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AlarmControlPanel.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AlarmControlPanel.java index da079596c8de7..026ce5048556c 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AlarmControlPanel.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/AlarmControlPanel.java @@ -15,7 +15,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.values.TextValue; -import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; +import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannelType; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import com.google.gson.annotations.SerializedName; @@ -75,24 +75,24 @@ public AlarmControlPanel(ComponentFactory.ComponentConfiguration componentConfig final String[] stateEnum = { channelConfiguration.stateDisarmed, channelConfiguration.stateArmedHome, channelConfiguration.stateArmedAway, channelConfiguration.statePending, channelConfiguration.stateTriggered }; - buildChannel(STATE_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, new TextValue(stateEnum), - getName(), componentConfiguration.getUpdateListener()) + buildChannel(STATE_CHANNEL_ID, ComponentChannelType.STRING, new TextValue(stateEnum), getName(), + componentConfiguration.getUpdateListener()) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate())// .build(); String commandTopic = channelConfiguration.commandTopic; if (commandTopic != null) { - buildChannel(SWITCH_DISARM_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + buildChannel(SWITCH_DISARM_CHANNEL_ID, ComponentChannelType.STRING, new TextValue(new String[] { channelConfiguration.payloadDisarm }), getName(), componentConfiguration.getUpdateListener()) .commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()).build(); - buildChannel(SWITCH_ARM_HOME_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + buildChannel(SWITCH_ARM_HOME_CHANNEL_ID, ComponentChannelType.STRING, new TextValue(new String[] { channelConfiguration.payloadArmHome }), getName(), componentConfiguration.getUpdateListener()) .commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()).build(); - buildChannel(SWITCH_ARM_AWAY_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + buildChannel(SWITCH_ARM_AWAY_CHANNEL_ID, ComponentChannelType.STRING, new TextValue(new String[] { channelConfiguration.payloadArmAway }), getName(), componentConfiguration.getUpdateListener()) .commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()).build(); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensor.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensor.java index f5a79c2bff87b..b6df93f18d6cf 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensor.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensor.java @@ -19,7 +19,7 @@ import org.openhab.binding.mqtt.generic.ChannelStateUpdateListener; import org.openhab.binding.mqtt.generic.values.OnOffValue; import org.openhab.binding.mqtt.generic.values.Value; -import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; +import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannelType; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.binding.mqtt.homeassistant.internal.listener.ExpireUpdateStateListener; import org.openhab.binding.mqtt.homeassistant.internal.listener.OffDelayUpdateStateListener; @@ -73,7 +73,7 @@ public BinarySensor(ComponentFactory.ComponentConfiguration componentConfigurati OnOffValue value = new OnOffValue(channelConfiguration.payloadOn, channelConfiguration.payloadOff); - buildChannel(SENSOR_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, value, getName(), + buildChannel(SENSOR_CHANNEL_ID, ComponentChannelType.SWITCH, value, getName(), getListener(componentConfiguration, value)) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()) .withAutoUpdatePolicy(AutoUpdatePolicy.VETO).build(); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Button.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Button.java index febb156a5eb5a..cff40ea8e4ade 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Button.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Button.java @@ -15,7 +15,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.values.TextValue; -import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; +import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannelType; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.core.thing.type.AutoUpdatePolicy; @@ -52,7 +52,7 @@ public Button(ComponentFactory.ComponentConfiguration componentConfiguration, bo TextValue value = new TextValue(new String[] { channelConfiguration.payloadPress }); - buildChannel(BUTTON_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, value, getName(), + buildChannel(BUTTON_CHANNEL_ID, ComponentChannelType.STRING, value, getName(), componentConfiguration.getUpdateListener()) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Camera.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Camera.java index 5fe21017c0a93..c1e934d432459 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Camera.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Camera.java @@ -14,7 +14,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.mqtt.generic.values.ImageValue; -import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; +import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannelType; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; /** @@ -44,7 +44,7 @@ public Camera(ComponentFactory.ComponentConfiguration componentConfiguration, bo ImageValue value = new ImageValue(); - buildChannel(CAMERA_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_IMAGE, value, getName(), + buildChannel(CAMERA_CHANNEL_ID, ComponentChannelType.IMAGE, value, getName(), componentConfiguration.getUpdateListener()).stateTopic(channelConfiguration.topic).build(); } } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Climate.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Climate.java index 3e3317f2725d2..1c7726bc52ced 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Climate.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Climate.java @@ -27,13 +27,12 @@ import org.openhab.binding.mqtt.generic.values.OnOffValue; import org.openhab.binding.mqtt.generic.values.TextValue; import org.openhab.binding.mqtt.generic.values.Value; -import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannel; +import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannelType; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.core.library.types.StringType; import org.openhab.core.library.unit.ImperialUnits; import org.openhab.core.library.unit.SIUnits; -import org.openhab.core.thing.type.ChannelTypeUID; import org.openhab.core.types.Command; import org.openhab.core.types.State; @@ -219,82 +218,81 @@ public Climate(ComponentFactory.ComponentConfiguration componentConfiguration, b : channelConfiguration.temperatureUnit.getDefaultPrecision(); final ChannelStateUpdateListener updateListener = componentConfiguration.getUpdateListener(); - ComponentChannel actionChannel = buildOptionalChannel(ACTION_CH_ID, - MqttBindingConstants.CHANNEL_TYPE_UID_STRING, new TextValue(ACTION_MODES.toArray(new String[0])), - updateListener, null, null, channelConfiguration.actionTemplate, channelConfiguration.actionTopic, - null); + ComponentChannel actionChannel = buildOptionalChannel(ACTION_CH_ID, ComponentChannelType.STRING, + new TextValue(ACTION_MODES.toArray(new String[0])), updateListener, null, null, + channelConfiguration.actionTemplate, channelConfiguration.actionTopic, null); final Predicate commandFilter = channelConfiguration.sendIfOff ? null : getCommandFilter(actionChannel); - buildOptionalChannel(AUX_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, new OnOffValue(), updateListener, - null, channelConfiguration.auxCommandTopic, channelConfiguration.auxStateTemplate, + buildOptionalChannel(AUX_CH_ID, ComponentChannelType.SWITCH, new OnOffValue(), updateListener, null, + channelConfiguration.auxCommandTopic, channelConfiguration.auxStateTemplate, channelConfiguration.auxStateTopic, commandFilter); - buildOptionalChannel(AWAY_MODE_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, new OnOffValue(), - updateListener, null, channelConfiguration.awayModeCommandTopic, - channelConfiguration.awayModeStateTemplate, channelConfiguration.awayModeStateTopic, commandFilter); + buildOptionalChannel(AWAY_MODE_CH_ID, ComponentChannelType.SWITCH, new OnOffValue(), updateListener, null, + channelConfiguration.awayModeCommandTopic, channelConfiguration.awayModeStateTemplate, + channelConfiguration.awayModeStateTopic, commandFilter); - buildOptionalChannel(CURRENT_TEMPERATURE_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_NUMBER, + buildOptionalChannel(CURRENT_TEMPERATURE_CH_ID, ComponentChannelType.NUMBER, new NumberValue(null, null, precision, channelConfiguration.temperatureUnit.getUnit()), updateListener, null, null, channelConfiguration.currentTemperatureTemplate, channelConfiguration.currentTemperatureTopic, commandFilter); - buildOptionalChannel(FAN_MODE_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + buildOptionalChannel(FAN_MODE_CH_ID, ComponentChannelType.STRING, new TextValue(channelConfiguration.fanModes.toArray(new String[0])), updateListener, channelConfiguration.fanModeCommandTemplate, channelConfiguration.fanModeCommandTopic, channelConfiguration.fanModeStateTemplate, channelConfiguration.fanModeStateTopic, commandFilter); List holdModes = channelConfiguration.holdModes; if (holdModes != null && !holdModes.isEmpty()) { - buildOptionalChannel(HOLD_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + buildOptionalChannel(HOLD_CH_ID, ComponentChannelType.STRING, new TextValue(holdModes.toArray(new String[0])), updateListener, channelConfiguration.holdCommandTemplate, channelConfiguration.holdCommandTopic, channelConfiguration.holdStateTemplate, channelConfiguration.holdStateTopic, commandFilter); } - buildOptionalChannel(MODE_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + buildOptionalChannel(MODE_CH_ID, ComponentChannelType.STRING, new TextValue(channelConfiguration.modes.toArray(new String[0])), updateListener, channelConfiguration.modeCommandTemplate, channelConfiguration.modeCommandTopic, channelConfiguration.modeStateTemplate, channelConfiguration.modeStateTopic, commandFilter); - buildOptionalChannel(SWING_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + buildOptionalChannel(SWING_CH_ID, ComponentChannelType.STRING, new TextValue(channelConfiguration.swingModes.toArray(new String[0])), updateListener, channelConfiguration.swingCommandTemplate, channelConfiguration.swingCommandTopic, channelConfiguration.swingStateTemplate, channelConfiguration.swingStateTopic, commandFilter); - buildOptionalChannel(TEMPERATURE_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_NUMBER, + buildOptionalChannel(TEMPERATURE_CH_ID, ComponentChannelType.NUMBER, new NumberValue(channelConfiguration.minTemp, channelConfiguration.maxTemp, channelConfiguration.tempStep, channelConfiguration.temperatureUnit.getUnit()), updateListener, channelConfiguration.temperatureCommandTemplate, channelConfiguration.temperatureCommandTopic, channelConfiguration.temperatureStateTemplate, channelConfiguration.temperatureStateTopic, commandFilter); - buildOptionalChannel(TEMPERATURE_HIGH_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_NUMBER, + buildOptionalChannel(TEMPERATURE_HIGH_CH_ID, ComponentChannelType.NUMBER, new NumberValue(channelConfiguration.minTemp, channelConfiguration.maxTemp, channelConfiguration.tempStep, channelConfiguration.temperatureUnit.getUnit()), updateListener, channelConfiguration.temperatureHighCommandTemplate, channelConfiguration.temperatureHighCommandTopic, channelConfiguration.temperatureHighStateTemplate, channelConfiguration.temperatureHighStateTopic, commandFilter); - buildOptionalChannel(TEMPERATURE_LOW_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_NUMBER, + buildOptionalChannel(TEMPERATURE_LOW_CH_ID, ComponentChannelType.NUMBER, new NumberValue(channelConfiguration.minTemp, channelConfiguration.maxTemp, channelConfiguration.tempStep, channelConfiguration.temperatureUnit.getUnit()), updateListener, channelConfiguration.temperatureLowCommandTemplate, channelConfiguration.temperatureLowCommandTopic, channelConfiguration.temperatureLowStateTemplate, channelConfiguration.temperatureLowStateTopic, commandFilter); - buildOptionalChannel(POWER_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, new OnOffValue(), - updateListener, null, channelConfiguration.powerCommandTopic, null, null, null); + buildOptionalChannel(POWER_CH_ID, ComponentChannelType.SWITCH, new OnOffValue(), updateListener, null, + channelConfiguration.powerCommandTopic, null, null, null); } @Nullable - private ComponentChannel buildOptionalChannel(String channelId, ChannelTypeUID channelTypeUID, Value valueState, + private ComponentChannel buildOptionalChannel(String channelId, ComponentChannelType channelType, Value valueState, ChannelStateUpdateListener channelStateUpdateListener, @Nullable String commandTemplate, @Nullable String commandTopic, @Nullable String stateTemplate, @Nullable String stateTopic, @Nullable Predicate commandFilter) { if ((commandTopic != null && !commandTopic.isBlank()) || (stateTopic != null && !stateTopic.isBlank())) { - return buildChannel(channelId, channelTypeUID, valueState, getName(), channelStateUpdateListener) + return buildChannel(channelId, channelType, valueState, getName(), channelStateUpdateListener) .stateTopic(stateTopic, stateTemplate, channelConfiguration.getValueTemplate()) .commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos(), commandTemplate) diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Cover.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Cover.java index 0264555094da4..077a7b94cd51e 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Cover.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Cover.java @@ -16,8 +16,8 @@ import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.values.RollershutterValue; import org.openhab.binding.mqtt.generic.values.TextValue; -import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannel; +import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannelType; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.core.library.types.StopMoveType; import org.openhab.core.library.types.StringType; @@ -96,17 +96,16 @@ public Cover(ComponentFactory.ComponentConfiguration componentConfiguration, boo TextValue value = new TextValue(new String[] { channelConfiguration.stateClosed, channelConfiguration.stateClosing, channelConfiguration.stateOpen, channelConfiguration.stateOpening, channelConfiguration.stateStopped }); - buildChannel(STATE_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, value, "State", + buildChannel(STATE_CHANNEL_ID, ComponentChannelType.STRING, value, "State", componentConfiguration.getUpdateListener()).stateTopic(stateTopic).isAdvanced(true).build(); } if (channelConfiguration.commandTopic != null) { - hiddenChannels - .add(stateChannel = buildChannel(STATE_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, - new TextValue(), "State", componentConfiguration.getUpdateListener()) - .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), - channelConfiguration.getQos()) - .build(false)); + hiddenChannels.add(stateChannel = buildChannel(STATE_CHANNEL_ID, ComponentChannelType.STRING, + new TextValue(), "State", componentConfiguration.getUpdateListener()) + .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), + channelConfiguration.getQos()) + .build(false)); } else { // no command topic. we need to make sure we send // integers for open and close @@ -134,7 +133,7 @@ public Cover(ComponentFactory.ComponentConfiguration componentConfiguration, boo channelConfiguration.payloadClose, channelConfiguration.payloadStop, channelConfiguration.stateOpen, channelConfiguration.stateClosed, inverted, channelConfiguration.setPositionTopic == null); - buildChannel(COVER_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_ROLLERSHUTTER, value, "Cover", + buildChannel(COVER_CHANNEL_ID, ComponentChannelType.ROLLERSHUTTER, value, "Cover", componentConfiguration.getUpdateListener()).stateTopic(rollershutterStateTopic, stateTemplate) .commandTopic(rollershutterCommandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) .commandFilter(command -> { 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 9487616913a10..9d412c1a14ba3 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 @@ -21,8 +21,8 @@ import org.openhab.binding.mqtt.generic.mapping.ColorMode; import org.openhab.binding.mqtt.generic.values.ColorValue; import org.openhab.binding.mqtt.generic.values.TextValue; -import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; 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; import org.openhab.core.library.types.OnOffType; @@ -61,8 +61,8 @@ public DefaultSchemaLight(ComponentFactory.ComponentConfiguration builder, boole @Override protected void buildChannels() { ComponentChannel localOnOffChannel; - localOnOffChannel = onOffChannel = buildChannel(ON_OFF_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, - onOffValue, "On/Off State", this) + localOnOffChannel = onOffChannel = buildChannel(ON_OFF_CHANNEL_ID, ComponentChannelType.SWITCH, onOffValue, + "On/Off State", this) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.stateValueTemplate) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) @@ -72,7 +72,7 @@ protected void buildChannels() { ComponentChannel localBrightnessChannel = null; if (channelConfiguration.brightnessStateTopic != null || channelConfiguration.brightnessCommandTopic != null) { localBrightnessChannel = brightnessChannel = buildChannel(BRIGHTNESS_CHANNEL_ID, - MqttBindingConstants.CHANNEL_TYPE_UID_DIMMER, brightnessValue, "Brightness", this) + ComponentChannelType.DIMMER, brightnessValue, "Brightness", this) .stateTopic(channelConfiguration.brightnessStateTopic, channelConfiguration.brightnessValueTemplate) .commandTopic(channelConfiguration.brightnessCommandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) @@ -80,7 +80,7 @@ protected void buildChannels() { } if (channelConfiguration.whiteCommandTopic != null) { - buildChannel(WHITE_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_DIMMER, brightnessValue, + buildChannel(WHITE_CHANNEL_ID, ComponentChannelType.DIMMER, brightnessValue, "Go directly to white of a specific brightness", this) .commandTopic(channelConfiguration.whiteCommandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) @@ -88,15 +88,14 @@ protected void buildChannels() { } if (channelConfiguration.colorModeStateTopic != null) { - buildChannel(COLOR_MODE_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, new TextValue(), - "Current color mode", this) + buildChannel(COLOR_MODE_CHANNEL_ID, ComponentChannelType.STRING, new TextValue(), "Current color mode", + this) .stateTopic(channelConfiguration.colorModeStateTopic, channelConfiguration.colorModeValueTemplate) .build(); } if (channelConfiguration.colorTempStateTopic != null || channelConfiguration.colorTempCommandTopic != null) { - buildChannel(COLOR_TEMP_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_NUMBER, colorTempValue, - "Color Temperature", this) + buildChannel(COLOR_TEMP_CHANNEL_ID, ComponentChannelType.NUMBER, colorTempValue, "Color Temperature", this) .stateTopic(channelConfiguration.colorTempStateTopic, channelConfiguration.colorTempValueTemplate) .commandTopic(channelConfiguration.colorTempCommandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) @@ -105,8 +104,8 @@ protected void buildChannels() { if (effectValue != null && (channelConfiguration.effectStateTopic != null || channelConfiguration.effectCommandTopic != null)) { - buildChannel(EFFECT_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, - Objects.requireNonNull(effectValue), "Lighting Effect", this) + buildChannel(EFFECT_CHANNEL_ID, ComponentChannelType.STRING, Objects.requireNonNull(effectValue), + "Lighting Effect", this) .stateTopic(channelConfiguration.effectStateTopic, channelConfiguration.effectValueTemplate) .commandTopic(channelConfiguration.effectCommandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) @@ -115,7 +114,7 @@ protected void buildChannels() { if (channelConfiguration.rgbStateTopic != null || channelConfiguration.rgbCommandTopic != null) { hasColorChannel = true; - hiddenChannels.add(rgbChannel = buildChannel(RGB_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_COLOR, + hiddenChannels.add(rgbChannel = buildChannel(RGB_CHANNEL_ID, ComponentChannelType.COLOR, new ColorValue(ColorMode.RGB, null, null, 100), "RGB state", this) .stateTopic(channelConfiguration.rgbStateTopic, channelConfiguration.rgbValueTemplate) .commandTopic(channelConfiguration.rgbCommandTopic, channelConfiguration.isRetain(), @@ -125,27 +124,27 @@ protected void buildChannels() { if (channelConfiguration.rgbwStateTopic != null || channelConfiguration.rgbwCommandTopic != null) { hasColorChannel = true; - hiddenChannels.add(buildChannel(RGBW_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, - new TextValue(), "RGBW state", this) - .stateTopic(channelConfiguration.rgbwStateTopic, channelConfiguration.rgbwValueTemplate) - .commandTopic(channelConfiguration.rgbwCommandTopic, channelConfiguration.isRetain(), - channelConfiguration.getQos()) - .build(false)); + hiddenChannels + .add(buildChannel(RGBW_CHANNEL_ID, ComponentChannelType.STRING, new TextValue(), "RGBW state", this) + .stateTopic(channelConfiguration.rgbwStateTopic, channelConfiguration.rgbwValueTemplate) + .commandTopic(channelConfiguration.rgbwCommandTopic, channelConfiguration.isRetain(), + channelConfiguration.getQos()) + .build(false)); } if (channelConfiguration.rgbwwStateTopic != null || channelConfiguration.rgbwwCommandTopic != null) { hasColorChannel = true; - hiddenChannels.add(buildChannel(RGBWW_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, - new TextValue(), "RGBWW state", this) - .stateTopic(channelConfiguration.rgbwwStateTopic, channelConfiguration.rgbwwValueTemplate) - .commandTopic(channelConfiguration.rgbwwCommandTopic, channelConfiguration.isRetain(), - channelConfiguration.getQos()) - .build(false)); + hiddenChannels.add( + buildChannel(RGBWW_CHANNEL_ID, ComponentChannelType.STRING, new TextValue(), "RGBWW state", this) + .stateTopic(channelConfiguration.rgbwwStateTopic, channelConfiguration.rgbwwValueTemplate) + .commandTopic(channelConfiguration.rgbwwCommandTopic, channelConfiguration.isRetain(), + channelConfiguration.getQos()) + .build(false)); } if (channelConfiguration.xyStateTopic != null || channelConfiguration.xyCommandTopic != null) { hasColorChannel = true; - hiddenChannels.add(xyChannel = buildChannel(XY_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_COLOR, + hiddenChannels.add(xyChannel = buildChannel(XY_CHANNEL_ID, ComponentChannelType.COLOR, new ColorValue(ColorMode.XYY, null, null, 100), "XY State", this) .stateTopic(channelConfiguration.xyStateTopic, channelConfiguration.xyValueTemplate) .commandTopic(channelConfiguration.xyCommandTopic, channelConfiguration.isRetain(), @@ -155,8 +154,8 @@ protected void buildChannels() { if (channelConfiguration.hsStateTopic != null || channelConfiguration.hsCommandTopic != null) { hasColorChannel = true; - hiddenChannels.add(this.hsChannel = buildChannel(HS_CHANNEL_ID, - MqttBindingConstants.CHANNEL_TYPE_UID_STRING, new TextValue(), "Hue and Saturation", this) + hiddenChannels.add(this.hsChannel = buildChannel(HS_CHANNEL_ID, ComponentChannelType.STRING, + new TextValue(), "Hue and Saturation", this) .stateTopic(channelConfiguration.hsStateTopic, channelConfiguration.hsValueTemplate) .commandTopic(channelConfiguration.hsCommandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) @@ -168,7 +167,7 @@ MqttBindingConstants.CHANNEL_TYPE_UID_STRING, new TextValue(), "Hue and Saturati if (localBrightnessChannel != null) { hiddenChannels.add(localBrightnessChannel); } - buildChannel(COLOR_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_COLOR, colorValue, "Color", this) + buildChannel(COLOR_CHANNEL_ID, ComponentChannelType.COLOR, colorValue, "Color", this) .commandTopic(DUMMY_TOPIC, channelConfiguration.isRetain(), channelConfiguration.getQos()) .commandFilter(this::handleColorCommand).build(); } else if (localBrightnessChannel != null) { diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DeviceTrigger.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DeviceTrigger.java index 96af915a099a5..91ea0456b65a4 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DeviceTrigger.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/DeviceTrigger.java @@ -15,7 +15,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.values.TextValue; -import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; +import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannelType; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.binding.mqtt.homeassistant.internal.exception.ConfigurationException; @@ -66,7 +66,7 @@ public DeviceTrigger(ComponentFactory.ComponentConfiguration componentConfigurat value = new TextValue(); } - buildChannel(channelConfiguration.type, MqttBindingConstants.CHANNEL_TYPE_UID_TRIGGER, value, getName(), + buildChannel(channelConfiguration.type, ComponentChannelType.TRIGGER, value, getName(), componentConfiguration.getUpdateListener()) .stateTopic(channelConfiguration.topic, channelConfiguration.getValueTemplate()).trigger(true).build(); } 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 e69701ac6992a..6b216a2bcb3c1 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 @@ -15,7 +15,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.values.OnOffValue; -import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; +import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannelType; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import com.google.gson.annotations.SerializedName; @@ -55,7 +55,7 @@ public Fan(ComponentFactory.ComponentConfiguration componentConfiguration, boole super(componentConfiguration, ChannelConfiguration.class, newStyleChannels); OnOffValue value = new OnOffValue(channelConfiguration.payloadOn, channelConfiguration.payloadOff); - buildChannel(SWITCH_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, value, getName(), + buildChannel(SWITCH_CHANNEL_ID, ComponentChannelType.SWITCH, value, getName(), componentConfiguration.getUpdateListener()) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), 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 9782ceca70d45..ca016efd345d9 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,7 +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.generic.internal.MqttBindingConstants; +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; @@ -85,8 +85,8 @@ protected void buildChannels() { 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, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, colorModeValue, - "Color Mode", this).isAdvanced(true).build(); + buildChannel(COLOR_MODE_CHANNEL_ID, ComponentChannelType.STRING, colorModeValue, "Color Mode", this) + .isAdvanced(true).build(); } if (channelConfiguration.colorMode) { @@ -100,27 +100,26 @@ protected void buildChannels() { } if (supportedColorModes.contains(LightColorMode.COLOR_MODE_COLOR_TEMP)) { - buildChannel(COLOR_TEMP_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_NUMBER, colorTempValue, - "Color Temperature", this).commandTopic(DUMMY_TOPIC, true, 1) + buildChannel(COLOR_TEMP_CHANNEL_ID, ComponentChannelType.NUMBER, colorTempValue, "Color Temperature", + this).commandTopic(DUMMY_TOPIC, true, 1) .commandFilter(command -> handleColorTempCommand(command)).build(); } } if (hasColorChannel) { - buildChannel(COLOR_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_COLOR, colorValue, "Color", this) + 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, MqttBindingConstants.CHANNEL_TYPE_UID_DIMMER, - brightnessValue, "Brightness", this).commandTopic(DUMMY_TOPIC, true, 1) - .commandFilter(this::handleCommand).build(); + brightnessChannel = buildChannel(BRIGHTNESS_CHANNEL_ID, ComponentChannelType.DIMMER, brightnessValue, + "Brightness", this).commandTopic(DUMMY_TOPIC, true, 1).commandFilter(this::handleCommand).build(); } else { - onOffChannel = buildChannel(ON_OFF_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, onOffValue, - "On/Off State", this).commandTopic(DUMMY_TOPIC, true, 1).commandFilter(this::handleCommand).build(); + onOffChannel = buildChannel(ON_OFF_CHANNEL_ID, ComponentChannelType.SWITCH, onOffValue, "On/Off State", + this).commandTopic(DUMMY_TOPIC, true, 1).commandFilter(this::handleCommand).build(); } if (effectValue != null) { - buildChannel(EFFECT_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, - Objects.requireNonNull(effectValue), "Lighting Effect", this).commandTopic(DUMMY_TOPIC, true, 1) + buildChannel(EFFECT_CHANNEL_ID, ComponentChannelType.STRING, Objects.requireNonNull(effectValue), + "Lighting Effect", this).commandTopic(DUMMY_TOPIC, true, 1) .commandFilter(command -> handleEffectCommand(command)).build(); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Lock.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Lock.java index 4dc077689ae41..ce3317256a620 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Lock.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Lock.java @@ -17,7 +17,7 @@ import org.openhab.binding.mqtt.generic.ChannelStateUpdateListener; import org.openhab.binding.mqtt.generic.values.OnOffValue; import org.openhab.binding.mqtt.generic.values.TextValue; -import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; +import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannelType; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.StringType; @@ -83,7 +83,7 @@ public Lock(ComponentFactory.ComponentConfiguration componentConfiguration, bool channelConfiguration.stateUnlocking, channelConfiguration.stateJammed }, channelConfiguration.payloadLock, channelConfiguration.payloadUnlock); - buildChannel(LOCK_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, lockValue, "Lock", + buildChannel(LOCK_CHANNEL_ID, ComponentChannelType.SWITCH, lockValue, "Lock", componentConfiguration.getUpdateListener()) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), @@ -105,7 +105,7 @@ public Lock(ComponentFactory.ComponentConfiguration componentConfiguration, bool stateValue = new TextValue(new String[] { channelConfiguration.stateJammed, channelConfiguration.stateLocked, channelConfiguration.stateLocking, channelConfiguration.stateUnlocked, channelConfiguration.stateUnlocking }, commands); - buildChannel(STATE_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, stateValue, "State", + buildChannel(STATE_CHANNEL_ID, ComponentChannelType.STRING, stateValue, "State", componentConfiguration.getUpdateListener()) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Number.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Number.java index c5316c69a1f3f..1d03661f880e7 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Number.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Number.java @@ -17,7 +17,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.values.NumberValue; -import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; +import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannelType; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.binding.mqtt.homeassistant.internal.exception.ConfigurationException; import org.openhab.core.types.util.UnitUtils; @@ -83,7 +83,7 @@ public Number(ComponentFactory.ComponentConfiguration componentConfiguration, bo NumberValue value = new NumberValue(channelConfiguration.min, channelConfiguration.max, channelConfiguration.step, UnitUtils.parseUnit(channelConfiguration.unitOfMeasurement)); - buildChannel(NUMBER_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_NUMBER, value, getName(), + buildChannel(NUMBER_CHANNEL_ID, ComponentChannelType.NUMBER, value, getName(), componentConfiguration.getUpdateListener()) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Scene.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Scene.java index 8fc649553ac93..d6e66a2bcb258 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Scene.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Scene.java @@ -15,7 +15,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.values.TextValue; -import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; +import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannelType; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.core.thing.type.AutoUpdatePolicy; @@ -50,7 +50,7 @@ public Scene(ComponentFactory.ComponentConfiguration componentConfiguration, boo TextValue value = new TextValue(new String[] { channelConfiguration.payloadOn }); - buildChannel(SCENE_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, value, getName(), + buildChannel(SCENE_CHANNEL_ID, ComponentChannelType.STRING, value, getName(), componentConfiguration.getUpdateListener()) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos()) diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Select.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Select.java index f2db9b43f86fc..b3ceccafe67c3 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Select.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Select.java @@ -15,7 +15,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.values.TextValue; -import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; +import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannelType; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.binding.mqtt.homeassistant.internal.exception.ConfigurationException; @@ -67,7 +67,7 @@ public Select(ComponentFactory.ComponentConfiguration componentConfiguration, bo TextValue value = new TextValue(channelConfiguration.options); - buildChannel(SELECT_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, value, getName(), + buildChannel(SELECT_CHANNEL_ID, ComponentChannelType.STRING, value, getName(), componentConfiguration.getUpdateListener()) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Sensor.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Sensor.java index e8809da07f427..9472490ca68c0 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Sensor.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Sensor.java @@ -21,10 +21,9 @@ import org.openhab.binding.mqtt.generic.values.NumberValue; import org.openhab.binding.mqtt.generic.values.TextValue; import org.openhab.binding.mqtt.generic.values.Value; -import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; +import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannelType; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.binding.mqtt.homeassistant.internal.listener.ExpireUpdateStateListener; -import org.openhab.core.thing.type.ChannelTypeUID; import org.openhab.core.types.util.UnitUtils; import com.google.gson.annotations.SerializedName; @@ -75,19 +74,19 @@ public Sensor(ComponentFactory.ComponentConfiguration componentConfiguration, bo Value value; String uom = channelConfiguration.unitOfMeasurement; String sc = channelConfiguration.stateClass; - ChannelTypeUID type; + ComponentChannelType type; if (uom != null && !uom.isBlank()) { value = new NumberValue(null, null, null, UnitUtils.parseUnit(uom)); - type = MqttBindingConstants.CHANNEL_TYPE_UID_NUMBER; + type = ComponentChannelType.NUMBER; } else if (sc != null && !sc.isBlank()) { // see state_class at https://developers.home-assistant.io/docs/core/entity/sensor#properties // > If not None, the sensor is assumed to be numerical value = new NumberValue(null, null, null, null); - type = MqttBindingConstants.CHANNEL_TYPE_UID_NUMBER; + type = ComponentChannelType.NUMBER; } else { value = new TextValue(); - type = MqttBindingConstants.CHANNEL_TYPE_UID_STRING; + type = ComponentChannelType.STRING; } String icon = channelConfiguration.getIcon(); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Switch.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Switch.java index 3e81741041e9a..b1288c151d374 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Switch.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Switch.java @@ -15,7 +15,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.values.OnOffValue; -import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; +import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannelType; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.binding.mqtt.homeassistant.internal.exception.ConfigurationException; @@ -73,7 +73,7 @@ public Switch(ComponentFactory.ComponentConfiguration componentConfiguration, bo OnOffValue value = new OnOffValue(channelConfiguration.stateOn, channelConfiguration.stateOff, channelConfiguration.payloadOn, channelConfiguration.payloadOff); - buildChannel(SWITCH_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, value, getName(), + buildChannel(SWITCH_CHANNEL_ID, ComponentChannelType.SWITCH, value, getName(), componentConfiguration.getUpdateListener()) .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Update.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Update.java index 6dbd3030fc32d..5ea64b4a24663 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Update.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Update.java @@ -20,8 +20,8 @@ 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.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannel; +import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannelType; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.core.io.transport.mqtt.MqttBrokerConnection; import org.openhab.core.library.types.StringType; @@ -150,8 +150,7 @@ public Update(ComponentFactory.ComponentConfiguration componentConfiguration, bo String commandTopic = channelConfiguration.commandTopic; String payloadInstall = channelConfiguration.payloadInstall; - var builder = buildChannel(UPDATE_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, value, getName(), - this); + var builder = buildChannel(UPDATE_CHANNEL_ID, ComponentChannelType.STRING, value, getName(), this); if (channelConfiguration.stateTopic != null) { builder.stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()); } @@ -164,8 +163,8 @@ public Update(ComponentFactory.ComponentConfiguration componentConfiguration, bo if (channelConfiguration.latestVersionTopic != null) { value = new TextValue(); - latestVersionChannel = buildChannel(LATEST_VERSION_CHANNEL_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, - value, getName(), this) + latestVersionChannel = buildChannel(LATEST_VERSION_CHANNEL_ID, ComponentChannelType.STRING, value, + getName(), this) .stateTopic(channelConfiguration.latestVersionTopic, channelConfiguration.latestVersionTemplate) .build(false); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Vacuum.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Vacuum.java index a133a3bc77fe3..0c5185267230a 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Vacuum.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Vacuum.java @@ -26,10 +26,9 @@ import org.openhab.binding.mqtt.generic.values.PercentageValue; import org.openhab.binding.mqtt.generic.values.TextValue; import org.openhab.binding.mqtt.generic.values.Value; -import org.openhab.binding.mqtt.homeassistant.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannel; +import org.openhab.binding.mqtt.homeassistant.internal.ComponentChannelType; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; -import org.openhab.core.thing.type.ChannelTypeUID; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -228,9 +227,8 @@ public Vacuum(ComponentFactory.ComponentConfiguration componentConfiguration, bo addPayloadToList(deviceSupportedFeatures, FEATURE_START, channelConfiguration.payloadStart, commands); } - buildOptionalChannel(COMMAND_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, - new TextValue(commands.toArray(new String[0])), updateListener, null, channelConfiguration.commandTopic, - null, null); + buildOptionalChannel(COMMAND_CH_ID, ComponentChannelType.STRING, new TextValue(commands.toArray(new String[0])), + updateListener, null, channelConfiguration.commandTopic, null, null); final var fanSpeedList = channelConfiguration.fanSpeedList; if (deviceSupportedFeatures.contains(FEATURE_FAN_SPEED) && fanSpeedList != null && !fanSpeedList.isEmpty()) { @@ -239,51 +237,50 @@ public Vacuum(ComponentFactory.ComponentConfiguration componentConfiguration, bo } var fanSpeedValue = new TextValue(fanSpeedList.toArray(new String[0])); if (channelConfiguration.schema == Schema.LEGACY) { - buildOptionalChannel(FAN_SPEED_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, fanSpeedValue, - updateListener, null, channelConfiguration.setFanSpeedTopic, - channelConfiguration.fanSpeedTemplate, channelConfiguration.fanSpeedTopic); + buildOptionalChannel(FAN_SPEED_CH_ID, ComponentChannelType.STRING, fanSpeedValue, updateListener, null, + channelConfiguration.setFanSpeedTopic, channelConfiguration.fanSpeedTemplate, + channelConfiguration.fanSpeedTopic); } else if (deviceSupportedFeatures.contains(FEATURE_STATUS)) { - buildOptionalChannel(FAN_SPEED_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, fanSpeedValue, - updateListener, null, channelConfiguration.setFanSpeedTopic, "{{ value_json.fan_speed }}", + buildOptionalChannel(FAN_SPEED_CH_ID, ComponentChannelType.STRING, fanSpeedValue, updateListener, null, + channelConfiguration.setFanSpeedTopic, "{{ value_json.fan_speed }}", channelConfiguration.stateTopic); } else { LOGGER.info("Status feature is disabled, unable to get fan speed."); - buildOptionalChannel(FAN_SPEED_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, fanSpeedValue, - updateListener, null, channelConfiguration.setFanSpeedTopic, null, null); + buildOptionalChannel(FAN_SPEED_CH_ID, ComponentChannelType.STRING, fanSpeedValue, updateListener, null, + channelConfiguration.setFanSpeedTopic, null, null); } } if (deviceSupportedFeatures.contains(FEATURE_SEND_COMMAND)) { - buildOptionalChannel(CUSTOM_COMMAND_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, new TextValue(), - updateListener, null, channelConfiguration.sendCommandTopic, null, null); + buildOptionalChannel(CUSTOM_COMMAND_CH_ID, ComponentChannelType.STRING, new TextValue(), updateListener, + null, channelConfiguration.sendCommandTopic, null, null); } if (channelConfiguration.schema == Schema.LEGACY) { // I assume, that if these topics defined in config, then we don't need to check features - buildOptionalChannel(BATTERY_LEVEL_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_DIMMER, + buildOptionalChannel(BATTERY_LEVEL_CH_ID, ComponentChannelType.DIMMER, new PercentageValue(BigDecimal.ZERO, BigDecimal.valueOf(100), BigDecimal.ONE, null, null), updateListener, null, null, channelConfiguration.batteryLevelTemplate, channelConfiguration.batteryLevelTopic); - buildOptionalChannel(CHARGING_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, - new OnOffValue(TRUE, FALSE), updateListener, null, null, channelConfiguration.chargingTemplate, + buildOptionalChannel(CHARGING_CH_ID, ComponentChannelType.SWITCH, new OnOffValue(TRUE, FALSE), + updateListener, null, null, channelConfiguration.chargingTemplate, channelConfiguration.chargingTopic); - buildOptionalChannel(CLEANING_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, - new OnOffValue(TRUE, FALSE), updateListener, null, null, channelConfiguration.cleaningTemplate, + buildOptionalChannel(CLEANING_CH_ID, ComponentChannelType.SWITCH, new OnOffValue(TRUE, FALSE), + updateListener, null, null, channelConfiguration.cleaningTemplate, channelConfiguration.cleaningTopic); - buildOptionalChannel(DOCKED_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_SWITCH, - new OnOffValue(TRUE, FALSE), updateListener, null, null, channelConfiguration.dockedTemplate, - channelConfiguration.dockedTopic); - buildOptionalChannel(ERROR_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, new TextValue(), - updateListener, null, null, channelConfiguration.errorTemplate, channelConfiguration.errorTopic); + buildOptionalChannel(DOCKED_CH_ID, ComponentChannelType.SWITCH, new OnOffValue(TRUE, FALSE), updateListener, + null, null, channelConfiguration.dockedTemplate, channelConfiguration.dockedTopic); + buildOptionalChannel(ERROR_CH_ID, ComponentChannelType.STRING, new TextValue(), updateListener, null, null, + channelConfiguration.errorTemplate, channelConfiguration.errorTopic); } else { if (deviceSupportedFeatures.contains(FEATURE_STATUS)) { // state key is mandatory - buildOptionalChannel(STATE_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, + buildOptionalChannel(STATE_CH_ID, ComponentChannelType.STRING, new TextValue(new String[] { STATE_CLEANING, STATE_DOCKED, STATE_PAUSED, STATE_IDLE, STATE_RETURNING, STATE_ERROR }), updateListener, null, null, "{{ value_json.state }}", channelConfiguration.stateTopic); if (deviceSupportedFeatures.contains(FEATURE_BATTERY)) { - buildOptionalChannel(BATTERY_LEVEL_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_DIMMER, + buildOptionalChannel(BATTERY_LEVEL_CH_ID, ComponentChannelType.DIMMER, new PercentageValue(BigDecimal.ZERO, BigDecimal.valueOf(100), BigDecimal.ONE, null, null), updateListener, null, null, "{{ value_json.battery_level }}", channelConfiguration.stateTopic); @@ -291,17 +288,16 @@ public Vacuum(ComponentFactory.ComponentConfiguration componentConfiguration, bo } } - buildOptionalChannel(JSON_ATTRIBUTES_CH_ID, MqttBindingConstants.CHANNEL_TYPE_UID_STRING, new TextValue(), - updateListener, null, null, channelConfiguration.jsonAttributesTemplate, - channelConfiguration.jsonAttributesTopic); + buildOptionalChannel(JSON_ATTRIBUTES_CH_ID, ComponentChannelType.STRING, new TextValue(), updateListener, null, + null, channelConfiguration.jsonAttributesTemplate, channelConfiguration.jsonAttributesTopic); } @Nullable - private ComponentChannel buildOptionalChannel(String channelId, ChannelTypeUID channelTypeUID, Value valueState, + private ComponentChannel buildOptionalChannel(String channelId, ComponentChannelType channelType, Value valueState, ChannelStateUpdateListener channelStateUpdateListener, @Nullable String commandTemplate, @Nullable String commandTopic, @Nullable String stateTemplate, @Nullable String stateTopic) { if ((commandTopic != null && !commandTopic.isBlank()) || (stateTopic != null && !stateTopic.isBlank())) { - return buildChannel(channelId, channelTypeUID, valueState, getName(), channelStateUpdateListener) + return buildChannel(channelId, channelType, valueState, getName(), channelStateUpdateListener) .stateTopic(stateTopic, stateTemplate, channelConfiguration.getValueTemplate()) .commandTopic(commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos(), commandTemplate) From 4c90379b76d9906f4384e59fcf849ee02d255121 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Mon, 12 Aug 2024 11:22:06 -0600 Subject: [PATCH 11/11] remove unused variables Signed-off-by: Cody Cutrer --- .../binding/mqtt/homeassistant/internal/ComponentChannel.java | 1 - .../internal/handler/HomeAssistantThingHandler.java | 1 - 2 files changed, 2 deletions(-) diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentChannel.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentChannel.java index 21f836fc4f9b1..24fcde6834692 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentChannel.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentChannel.java @@ -224,7 +224,6 @@ public ComponentChannel build(boolean addToComponent) { ChannelUID channelUID; ChannelState channelState; Channel channel; - ChannelType type; channelUID = component.buildChannelUID(channelID); channelState = new HomeAssistantChannelState( diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java index 0aec229aabb56..aa2ee5fcfe5e3 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandler.java @@ -129,7 +129,6 @@ public HomeAssistantThingHandler(Thing thing, MqttChannelTypeProvider channelTyp this.attributeReceiveTimeout = attributeReceiveTimeout; this.delayedProcessing = new DelayedBatchProcessing<>(attributeReceiveTimeout, this, scheduler); - Map properties = getThing().getProperties(); newStyleChannels = "true".equals(thing.getProperties().get("newStyleChannels")); this.discoverComponents = new DiscoverComponents(thing.getUID(), scheduler, this, this, gson,