]> git.basschouten.com Git - openhab-addons.git/blob
f418dfe43edf9129213e11fbf566f73942bdd0e3
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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.alarmdecoder.internal.handler;
14
15 import java.io.BufferedReader;
16 import java.io.BufferedWriter;
17 import java.io.IOException;
18 import java.io.InputStreamReader;
19 import java.io.OutputStreamWriter;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.binding.alarmdecoder.internal.config.SerialBridgeConfig;
24 import org.openhab.core.io.transport.serial.PortInUseException;
25 import org.openhab.core.io.transport.serial.SerialPort;
26 import org.openhab.core.io.transport.serial.SerialPortIdentifier;
27 import org.openhab.core.io.transport.serial.SerialPortManager;
28 import org.openhab.core.io.transport.serial.UnsupportedCommOperationException;
29 import org.openhab.core.thing.Bridge;
30 import org.openhab.core.thing.ThingStatus;
31 import org.openhab.core.thing.ThingStatusDetail;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 /**
36  * Handler responsible for communicating via a serial port with the Nu Tech Alarm Decoder device.
37  * Based on code from the original OH1 alarmdecoder binding. Some OHC serial transport code taken from the Zigbee
38  * binding.
39  *
40  * @author Bernd Pfrommer - Initial contribution (OH1 version)
41  * @author Bob Adair - Re-factored into OH2 binding and rewrote to use OHC serial transport.
42  */
43 @NonNullByDefault
44 public class SerialBridgeHandler extends ADBridgeHandler {
45
46     private final Logger logger = LoggerFactory.getLogger(SerialBridgeHandler.class);
47
48     private SerialBridgeConfig config = new SerialBridgeConfig();
49     private final SerialPortManager serialPortManager;
50     private @NonNullByDefault({}) SerialPortIdentifier portIdentifier;
51     private @Nullable SerialPort serialPort;
52     private int serialPortSpeed = 115200;
53
54     public SerialBridgeHandler(Bridge bridge, SerialPortManager serialPortManager) {
55         super(bridge);
56         this.serialPortManager = serialPortManager;
57     }
58
59     @Override
60     public void initialize() {
61         logger.debug("Initializing serial bridge handler");
62         config = getConfigAs(SerialBridgeConfig.class);
63         discovery = config.discovery;
64
65         if (config.serialPort.isEmpty()) {
66             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "no serial port configured");
67             return;
68         }
69
70         if (config.bitrate > 0) {
71             serialPortSpeed = config.bitrate;
72         }
73
74         portIdentifier = serialPortManager.getIdentifier(config.serialPort);
75         if (portIdentifier == null) {
76             logger.debug("Serial Error: Port {} does not exist.", config.serialPort);
77             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
78                     "Configured serial port does not exist");
79             return;
80         }
81
82         connect();
83
84         logger.trace("Finished initializing serial bridge handler");
85     }
86
87     @Override
88     protected synchronized void connect() {
89         disconnect(); // make sure we are disconnected
90         try {
91             SerialPort serialPort = portIdentifier.open("org.openhab.binding.alarmdecoder", 100);
92             serialPort.setSerialPortParams(serialPortSpeed, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
93                     SerialPort.PARITY_NONE);
94             serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN | SerialPort.FLOWCONTROL_RTSCTS_OUT);
95             // Note: The V1 code called disableReceiveFraming() and disableReceiveThreshold() here
96
97             this.serialPort = serialPort;
98             reader = new BufferedReader(new InputStreamReader(serialPort.getInputStream(), AD_CHARSET));
99             writer = new BufferedWriter(new OutputStreamWriter(serialPort.getOutputStream(), AD_CHARSET));
100
101             logger.debug("connected to serial port: {}", config.serialPort);
102             panelReadyReceived = false;
103             startMsgReader();
104             updateStatus(ThingStatus.ONLINE);
105         } catch (PortInUseException e) {
106             logger.debug("Cannot open serial port: {}, it is already in use", config.serialPort);
107             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Serial port already in use");
108         } catch (UnsupportedCommOperationException | IOException | IllegalStateException e) {
109             logger.debug("Error connecting to serial port: {}", e.getMessage());
110             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
111         }
112     }
113
114     @Override
115     protected synchronized void disconnect() {
116         logger.trace("Disconnecting");
117         SerialPort sp = serialPort;
118         if (sp != null) {
119             logger.trace("Closing serial port");
120             sp.close();
121             serialPort = null;
122         }
123
124         stopMsgReader();
125
126         BufferedReader br = reader;
127         if (br != null) {
128             logger.trace("Closing reader");
129             try {
130                 br.close();
131             } catch (IOException e) {
132                 logger.info("IO Exception closing reader: {}", e.getMessage());
133             } finally {
134                 reader = null;
135             }
136         }
137
138         BufferedWriter bw = writer;
139         if (bw != null) {
140             logger.trace("Closing writer");
141             try {
142                 bw.close();
143             } catch (IOException e) {
144                 logger.info("IO Exception closing writer: {}", e.getMessage());
145             } finally {
146                 writer = null;
147             }
148         }
149     }
150 }