]> git.basschouten.com Git - openhab-addons.git/blob
88a81f8bb2963a4d07f5e08fda71e79c7700cef9
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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.satel.internal.protocol;
14
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.io.OutputStream;
18 import java.util.TooManyListenersException;
19
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.openhab.core.io.transport.serial.PortInUseException;
22 import org.openhab.core.io.transport.serial.SerialPort;
23 import org.openhab.core.io.transport.serial.SerialPortEvent;
24 import org.openhab.core.io.transport.serial.SerialPortEventListener;
25 import org.openhab.core.io.transport.serial.SerialPortIdentifier;
26 import org.openhab.core.io.transport.serial.SerialPortManager;
27 import org.openhab.core.io.transport.serial.UnsupportedCommOperationException;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 /**
32  * Represents Satel INT-RS module. Implements methods required to connect and
33  * communicate with that module over serial protocol.
34  *
35  * @author Krzysztof Goworek - Initial contribution
36  */
37 @NonNullByDefault
38 public class IntRSModule extends SatelModule {
39
40     private final Logger logger = LoggerFactory.getLogger(IntRSModule.class);
41
42     private final String port;
43
44     private final SerialPortManager serialPortManager;
45
46     /**
47      * Creates new instance with port and timeout set to specified values.
48      *
49      * @param port serial port the module is connected to
50      * @param serialPortManager serial port manager object
51      * @param timeout timeout value in milliseconds for connect/read/write operations
52      * @param extPayloadSupport if <code>true</code>, the module supports extended command payload for reading
53      *            INTEGRA 256 state
54      */
55     public IntRSModule(String port, SerialPortManager serialPortManager, int timeout, boolean extPayloadSupport) {
56         super(timeout, extPayloadSupport);
57
58         this.port = port;
59         this.serialPortManager = serialPortManager;
60     }
61
62     @Override
63     protected CommunicationChannel connect() throws ConnectionFailureException {
64         logger.info("Connecting to INT-RS module at {}", this.port);
65
66         try {
67             SerialPortIdentifier portIdentifier = serialPortManager.getIdentifier(this.port);
68             if (portIdentifier == null) {
69                 throw new ConnectionFailureException(String.format("Port %s does not exist", this.port));
70             }
71             SerialPort serialPort = portIdentifier.open("org.openhab.binding.satel", 2000);
72             serialPort.setSerialPortParams(19200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
73             serialPort.enableReceiveTimeout(this.getTimeout());
74             // RXTX serial port library causes high CPU load
75             // Start event listener, which will just sleep and slow down event
76             // loop
77             serialPort.addEventListener(new SerialPortEventListener() {
78                 @Override
79                 public void serialEvent(SerialPortEvent ev) {
80                     try {
81                         logger.trace("RXTX library CPU load workaround, sleep forever");
82                         Thread.sleep(Long.MAX_VALUE);
83                     } catch (InterruptedException e) {
84                     }
85                 }
86             });
87             serialPort.notifyOnDataAvailable(true);
88
89             logger.info("INT-RS module connected successfuly");
90             return new SerialCommunicationChannel(serialPort);
91         } catch (PortInUseException e) {
92             throw new ConnectionFailureException(String.format("Port %s in use", this.port), e);
93         } catch (UnsupportedCommOperationException e) {
94             throw new ConnectionFailureException(String.format("Unsupported comm operation on port %s", this.port), e);
95         } catch (TooManyListenersException e) {
96             throw new ConnectionFailureException(String.format("Too many listeners on port %s", this.port), e);
97         }
98     }
99
100     private class SerialCommunicationChannel implements CommunicationChannel {
101
102         private SerialPort serialPort;
103
104         public SerialCommunicationChannel(SerialPort serialPort) {
105             this.serialPort = serialPort;
106         }
107
108         @Override
109         public InputStream getInputStream() throws IOException {
110             final InputStream stream = this.serialPort.getInputStream();
111             if (stream != null) {
112                 return stream;
113             }
114             throw new IOException("Selected port doesn't support receiving data: " + this.serialPort.getName());
115         }
116
117         @Override
118         public OutputStream getOutputStream() throws IOException {
119             final OutputStream stream = this.serialPort.getOutputStream();
120             if (stream != null) {
121                 return stream;
122             }
123             throw new IOException("Selected port doesn't support sending data: " + this.serialPort.getName());
124         }
125
126         @Override
127         public void disconnect() {
128             logger.debug("Closing connection to INT-RS module");
129             try {
130                 this.serialPort.close();
131                 logger.info("Connection to INT-RS module has been closed");
132             } catch (Exception e) {
133                 logger.error("An error occurred during closing serial port", e);
134             }
135         }
136     }
137 }