2 * Copyright (c) 2010-2023 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;
16 import java.io.IOException;
18 import java.util.HashSet;
21 import org.jivesoftware.smack.AbstractXMPPConnection;
22 import org.jivesoftware.smack.ConnectionListener;
23 import org.jivesoftware.smack.ReconnectionManager;
24 import org.jivesoftware.smack.SmackException;
25 import org.jivesoftware.smack.XMPPConnection;
26 import org.jivesoftware.smack.XMPPException;
27 import org.jivesoftware.smack.chat2.Chat;
28 import org.jivesoftware.smack.chat2.ChatManager;
29 import org.jivesoftware.smack.chat2.IncomingChatMessageListener;
30 import org.jivesoftware.smack.packet.Message;
31 import org.jivesoftware.smack.tcp.XMPPTCPConnection;
32 import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
33 import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
34 import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity;
35 import org.jivesoftware.smackx.httpfileupload.HttpFileUploadManager;
36 import org.jxmpp.jid.EntityBareJid;
37 import org.jxmpp.jid.impl.JidCreate;
38 import org.jxmpp.stringprep.XmppStringprepException;
39 import org.openhab.binding.xmppclient.internal.handler.XMPPClientMessageSubscriber;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
44 * The {@link XMPPClient} is lib for handling XMPP connection and messaging
46 * @author Pavel Gololobov - Initial contribution
48 public class XMPPClient implements IncomingChatMessageListener, ConnectionListener {
49 private final Logger logger = LoggerFactory.getLogger(XMPPClient.class);
50 private AbstractXMPPConnection connection;
51 private ChatManager chatManager;
52 private HttpFileUploadManager httpFileUploadManager;
53 private Set<XMPPClientMessageSubscriber> subscribers = new HashSet<>();
55 public void subscribe(XMPPClientMessageSubscriber channel) {
56 logger.debug("Channel {} subscribed", channel.getName());
57 subscribers.add(channel);
60 public void unsubscribe(XMPPClientMessageSubscriber channel) {
61 logger.debug("Channel {} unsubscribed", channel.getName());
62 subscribers.remove(channel);
65 public void connect(String host, Integer port, String login, String domain, String password)
66 throws XMPPException, SmackException, IOException {
68 String serverHost = domain;
69 if ((host != null) && !host.isEmpty()) {
73 XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder() //
74 .setHost(serverHost) //
76 .setUsernameAndPassword(login, password) //
77 .setXmppDomain(domain) //
80 connection = new XMPPTCPConnection(config);
81 connection.addConnectionListener(this);
83 ReconnectionManager reconnectionManager = ReconnectionManager.getInstanceFor(connection);
84 reconnectionManager.enableAutomaticReconnection();
86 Identity identity = new Identity("client", "openHAB", "bot");
87 ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
88 sdm.setIdentity(identity);
91 connection.connect().login();
92 } catch (InterruptedException ex) {
95 chatManager = ChatManager.getInstanceFor(connection);
96 chatManager.addIncomingListener(this);
97 httpFileUploadManager = HttpFileUploadManager.getInstanceFor(connection);
100 public void disconnect() {
101 if (connection != null) {
102 connection.disconnect();
106 public void sendMessage(String to, String message) {
107 if (connection == null) {
108 logger.warn("XMPP connection is null");
111 if (chatManager == null) {
112 logger.warn("XMPP chatManager is null");
116 EntityBareJid jid = JidCreate.entityBareFrom(to);
117 Chat chat = chatManager.chatWith(jid);
119 } catch (XmppStringprepException | SmackException.NotConnectedException | InterruptedException e) {
120 logger.info("XMPP message sending error", e);
124 public void sendImageByHTTP(String to, String filename) {
125 if (connection == null) {
126 logger.warn("XMPP connection is null");
129 if (httpFileUploadManager == null) {
130 logger.warn("XMPP httpFileUploadManager is null");
134 URL u = httpFileUploadManager.uploadFile(new File(filename));
136 this.sendMessage(to, u.toString());
137 } catch (XMPPException.XMPPErrorException | SmackException | InterruptedException | IOException e) {
138 logger.warn("XMPP HTTP image sending error", e);
143 public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) {
144 logger.debug("XMPP {} says {}", from.asBareJid().toString(), message.getBody());
145 for (XMPPClientMessageSubscriber subscriber : subscribers) {
146 logger.debug("Push to subscriber {}", subscriber.getName());
147 subscriber.processMessage(from.asBareJid().toString(), message.getBody());
152 public void connected(XMPPConnection connection) {
153 logger.debug("Connected to XMPP server.");
157 public void authenticated(XMPPConnection connection, boolean resumed) {
158 logger.debug("Authenticated to XMPP server.");
162 public void connectionClosed() {
163 logger.debug("XMPP connection was closed.");
167 public void connectionClosedOnError(Exception e) {
168 logger.debug("Connection to XMPP server was lost.");
169 if (connection != null) {
170 connection.disconnect();
172 connection.connect().login();
173 } catch (SmackException | IOException | XMPPException | InterruptedException ex) {
174 logger.info("XMPP connection error", ex);