2 * Copyright (c) 2010-2024 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.denonmarantz.internal.connector.telnet;
15 import java.io.BufferedReader;
16 import java.io.IOException;
17 import java.io.InputStreamReader;
18 import java.io.OutputStreamWriter;
19 import java.net.InetSocketAddress;
20 import java.net.Socket;
21 import java.net.SocketTimeoutException;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.openhab.binding.denonmarantz.internal.config.DenonMarantzConfiguration;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
29 * Manage telnet connection to the Denon/Marantz Receiver
31 * @author Jeroen Idserda - Initial contribution (1.x Binding)
32 * @author Jan-Willem Veldhuis - Refactored for 2.x
34 public class DenonMarantzTelnetClientThread extends Thread {
36 private Logger logger = LoggerFactory.getLogger(DenonMarantzTelnetClientThread.class);
38 private static final Integer RECONNECT_DELAY = 60000; // 1 minute
40 private static final Integer TIMEOUT = 60000; // 1 minute
42 private DenonMarantzConfiguration config;
44 private DenonMarantzTelnetListener listener;
46 private boolean connected = false;
48 private Socket socket;
50 private OutputStreamWriter out;
52 private @Nullable BufferedReader in;
54 public DenonMarantzTelnetClientThread(DenonMarantzConfiguration config, DenonMarantzTelnetListener listener) {
55 logger.debug("Denon listener created");
57 this.listener = listener;
62 while (!isInterrupted()) {
64 connectTelnetSocket();
70 BufferedReader in = this.in;
75 logger.debug("No more data read from client. Disconnecting..");
76 listener.telnetClientConnected(false);
80 logger.trace("Received from {}: {}", config.getHost(), line);
81 if (!line.isBlank()) {
82 listener.receivedLine(line);
84 } catch (SocketTimeoutException e) {
85 logger.trace("Socket timeout");
86 // Disconnects are not always detected unless you write to the socket.
90 } catch (IOException e2) {
91 logger.debug("Error writing to socket");
94 } catch (IOException e) {
95 if (!isInterrupted()) {
96 // only log if we don't stop this on purpose causing a SocketClosed
97 logger.debug("Error in telnet connection ", e);
100 listener.telnetClientConnected(false);
102 } while (!isInterrupted() && connected);
105 logger.debug("Stopped client thread");
108 public void sendCommand(String command) {
111 out.write(command + '\r');
113 } catch (IOException e) {
114 logger.debug("Error sending command", e);
117 logger.debug("Cannot send command, no telnet connection");
121 public void shutdown() {
125 private void connectTelnetSocket() {
129 while (!isInterrupted() && (socket == null || !socket.isConnected())) {
132 logger.debug("Connecting to {}", config.getHost());
134 // Use raw socket instead of TelnetClient here because TelnetClient sends an
135 // extra newline char after each write which causes the connection to become
137 socket = new Socket();
138 socket.connect(new InetSocketAddress(config.getHost(), config.getTelnetPort()), TIMEOUT);
139 socket.setKeepAlive(true);
140 socket.setSoTimeout(TIMEOUT);
142 in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
143 out = new OutputStreamWriter(socket.getOutputStream(), "UTF-8");
146 listener.telnetClientConnected(true);
147 logger.debug("Denon telnet client connected to {}", config.getHost());
148 } catch (IOException e) {
149 logger.debug("Cannot connect to {}", config.getHost(), e);
150 listener.telnetClientConnected(false);
151 } catch (InterruptedException e) {
152 logger.debug("Interrupted while connecting to {}", config.getHost(), e);
153 Thread.currentThread().interrupt();
155 delay = RECONNECT_DELAY;
159 public boolean isConnected() {
163 private void disconnect() {
164 if (socket != null) {
165 logger.debug("Disconnecting socket");
168 } catch (IOException e) {
169 logger.debug("Error while disconnecting telnet client", e);
174 listener.telnetClientConnected(false);