rusEfi console usability: auto-detect serial port

This commit is contained in:
rusefi 2019-08-14 22:40:12 -04:00
parent ec80aaffaa
commit bde6b65c9a
5 changed files with 152 additions and 5 deletions

View File

@ -0,0 +1,10 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Launcher Auto" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="com.rusefi.Launcher" />
<module name="ui" />
<option name="PROGRAM_PARAMETERS" value="auto" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@ -1,6 +1,7 @@
package com.rusefi;
import com.fathzer.soft.javaluator.DoubleEvaluator;
import com.rusefi.autodetect.PortDetector;
import com.rusefi.binaryprotocol.BinaryProtocol;
import com.rusefi.binaryprotocol.BinaryProtocolHolder;
import com.rusefi.config.generated.Fields;
@ -47,7 +48,7 @@ import static com.rusefi.ui.storage.PersistentConfiguration.getConfig;
* @see EngineSnifferPanel
*/
public class Launcher {
public static final int CONSOLE_VERSION = 20190809;
public static final int CONSOLE_VERSION = 20190814;
public static final String INPUT_FILES_PATH = "..";
private static final String TAB_INDEX = "main_tab";
protected static final String PORT_KEY = "port";
@ -301,6 +302,10 @@ public class Launcher {
System.exit(0);
}
/**
* rusEfi console entry point
* @see StartupFrame if no parameters specified
*/
public static void main(final String[] args) throws Exception {
String toolName = args.length == 0 ? null : args[0];
if (TOOL_NAME_COMPILE_FSIO_FILE.equalsIgnoreCase(toolName)) {
@ -364,8 +369,23 @@ public class Launcher {
boolean isBaudRateDefined = args.length > 1;
if (isBaudRateDefined)
PortHolder.BAUD_RATE = Integer.parseInt(args[1]);
String port = null;
if (isPortDefined)
port = args[0];
if (isPortDefined && port.toLowerCase().startsWith("auto")) {
String autoDetectedPort = PortDetector.autoDetectSerial();
if (autoDetectedPort == null) {
isPortDefined = false;
} else {
port = autoDetectedPort;
}
}
if (isPortDefined) {
new Launcher(args[0]);
new Launcher(port);
} else {
for (String p : SerialPortList.getPortNames())
MessagesCentral.getInstance().postMessage(Launcher.class, "Available port: " + p);

View File

@ -1,5 +1,6 @@
package com.rusefi;
import com.rusefi.autodetect.PortDetector;
import com.rusefi.io.LinkManager;
import com.rusefi.io.serial.PortHolder;
import com.rusefi.io.tcp.TcpConnector;
@ -45,6 +46,7 @@ public class StartupFrame {
private static final String LOGO = "logo.gif";
public static final String LINK_TEXT = "rusEfi (c) 2012-2019";
private static final String URI = "http://rusefi.com/?java_console";
private static final String AUTO_SERIAL = "Auto Serial";
private final JFrame frame;
private final Timer scanPortsTimes = new Timer(1000, new ActionListener() {
@ -122,9 +124,16 @@ public class StartupFrame {
connect.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
disposeFrameAndProceed();
PortHolder.BAUD_RATE = Integer.parseInt((String) comboSpeeds.getSelectedItem());
new Launcher(comboPorts.getSelectedItem().toString());
String selectedPort = comboPorts.getSelectedItem().toString();
if (AUTO_SERIAL.equals(selectedPort)) {
String autoDetectedPort = PortDetector.autoDetectPort(StartupFrame.this.frame);
if (autoDetectedPort == null)
return;
selectedPort = autoDetectedPort;
}
disposeFrameAndProceed();
new Launcher(selectedPort);
}
});
@ -230,7 +239,10 @@ public class StartupFrame {
@NotNull
private List<String> findAllAvailablePorts() {
List<String> ports = new ArrayList<>();
ports.addAll(Arrays.asList(SerialPortList.getPortNames()));
String[] serialPorts = SerialPortList.getPortNames();
if (serialPorts.length > 0 || serialPorts.length < 15)
ports.add(AUTO_SERIAL);
ports.addAll(Arrays.asList(serialPorts));
ports.addAll(TcpConnector.getAvailablePorts());
return ports;
}

View File

@ -0,0 +1,49 @@
package com.rusefi.autodetect;
import jssc.SerialPortList;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
/**
* (c) Andrey Belomutskiy 2013-2019
*/
public class PortDetector {
/**
* Connect to all serial ports and find out which one respond first
*/
public static String autoDetectSerial() {
String[] serialPorts = SerialPortList.getPortNames();
List<Thread> serialFinder = new ArrayList<>();
CountDownLatch portFound = new CountDownLatch(1);
AtomicReference<String> result = new AtomicReference<>();
for (String serialPort : serialPorts) {
Thread thread = new Thread(new SerialAutoChecker(serialPort, portFound, result));
serialFinder.add(thread);
thread.start();
}
try {
portFound.await(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
for (Thread thread : serialFinder)
thread.interrupt();
return result.get();
}
@Nullable
public static String autoDetectPort(JFrame parent) {
String autoDetectedPort = autoDetectSerial();
if (autoDetectedPort == null) {
JOptionPane.showMessageDialog(parent, "Failed to located device");
return null;
}
return autoDetectedPort;
}
}

View File

@ -0,0 +1,56 @@
package com.rusefi.autodetect;
import com.opensr5.Logger;
import com.rusefi.FileLog;
import com.rusefi.binaryprotocol.BinaryProtocol;
import com.rusefi.binaryprotocol.BinaryProtocolCommands;
import com.rusefi.binaryprotocol.IncomingDataBuffer;
import com.rusefi.config.generated.Fields;
import com.rusefi.io.IoStream;
import com.rusefi.io.serial.PortHolder;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import static com.rusefi.binaryprotocol.IoHelper.checkResponseCode;
class SerialAutoChecker implements Runnable {
private final String serialPort;
private final CountDownLatch portFound;
private final AtomicReference<String> result;
public SerialAutoChecker(String serialPort, CountDownLatch portFound, AtomicReference<String> result) {
this.serialPort = serialPort;
this.portFound = portFound;
this.result = result;
}
@Override
public void run() {
PortHolder.EstablishConnection establishConnection = new PortHolder.EstablishConnection(serialPort).invoke();
if (!establishConnection.isConnected())
return;
IoStream stream = establishConnection.getStream();
Logger logger = FileLog.LOGGER;
IncomingDataBuffer incomingData = new IncomingDataBuffer(logger);
stream.setInputListener(incomingData::addData);
try {
BinaryProtocol.sendPacket(new byte[]{BinaryProtocolCommands.COMMAND_HELLO}, logger, stream);
byte[] response = incomingData.getPacket(logger, "", false, System.currentTimeMillis());
if (!checkResponseCode(response, BinaryProtocolCommands.RESPONSE_OK))
return;
String message = new String(response, 1, response.length - 1);
System.out.println("Got " + message + " from " + serialPort);
if (message.startsWith(Fields.TS_SIGNATURE)) {
result.set(serialPort);
portFound.countDown();
}
} catch (IOException | InterruptedException ignore) {
return;
} finally {
stream.close();
}
}
}