]> git.basschouten.com Git - openhab-addons.git/blob
f584b04eed60c7d1e9b5709d63be2838baef6d49
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.lirc.internal.connector;
14
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.io.OutputStream;
18 import java.io.PrintWriter;
19 import java.net.Socket;
20 import java.net.UnknownHostException;
21 import java.util.Set;
22 import java.util.concurrent.CopyOnWriteArraySet;
23
24 import org.openhab.binding.lirc.internal.config.LIRCBridgeConfiguration;
25 import org.openhab.binding.lirc.internal.messages.LIRCButtonEvent;
26 import org.openhab.binding.lirc.internal.messages.LIRCResponse;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30 /**
31  * Connector for communication with the LIRC server
32  *
33  * @author Andrew Nagle - Initial contribution
34  */
35 public class LIRCConnector {
36
37     private final Logger logger = LoggerFactory.getLogger(LIRCConnector.class);
38
39     private Set<LIRCEventListener> listeners = new CopyOnWriteArraySet<>();
40     private Socket socket;
41     private InputStream in;
42     private OutputStream out;
43     private PrintWriter outWriter;
44     private Thread readerThread;
45
46     public void addEventListener(LIRCEventListener listener) {
47         listeners.add(listener);
48     }
49
50     public void removeEventListener(LIRCEventListener listener) {
51         listeners.remove(listener);
52     }
53
54     public void connect(LIRCBridgeConfiguration config) throws UnknownHostException, IOException {
55         logger.debug("Connecting");
56
57         // Consider adding support for Unix Domain sockets as well.
58         // This would allow us to autodiscover the local LIRC server.
59         // The junixsocket library should work nicely
60         socket = new Socket(config.getHost(), config.getPortNumber());
61         out = socket.getOutputStream();
62         in = socket.getInputStream();
63         outWriter = new PrintWriter(out, true);
64         readerThread = new LIRCStreamReader(this, in);
65         readerThread.start();
66     }
67
68     public void disconnect() {
69         logger.debug("Disconnecting");
70         if (readerThread != null) {
71             logger.debug("Interrupt stream listener");
72             readerThread.interrupt();
73             readerThread = null;
74         }
75         if (outWriter != null) {
76             logger.debug("Close print writer stream");
77             outWriter.close();
78             outWriter = null;
79         }
80         if (socket != null) {
81             logger.debug("Close socket");
82             try {
83                 socket.close();
84             } catch (IOException e) {
85                 logger.debug("Error while closing the socket: {}", e.getMessage());
86             }
87             socket = null;
88             out = null;
89             in = null;
90         }
91         logger.debug("Disconnected");
92     }
93
94     /**
95      * Begins discovery of all remotes the LIRC server knows about.
96      */
97     public void startRemoteDiscovery() {
98         sendCommand("LIST");
99     }
100
101     /**
102      * Transmits the button press for the specified remote.
103      *
104      * @param remote
105      *            Name of the remote
106      * @param button
107      *            Button to press
108      */
109     public void transmit(String remote, String button) {
110         int timesToSend = 1;
111         String buttonName;
112         String[] parts = button.split(" ");
113         if (parts.length > 1) {
114             buttonName = parts[0];
115             timesToSend = Integer.parseInt(parts[1]);
116         } else {
117             buttonName = button;
118         }
119         transmit(remote, buttonName, timesToSend);
120     }
121
122     /**
123      * Transmits the button press for the specified remote
124      *
125      * @param remote
126      *            Name of the remote
127      * @param button
128      *            Button to press
129      * @param timesToSend
130      *            Number of times to transmit the button
131      */
132     public void transmit(String remote, String button, int timesToSend) {
133         // The last parameter is the number of times the command should be repeated.
134         // For example, the command "SEND_ONCE TV KEY_VOLUMEUP 4" will transmit
135         // the volume up code 5 times.
136         sendCommand(String.format("SEND_ONCE %s %s %s", remote, button, timesToSend - 1));
137     }
138
139     private synchronized void sendCommand(String command) {
140         outWriter.println(command);
141         outWriter.flush();
142     }
143
144     /**
145      * Sends a button pressed event to all listeners
146      *
147      * @param buttonEvent
148      *            the button pressed
149      */
150     public synchronized void sendButtonToListeners(LIRCButtonEvent buttonEvent) {
151         try {
152             for (LIRCEventListener listener : listeners) {
153                 listener.buttonPressed(buttonEvent);
154             }
155         } catch (Exception e) {
156             logger.error("Error invoking event listener", e);
157         }
158     }
159
160     /**
161      * Sends an error message to all listeners
162      *
163      * @param error
164      *            error message to send
165      */
166     public synchronized void sendErrorToListeners(String error) {
167         try {
168             for (LIRCEventListener listener : listeners) {
169                 listener.errorOccured(error);
170             }
171         } catch (Exception e) {
172             logger.error("Error invoking event listener", e);
173         }
174     }
175
176     /**
177      * Sends a LIRC message to all listeners
178      *
179      * @param message
180      *            message to send
181      */
182     public synchronized void sendMessageToListeners(LIRCResponse message) {
183         try {
184             for (LIRCEventListener listener : listeners) {
185                 listener.messageReceived(message);
186             }
187         } catch (Exception e) {
188             logger.error("Error invoking event listener", e);
189         }
190     }
191 }