2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.epsonprojector.internal.connector;
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.io.OutputStream;
18 import java.nio.charset.StandardCharsets;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.binding.epsonprojector.internal.EpsonProjectorException;
23 import org.openhab.core.io.transport.serial.PortInUseException;
24 import org.openhab.core.io.transport.serial.SerialPort;
25 import org.openhab.core.io.transport.serial.SerialPortEvent;
26 import org.openhab.core.io.transport.serial.SerialPortEventListener;
27 import org.openhab.core.io.transport.serial.SerialPortIdentifier;
28 import org.openhab.core.io.transport.serial.SerialPortManager;
29 import org.openhab.core.io.transport.serial.UnsupportedCommOperationException;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
34 * Connector for serial port communication.
36 * @author Pauli Anttila - Initial contribution
37 * @author Michael Lobstein - Improvements for OH3
40 public class EpsonProjectorSerialConnector implements EpsonProjectorConnector, SerialPortEventListener {
42 private final Logger logger = LoggerFactory.getLogger(EpsonProjectorSerialConnector.class);
43 private final String serialPortName;
44 private final SerialPortManager serialPortManager;
46 private @Nullable InputStream in = null;
47 private @Nullable OutputStream out = null;
48 private @Nullable SerialPort serialPort = null;
50 public EpsonProjectorSerialConnector(SerialPortManager serialPortManager, String serialPort) {
51 this.serialPortManager = serialPortManager;
52 this.serialPortName = serialPort;
56 public void connect() throws EpsonProjectorException {
58 logger.debug("Open connection to serial port '{}'", serialPortName);
60 SerialPortIdentifier serialPortIdentifier = serialPortManager.getIdentifier(serialPortName);
62 if (serialPortIdentifier == null) {
63 throw new IOException("Unknown serial port");
65 SerialPort serialPort = serialPortIdentifier.open(this.getClass().getName(), 2000);
66 serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
67 serialPort.enableReceiveThreshold(1);
68 serialPort.disableReceiveTimeout();
70 InputStream in = serialPort.getInputStream();
71 OutputStream out = serialPort.getOutputStream();
73 if (in != null && out != null) {
75 if (in.markSupported()) {
79 serialPort.notifyOnDataAvailable(true);
81 this.serialPort = serialPort;
85 } catch (PortInUseException | UnsupportedCommOperationException | IOException e) {
86 throw new EpsonProjectorException(e);
91 public void disconnect() throws EpsonProjectorException {
92 InputStream in = this.in;
93 OutputStream out = this.out;
94 SerialPort serialPort = this.serialPort;
97 logger.debug("Close serial out stream");
100 } catch (IOException e) {
101 logger.debug("Error occurred when closing serial out stream: {}", e.getMessage());
106 logger.debug("Close serial in stream");
109 } catch (IOException e) {
110 logger.debug("Error occurred when closing serial in stream: {}", e.getMessage());
114 if (serialPort != null) {
115 logger.debug("Close serial port");
117 serialPort.removeEventListener();
118 this.serialPort = null;
121 logger.debug("Closed");
125 public String sendMessage(String data, int timeout) throws EpsonProjectorException {
126 InputStream in = this.in;
127 OutputStream out = this.out;
129 if (in == null || out == null) {
136 if (in != null && out != null) {
137 // flush input stream
138 if (in.markSupported()) {
141 while (in.available() > 0) {
142 int availableBytes = in.available();
144 if (availableBytes > 0) {
145 byte[] tmpData = new byte[availableBytes];
146 in.read(tmpData, 0, availableBytes);
150 return sendMmsg(data, timeout);
154 } catch (IOException e) {
155 logger.debug("IO error occurred...reconnect and resend once: {}", e.getMessage());
160 return sendMmsg(data, timeout);
161 } catch (IOException e1) {
162 throw new EpsonProjectorException(e);
168 public void serialEvent(SerialPortEvent arg0) {
171 private String sendMmsg(String data, int timeout) throws IOException, EpsonProjectorException {
174 InputStream in = this.in;
175 OutputStream out = this.out;
177 if (in != null && out != null) {
178 out.write(data.getBytes(StandardCharsets.US_ASCII));
179 out.write("\r\n".getBytes(StandardCharsets.US_ASCII));
182 long startTime = System.currentTimeMillis();
183 long elapsedTime = 0;
185 while (elapsedTime < timeout) {
186 int availableBytes = in.available();
187 if (availableBytes > 0) {
188 byte[] tmpData = new byte[availableBytes];
189 int readBytes = in.read(tmpData, 0, availableBytes);
190 resp = resp.concat(new String(tmpData, 0, readBytes, StandardCharsets.US_ASCII));
192 if (resp.contains(":")) {
198 } catch (InterruptedException e) {
199 throw new EpsonProjectorException(e);
203 elapsedTime = System.currentTimeMillis() - startTime;