diff --git a/java_console/autotest/src/com/rusefi/AutoTest.java b/java_console/autotest/src/com/rusefi/AutoTest.java index 454aa9edb4..c43871e26b 100644 --- a/java_console/autotest/src/com/rusefi/AutoTest.java +++ b/java_console/autotest/src/com/rusefi/AutoTest.java @@ -314,7 +314,7 @@ public class AutoTest { } private static void sendComplexCommand(String command) { - sendCommand(command, COMPLEX_COMMAND_RETRY, IoUtil.CMD_TIMEOUT); + sendCommand(command, COMPLEX_COMMAND_RETRY, Timeouts.CMD_TIMEOUT); } private static void assertWaveNull(WaveChart chart, String key) { diff --git a/java_console/autotest/src/com/rusefi/IoUtil.java b/java_console/autotest/src/com/rusefi/IoUtil.java index e9f6c98463..d251bcb864 100644 --- a/java_console/autotest/src/com/rusefi/IoUtil.java +++ b/java_console/autotest/src/com/rusefi/IoUtil.java @@ -19,7 +19,6 @@ import static com.rusefi.waves.WaveReport.isCloseEnough; * 3/19/14. */ public class IoUtil { - protected static final int CMD_TIMEOUT = 20; /** * Send a command and wait for the confirmation @@ -27,7 +26,7 @@ public class IoUtil { * @throws IllegalStateException if command was not confirmed */ static void sendCommand(String command) { - sendCommand(command, CommandQueue.DEFAULT_TIMEOUT, CMD_TIMEOUT); + sendCommand(command, CommandQueue.DEFAULT_TIMEOUT, Timeouts.CMD_TIMEOUT); } static void sendCommand(String command, int retryTimeoutMs, int totalTimeoutSeconds) { diff --git a/java_console/io/src/com/rusefi/Timeouts.java b/java_console/io/src/com/rusefi/Timeouts.java new file mode 100644 index 0000000000..6bbf8084f7 --- /dev/null +++ b/java_console/io/src/com/rusefi/Timeouts.java @@ -0,0 +1,16 @@ +package com.rusefi; + +/** + * All i/o timeouts in one place + */ +public interface Timeouts { + int SECOND = 1000; + + int COMMAND_TIMEOUT_SEC = 10; // seconds + + int RESTART_DELAY = 20 * SECOND; + + int BINARY_IO_TIMEOUT = 10 * SECOND; + int CMD_TIMEOUT = 20; +} + diff --git a/java_console/io/src/com/rusefi/binaryprotocol/BinaryProtocol.java b/java_console/io/src/com/rusefi/binaryprotocol/BinaryProtocol.java index 45d1e19153..1abad6e32a 100644 --- a/java_console/io/src/com/rusefi/binaryprotocol/BinaryProtocol.java +++ b/java_console/io/src/com/rusefi/binaryprotocol/BinaryProtocol.java @@ -3,6 +3,7 @@ package com.rusefi.binaryprotocol; import com.rusefi.ConfigurationImage; import com.rusefi.ConfigurationImageDiff; import com.rusefi.Logger; +import com.rusefi.Timeouts; import com.rusefi.core.Pair; import com.rusefi.io.DataListener; import com.rusefi.io.serial.SerialPortReader; @@ -24,7 +25,6 @@ public class BinaryProtocol { private static final byte RESPONSE_BURN_OK = 0x04; private static final byte RESPONSE_COMMAND_OK = 0x07; private static final int SWITCH_TO_BINARY_RESPONSE = 0xA7E; - private static final int TIMEOUT = 30 * 1000; private final Logger logger; private final SerialPort serialPort; @@ -84,13 +84,18 @@ public class BinaryProtocol { waitForBytes(2, start); int response = cbb.getShort(); if (response != SWITCH_TO_BINARY_RESPONSE) { - logger.error("Unexpected response, re-trying"); + logger.error(String.format("Unexpected response [%x], re-trying", response)); continue; } } - } catch (SerialPortException | EOFException | InterruptedException e) { + } catch (SerialPortException | EOFException e) { + close(); + System.out.println("exception: " + e); + return; + } catch (InterruptedException e) { throw new IllegalStateException(e); } + logger.info("Switched to binary protocol"); break; } } @@ -102,6 +107,12 @@ public class BinaryProtocol { logger.error("Unexpected pending data: " + pending); cbb.get(new byte[pending]); } + try { + serialPort.purgePort(SerialPort.PURGE_RXCLEAR | SerialPort.PURGE_TXCLEAR); + } catch (SerialPortException e) { + logger.info("Error while purge: " + e); + close(); + } } } @@ -228,6 +239,8 @@ public class BinaryProtocol { * @return null in case of IO issues */ public byte[] exchange(byte[] packet) { + if (isClosed) + return null; dropPending(); try { sendCrcPacket(packet); @@ -236,11 +249,20 @@ public class BinaryProtocol { throw new IllegalStateException(e); } catch (SerialPortException | EOFException e) { logger.error("exchange failed: " + e); - isClosed = true; + close(); return null; } } + private void close() { + isClosed = true; + try { + serialPort.closePort(); + } catch (SerialPortException e) { + logger.error("Error closing port: " + e); + } + } + public void writeData(byte[] content, Integer offset, int size, Logger logger) throws SerialPortException, EOFException, InterruptedException { if (size > BLOCKING_FACTOR) { writeData(content, offset, BLOCKING_FACTOR, logger); @@ -258,7 +280,8 @@ public class BinaryProtocol { System.arraycopy(content, offset, packet, 7, size); - while (true) { + long start = System.currentTimeMillis(); + while (!isClosed && (System.currentTimeMillis() - start < Timeouts.BINARY_IO_TIMEOUT)) { byte[] response = exchange(packet); if (!checkResponseCode(response, RESPONSE_OK) || response.length != 1) { logger.error("writeData: Something is wrong, retrying..."); @@ -307,7 +330,7 @@ public class BinaryProtocol { logger.info("Waiting for " + count + " byte(s)"); synchronized (cbb) { while (cbb.length() < count) { - int timeout = (int) (start + TIMEOUT - System.currentTimeMillis()); + int timeout = (int) (start + Timeouts.BINARY_IO_TIMEOUT - System.currentTimeMillis()); if (timeout <= 0) { return true; // timeout. Sad face. } @@ -354,13 +377,15 @@ public class BinaryProtocol { command[0] = 'E'; System.arraycopy(asBytes, 0, command, 1, asBytes.length); - while (true) { + long start = System.currentTimeMillis(); + while (!isClosed && (System.currentTimeMillis() - start < Timeouts.BINARY_IO_TIMEOUT)) { byte[] response = exchange(command); if (!checkResponseCode(response, RESPONSE_COMMAND_OK) || response.length != 1) { continue; } return false; } + return true; } public String requestText() { diff --git a/java_console/io/src/com/rusefi/io/LinkManager.java b/java_console/io/src/com/rusefi/io/LinkManager.java index d8d0bd9332..6ef9ebe9b5 100644 --- a/java_console/io/src/com/rusefi/io/LinkManager.java +++ b/java_console/io/src/com/rusefi/io/LinkManager.java @@ -54,7 +54,15 @@ public class LinkManager { public static final LinkedBlockingQueue COMMUNICATION_QUEUE = new LinkedBlockingQueue<>(); public static final ExecutorService COMMUNICATION_EXECUTOR = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, - COMMUNICATION_QUEUE); + COMMUNICATION_QUEUE, + new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread t = Executors.defaultThreadFactory().newThread(r); + t.setName("communication executor");; + return t; + } + }); public static EngineState engineState = new EngineState(new EngineState.EngineStateListenerImpl() { @Override public void beforeLine(String fullLine) { diff --git a/java_console/io/src/com/rusefi/io/serial/PortHolder.java b/java_console/io/src/com/rusefi/io/serial/PortHolder.java index bf66ba6a37..5527ef518d 100644 --- a/java_console/io/src/com/rusefi/io/serial/PortHolder.java +++ b/java_console/io/src/com/rusefi/io/serial/PortHolder.java @@ -2,6 +2,7 @@ package com.rusefi.io.serial; import com.rusefi.FileLog; import com.rusefi.Logger; +import com.rusefi.Timeouts; import com.rusefi.binaryprotocol.BinaryProtocol; import com.rusefi.core.MessagesCentral; import com.rusefi.io.CommandQueue; @@ -24,9 +25,6 @@ public class PortHolder { // private static final int BAUD_RATE = 8 * 115200;// 921600; // private static final int BAUD_RATE = 2 * 115200; private static final int BAUD_RATE = 115200; - private static final int SECOND = 1000; - private static final int MINUTE = 60 * SECOND; - private static final int COMMAND_TIMEOUT_SEC = 10; // seconds private static PortHolder instance = new PortHolder(); private final Object portLock = new Object(); @@ -85,6 +83,9 @@ public class PortHolder { if (bp.isClosed) return false; + if (!LinkManager.COMMUNICATION_QUEUE.isEmpty()) { + System.out.println("Current queue: " + LinkManager.COMMUNICATION_QUEUE.size()); + } Runnable textPull = new Runnable() { @Override public void run() { @@ -166,7 +167,7 @@ public class PortHolder { }); try { - f.get(COMMAND_TIMEOUT_SEC, TimeUnit.SECONDS); + f.get(Timeouts.COMMAND_TIMEOUT_SEC, TimeUnit.SECONDS); } catch (ExecutionException e) { throw new IllegalStateException(e); } catch (TimeoutException e) { diff --git a/java_console/ui/src/com/rusefi/ui/ConnectionWatchdog.java b/java_console/ui/src/com/rusefi/ui/ConnectionWatchdog.java index 227d77fb48..17b4c7a932 100644 --- a/java_console/ui/src/com/rusefi/ui/ConnectionWatchdog.java +++ b/java_console/ui/src/com/rusefi/ui/ConnectionWatchdog.java @@ -1,5 +1,6 @@ package com.rusefi.ui; +import com.rusefi.Timeouts; import com.rusefi.core.EngineTimeListener; import com.rusefi.io.LinkManager; @@ -8,16 +9,12 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class ConnectionWatchdog { - /** - * 10 seconds - */ - private static final int RESTART_DELAY = 10000; private ConnectionWatchdog() { } public static void start() { - final Timer reconnectTimer = new Timer(RESTART_DELAY, new ActionListener() { + final Timer reconnectTimer = new Timer(Timeouts.RESTART_DELAY, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { LinkManager.restart();