/** * Copyright (c) 2010-2016 by the respective copyright holders. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.openhab.binding.denon.internal; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.net.SocketTimeoutException; import org.apache.commons.lang.StringUtils; import org.apache.commons.net.telnet.TelnetClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Manage telnet connection to the Denon Receiver * * @author Jeroen Idserda * @since 1.7.0 */ public class DenonListener extends Thread { private static final Logger logger = LoggerFactory.getLogger(DenonListener.class); private static final Integer RECONNECT_DELAY = 60000; // 1 minute private static final Integer TIMEOUT = 60000; // 1 minute private DenonConnectionProperties connection; private DenonUpdateReceivedCallback callback; private TelnetClient tc; private boolean running = true; private boolean connected = false; public DenonListener(DenonConnectionProperties connection, DenonUpdateReceivedCallback callback) { logger.debug("Denon listener created"); this.connection = connection; this.callback = callback; this.tc = createTelnetClient(); } @Override public void run() { while (running) { if (!connected) { connectTelnetClient(); } InputStream is = tc.getInputStream(); PrintWriter out = new PrintWriter(tc.getOutputStream(), true); int readCount = 0; byte[] buffer = new byte[4096]; do { try { readCount = is.read(buffer); if (readCount > -1) { String line = StringUtils.trim(new String(buffer, 0, readCount)); if (!StringUtils.isBlank(line)) { logger.trace("Received from {}: {}", connection.getHost(), line); callback.updateReceived(line); } } else { throw new IOException("Telnet connection disconnected"); } } catch (SocketTimeoutException e) { logger.trace("Socket timeout"); // Disconnects are not always detected unless you write to the socket. out.print(" "); out.flush(); } catch (IOException e) { callback.listenerDisconnected(); logger.debug("Error in telnet connection", e); connected = false; } } while (running && connected); } } public void shutdown() { this.running = false; disconnect(); } private void connectTelnetClient() { disconnect(); int delay = 0; while (!tc.isConnected()) { try { Thread.sleep(delay); logger.debug("Connecting to {}", connection.getHost()); tc.connect(connection.getHost(), connection.getTelnetPort()); callback.listenerConnected(); connected = true; } catch (IOException e) { logger.debug("Cannot connect to {}", connection.getHost(), e); } catch (InterruptedException e) { logger.debug("Interrupted while connecting to {}", connection.getHost(), e); } delay = RECONNECT_DELAY; } logger.debug("Denon telnet client connected to {}", connection.getHost()); } private void disconnect() { if (tc != null) { try { this.tc.disconnect(); } catch (IOException e) { logger.debug("Error while disconnecting telnet client", e); } } } private TelnetClient createTelnetClient() { TelnetClient tc = new TelnetClient(); tc.setDefaultTimeout(TIMEOUT); return tc; } }