diff --git a/java_console/io/src/main/java/com/rusefi/autodetect/PortDetector.java b/java_console/io/src/main/java/com/rusefi/autodetect/PortDetector.java index e3c41a9e65..af29b0f1e4 100644 --- a/java_console/io/src/main/java/com/rusefi/autodetect/PortDetector.java +++ b/java_console/io/src/main/java/com/rusefi/autodetect/PortDetector.java @@ -24,16 +24,21 @@ public class PortDetector { private static final NamedThreadFactory AUTO_DETECT_PORT = new NamedThreadFactory("AutoDetectPort"); public static final String AUTO = "auto"; + public enum DetectorMode { + DETECT_TS, + DETECT_ELM327, + } + /** * Connect to all serial ports and find out which one respond first * @param callback * @return port name on which rusEFI was detected or null if none */ @NotNull - public static SerialAutoChecker.AutoDetectResult autoDetectSerial(Function callback) { + public static SerialAutoChecker.AutoDetectResult autoDetectSerial(Function callback, PortDetector.DetectorMode mode) { String rusEfiAddress = System.getProperty("rusefi.address"); if (rusEfiAddress != null) { - return getSignatureFromPorts(callback, new String[] {rusEfiAddress}); + return getSignatureFromPorts(mode, callback, new String[] {rusEfiAddress}); } String[] serialPorts = getPortNames(); if (serialPorts.length == 0) { @@ -41,11 +46,11 @@ public class PortDetector { return new SerialAutoChecker.AutoDetectResult(null, null); } log.info("Trying " + Arrays.toString(serialPorts)); - return getSignatureFromPorts(callback, serialPorts); + return getSignatureFromPorts(mode, callback, serialPorts); } @NotNull - private static SerialAutoChecker.AutoDetectResult getSignatureFromPorts(Function callback, String[] serialPorts) { + private static SerialAutoChecker.AutoDetectResult getSignatureFromPorts(DetectorMode mode, Function callback, String[] serialPorts) { List serialFinder = new ArrayList<>(); CountDownLatch portFound = new CountDownLatch(1); AtomicReference result = new AtomicReference<>(); @@ -53,7 +58,7 @@ public class PortDetector { Thread thread = AUTO_DETECT_PORT.newThread(new Runnable() { @Override public void run() { - new SerialAutoChecker(serialPort, portFound).openAndCheckResponse(result, callback); + new SerialAutoChecker(mode, serialPort, portFound).openAndCheckResponse(result, callback); } @Override @@ -88,6 +93,10 @@ public class PortDetector { return autoDetectResult; } + public static SerialAutoChecker.AutoDetectResult autoDetectSerial(Function callback) { + return autoDetectSerial(callback, PortDetector.DetectorMode.DETECT_TS); + } + private static String[] getPortNames() { // long now = System.currentTimeMillis(); String[] portNames = LinkManager.getCommPorts(); diff --git a/java_console/io/src/main/java/com/rusefi/autodetect/SerialAutoChecker.java b/java_console/io/src/main/java/com/rusefi/autodetect/SerialAutoChecker.java index c9a67299ee..72b9491e3f 100644 --- a/java_console/io/src/main/java/com/rusefi/autodetect/SerialAutoChecker.java +++ b/java_console/io/src/main/java/com/rusefi/autodetect/SerialAutoChecker.java @@ -4,6 +4,7 @@ import com.devexperts.logging.Logging; import com.rusefi.binaryprotocol.IncomingDataBuffer; import com.rusefi.config.generated.Fields; import com.rusefi.io.IoStream; +import com.rusefi.io.can.Elm327Connector; import com.rusefi.io.commands.HelloCommand; import com.rusefi.io.serial.SerialIoStreamJSerialComm; import org.jetbrains.annotations.Nullable; @@ -17,15 +18,23 @@ import static com.rusefi.binaryprotocol.IoHelper.checkResponseCode; public class SerialAutoChecker { private final static Logging log = Logging.getLogging(SerialAutoChecker.class); + private final PortDetector.DetectorMode mode; private final String serialPort; private final CountDownLatch portFound; - public SerialAutoChecker(String serialPort, CountDownLatch portFound) { + public SerialAutoChecker(PortDetector.DetectorMode mode, String serialPort, CountDownLatch portFound) { + this.mode = mode; this.serialPort = serialPort; this.portFound = portFound; } public String checkResponse(IoStream stream, Function callback) { + if (mode == PortDetector.DetectorMode.DETECT_ELM327) { + if (Elm327Connector.checkConnection(serialPort, SerialIoStreamJSerialComm.openPort(serialPort))) { + return serialPort; + } + return null; + } IncomingDataBuffer incomingData = stream.getDataBuffer(); try { HelloCommand.send(stream); diff --git a/java_console/io/src/main/java/com/rusefi/io/can/Elm327Connector.java b/java_console/io/src/main/java/com/rusefi/io/can/Elm327Connector.java index 3760ce222d..1cebd363ef 100644 --- a/java_console/io/src/main/java/com/rusefi/io/can/Elm327Connector.java +++ b/java_console/io/src/main/java/com/rusefi/io/can/Elm327Connector.java @@ -2,7 +2,6 @@ package com.rusefi.io.can; import com.devexperts.logging.Logging; import com.opensr5.io.DataListener; -import com.romraider.util.HexUtil; import com.rusefi.io.IoStream; import com.rusefi.io.serial.BaudRateHolder; import com.rusefi.io.serial.SerialIoStreamJSerialComm; @@ -12,11 +11,9 @@ import com.rusefi.io.tcp.TcpConnector; import java.io.Closeable; import java.io.IOException; -import java.lang.Thread; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -87,9 +84,9 @@ public class Elm327Connector implements Closeable, DataListener { } - public static boolean checkConnection(String serialPort) { + public static boolean checkConnection(String serialPort, IoStream stream) { Elm327Connector con = new Elm327Connector(); - boolean found = con.initConnection(serialPort); + boolean found = con.initConnection(serialPort, stream); con.close(); return found; } @@ -97,7 +94,7 @@ public class Elm327Connector implements Closeable, DataListener { public void start(String serialPort) { log.info("* Elm327.start()"); - if (initConnection(serialPort)) { + if (initConnection(serialPort, SerialIoStreamJSerialComm.openPort(serialPort))) { // reset to defaults sendCommand("ATD", "OK"); @@ -210,18 +207,18 @@ public class Elm327Connector implements Closeable, DataListener { /////////////////////////////////////////////////////// - private boolean initConnection(String serialPort) { + private boolean initConnection(String msg, IoStream stream) { // todo: this seems like a hack-ish way? Shouldn't be openPort(port, baudrate)? BaudRateHolder.INSTANCE.baudRate = ELM327_DEFAULT_BAUDRATE; - this.stream = SerialIoStreamJSerialComm.openPort(serialPort); + this.stream = stream; this.stream.setInputListener(this); if (sendCommand("ATZ", "ELM327 v[0-9]+\\.[0-9]+", BIG_TIMEOUT) != null) { - log.info("ELM DETECTED on " + serialPort + "!"); + log.info("ELM DETECTED on " + msg + "!"); return true; } - log.info("ELM NOT FOUND on " + serialPort + "!"); + log.info("ELM NOT FOUND on " + msg + "!"); return false; } diff --git a/java_console/io/src/main/java/com/rusefi/io/can/HexUtil.java b/java_console/io/src/main/java/com/rusefi/io/can/HexUtil.java new file mode 100644 index 0000000000..24582b6b1a --- /dev/null +++ b/java_console/io/src/main/java/com/rusefi/io/can/HexUtil.java @@ -0,0 +1,43 @@ +package com.rusefi.io.can; + +public class HexUtil { + public static byte[] asBytes(String hex) { + if (hex.indexOf(' ') >= 0) { + hex = hex.replaceAll(" ", ""); + } + if (hex.startsWith("0x")) { + hex = hex.substring(2); + } + return hexToBytes(hex); + } + + private static byte[] hexToBytes(String s) { + return hexToBytes(s, 0); + } + + private static byte[] hexToBytes(String s, int off) { + byte[] bs = new byte[off + (1 + s.length()) / 2]; + hexToBytes(s, bs, off); + return bs; + } + + private static void hexToBytes(String s, byte[] out, int off) throws NumberFormatException, IndexOutOfBoundsException { + int slen = s.length(); + if ((slen % 2) != 0) { + s = '0' + s; + } + if (out.length < off + slen / 2) { + throw new IndexOutOfBoundsException("Output buffer too small for input (" + out.length + "<" + off + slen / 2 + ")"); + } + // Safe to assume the string is even length + byte b1, b2; + for (int i = 0; i < slen; i += 2) { + b1 = (byte) Character.digit(s.charAt(i), 16); + b2 = (byte) Character.digit(s.charAt(i + 1), 16); + if ((b1 < 0) || (b2 < 0)) { + throw new NumberFormatException(); + } + out[off + i / 2] = (byte) (b1 << 4 | b2); + } + } +} diff --git a/java_console/ui/src/main/java/com/rusefi/maintenance/DfuFlasher.java b/java_console/ui/src/main/java/com/rusefi/maintenance/DfuFlasher.java index b96064541c..dfdf6b2c2c 100644 --- a/java_console/ui/src/main/java/com/rusefi/maintenance/DfuFlasher.java +++ b/java_console/ui/src/main/java/com/rusefi/maintenance/DfuFlasher.java @@ -72,7 +72,7 @@ public class DfuFlasher { wnd.append("Using selected " + port + "\n"); IoStream stream = SerialIoStreamJSerialComm.openPort(port); AtomicReference signature = new AtomicReference<>(); - new SerialAutoChecker(port, new CountDownLatch(1)).checkResponse(stream, new Function() { + new SerialAutoChecker(PortDetector.DetectorMode.DETECT_TS, port, new CountDownLatch(1)).checkResponse(stream, new Function() { @Override public Void apply(SerialAutoChecker.CallbackContext callbackContext) { signature.set(callbackContext.getSignature()); diff --git a/java_console/ui/src/main/java/com/rusefi/tools/ConsoleTools.java b/java_console/ui/src/main/java/com/rusefi/tools/ConsoleTools.java index 71c8bfeb5b..353514e126 100644 --- a/java_console/ui/src/main/java/com/rusefi/tools/ConsoleTools.java +++ b/java_console/ui/src/main/java/com/rusefi/tools/ConsoleTools.java @@ -65,6 +65,7 @@ public class ConsoleTools { registerTool("network_connector", strings -> NetworkConnectorStartup.start(), "Connect your rusEFI ECU to rusEFI Online"); registerTool("network_authenticator", strings -> LocalApplicationProxy.start(), "rusEFI Online Authenticator"); + registerTool("elm327_connector", strings -> Elm327ConnectorStartup.start(), "Connect your rusEFI ECU using ELM327 CAN-bus adapter"); registerTool("print_auth_token", args -> printAuthToken(), "Print current rusEFI Online authentication token."); registerTool("print_vehicle_token", args -> printVehicleToken(), "Prints vehicle access token."); diff --git a/java_console/ui/src/main/java/com/rusefi/tools/Elm327ConnectorStartup.java b/java_console/ui/src/main/java/com/rusefi/tools/Elm327ConnectorStartup.java index cf66efee8e..10d88be7be 100644 --- a/java_console/ui/src/main/java/com/rusefi/tools/Elm327ConnectorStartup.java +++ b/java_console/ui/src/main/java/com/rusefi/tools/Elm327ConnectorStartup.java @@ -15,7 +15,7 @@ public class Elm327ConnectorStartup { return; } - (new Elm327Connector()).start(autoDetectedPort); + new Elm327Connector().start(autoDetectedPort); log.info("Running Elm327 connector for " + autoDetectedPort); } }