]> git.basschouten.com Git - openhab-addons.git/blob
03cfbd7cd4aba14e800069f146ce0bda41eca5c0
[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.powermax.internal.connector;
14
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.io.OutputStream;
18 import java.util.ArrayList;
19 import java.util.List;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.binding.powermax.internal.message.PowermaxBaseMessage;
24 import org.openhab.binding.powermax.internal.message.PowermaxMessageEvent;
25 import org.openhab.binding.powermax.internal.message.PowermaxMessageEventListener;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 /**
30  * An abstract class for the communication with the Visonic alarm panel that
31  * handles stuff common to all communication types
32  *
33  * @author Laurent Garnier - Initial contribution
34  */
35 @NonNullByDefault
36 public abstract class PowermaxConnector implements PowermaxConnectorInterface {
37
38     private final Logger logger = LoggerFactory.getLogger(PowermaxConnector.class);
39
40     protected final String readerThreadName;
41     private final List<PowermaxMessageEventListener> listeners = new ArrayList<>();
42
43     private @Nullable InputStream input;
44     private @Nullable OutputStream output;
45     private boolean connected;
46     private @Nullable Thread readerThread;
47     private long waitingForResponse;
48
49     public PowermaxConnector(String readerThreadName) {
50         this.readerThreadName = readerThreadName;
51     }
52
53     @Override
54     public abstract void open() throws Exception;
55
56     @Override
57     public abstract void close();
58
59     /**
60      * Cleanup everything; to be called when closing the communication
61      */
62     protected void cleanup(boolean closeStreams) {
63         logger.debug("cleanup(): cleaning up Connection");
64
65         Thread thread = readerThread;
66         if (thread != null) {
67             thread.interrupt();
68             try {
69                 thread.join();
70             } catch (InterruptedException e) {
71             }
72         }
73
74         if (closeStreams) {
75             OutputStream out = output;
76             if (out != null) {
77                 try {
78                     out.close();
79                 } catch (IOException e) {
80                     logger.debug("Error while closing the output stream: {}", e.getMessage());
81                 }
82             }
83
84             InputStream in = input;
85             if (in != null) {
86                 try {
87                     in.close();
88                 } catch (IOException e) {
89                     logger.debug("Error while closing the input stream: {}", e.getMessage());
90                 }
91             }
92         }
93
94         readerThread = null;
95         input = null;
96         output = null;
97
98         logger.debug("cleanup(): Connection Cleanup");
99     }
100
101     /**
102      * Handles an incoming message
103      *
104      * @param incomingMessage the received message as a table of bytes
105      */
106     public void handleIncomingMessage(byte[] incomingMessage) {
107         PowermaxMessageEvent event = new PowermaxMessageEvent(this,
108                 PowermaxBaseMessage.getMessageHandler(incomingMessage));
109
110         // send message to event listeners
111         listeners.forEach(listener -> listener.onNewMessageEvent(event));
112     }
113
114     /**
115      * Handles a communication failure
116      */
117     public void handleCommunicationFailure(@Nullable String message) {
118         close();
119         listeners.forEach(listener -> listener.onCommunicationFailure(message != null ? message : ""));
120     }
121
122     @Override
123     public void sendMessage(byte[] data) {
124         try {
125             OutputStream out = output;
126             if (out == null) {
127                 throw new IOException("output stream is undefined");
128             }
129             out.write(data);
130             out.flush();
131         } catch (IOException e) {
132             logger.debug("sendMessage(): Writing error: {}", e.getMessage(), e);
133             handleCommunicationFailure(e.getMessage());
134         }
135     }
136
137     @Override
138     public int read(byte[] buffer) throws IOException {
139         InputStream in = input;
140         if (in == null) {
141             throw new IOException("input stream is undefined");
142         }
143         return in.read(buffer);
144     }
145
146     @Override
147     public void addEventListener(PowermaxMessageEventListener listener) {
148         listeners.add(listener);
149     }
150
151     @Override
152     public void removeEventListener(PowermaxMessageEventListener listener) {
153         listeners.remove(listener);
154     }
155
156     /**
157      * @return the input stream
158      */
159     public @Nullable InputStream getInput() {
160         return input;
161     }
162
163     /**
164      * Set the input stream
165      *
166      * @param input the input stream
167      */
168     public void setInput(@Nullable InputStream input) {
169         this.input = input;
170     }
171
172     /**
173      * @return the output stream
174      */
175     public @Nullable OutputStream getOutput() {
176         return output;
177     }
178
179     /**
180      * Set the output stream
181      *
182      * @param output the output stream
183      */
184     public void setOutput(@Nullable OutputStream output) {
185         this.output = output;
186     }
187
188     /**
189      * @return true if connected or false if not
190      */
191     @Override
192     public boolean isConnected() {
193         return connected;
194     }
195
196     /**
197      * Set the connection state
198      *
199      * @param connected true if connected or false if not
200      */
201     public void setConnected(boolean connected) {
202         this.connected = connected;
203     }
204
205     /**
206      * @return the thread that handles the message reading
207      */
208     public @Nullable Thread getReaderThread() {
209         return readerThread;
210     }
211
212     /**
213      * Set the thread that handles the message reading
214      *
215      * @param readerThread the thread
216      */
217     public void setReaderThread(Thread readerThread) {
218         this.readerThread = readerThread;
219     }
220
221     /**
222      * @return the start time of the time frame to receive a response
223      */
224     public synchronized long getWaitingForResponse() {
225         return waitingForResponse;
226     }
227
228     /**
229      * Set the start time of the time frame to receive a response
230      *
231      * @param waitingForResponse the time in milliseconds
232      */
233     public synchronized void setWaitingForResponse(long waitingForResponse) {
234         this.waitingForResponse = waitingForResponse;
235     }
236 }