2 * Copyright (c) 2010-2020 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.xmppclient.internal;
15 import java.io.IOException;
16 import java.util.HashSet;
19 import org.jivesoftware.smack.AbstractXMPPConnection;
20 import org.jivesoftware.smack.ConnectionListener;
21 import org.jivesoftware.smack.ReconnectionManager;
22 import org.jivesoftware.smack.SmackException;
23 import org.jivesoftware.smack.XMPPConnection;
24 import org.jivesoftware.smack.XMPPException;
25 import org.jivesoftware.smack.chat2.Chat;
26 import org.jivesoftware.smack.chat2.ChatManager;
27 import org.jivesoftware.smack.chat2.IncomingChatMessageListener;
28 import org.jivesoftware.smack.packet.Message;
29 import org.jivesoftware.smack.tcp.XMPPTCPConnection;
30 import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
31 import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
32 import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity;
33 import org.jxmpp.jid.EntityBareJid;
34 import org.jxmpp.jid.impl.JidCreate;
35 import org.jxmpp.stringprep.XmppStringprepException;
36 import org.openhab.binding.xmppclient.internal.handler.XMPPClientMessageSubscriber;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
41 * The {@link XMPPClient} is lib for handling XMPP connection and messaging
43 * @author Pavel Gololobov - Initial contribution
45 public class XMPPClient implements IncomingChatMessageListener, ConnectionListener {
46 private final Logger logger = LoggerFactory.getLogger(XMPPClient.class);
47 private AbstractXMPPConnection connection;
48 private ChatManager chatManager;
49 private Set<XMPPClientMessageSubscriber> subscribers = new HashSet<>();
51 public void subscribe(XMPPClientMessageSubscriber channel) {
52 logger.debug("Channel {} subscribed", channel.getName());
53 subscribers.add(channel);
56 public void unsubscribe(XMPPClientMessageSubscriber channel) {
57 logger.debug("Channel {} unsubscribed", channel.getName());
58 subscribers.remove(channel);
61 public void connect(String host, Integer port, String login, String domain, String password)
62 throws XMPPException, SmackException, IOException {
64 String serverHost = domain;
65 if ((host != null) && !host.isEmpty()) {
69 XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder() //
70 .setHost(serverHost) //
72 .setUsernameAndPassword(login, password) //
73 .setXmppDomain(domain) //
76 connection = new XMPPTCPConnection(config);
77 connection.addConnectionListener(this);
79 ReconnectionManager reconnectionManager = ReconnectionManager.getInstanceFor(connection);
80 reconnectionManager.enableAutomaticReconnection();
82 Identity identity = new Identity("client", "openHAB", "bot");
83 ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
84 sdm.setIdentity(identity);
87 connection.connect().login();
88 } catch (InterruptedException ex) {
91 chatManager = ChatManager.getInstanceFor(connection);
92 chatManager.addIncomingListener(this);
95 public void disconnect() {
96 if (connection != null) {
97 connection.disconnect();
101 public void sendMessage(String to, String message) {
102 if (connection == null) {
103 logger.warn("XMPP connection is null");
106 if (chatManager == null) {
107 logger.warn("XMPP chatManager is null");
111 EntityBareJid jid = JidCreate.entityBareFrom(to);
112 Chat chat = chatManager.chatWith(jid);
114 } catch (XmppStringprepException | SmackException.NotConnectedException | InterruptedException e) {
115 logger.info("XMPP message sending error", e);
120 public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) {
121 logger.debug("XMPP {} says {}", from.asBareJid().toString(), message.getBody());
122 for (XMPPClientMessageSubscriber subscriber : subscribers) {
123 logger.debug("Push to subscriber {}", subscriber.getName());
124 subscriber.processMessage(from.asBareJid().toString(), message.getBody());
129 public void connected(XMPPConnection connection) {
130 logger.debug("Connected to XMPP server.");
134 public void authenticated(XMPPConnection connection, boolean resumed) {
135 logger.debug("Authenticated to XMPP server.");
139 public void connectionClosed() {
140 logger.debug("XMPP connection was closed.");
144 public void connectionClosedOnError(Exception e) {
145 logger.debug("Connection to XMPP server was lost.");
146 if (connection != null) {
147 connection.disconnect();
149 connection.connect().login();
150 } catch (SmackException | IOException | XMPPException | InterruptedException ex) {
151 logger.info("XMPP connection error", ex);