diff --git a/bundles/org.openhab.binding.xmppclient/README.md b/bundles/org.openhab.binding.xmppclient/README.md index 8a8d944feec..e7133375d4c 100644 --- a/bundles/org.openhab.binding.xmppclient/README.md +++ b/bundles/org.openhab.binding.xmppclient/README.md @@ -26,22 +26,23 @@ Bridge xmppclient:xmppBridge:xmpp "XMPP Client" [ host="xmpp.example.com", port= **xmppBridge** parameters: -| Name | Label | Description | Required | Default value | -|----------|--------------------|-------------------------------------------|-----------|-----------------------| -| username | Username | The XMPP username (left part of JID) | true | - | -| domain | Domain | The XMPP domain name (right part of JID) | true | - | -| password | Password | The XMPP user password | true | - | -| host | Server Hostname/IP | The IP/Hostname of the XMPP server | false | as "domain" parameter | -| port | XMPP server Port | The typical port is 5222 | false | 5222 | +| Name | Label | Description | Required | Default value | +|--------------|--------------------|--------------------------------------------------------------------|----------|-----------------------| +| username | Username | The XMPP username (left part of JID) | true | - | +| domain | Domain | The XMPP domain name (right part of JID) | true | - | +| password | Password | The XMPP user password | true | - | +| host | Server Hostname/IP | The IP/Hostname of the XMPP server | false | as "domain" parameter | +| port | XMPP server Port | The typical port is 5222 | false | 5222 | +| securityMode | Security Mode | Sets the TLS security mode: `required`, `ifpossible` or `disabled` | false | `required` | ## Channels **publishTrigger** parameters: -| Name | Label | Description | Required | -|-----------|---------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------| -| payload | Payload condition | An optional condition on the value | false | -| separator | Separator character | The trigger channel payload usually only contains the received text. If you define a separator character, for example '#', the sender UID and received text will be in the trigger channel payload. For example: pavel@example.com#My Message Text | false | +| Name | Label | Description | Required | +|-----------|---------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------| +| payload | Payload condition | An optional condition on the value | false | +| separator | Separator character | The trigger channel payload usually only contains the received text. If you define a separator character, for example '#', the sender UID and received text will be in the trigger channel payload. For example: pavel@example.com#My Message Text | false | ## Example Rules diff --git a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/XMPPClientBindingConstants.java b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/XMPPClientBindingConstants.java index da29d009a2c..9e45e2a985f 100644 --- a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/XMPPClientBindingConstants.java +++ b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/XMPPClientBindingConstants.java @@ -12,6 +12,7 @@ */ package org.openhab.binding.xmppclient.internal; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.thing.ThingTypeUID; /** @@ -20,6 +21,7 @@ import org.openhab.core.thing.ThingTypeUID; * * @author Pavel Gololobov - Initial contribution */ +@NonNullByDefault public class XMPPClientBindingConstants { private static final String BINDING_ID = "xmppclient"; diff --git a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/XMPPClientHandlerFactory.java b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/XMPPClientHandlerFactory.java index 098c8658274..5a92aa2b6db 100644 --- a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/XMPPClientHandlerFactory.java +++ b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/XMPPClientHandlerFactory.java @@ -14,6 +14,8 @@ package org.openhab.binding.xmppclient.internal; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.xmppclient.internal.handler.XMPPClientHandler; import org.openhab.core.thing.Bridge; import org.openhab.core.thing.Thing; @@ -29,6 +31,7 @@ import org.osgi.service.component.annotations.Component; * * @author Pavel Gololobov - Initial contribution */ +@NonNullByDefault @Component(configurationPid = "binding.xmppclient", service = ThingHandlerFactory.class) public class XMPPClientHandlerFactory extends BaseThingHandlerFactory { private static final Set SUPPORTED_THING_TYPES_UIDS = Set @@ -40,7 +43,7 @@ public class XMPPClientHandlerFactory extends BaseThingHandlerFactory { } @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (thingTypeUID.equals(XMPPClientBindingConstants.BRIDGE_TYPE_XMPP)) { diff --git a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/action/XMPPActions.java b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/action/XMPPActions.java index 9fac03a8859..4bcc6b509e5 100644 --- a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/action/XMPPActions.java +++ b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/action/XMPPActions.java @@ -14,7 +14,7 @@ package org.openhab.binding.xmppclient.internal.action; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.xmppclient.internal.XMPPClient; +import org.openhab.binding.xmppclient.internal.client.XMPPClient; import org.openhab.binding.xmppclient.internal.handler.XMPPClientHandler; import org.openhab.core.automation.annotation.ActionInput; import org.openhab.core.automation.annotation.RuleAction; @@ -35,7 +35,7 @@ import org.slf4j.LoggerFactory; @ThingActionsScope(name = "xmppclient") @NonNullByDefault public class XMPPActions implements ThingActions { - private static final Logger logger = LoggerFactory.getLogger(XMPPActions.class); + private final Logger logger = LoggerFactory.getLogger(XMPPActions.class); private @Nullable XMPPClientHandler handler; @Override @@ -58,12 +58,8 @@ public class XMPPActions implements ThingActions { } XMPPClient connection = clientHandler.getXMPPClient(); - if (connection == null) { - logger.warn("XMPP ThingHandler connection is null"); - return; - } - if ((to == null) || (text == null)) { - logger.info("Skipping XMPP messaging to {} value {}", to, text); + if (to == null || text == null) { + logger.warn("Skipping XMPP messaging to {} value {}", to, text); return; } connection.sendMessage(to, text); @@ -80,11 +76,7 @@ public class XMPPActions implements ThingActions { } XMPPClient connection = clientHandler.getXMPPClient(); - if (connection == null) { - logger.warn("XMPP ThingHandler connection is null"); - return; - } - if ((to == null) || (filename == null)) { + if (to == null || filename == null) { logger.warn("Skipping XMPP messaging to {} value {}", to, filename); return; } diff --git a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/XMPPClient.java b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/client/XMPPClient.java similarity index 59% rename from bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/XMPPClient.java rename to bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/client/XMPPClient.java index e95c49f04e5..4ca39840436 100644 --- a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/XMPPClient.java +++ b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/client/XMPPClient.java @@ -10,15 +10,19 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.xmppclient.internal; +package org.openhab.binding.xmppclient.internal.client; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.HashSet; +import java.util.Objects; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.jivesoftware.smack.AbstractXMPPConnection; +import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode; import org.jivesoftware.smack.ConnectionListener; import org.jivesoftware.smack.ReconnectionManager; import org.jivesoftware.smack.SmackException; @@ -44,13 +48,20 @@ import org.slf4j.LoggerFactory; * The {@link XMPPClient} is lib for handling XMPP connection and messaging * * @author Pavel Gololobov - Initial contribution + * @author Leo Siepel - Add reconnection logic */ +@NonNullByDefault public class XMPPClient implements IncomingChatMessageListener, ConnectionListener { private final Logger logger = LoggerFactory.getLogger(XMPPClient.class); - private AbstractXMPPConnection connection; - private ChatManager chatManager; - private HttpFileUploadManager httpFileUploadManager; + private @Nullable AbstractXMPPConnection connection; + private @Nullable ChatManager chatManager; + private @Nullable HttpFileUploadManager httpFileUploadManager; private Set subscribers = new HashSet<>(); + private final XMPPClientEventlistener eventListener; + + public XMPPClient(XMPPClientEventlistener eventListener) { + this.eventListener = eventListener; + } public void subscribe(XMPPClientMessageSubscriber channel) { logger.debug("Channel {} subscribed", channel.getName()); @@ -62,25 +73,32 @@ public class XMPPClient implements IncomingChatMessageListener, ConnectionListen subscribers.remove(channel); } - public void connect(String host, Integer port, String login, String domain, String password) - throws XMPPException, SmackException, IOException { + public void connect(String host, Integer port, String login, String domain, String password, + SecurityMode securityMode) throws XMPPClientConfigException, XMPPClientException { disconnect(); String serverHost = domain; - if ((host != null) && !host.isEmpty()) { + if (!host.isBlank()) { serverHost = host; } - XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder() // - .setHost(serverHost) // - .setPort(port) // - .setUsernameAndPassword(login, password) // - .setXmppDomain(domain) // - .build(); + XMPPTCPConnectionConfiguration config; + try { + config = XMPPTCPConnectionConfiguration.builder() // + .setHost(serverHost) // + .setPort(port) // + .setUsernameAndPassword(login, password) // + .setXmppDomain(domain) // + .setSecurityMode(securityMode)// + .build(); + } catch (XmppStringprepException e) { + throw new XMPPClientConfigException(Objects.requireNonNullElse(e.getMessage(), "Unknown error message")); + } - connection = new XMPPTCPConnection(config); - connection.addConnectionListener(this); + AbstractXMPPConnection connectionLocal = new XMPPTCPConnection(config); + connection = connectionLocal; + connectionLocal.addConnectionListener(this); - ReconnectionManager reconnectionManager = ReconnectionManager.getInstanceFor(connection); + ReconnectionManager reconnectionManager = ReconnectionManager.getInstanceFor(connectionLocal); reconnectionManager.enableAutomaticReconnection(); Identity identity = new Identity("client", "openHAB", "bot"); @@ -88,16 +106,20 @@ public class XMPPClient implements IncomingChatMessageListener, ConnectionListen sdm.setIdentity(identity); try { - connection.connect().login(); - } catch (InterruptedException ex) { + connectionLocal.connect().login(); + } catch (InterruptedException | XMPPException | SmackException | IOException e) { + throw new XMPPClientException(Objects.requireNonNullElse(e.getMessage(), "Unknown error message"), + e.getCause()); } - chatManager = ChatManager.getInstanceFor(connection); + ChatManager chatManager = ChatManager.getInstanceFor(connection); chatManager.addIncomingListener(this); + this.chatManager = chatManager; httpFileUploadManager = HttpFileUploadManager.getInstanceFor(connection); } public void disconnect() { + AbstractXMPPConnection connection = this.connection; if (connection != null) { connection.disconnect(); } @@ -105,11 +127,13 @@ public class XMPPClient implements IncomingChatMessageListener, ConnectionListen public void sendMessage(String to, String message) { if (connection == null) { - logger.warn("XMPP connection is null"); + eventListener.onErrorEvent("XMPP connection is null"); return; } + + ChatManager chatManager = this.chatManager; if (chatManager == null) { - logger.warn("XMPP chatManager is null"); + eventListener.onErrorEvent("XMPP chatManager is null"); return; } try { @@ -117,7 +141,7 @@ public class XMPPClient implements IncomingChatMessageListener, ConnectionListen Chat chat = chatManager.chatWith(jid); chat.send(message); } catch (XmppStringprepException | SmackException.NotConnectedException | InterruptedException e) { - logger.info("XMPP message sending error", e); + logger.warn("XMPP message sending error", e); } } @@ -126,12 +150,13 @@ public class XMPPClient implements IncomingChatMessageListener, ConnectionListen logger.warn("XMPP connection is null"); return; } - if (httpFileUploadManager == null) { + HttpFileUploadManager httpFileUploadManagerLocal = httpFileUploadManager; + if (httpFileUploadManagerLocal == null) { logger.warn("XMPP httpFileUploadManager is null"); return; } try { - URL u = httpFileUploadManager.uploadFile(new File(filename)); + URL u = httpFileUploadManagerLocal.uploadFile(new File(filename)); // Use Stanza oob this.sendMessage(to, u.toString()); } catch (XMPPException.XMPPErrorException | SmackException | InterruptedException | IOException e) { @@ -140,7 +165,12 @@ public class XMPPClient implements IncomingChatMessageListener, ConnectionListen } @Override - public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) { + public void newIncomingMessage(@Nullable EntityBareJid from, @Nullable Message message, @Nullable Chat chat) { + if (from == null || message == null || chat == null) { + logger.debug("newIncomingMessage with atleast one null argument, should not happen"); + return; + } + logger.debug("XMPP {} says {}", from.asBareJid().toString(), message.getBody()); for (XMPPClientMessageSubscriber subscriber : subscribers) { logger.debug("Push to subscriber {}", subscriber.getName()); @@ -149,30 +179,26 @@ public class XMPPClient implements IncomingChatMessageListener, ConnectionListen } @Override - public void connected(XMPPConnection connection) { + public void connected(@Nullable XMPPConnection connection) { logger.debug("Connected to XMPP server."); + eventListener.onAllOk(); } @Override - public void authenticated(XMPPConnection connection, boolean resumed) { + public void authenticated(@Nullable XMPPConnection connection, boolean resumed) { logger.debug("Authenticated to XMPP server."); + eventListener.onAllOk(); } @Override public void connectionClosed() { logger.debug("XMPP connection was closed."); + eventListener.onErrorEvent("XMPP connection was closed."); } @Override - public void connectionClosedOnError(Exception e) { + public void connectionClosedOnError(@Nullable Exception e) { logger.debug("Connection to XMPP server was lost."); - if (connection != null) { - connection.disconnect(); - try { - connection.connect().login(); - } catch (SmackException | IOException | XMPPException | InterruptedException ex) { - logger.info("XMPP connection error", ex); - } - } + eventListener.onErrorEvent("XMPP connection was closed."); } } diff --git a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/client/XMPPClientConfigException.java b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/client/XMPPClientConfigException.java new file mode 100644 index 00000000000..c474c8c4ea4 --- /dev/null +++ b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/client/XMPPClientConfigException.java @@ -0,0 +1,40 @@ +/** + * 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.xmppclient.internal.client; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link XMPPClientConfigException} represents a binding specific {@link Exception}. + * + * @author Leo Siepel - Initial contribution + */ + +@NonNullByDefault +public class XMPPClientConfigException extends Exception { + + private static final long serialVersionUID = 1L; + + public XMPPClientConfigException(String message) { + super(message); + } + + public XMPPClientConfigException(String message, @Nullable Throwable cause) { + super(message, cause); + } + + public XMPPClientConfigException(@Nullable Throwable cause) { + super(cause); + } +} diff --git a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/client/XMPPClientEventlistener.java b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/client/XMPPClientEventlistener.java new file mode 100644 index 00000000000..e1fb7a2257d --- /dev/null +++ b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/client/XMPPClientEventlistener.java @@ -0,0 +1,29 @@ +/** + * 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.xmppclient.internal.client; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link XMPPClientEventlistener} is an interface for handling XMPP connection events. + * + * @author Leo Siepel - Initial Contribution + */ + +@NonNullByDefault +public interface XMPPClientEventlistener { + + void onErrorEvent(String errorMessage); + + void onAllOk(); +} diff --git a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/client/XMPPClientException.java b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/client/XMPPClientException.java new file mode 100644 index 00000000000..5967a397ca2 --- /dev/null +++ b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/client/XMPPClientException.java @@ -0,0 +1,40 @@ +/** + * 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.xmppclient.internal.client; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link XMPPClientException} represents a binding specific {@link Exception}. + * + * @author Leo Siepel - Initial contribution + */ + +@NonNullByDefault +public class XMPPClientException extends Exception { + + private static final long serialVersionUID = 1L; + + public XMPPClientException(String message) { + super(message); + } + + public XMPPClientException(String message, @Nullable Throwable cause) { + super(message, cause); + } + + public XMPPClientException(@Nullable Throwable cause) { + super(cause); + } +} diff --git a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/handler/PublishTriggerChannel.java b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/handler/PublishTriggerChannel.java index 807f62ba6a9..21c19627293 100644 --- a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/handler/PublishTriggerChannel.java +++ b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/handler/PublishTriggerChannel.java @@ -12,7 +12,8 @@ */ package org.openhab.binding.xmppclient.internal.handler; -import org.openhab.binding.xmppclient.internal.XMPPClient; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.xmppclient.internal.client.XMPPClient; import org.openhab.core.thing.ChannelUID; /** @@ -22,6 +23,7 @@ import org.openhab.core.thing.ChannelUID; * * @author Pavel Gololobov - Initial contribution */ +@NonNullByDefault public class PublishTriggerChannel implements XMPPClientMessageSubscriber { private final XMPPClient connection; private final PublishTriggerChannelConfig config; diff --git a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/handler/XMPPClientConfiguration.java b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/handler/XMPPClientConfiguration.java index 62f0d5b214a..b2f0bfdef55 100644 --- a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/handler/XMPPClientConfiguration.java +++ b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/handler/XMPPClientConfiguration.java @@ -14,6 +14,7 @@ package org.openhab.binding.xmppclient.internal.handler; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode; /** * The {@link XMPPClientConfiguration} class contains fields mapping thing configuration parameters. @@ -27,4 +28,10 @@ public class XMPPClientConfiguration { public String username = ""; public String password = ""; public String domain = ""; + public String securityMode = SecurityMode.required.toString(); + + public boolean isValid() { + String host = this.host; + return !(host == null || host.isBlank()); + } } diff --git a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/handler/XMPPClientHandler.java b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/handler/XMPPClientHandler.java index a32c8771f3b..3c7cfc2dbfd 100644 --- a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/handler/XMPPClientHandler.java +++ b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/handler/XMPPClientHandler.java @@ -12,17 +12,20 @@ */ package org.openhab.binding.xmppclient.internal.handler; -import java.io.IOException; import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.concurrent.TimeUnit; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPException; -import org.openhab.binding.xmppclient.internal.XMPPClient; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode; import org.openhab.binding.xmppclient.internal.action.XMPPActions; +import org.openhab.binding.xmppclient.internal.client.XMPPClient; +import org.openhab.binding.xmppclient.internal.client.XMPPClientConfigException; +import org.openhab.binding.xmppclient.internal.client.XMPPClientEventlistener; +import org.openhab.binding.xmppclient.internal.client.XMPPClientException; import org.openhab.core.thing.Bridge; import org.openhab.core.thing.Channel; import org.openhab.core.thing.ChannelUID; @@ -40,15 +43,15 @@ import org.slf4j.LoggerFactory; * * @author Pavel Gololobov - Initial contribution */ - -public class XMPPClientHandler extends BaseBridgeHandler { +@NonNullByDefault +public class XMPPClientHandler extends BaseBridgeHandler implements XMPPClientEventlistener { private final Logger logger = LoggerFactory.getLogger(XMPPClientHandler.class); private XMPPClient xmppClient; - private XMPPClientConfiguration config; private final Map channelStateByChannelUID = new HashMap<>(); public XMPPClientHandler(Bridge thing) { super(thing); + xmppClient = new XMPPClient(this); } public XMPPClient getXMPPClient() { @@ -85,12 +88,22 @@ public class XMPPClientHandler extends BaseBridgeHandler { } private void doConnect() { - config = getConfigAs(XMPPClientConfiguration.class); - xmppClient = new XMPPClient(); + XMPPClientConfiguration config = getConfigAs(XMPPClientConfiguration.class); + if (!config.isValid()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Please check configuration"); + return; + } + try { - xmppClient.connect(config.host, config.port, config.username, config.domain, config.password); - } catch (SmackException | IOException | XMPPException e) { - logger.info("XMPP connection error", e); + xmppClient.connect(Objects.requireNonNullElse(config.host, ""), config.port, config.username, config.domain, + config.password, SecurityMode.valueOf(config.securityMode)); + updateStatus(ThingStatus.ONLINE); + } catch (XMPPClientConfigException e) { + logger.debug("XMPP connection error", e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage()); + return; + } catch (XMPPClientException e) { + logger.debug("XMPP connection error", e); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); return; } @@ -103,7 +116,15 @@ public class XMPPClientHandler extends BaseBridgeHandler { logger.info("XMPP added channel {} payload {}", channel.getUID().toString(), channelConfig.payload); } channelStateByChannelUID.values().forEach(c -> c.start()); + } + @Override + public void onErrorEvent(String errorMessage) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, errorMessage); + } + + @Override + public void onAllOk() { updateStatus(ThingStatus.ONLINE); } } diff --git a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/handler/XMPPClientMessageSubscriber.java b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/handler/XMPPClientMessageSubscriber.java index 8765c535123..a401316efc6 100644 --- a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/handler/XMPPClientMessageSubscriber.java +++ b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/handler/XMPPClientMessageSubscriber.java @@ -12,11 +12,14 @@ */ package org.openhab.binding.xmppclient.internal.handler; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * Subscriber interface * * @author Pavel Gololobov - Initial contribution */ +@NonNullByDefault public interface XMPPClientMessageSubscriber { void processMessage(String from, String payload); diff --git a/bundles/org.openhab.binding.xmppclient/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.xmppclient/src/main/resources/OH-INF/thing/thing-types.xml index b9841ddce73..ea506032b3c 100644 --- a/bundles/org.openhab.binding.xmppclient/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.xmppclient/src/main/resources/OH-INF/thing/thing-types.xml @@ -30,6 +30,19 @@ The default port is 5222. + true + + + + An enumeration for TLS security modes that are available when making a connection to the XMPP server. + true + + + + + + required + true