]> git.basschouten.com Git - openhab-addons.git/commitdiff
[mqtt.homeassistant] Add support for Button component (#15892)
authorCody Cutrer <cody@cutrer.us>
Sun, 19 Nov 2023 16:06:54 +0000 (09:06 -0700)
committerGitHub <noreply@github.com>
Sun, 19 Nov 2023 16:06:54 +0000 (17:06 +0100)
* [mqtt.homeassistant] Add support for Button component
* use a StringValue instead of an OnOffValue

---------

Signed-off-by: Cody Cutrer <cody@cutrer.us>
bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Button.java [new file with mode: 0644]
bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/ComponentFactory.java
bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponentTests.java
bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/ButtonTests.java [new file with mode: 0644]

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
new file mode 100644 (file)
index 0000000..97aa60f
--- /dev/null
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2010-2023 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.component;
+
+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.internal.config.dto.AbstractChannelConfiguration;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * An MQTT button, following the https://www.home-assistant.io/integrations/button.mqtt/ specification.
+ *
+ * @author Cody Cutrer - Initial contribution
+ */
+@NonNullByDefault
+public class Button extends AbstractComponent<Button.ChannelConfiguration> {
+    public static final String BUTTON_CHANNEL_ID = "button";
+
+    /**
+     * Configuration class for MQTT component
+     */
+    static class ChannelConfiguration extends AbstractChannelConfiguration {
+        ChannelConfiguration() {
+            super("MQTT Button");
+        }
+
+        protected @Nullable Boolean optimistic;
+
+        @SerializedName("command_topic")
+        protected @Nullable String commandTopic;
+
+        @SerializedName("payload_press")
+        protected String payloadPress = "PRESS";
+    }
+
+    public Button(ComponentFactory.ComponentConfiguration componentConfiguration) {
+        super(componentConfiguration, ChannelConfiguration.class);
+
+        TextValue value = new TextValue(new String[] { channelConfiguration.payloadPress });
+
+        buildChannel(BUTTON_CHANNEL_ID, value, getName(), componentConfiguration.getUpdateListener())
+                .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(),
+                        channelConfiguration.getQos())
+                .build();
+    }
+}
index 9855eec9c49ce0e771e107f1caed15f1ddc59652..6c95d5eeddecc13d55c063d4fe17951d3d36a5e2 100644 (file)
@@ -57,6 +57,8 @@ public class ComponentFactory {
                 return new AlarmControlPanel(componentConfiguration);
             case "binary_sensor":
                 return new BinarySensor(componentConfiguration);
+            case "button":
+                return new Button(componentConfiguration);
             case "camera":
                 return new Camera(componentConfiguration);
             case "cover":
index fc5d8c3cf1369307a0be505345f003052da68e83..e2d88086db78636b9de492abfdb6804683265a59 100644 (file)
@@ -230,6 +230,15 @@ public abstract class AbstractComponentTests extends AbstractHomeAssistantTests
                 ArgumentMatchers.eq(payload.getBytes(StandardCharsets.UTF_8)), anyInt(), anyBoolean());
     }
 
+    /**
+     * Assert that nothing was published on given topic.
+     *
+     * @param mqttTopic Mqtt topic
+     */
+    protected void assertNothingPublished(String mqttTopic) {
+        verify(bridgeConnection, never()).publish(eq(mqttTopic), any(), anyInt(), anyBoolean());
+    }
+
     /**
      * Publish payload to all subscribers on specified topic.
      *
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/ButtonTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/ButtonTests.java
new file mode 100644 (file)
index 0000000..943a6c4
--- /dev/null
@@ -0,0 +1,72 @@
+/**
+ * Copyright (c) 2010-2023 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.component;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.Test;
+import org.openhab.binding.mqtt.generic.values.TextValue;
+import org.openhab.core.library.types.StringType;
+
+/**
+ * Tests for {@link Button}
+ *
+ * @author Cody Cutrer - Initial contribution
+ */
+@NonNullByDefault
+public class ButtonTests extends AbstractComponentTests {
+    public static final String CONFIG_TOPIC = "button/0x847127fffe11dd6a_auto_lock_zigbee2mqtt";
+
+    @SuppressWarnings("null")
+    @Test
+    public void testButton() {
+        var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC), """
+                  {
+                    "dev_cla":"restart",
+                    "name":"Restart",
+                    "entity_category":"config",
+                    "cmd_t":"esphome/single-car-gdo/button/restart/command",
+                    "avty_t":"esphome/single-car-gdo/status",
+                    "uniq_id":"78e36d645710-button-ba0e8e32",
+                    "dev":{
+                      "ids":"78e36d645710",
+                      "name":"Single Car Garage Door Opener",
+                      "sw":"esphome v2023.10.4 Nov  1 2023, 09:27:02",
+                      "mdl":"esp32dev",
+                      "mf":"espressif"}
+                    }
+                """);
+
+        assertThat(component.channels.size(), is(1));
+        assertThat(component.getName(), is("Restart"));
+
+        assertChannel(component, Button.BUTTON_CHANNEL_ID, "", "esphome/single-car-gdo/button/restart/command",
+                "Restart", TextValue.class);
+
+        assertThrows(IllegalArgumentException.class,
+                () -> component.getChannel(Button.BUTTON_CHANNEL_ID).getState().publishValue(new StringType("ON")));
+        assertNothingPublished("esphome/single-car-gdo/button/restart/command");
+        component.getChannel(Button.BUTTON_CHANNEL_ID).getState().publishValue(new StringType("PRESS"));
+        assertPublished("esphome/single-car-gdo/button/restart/command", "PRESS");
+    }
+
+    @Override
+    protected Set<String> getConfigTopics() {
+        return Set.of(CONFIG_TOPIC);
+    }
+}