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 static org.openhab.binding.epsonprojector.internal.EpsonProjectorBindingConstants.DEFAULT_PORT;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.io.OutputStream;
20 import java.net.Socket;
21 import java.nio.charset.StandardCharsets;
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.openhab.binding.epsonprojector.internal.EpsonProjectorException;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
30 * Connector for TCP communication.
32 * @author Pauli Anttila - Initial contribution
33 * @author Michael Lobstein - Improvements for OH3
36 public class EpsonProjectorTcpConnector implements EpsonProjectorConnector {
37 private static final String ESC_VP_HANDSHAKE = "ESC/VP.net\u0010\u0003\u0000\u0000\u0000\u0000";
39 private final Logger logger = LoggerFactory.getLogger(EpsonProjectorTcpConnector.class);
40 private final String ip;
41 private final int port;
43 private @Nullable Socket socket = null;
44 private @Nullable InputStream in = null;
45 private @Nullable OutputStream out = null;
47 public EpsonProjectorTcpConnector(String ip, int port) {
53 public void connect() throws EpsonProjectorException {
54 logger.debug("Open connection to address'{}:{}'", ip, port);
57 Socket socket = new Socket(ip, port);
59 in = socket.getInputStream();
60 out = socket.getOutputStream();
61 } catch (IOException e) {
62 throw new EpsonProjectorException(e);
65 // Projectors with built in Ethernet listen on 3629, we must send the handshake to initialize the connection
66 if (port == DEFAULT_PORT) {
68 String response = sendMessage(ESC_VP_HANDSHAKE, 5000);
69 logger.debug("Response to initialisation of ESC/VP.net is: {}", response);
70 } catch (EpsonProjectorException e) {
71 logger.debug("Error within initialisation of ESC/VP.net: {}", e.getMessage());
77 public void disconnect() throws EpsonProjectorException {
78 OutputStream out = this.out;
81 logger.debug("Close tcp out stream");
84 } catch (IOException e) {
85 logger.debug("Error occurred when closing tcp out stream: {}", e.getMessage());
89 InputStream in = this.in;
91 logger.debug("Close tcp in stream");
94 } catch (IOException e) {
95 logger.debug("Error occurred when closing tcp in stream: {}", e.getMessage());
99 Socket socket = this.socket;
100 if (socket != null) {
101 logger.debug("Closing socket");
104 } catch (IOException e) {
105 logger.debug("Error occurred when closing tcp socket: {}", e.getMessage());
113 logger.debug("Closed");
117 public String sendMessage(String data, int timeout) throws EpsonProjectorException {
118 InputStream in = this.in;
119 OutputStream out = this.out;
121 if (in == null || out == null) {
129 // flush input stream
130 if (in.markSupported()) {
133 while (in.available() > 0) {
134 int availableBytes = in.available();
136 if (availableBytes > 0) {
137 byte[] tmpData = new byte[availableBytes];
138 in.read(tmpData, 0, availableBytes);
142 return sendMmsg(data, timeout);
146 } catch (IOException e) {
147 logger.debug("IO error occurred...reconnect and resend once: {}", e.getMessage());
152 return sendMmsg(data, timeout);
153 } catch (IOException e1) {
154 throw new EpsonProjectorException(e);
159 private String sendMmsg(String data, int timeout) throws IOException, EpsonProjectorException {
162 InputStream in = this.in;
163 OutputStream out = this.out;
165 if (in != null && out != null) {
166 out.write(data.getBytes(StandardCharsets.US_ASCII));
167 out.write("\r\n".getBytes(StandardCharsets.US_ASCII));
170 long startTime = System.currentTimeMillis();
171 long elapsedTime = 0;
173 while (elapsedTime < timeout) {
174 int availableBytes = in.available();
175 if (availableBytes > 0) {
176 byte[] tmpData = new byte[availableBytes];
177 int readBytes = in.read(tmpData, 0, availableBytes);
178 resp = resp.concat(new String(tmpData, 0, readBytes, StandardCharsets.US_ASCII));
180 if (resp.contains(":")) {
186 } catch (InterruptedException e) {
187 throw new EpsonProjectorException(e);
191 elapsedTime = System.currentTimeMillis() - startTime;