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 3263cde93b..e3c41a9e65 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 @@ -22,6 +22,7 @@ public class PortDetector { private final static Logging log = Logging.getLogging(PortDetector.class); private static final NamedThreadFactory AUTO_DETECT_PORT = new NamedThreadFactory("AutoDetectPort"); + public static final String AUTO = "auto"; /** * Connect to all serial ports and find out which one respond first @@ -111,6 +112,6 @@ public class PortDetector { } public static boolean isAutoPort(String port) { - return port.toLowerCase().startsWith("auto"); + return port.toLowerCase().startsWith(AUTO); } } diff --git a/java_console/io/src/main/java/com/rusefi/io/DfuHelper.java b/java_console/io/src/main/java/com/rusefi/io/DfuHelper.java index d583a97ea9..ef2c5a35fb 100644 --- a/java_console/io/src/main/java/com/rusefi/io/DfuHelper.java +++ b/java_console/io/src/main/java/com/rusefi/io/DfuHelper.java @@ -6,6 +6,7 @@ import com.rusefi.SignatureHelper; import com.rusefi.autoupdate.Autoupdate; import com.rusefi.binaryprotocol.BinaryProtocol; import com.rusefi.config.generated.Fields; +import com.rusefi.ui.StatusConsumer; import javax.swing.*; import java.io.IOException; @@ -16,7 +17,7 @@ import static com.rusefi.binaryprotocol.BinaryProtocol.sleep; public class DfuHelper { private static final String PREFIX = "rusefi_bundle"; - public static void sendDfuRebootCommand(IoStream stream, StringBuilder messages) { + public static void sendDfuRebootCommand(IoStream stream, StatusConsumer messages) { byte[] command = BinaryProtocol.getTextCommandBytes(Fields.CMD_REBOOT_DFU); try { stream.sendPacket(command); @@ -27,7 +28,7 @@ public class DfuHelper { } } - public static boolean sendDfuRebootCommand(JComponent parent, String signature, IoStream stream, StringBuilder messages) { + public static boolean sendDfuRebootCommand(JComponent parent, String signature, IoStream stream, StatusConsumer messages) { RusEfiSignature s = SignatureHelper.parse(signature); String bundleName = Autoupdate.readBundleFullName(); if (bundleName != null && s != null) { diff --git a/java_console/ui/src/main/java/com/rusefi/ui/StatusConsumer.java b/java_console/io/src/main/java/com/rusefi/ui/StatusConsumer.java similarity index 76% rename from java_console/ui/src/main/java/com/rusefi/ui/StatusConsumer.java rename to java_console/io/src/main/java/com/rusefi/ui/StatusConsumer.java index a911fff07d..45154a6827 100644 --- a/java_console/ui/src/main/java/com/rusefi/ui/StatusConsumer.java +++ b/java_console/io/src/main/java/com/rusefi/ui/StatusConsumer.java @@ -2,4 +2,6 @@ package com.rusefi.ui; public interface StatusConsumer { void appendMsg(String s); + + void append(String s); } 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 e392a721b7..3837d7fa17 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 @@ -11,6 +11,7 @@ import com.rusefi.io.IoStream; import com.rusefi.io.serial.SerialIoStreamJSerialComm; import com.rusefi.ui.StatusWindow; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.io.BufferedReader; @@ -40,46 +41,11 @@ public class DfuFlasher { return; } String port = selectedItem.toString(); - StringBuilder messages = new StringBuilder(); - AtomicBoolean isSignatureValidated = new AtomicBoolean(true); - if (!PortDetector.isAutoPort(port)) { - messages.append("Using selected " + port + "\n"); - IoStream stream = SerialIoStreamJSerialComm.openPort(port); - AtomicReference signature = new AtomicReference<>(); - new SerialAutoChecker(port, new CountDownLatch(1)).checkResponse(stream, new Function() { - @Override - public Void apply(SerialAutoChecker.CallbackContext callbackContext) { - signature.set(callbackContext.getSignature()); - return null; - } - }); - if (signature.get() == null) { - JOptionPane.showMessageDialog(ConsoleUI.getFrame(), "rusEFI has not responded on selected " + port + "\n" + - "Maybe try automatic serial port detection?"); - return; - } - boolean isSignatureValidatedLocal = DfuHelper.sendDfuRebootCommand(parent, signature.get(), stream, messages); - isSignatureValidated.set(isSignatureValidatedLocal); - } else { - messages.append("Auto-detecting port...\n"); - // instead of opening the just-detected port we execute the command using the same stream we used to discover port - // it's more reliable this way - port = PortDetector.autoDetectSerial(callbackContext -> { - boolean isSignatureValidatedLocal = DfuHelper.sendDfuRebootCommand(parent, callbackContext.getSignature(), callbackContext.getStream(), messages); - isSignatureValidated.set(isSignatureValidatedLocal); - return null; - }).getSerialPort(); - if (port == null) { - JOptionPane.showMessageDialog(ConsoleUI.getFrame(), "rusEFI serial port not detected"); - return; - } else { - messages.append("Detected rusEFI on " + port + "\n"); - } - } - StatusWindow wnd = new StatusWindow(); - wnd.showFrame(appendBundleName("DFU status " + Launcher.CONSOLE_VERSION)); - wnd.appendMsg(messages.toString()); + StatusWindow wnd = createStatusWindow(); + + AtomicBoolean isSignatureValidated = rebootToDfu(parent, port, wnd); + if (isSignatureValidated == null) return; if (isSignatureValidated.get()) { if (!ProgramSelector.IS_WIN) { wnd.appendMsg("Switched to DFU mode!"); @@ -95,9 +61,55 @@ public class DfuFlasher { } } - public static void runDfuProgramming() { + @Nullable + public static AtomicBoolean rebootToDfu(JComponent parent, String port, StatusWindow wnd) { + AtomicBoolean isSignatureValidated = new AtomicBoolean(true); + if (!PortDetector.isAutoPort(port)) { + 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() { + @Override + public Void apply(SerialAutoChecker.CallbackContext callbackContext) { + signature.set(callbackContext.getSignature()); + return null; + } + }); + if (signature.get() == null) { + JOptionPane.showMessageDialog(ConsoleUI.getFrame(), "rusEFI has not responded on selected " + port + "\n" + + "Maybe try automatic serial port detection?"); + return null; + } + boolean isSignatureValidatedLocal = DfuHelper.sendDfuRebootCommand(parent, signature.get(), stream, wnd); + isSignatureValidated.set(isSignatureValidatedLocal); + } else { + wnd.append("Auto-detecting port...\n"); + // instead of opening the just-detected port we execute the command using the same stream we used to discover port + // it's more reliable this way + port = PortDetector.autoDetectSerial(callbackContext -> { + boolean isSignatureValidatedLocal = DfuHelper.sendDfuRebootCommand(parent, callbackContext.getSignature(), callbackContext.getStream(), wnd); + isSignatureValidated.set(isSignatureValidatedLocal); + return null; + }).getSerialPort(); + if (port == null) { + JOptionPane.showMessageDialog(ConsoleUI.getFrame(), "rusEFI serial port not detected"); + return null; + } else { + wnd.append("Detected rusEFI on " + port + "\n"); + } + } + return isSignatureValidated; + } + + @NotNull + protected static StatusWindow createStatusWindow() { StatusWindow wnd = new StatusWindow(); wnd.showFrame(appendBundleName("DFU status " + Launcher.CONSOLE_VERSION)); + return wnd; + } + + public static void runDfuProgramming() { + StatusWindow wnd = createStatusWindow(); ExecHelper.submitAction(() -> executeDFU(wnd), DfuFlasher.class + " thread"); } diff --git a/java_console/ui/src/main/java/com/rusefi/maintenance/ProgramSelector.java b/java_console/ui/src/main/java/com/rusefi/maintenance/ProgramSelector.java index aa1005ea4c..1d99b16812 100644 --- a/java_console/ui/src/main/java/com/rusefi/maintenance/ProgramSelector.java +++ b/java_console/ui/src/main/java/com/rusefi/maintenance/ProgramSelector.java @@ -1,6 +1,8 @@ package com.rusefi.maintenance; +import com.rusefi.autodetect.PortDetector; import com.rusefi.autoupdate.AutoupdateUtil; +import com.rusefi.ui.StatusWindow; import com.rusefi.ui.util.URLLabel; import org.jetbrains.annotations.NotNull; @@ -16,6 +18,8 @@ public class ProgramSelector { private static final String AUTO_DFU = "Auto DFU"; private static final String MANUAL_DFU = "Manual DFU"; + private static final String DFU_SWITCH = "Switch to DFU"; + private static final String DFU_ERASE = "Full Erase"; private static final String ST_LINK = "ST-LINK"; public static final boolean IS_WIN = System.getProperty("os.name").toLowerCase().contains("win"); @@ -31,13 +35,15 @@ public class ProgramSelector { mode.addItem(AUTO_DFU); if (IS_WIN) { mode.addItem(MANUAL_DFU); + mode.addItem(DFU_ERASE); mode.addItem(ST_LINK); } + mode.addItem(DFU_SWITCH); controls.add(mode); String persistedMode = getConfig().getRoot().getProperty(getClass().getSimpleName()); - if (Arrays.asList(AUTO_DFU, MANUAL_DFU, ST_LINK).contains(persistedMode)) + if (Arrays.asList(AUTO_DFU, MANUAL_DFU, ST_LINK, DFU_ERASE, DFU_SWITCH).contains(persistedMode)) mode.setSelectedItem(persistedMode); JButton updateFirmware = new JButton("Update Firmware", @@ -51,16 +57,21 @@ public class ProgramSelector { getConfig().getRoot().setProperty(getClass().getSimpleName(), selectedMode); - boolean isAutoDfu = selectedMode.equals(AUTO_DFU); - boolean isManualDfu = selectedMode.equals(MANUAL_DFU); - // todo: add ST-LINK no-assert mode - if (isAutoDfu) { + if (selectedMode.equals(AUTO_DFU)) { DfuFlasher.doAutoDfu(comboPorts.getSelectedItem(), comboPorts); - } else if (isManualDfu) { + } else if (selectedMode.equals(MANUAL_DFU)) { DfuFlasher.runDfuProgramming(); - } else { + } else if (selectedMode.equals(ST_LINK)) { + // todo: add ST-LINK no-assert mode? or not? FirmwareFlasher.doUpdateFirmware(FirmwareFlasher.IMAGE_FILE, updateFirmware); + } else if (selectedMode.equals(DFU_SWITCH)) { + StatusWindow wnd = DfuFlasher.createStatusWindow(); + Object selected = comboPorts.getSelectedItem(); + String port = selected == null ? PortDetector.AUTO : selected.toString(); + DfuFlasher.rebootToDfu(comboPorts, port, wnd); + } else { + throw new IllegalArgumentException("How did you " + selectedMode); } } }); diff --git a/java_console/ui/src/main/java/com/rusefi/ui/StatusWindow.java b/java_console/ui/src/main/java/com/rusefi/ui/StatusWindow.java index 1fefe8afec..a2eeee02b2 100644 --- a/java_console/ui/src/main/java/com/rusefi/ui/StatusWindow.java +++ b/java_console/ui/src/main/java/com/rusefi/ui/StatusWindow.java @@ -72,6 +72,11 @@ public class StatusWindow implements StatusConsumer { }); } + @Override + public void append(String s) { + appendMsg(s); + } + public void setStatus(String status) { bottomStatusLabel.setText(status); }