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.*;
20 import org.jivesoftware.smack.chat2.Chat;
21 import org.jivesoftware.smack.chat2.ChatManager;
22 import org.jivesoftware.smack.chat2.IncomingChatMessageListener;
23 import org.jivesoftware.smack.packet.Message;
24 import org.jivesoftware.smack.tcp.XMPPTCPConnection;
25 import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
26 import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
27 import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity;
28 import org.jxmpp.jid.EntityBareJid;
29 import org.jxmpp.jid.impl.JidCreate;
30 import org.jxmpp.stringprep.XmppStringprepException;
31 import org.openhab.binding.xmppclient.handler.XMPPClientMessageSubscriber;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
36 * The {@link XMPPClient} is lib for handling XMPP connection and messaging
38 * @author Pavel Gololobov - Initial contribution
40 public class XMPPClient implements IncomingChatMessageListener, ConnectionListener {
41 private final Logger logger = LoggerFactory.getLogger(XMPPClient.class);
42 private AbstractXMPPConnection connection;
43 private ChatManager chatManager;
44 private Set<XMPPClientMessageSubscriber> subscribers = new HashSet<>();
46 public void subscribe(XMPPClientMessageSubscriber channel) {
47 logger.debug("Channel {} subscribed", channel.getName());
48 subscribers.add(channel);
51 public void unsubscribe(XMPPClientMessageSubscriber channel) {
52 logger.debug("Channel {} unsubscribed", channel.getName());
53 subscribers.remove(channel);
56 public void connect(String host, Integer port, String login, String domain, String password)
57 throws XMPPException, SmackException, IOException {
59 String serverHost = domain;
60 if ((host != null) && !host.isEmpty()) {
64 XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder() //
65 .setHost(serverHost) //
67 .setUsernameAndPassword(login, password) //
68 .setXmppDomain(domain) //
71 connection = new XMPPTCPConnection(config);
72 connection.addConnectionListener(this);
74 ReconnectionManager reconnectionManager = ReconnectionManager.getInstanceFor(connection);
75 reconnectionManager.enableAutomaticReconnection();
77 Identity identity = new Identity("client", "openHAB", "bot");
78 ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
79 sdm.setIdentity(identity);
82 connection.connect().login();
83 } catch (InterruptedException ex) {
86 chatManager = ChatManager.getInstanceFor(connection);
87 chatManager.addIncomingListener(this);
90 public void disconnect() {
91 if (connection != null) {
92 connection.disconnect();
96 public void sendMessage(String to, String message) {
97 if (connection == null) {
98 logger.warn("XMPP connection is null");
101 if (chatManager == null) {
102 logger.warn("XMPP chatManager is null");
106 EntityBareJid jid = JidCreate.entityBareFrom(to);
107 Chat chat = chatManager.chatWith(jid);
109 } catch (XmppStringprepException | SmackException.NotConnectedException | InterruptedException e) {
110 logger.info("XMPP message sending error", e);
115 public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) {
116 logger.debug("XMPP {} says {}", from.asBareJid().toString(), message.getBody());
117 for (XMPPClientMessageSubscriber subscriber : subscribers) {
118 logger.debug("Push to subscriber {}", subscriber.getName());
119 subscriber.processMessage(from.asBareJid().toString(), message.getBody());
124 public void connected(XMPPConnection connection) {
125 logger.debug("Connected to XMPP server.");
129 public void authenticated(XMPPConnection connection, boolean resumed) {
130 logger.debug("Authenticated to XMPP server.");
134 public void connectionClosed() {
135 logger.debug("XMPP connection was closed.");
139 public void connectionClosedOnError(Exception e) {
140 logger.debug("Connection to XMPP server was lost.");
141 if (connection != null) {
142 connection.disconnect();
144 connection.connect().login();
145 } catch (SmackException | IOException | XMPPException | InterruptedException ex) {
146 logger.info("XMPP connection error", ex);