[mqtt.homeassistant] VETO updates to read only channels (#15937)

I.e. Button, Scene, and Binary Sensors.

Also ensure we set up the CommandDescription, since some value types mights use it.

Signed-off-by: Cody Cutrer <cody@cutrer.us>
This commit is contained in:
Cody Cutrer 2023-11-25 04:27:05 -07:00 committed by GitHub
parent a13fd80bfe
commit 935415aa6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 30 additions and 11 deletions

View File

@ -33,12 +33,14 @@ import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
import org.openhab.core.thing.Channel; import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.binding.builder.ChannelBuilder; import org.openhab.core.thing.binding.builder.ChannelBuilder;
import org.openhab.core.thing.type.AutoUpdatePolicy;
import org.openhab.core.thing.type.ChannelDefinition; import org.openhab.core.thing.type.ChannelDefinition;
import org.openhab.core.thing.type.ChannelDefinitionBuilder; import org.openhab.core.thing.type.ChannelDefinitionBuilder;
import org.openhab.core.thing.type.ChannelType; import org.openhab.core.thing.type.ChannelType;
import org.openhab.core.thing.type.ChannelTypeBuilder; import org.openhab.core.thing.type.ChannelTypeBuilder;
import org.openhab.core.thing.type.ChannelTypeUID; import org.openhab.core.thing.type.ChannelTypeUID;
import org.openhab.core.types.Command; import org.openhab.core.types.Command;
import org.openhab.core.types.CommandDescription;
import org.openhab.core.types.StateDescriptionFragment; import org.openhab.core.types.StateDescriptionFragment;
/** /**
@ -130,6 +132,7 @@ public class ComponentChannel {
private boolean retain; private boolean retain;
private boolean trigger; private boolean trigger;
private boolean isAdvanced; private boolean isAdvanced;
private @Nullable AutoUpdatePolicy autoUpdatePolicy;
private @Nullable Integer qos; private @Nullable Integer qos;
private @Nullable Predicate<Command> commandFilter; private @Nullable Predicate<Command> commandFilter;
@ -203,6 +206,11 @@ public class ComponentChannel {
return this; return this;
} }
public Builder withAutoUpdatePolicy(@Nullable AutoUpdatePolicy autoUpdatePolicy) {
this.autoUpdatePolicy = autoUpdatePolicy;
return this;
}
public Builder commandFilter(@Nullable Predicate<Command> commandFilter) { public Builder commandFilter(@Nullable Predicate<Command> commandFilter) {
this.commandFilter = commandFilter; this.commandFilter = commandFilter;
return this; return this;
@ -237,23 +245,26 @@ public class ComponentChannel {
isAdvanced = true; isAdvanced = true;
} }
ChannelTypeBuilder typeBuilder;
if (this.trigger) { if (this.trigger) {
type = ChannelTypeBuilder.trigger(channelTypeUID, label) typeBuilder = ChannelTypeBuilder.trigger(channelTypeUID, label);
.withConfigDescriptionURI(URI.create(MqttBindingConstants.CONFIG_HA_CHANNEL))
.isAdvanced(isAdvanced).build();
} else { } else {
StateDescriptionFragment description = valueState.createStateDescription(commandTopic == null).build(); StateDescriptionFragment stateDescription = valueState.createStateDescription(commandTopic == null)
type = ChannelTypeBuilder.state(channelTypeUID, label, channelState.getItemType()) .build();
.withConfigDescriptionURI(URI.create(MqttBindingConstants.CONFIG_HA_CHANNEL)) CommandDescription commandDescription = valueState.createCommandDescription().build();
.withStateDescriptionFragment(description).isAdvanced(isAdvanced).build(); typeBuilder = ChannelTypeBuilder.state(channelTypeUID, label, channelState.getItemType())
.withStateDescriptionFragment(stateDescription).withCommandDescription(commandDescription);
} }
type = typeBuilder.withConfigDescriptionURI(URI.create(MqttBindingConstants.CONFIG_HA_CHANNEL))
.isAdvanced(isAdvanced).build();
Configuration configuration = new Configuration(); Configuration configuration = new Configuration();
configuration.put("config", component.getChannelConfigurationJson()); configuration.put("config", component.getChannelConfigurationJson());
component.getHaID().toConfig(configuration); component.getHaID().toConfig(configuration);
channel = ChannelBuilder.create(channelUID, channelState.getItemType()).withType(channelTypeUID) channel = ChannelBuilder.create(channelUID, channelState.getItemType()).withType(channelTypeUID)
.withKind(type.getKind()).withLabel(label).withConfiguration(configuration).build(); .withKind(type.getKind()).withLabel(label).withConfiguration(configuration)
.withAutoUpdatePolicy(autoUpdatePolicy).build();
ComponentChannel result = new ComponentChannel(channelUID, channelState, channel, type, channelTypeUID, ComponentChannel result = new ComponentChannel(channelUID, channelState, channel, type, channelTypeUID,
channelStateUpdateListener); channelStateUpdateListener);

View File

@ -22,6 +22,7 @@ import org.openhab.binding.mqtt.generic.values.Value;
import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; 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.ExpireUpdateStateListener;
import org.openhab.binding.mqtt.homeassistant.internal.listener.OffDelayUpdateStateListener; import org.openhab.binding.mqtt.homeassistant.internal.listener.OffDelayUpdateStateListener;
import org.openhab.core.thing.type.AutoUpdatePolicy;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
@ -72,7 +73,8 @@ public class BinarySensor extends AbstractComponent<BinarySensor.ChannelConfigur
OnOffValue value = new OnOffValue(channelConfiguration.payloadOn, channelConfiguration.payloadOff); OnOffValue value = new OnOffValue(channelConfiguration.payloadOn, channelConfiguration.payloadOff);
buildChannel(SENSOR_CHANNEL_ID, value, "value", getListener(componentConfiguration, value)) buildChannel(SENSOR_CHANNEL_ID, value, "value", getListener(componentConfiguration, value))
.stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()).build(); .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate())
.withAutoUpdatePolicy(AutoUpdatePolicy.VETO).build();
} }
private ChannelStateUpdateListener getListener(ComponentFactory.ComponentConfiguration componentConfiguration, private ChannelStateUpdateListener getListener(ComponentFactory.ComponentConfiguration componentConfiguration,

View File

@ -16,6 +16,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.mqtt.generic.values.TextValue; import org.openhab.binding.mqtt.generic.values.TextValue;
import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration;
import org.openhab.core.thing.type.AutoUpdatePolicy;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
@ -53,6 +54,6 @@ public class Button extends AbstractComponent<Button.ChannelConfiguration> {
buildChannel(BUTTON_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener()) buildChannel(BUTTON_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener())
.commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(),
channelConfiguration.getQos()) channelConfiguration.getQos())
.build(); .withAutoUpdatePolicy(AutoUpdatePolicy.VETO).build();
} }
} }

View File

@ -16,6 +16,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.mqtt.generic.values.TextValue; import org.openhab.binding.mqtt.generic.values.TextValue;
import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration;
import org.openhab.core.thing.type.AutoUpdatePolicy;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
@ -51,6 +52,6 @@ public class Scene extends AbstractComponent<Scene.ChannelConfiguration> {
buildChannel(SCENE_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener()) buildChannel(SCENE_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener())
.commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(),
channelConfiguration.getQos()) channelConfiguration.getQos())
.build(); .withAutoUpdatePolicy(AutoUpdatePolicy.VETO).build();
} }
} }

View File

@ -16,12 +16,14 @@ import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.openhab.binding.mqtt.generic.values.TextValue; import org.openhab.binding.mqtt.generic.values.TextValue;
import org.openhab.core.library.types.StringType; import org.openhab.core.library.types.StringType;
import org.openhab.core.thing.type.AutoUpdatePolicy;
/** /**
* Tests for {@link Button} * Tests for {@link Button}
@ -57,6 +59,8 @@ public class ButtonTests extends AbstractComponentTests {
assertChannel(component, Button.BUTTON_CHANNEL_ID, "", "esphome/single-car-gdo/button/restart/command", assertChannel(component, Button.BUTTON_CHANNEL_ID, "", "esphome/single-car-gdo/button/restart/command",
"Restart", TextValue.class); "Restart", TextValue.class);
assertThat(Objects.requireNonNull(component.getChannel(Button.BUTTON_CHANNEL_ID)).getChannel()
.getAutoUpdatePolicy(), is(AutoUpdatePolicy.VETO));
assertThrows(IllegalArgumentException.class, assertThrows(IllegalArgumentException.class,
() -> component.getChannel(Button.BUTTON_CHANNEL_ID).getState().publishValue(new StringType("ON"))); () -> component.getChannel(Button.BUTTON_CHANNEL_ID).getState().publishValue(new StringType("ON")));