]> git.basschouten.com Git - openhab-addons.git/blob
e95c49f04e577a97b958d965c7f6716eb829d8c2
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.xmppclient.internal;
14
15 import java.io.File;
16 import java.io.IOException;
17 import java.net.URL;
18 import java.util.HashSet;
19 import java.util.Set;
20
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;
42
43 /**
44  * The {@link XMPPClient} is lib for handling XMPP connection and messaging
45  *
46  * @author Pavel Gololobov - Initial contribution
47  */
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<>();
54
55     public void subscribe(XMPPClientMessageSubscriber channel) {
56         logger.debug("Channel {} subscribed", channel.getName());
57         subscribers.add(channel);
58     }
59
60     public void unsubscribe(XMPPClientMessageSubscriber channel) {
61         logger.debug("Channel {} unsubscribed", channel.getName());
62         subscribers.remove(channel);
63     }
64
65     public void connect(String host, Integer port, String login, String domain, String password)
66             throws XMPPException, SmackException, IOException {
67         disconnect();
68         String serverHost = domain;
69         if ((host != null) && !host.isEmpty()) {
70             serverHost = host;
71         }
72
73         XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder() //
74                 .setHost(serverHost) //
75                 .setPort(port) //
76                 .setUsernameAndPassword(login, password) //
77                 .setXmppDomain(domain) //
78                 .build();
79
80         connection = new XMPPTCPConnection(config);
81         connection.addConnectionListener(this);
82
83         ReconnectionManager reconnectionManager = ReconnectionManager.getInstanceFor(connection);
84         reconnectionManager.enableAutomaticReconnection();
85
86         Identity identity = new Identity("client", "openHAB", "bot");
87         ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
88         sdm.setIdentity(identity);
89
90         try {
91             connection.connect().login();
92         } catch (InterruptedException ex) {
93         }
94
95         chatManager = ChatManager.getInstanceFor(connection);
96         chatManager.addIncomingListener(this);
97         httpFileUploadManager = HttpFileUploadManager.getInstanceFor(connection);
98     }
99
100     public void disconnect() {
101         if (connection != null) {
102             connection.disconnect();
103         }
104     }
105
106     public void sendMessage(String to, String message) {
107         if (connection == null) {
108             logger.warn("XMPP connection is null");
109             return;
110         }
111         if (chatManager == null) {
112             logger.warn("XMPP chatManager is null");
113             return;
114         }
115         try {
116             EntityBareJid jid = JidCreate.entityBareFrom(to);
117             Chat chat = chatManager.chatWith(jid);
118             chat.send(message);
119         } catch (XmppStringprepException | SmackException.NotConnectedException | InterruptedException e) {
120             logger.info("XMPP message sending error", e);
121         }
122     }
123
124     public void sendImageByHTTP(String to, String filename) {
125         if (connection == null) {
126             logger.warn("XMPP connection is null");
127             return;
128         }
129         if (httpFileUploadManager == null) {
130             logger.warn("XMPP httpFileUploadManager is null");
131             return;
132         }
133         try {
134             URL u = httpFileUploadManager.uploadFile(new File(filename));
135             // Use Stanza oob
136             this.sendMessage(to, u.toString());
137         } catch (XMPPException.XMPPErrorException | SmackException | InterruptedException | IOException e) {
138             logger.warn("XMPP HTTP image sending error", e);
139         }
140     }
141
142     @Override
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());
148         }
149     }
150
151     @Override
152     public void connected(XMPPConnection connection) {
153         logger.debug("Connected to XMPP server.");
154     }
155
156     @Override
157     public void authenticated(XMPPConnection connection, boolean resumed) {
158         logger.debug("Authenticated to XMPP server.");
159     }
160
161     @Override
162     public void connectionClosed() {
163         logger.debug("XMPP connection was closed.");
164     }
165
166     @Override
167     public void connectionClosedOnError(Exception e) {
168         logger.debug("Connection to XMPP server was lost.");
169         if (connection != null) {
170             connection.disconnect();
171             try {
172                 connection.connect().login();
173             } catch (SmackException | IOException | XMPPException | InterruptedException ex) {
174                 logger.info("XMPP connection error", ex);
175             }
176         }
177     }
178 }