[denonmarantz] Run the Telnet socket in a dedicated thread (#9511)
* Run the Telnet socket in a dedicated thread, not from the shared thread pool. Fixes #9494 Signed-off-by: Jan-Willem Veldhuis <jwveldhuis@gmail.com>
This commit is contained in:
parent
9d36c31d76
commit
d014ac6350
@ -29,9 +29,9 @@ import org.openhab.binding.denonmarantz.internal.connector.telnet.DenonMarantzTe
|
||||
public class DenonMarantzConnectorFactory {
|
||||
|
||||
public DenonMarantzConnector getConnector(DenonMarantzConfiguration config, DenonMarantzState state,
|
||||
ScheduledExecutorService scheduler, HttpClient httpClient) {
|
||||
ScheduledExecutorService scheduler, HttpClient httpClient, String thingUID) {
|
||||
if (config.isTelnet()) {
|
||||
return new DenonMarantzTelnetConnector(config, state, scheduler);
|
||||
return new DenonMarantzTelnetConnector(config, state, scheduler, thingUID);
|
||||
} else {
|
||||
return new DenonMarantzHttpConnector(config, state, scheduler, httpClient);
|
||||
}
|
||||
|
||||
@ -31,9 +31,9 @@ import org.slf4j.LoggerFactory;
|
||||
* @author Jeroen Idserda - Initial contribution (1.x Binding)
|
||||
* @author Jan-Willem Veldhuis - Refactored for 2.x
|
||||
*/
|
||||
public class DenonMarantzTelnetClient implements Runnable {
|
||||
public class DenonMarantzTelnetClientThread extends Thread {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(DenonMarantzTelnetClient.class);
|
||||
private Logger logger = LoggerFactory.getLogger(DenonMarantzTelnetClientThread.class);
|
||||
|
||||
private static final Integer RECONNECT_DELAY = 60000; // 1 minute
|
||||
|
||||
@ -43,8 +43,6 @@ public class DenonMarantzTelnetClient implements Runnable {
|
||||
|
||||
private DenonMarantzTelnetListener listener;
|
||||
|
||||
private boolean running = true;
|
||||
|
||||
private boolean connected = false;
|
||||
|
||||
private Socket socket;
|
||||
@ -53,7 +51,7 @@ public class DenonMarantzTelnetClient implements Runnable {
|
||||
|
||||
private BufferedReader in;
|
||||
|
||||
public DenonMarantzTelnetClient(DenonMarantzConfiguration config, DenonMarantzTelnetListener listener) {
|
||||
public DenonMarantzTelnetClientThread(DenonMarantzConfiguration config, DenonMarantzTelnetListener listener) {
|
||||
logger.debug("Denon listener created");
|
||||
this.config = config;
|
||||
this.listener = listener;
|
||||
@ -61,7 +59,7 @@ public class DenonMarantzTelnetClient implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (running) {
|
||||
while (!isInterrupted()) {
|
||||
if (!connected) {
|
||||
connectTelnetSocket();
|
||||
}
|
||||
@ -90,20 +88,21 @@ public class DenonMarantzTelnetClient implements Runnable {
|
||||
connected = false;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (!Thread.currentThread().isInterrupted()) {
|
||||
if (!isInterrupted()) {
|
||||
// only log if we don't stop this on purpose causing a SocketClosed
|
||||
logger.debug("Error in telnet connection ", e);
|
||||
}
|
||||
connected = false;
|
||||
listener.telnetClientConnected(false);
|
||||
}
|
||||
} while (running && connected);
|
||||
} while (!isInterrupted() && connected);
|
||||
}
|
||||
disconnect();
|
||||
logger.debug("Stopped client thread");
|
||||
}
|
||||
|
||||
public void sendCommand(String command) {
|
||||
if (out != null) {
|
||||
logger.debug("Sending command {}", command);
|
||||
try {
|
||||
out.write(command + '\r');
|
||||
out.flush();
|
||||
@ -116,7 +115,6 @@ public class DenonMarantzTelnetClient implements Runnable {
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
this.running = false;
|
||||
disconnect();
|
||||
}
|
||||
|
||||
@ -124,13 +122,14 @@ public class DenonMarantzTelnetClient implements Runnable {
|
||||
disconnect();
|
||||
int delay = 0;
|
||||
|
||||
while (this.running && (socket == null || !socket.isConnected())) {
|
||||
while (!isInterrupted() && (socket == null || !socket.isConnected())) {
|
||||
try {
|
||||
Thread.sleep(delay);
|
||||
logger.debug("Connecting to {}", config.getHost());
|
||||
|
||||
// Use raw socket instead of TelnetClient here because TelnetClient sends an extra newline char
|
||||
// after each write which causes the connection to become unresponsive.
|
||||
// Use raw socket instead of TelnetClient here because TelnetClient sends an
|
||||
// extra newline char after each write which causes the connection to become
|
||||
// unresponsive.
|
||||
socket = new Socket();
|
||||
socket.connect(new InetSocketAddress(config.getHost(), config.getTelnetPort()), TIMEOUT);
|
||||
socket.setKeepAlive(true);
|
||||
@ -141,6 +140,7 @@ public class DenonMarantzTelnetClient implements Runnable {
|
||||
|
||||
connected = true;
|
||||
listener.telnetClientConnected(true);
|
||||
logger.debug("Denon telnet client connected to {}", config.getHost());
|
||||
} catch (IOException e) {
|
||||
logger.debug("Cannot connect to {}", config.getHost(), e);
|
||||
listener.telnetClientConnected(false);
|
||||
@ -149,8 +149,6 @@ public class DenonMarantzTelnetClient implements Runnable {
|
||||
}
|
||||
delay = RECONNECT_DELAY;
|
||||
}
|
||||
|
||||
logger.debug("Denon telnet client connected to {}", config.getHost());
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
@ -46,7 +46,7 @@ public class DenonMarantzTelnetConnector extends DenonMarantzConnector implement
|
||||
|
||||
private static final BigDecimal NINETYNINE = new BigDecimal("99");
|
||||
|
||||
private DenonMarantzTelnetClient telnetClient;
|
||||
private DenonMarantzTelnetClientThread telnetClientThread;
|
||||
|
||||
private boolean displayNowplaying = false;
|
||||
|
||||
@ -54,13 +54,14 @@ public class DenonMarantzTelnetConnector extends DenonMarantzConnector implement
|
||||
|
||||
private Future<?> telnetStateRequest;
|
||||
|
||||
private Future<?> telnetRunnable;
|
||||
private String thingUID;
|
||||
|
||||
public DenonMarantzTelnetConnector(DenonMarantzConfiguration config, DenonMarantzState state,
|
||||
ScheduledExecutorService scheduler) {
|
||||
ScheduledExecutorService scheduler, String thingUID) {
|
||||
this.config = config;
|
||||
this.scheduler = scheduler;
|
||||
this.state = state;
|
||||
this.thingUID = thingUID;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -68,8 +69,9 @@ public class DenonMarantzTelnetConnector extends DenonMarantzConnector implement
|
||||
*/
|
||||
@Override
|
||||
public void connect() {
|
||||
telnetClient = new DenonMarantzTelnetClient(config, this);
|
||||
telnetRunnable = scheduler.submit(telnetClient);
|
||||
telnetClientThread = new DenonMarantzTelnetClientThread(config, this);
|
||||
telnetClientThread.setName("OH-binding-" + thingUID);
|
||||
telnetClientThread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -98,9 +100,12 @@ public class DenonMarantzTelnetConnector extends DenonMarantzConnector implement
|
||||
telnetStateRequest = null;
|
||||
}
|
||||
|
||||
if (telnetClient != null && !telnetRunnable.isDone()) {
|
||||
telnetRunnable.cancel(true);
|
||||
telnetClient.shutdown();
|
||||
if (telnetClientThread != null) {
|
||||
telnetClientThread.interrupt();
|
||||
// Invoke a shutdown after interrupting the thread to close the socket immediately,
|
||||
// otherwise the client keeps running until a line was received from the telnet connection
|
||||
telnetClientThread.shutdown();
|
||||
telnetClientThread = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -262,7 +267,7 @@ public class DenonMarantzTelnetConnector extends DenonMarantzConnector implement
|
||||
logger.warn("Trying to send empty command");
|
||||
return;
|
||||
}
|
||||
telnetClient.sendCommand(command);
|
||||
telnetClientThread.sendCommand(command);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -314,7 +314,8 @@ public class DenonMarantzHandler extends BaseThingHandler implements DenonMarant
|
||||
if (connector != null) {
|
||||
connector.dispose();
|
||||
}
|
||||
connector = connectorFactory.getConnector(config, denonMarantzState, scheduler, httpClient);
|
||||
connector = connectorFactory.getConnector(config, denonMarantzState, scheduler, httpClient,
|
||||
this.getThing().getUID().getAsString());
|
||||
connector.connect();
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user