From 80819ca503d8680b98044ea323adaa5503c06444 Mon Sep 17 00:00:00 2001 From: jimtng <2554958+jimtng@users.noreply.github.com> Date: Thu, 3 Feb 2022 21:42:54 +1000 Subject: [PATCH] [mqtt] Support birth and shutdown message (#12152) Signed-off-by: Jimmy Tanagra --- bundles/org.openhab.binding.mqtt/README.md | 20 ++++++++-- .../binding/mqtt/handler/BrokerHandler.java | 31 ++++++++++++--- .../mqtt/handler/BrokerHandlerConfig.java | 10 +++++ .../resources/OH-INF/thing/thing-types.xml | 38 +++++++++++++++++++ 4 files changed, 89 insertions(+), 10 deletions(-) diff --git a/bundles/org.openhab.binding.mqtt/README.md b/bundles/org.openhab.binding.mqtt/README.md index 89544c24cce..b41323a04c9 100644 --- a/bundles/org.openhab.binding.mqtt/README.md +++ b/bundles/org.openhab.binding.mqtt/README.md @@ -38,10 +38,22 @@ Reconnect parameters are: An MQTT last will and testament can be configured: -* __lwtMessage__: An optional last will and testament message. Defaults to empty. -* __lwtTopic__: The last will topic. Defaults to empty and therefore disables the last will. -* __lwtQos__: The optional qos of the last will. Defaults to 0. -* __lwtRetain__: Retain last will message. Defaults to false. +* __lwtMessage__: An optional last will and testament message. Defaults to empty. +* __lwtTopic__: The last will topic. Defaults to empty and therefore disables the last will. +* __lwtQos__: The optional qos of the last will. Defaults to 0. +* __lwtRetain__: Retain last will message. Defaults to true. + +An MQTT message can be published upon a successful connection to the MQTT broker with these parameters: + +* __birthMessage__: An optional message to be published once the bridge established a connection to the MQTT broker. Defaults to empty. +* __birthTopic__: The birth topic. Defaults to empty and therefore no birth message will be published. +* __birthRetain__: Retain the birth message. Defaults to true. + +An MQTT message can be published just before disconnecting from the broker with these parameters: + +* __shutdownMessage__: An optional message to be published before the bridge disconnects from the MQTT broker. Defaults to empty. +* __shutdownTopic__: The shutdown topic. Defaults to empty and therefore no shutdown message will be published. +* __shutdownRetain__: Retain the shutdown message. Defaults to true. For more security, the following optional parameters can be altered: diff --git a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/BrokerHandler.java b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/BrokerHandler.java index c5eb7345c86..d7cf35686a6 100644 --- a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/BrokerHandler.java +++ b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/BrokerHandler.java @@ -13,6 +13,7 @@ package org.openhab.binding.mqtt.handler; import java.security.NoSuchAlgorithmException; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -44,6 +45,7 @@ import org.slf4j.LoggerFactory; * connection to the {@link MqttService}. * * @author David Graeff - Initial contribution + * @author Jimmy Tanagra - Add birth and shutdown message */ @NonNullByDefault public class BrokerHandler extends AbstractBrokerHandler implements PinnedCallback { @@ -60,12 +62,16 @@ public class BrokerHandler extends AbstractBrokerHandler implements PinnedCallba // Store generated client ID if none was set by the user final MqttBrokerConnection connection = this.connection; String clientID = config.clientID; - if (connection != null && state == MqttConnectionState.CONNECTED && (clientID == null || clientID.isBlank())) { - clientID = connection.getClientId(); - config.clientID = clientID; - Configuration editConfig = editConfiguration(); - editConfig.put("clientid", clientID); - updateConfiguration(editConfig); + if (connection != null && state == MqttConnectionState.CONNECTED) { + if (clientID == null || clientID.isBlank()) { + clientID = connection.getClientId(); + config.clientID = clientID; + Configuration editConfig = editConfiguration(); + editConfig.put("clientid", clientID); + updateConfiguration(editConfig); + } else { + publish(config.birthTopic, config.birthMessage, config.birthRetain); + } } } @@ -114,6 +120,8 @@ public class BrokerHandler extends AbstractBrokerHandler implements PinnedCallba public void dispose() { try { if (connection != null) { + publish(config.shutdownTopic, config.shutdownMessage, config.shutdownRetain).get(1000, + TimeUnit.MILLISECONDS); connection.stop().get(1000, TimeUnit.MILLISECONDS); } else { logger.warn("Trying to dispose handler {} but connection is already null. Most likely this is a bug.", @@ -236,4 +244,15 @@ public class BrokerHandler extends AbstractBrokerHandler implements PinnedCallba super.initialize(); } + + /** + * Calls the @NonNull MqttBrokerConnection::publish() with @Nullable topic and message + */ + private CompletableFuture publish(@Nullable String topic, @Nullable String message, boolean retain) { + if (topic == null || connection == null) { + return CompletableFuture.completedFuture(true); + } + String nonNullMessage = message != null ? message : ""; + return connection.publish(topic, nonNullMessage.getBytes(), connection.getQos(), retain); + } } diff --git a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/BrokerHandlerConfig.java b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/BrokerHandlerConfig.java index 5c8a2727bc9..170078fa1a6 100644 --- a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/BrokerHandlerConfig.java +++ b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/BrokerHandlerConfig.java @@ -36,4 +36,14 @@ public class BrokerHandlerConfig extends MqttBrokerConnectionConfig { public String publickey = ""; public boolean enableDiscovery = true; + + // Birth message parameters + public @Nullable String birthTopic; + public @Nullable String birthMessage; + public Boolean birthRetain = true; + + // Shutdown message parameters + public @Nullable String shutdownTopic; + public @Nullable String shutdownMessage; + public Boolean shutdownRetain = true; } diff --git a/bundles/org.openhab.binding.mqtt/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.mqtt/src/main/resources/OH-INF/thing/thing-types.xml index 9c7a16ef3df..0f9f5a68aa5 100644 --- a/bundles/org.openhab.binding.mqtt/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.mqtt/src/main/resources/OH-INF/thing/thing-types.xml @@ -94,6 +94,44 @@ true + + + The message to send to the broker when a connection is established. + true + + + + + Defaults to empty and therefore disables the birth message. + true + + + + + True if the birth message should be retained (defaults to true) + true + true + + + + + The message to send to the broker before the connection terminates. + true + + + + + Defaults to empty and therefore disables the shutdown message. + true + + + + + True if the shutdown message should be retained (defaults to true) + false + true + + The MQTT username