Startup Frame should scan for available hardware fix #4633

This commit is contained in:
rusefillc 2022-10-03 23:00:26 -04:00
parent 50344d32df
commit 771b907156
3 changed files with 114 additions and 48 deletions

View File

@ -2,11 +2,11 @@ package com.rusefi;
import com.rusefi.io.LinkManager; import com.rusefi.io.LinkManager;
import com.rusefi.io.tcp.TcpConnector; import com.rusefi.io.tcp.TcpConnector;
import com.rusefi.maintenance.DfuFlasher;
import com.rusefi.ui.StatusConsumer;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import static com.rusefi.FileLog.isLinux; import static com.rusefi.FileLog.isLinux;
@ -23,54 +23,66 @@ public enum SerialPortScanner {
private static final boolean SHOW_SOCKETCAN = isLinux(); private static final boolean SHOW_SOCKETCAN = isLinux();
static final String AUTO_SERIAL = "Auto Serial"; static final String AUTO_SERIAL = "Auto Serial";
@NotNull
private final List<String> knownPorts = new ArrayList<>();
public List<Listener> listeners = new CopyOnWriteArrayList<>(); private final Object lock = new Object();
@NotNull
private AvailableHardware knownHardware = new AvailableHardware(Collections.emptyList(), false, false);
private final List<Listener> listeners = new CopyOnWriteArrayList<>();
public void addListener(Listener listener) {
boolean shouldStart = listeners.isEmpty();
listeners.add(listener);
if (shouldStart)
startTimer();
}
/** /**
* Find all available serial ports and checks if simulator local TCP port is available * Find all available serial ports and checks if simulator local TCP port is available
*/ */
private void findAllAvailablePorts(boolean includeSlowTcpLookup) { private void findAllAvailablePorts(boolean includeSlowTcpLookup) {
List<String> ports = new ArrayList<>(); List<String> ports = new ArrayList<>();
boolean dfuConnected;
boolean stLinkConnected;
String[] serialPorts = LinkManager.getCommPorts(); String[] serialPorts = LinkManager.getCommPorts();
if (serialPorts.length > 0) if (serialPorts.length > 0)
ports.add(AUTO_SERIAL); ports.add(AUTO_SERIAL);
ports.addAll(Arrays.asList(serialPorts)); ports.addAll(Arrays.asList(serialPorts));
if (includeSlowTcpLookup)
if (includeSlowTcpLookup) {
ports.addAll(TcpConnector.getAvailablePorts()); ports.addAll(TcpConnector.getAvailablePorts());
dfuConnected = DfuFlasher.detectSTM32BootloaderDriverState(StatusConsumer.VOID);
stLinkConnected = DfuFlasher.detectStLink(StatusConsumer.VOID);
} else {
dfuConnected = false;
stLinkConnected = false;
}
if (SHOW_PCAN) if (SHOW_PCAN)
ports.add(LinkManager.PCAN); ports.add(LinkManager.PCAN);
if (SHOW_SOCKETCAN) if (SHOW_SOCKETCAN)
ports.add(LinkManager.SOCKET_CAN); ports.add(LinkManager.SOCKET_CAN);
boolean isListUpdated; boolean isListUpdated;
synchronized (knownPorts) { AvailableHardware currentHardware = new AvailableHardware(ports, dfuConnected, stLinkConnected);
isListUpdated = knownPorts.equals(ports); synchronized (lock) {
knownPorts.clear(); isListUpdated = !knownHardware.equals(currentHardware);
knownPorts.addAll(ports); knownHardware = currentHardware;
} }
if (isListUpdated) { if (isListUpdated) {
for (Listener listener : listeners) for (Listener listener : listeners)
listener.onChange(); listener.onChange(currentHardware);
} }
} }
@NotNull private void startTimer() {
public List<String> getKnownPorts() {
synchronized (knownPorts) {
return new ArrayList<>(knownPorts);
}
}
public void startTimer() {
Thread portsScanner = new Thread(() -> { Thread portsScanner = new Thread(() -> {
boolean isFirstTime = true; boolean isFirstTime = true;
while (isRunning) { while (isRunning) {
findAllAvailablePorts(!isFirstTime); findAllAvailablePorts(!isFirstTime);
isFirstTime = false; isFirstTime = false;
try { try {
Thread.sleep(1000); Thread.sleep(300);
} catch (InterruptedException e) { } catch (InterruptedException e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
@ -86,6 +98,44 @@ public enum SerialPortScanner {
} }
interface Listener { interface Listener {
void onChange(); void onChange(AvailableHardware currentHardware);
}
public static class AvailableHardware {
private final List<String> ports;
private final boolean dfuFound;
private final boolean stLinkConnected;
public <T> AvailableHardware(List<String> ports, boolean dfuFound, boolean stLinkConnected) {
this.ports = ports;
this.dfuFound = dfuFound;
this.stLinkConnected = stLinkConnected;
}
@NotNull
public List<String> getKnownPorts() {
return new ArrayList<>(ports);
}
public boolean isDfuFound() {
return dfuFound;
}
public boolean isStLinkConnected() {
return stLinkConnected;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AvailableHardware that = (AvailableHardware) o;
return dfuFound == that.dfuFound && stLinkConnected == that.stLinkConnected && ports.equals(that.ports);
}
public boolean isEmpty() {
return !dfuFound && !stLinkConnected && ports.isEmpty();
}
} }
} }

View File

@ -57,9 +57,6 @@ public class StartupFrame {
private final JPanel connectPanel = new JPanel(new FlowLayout()); private final JPanel connectPanel = new JPanel(new FlowLayout());
// todo: move this line to the connectPanel // todo: move this line to the connectPanel
private final JComboBox<String> comboPorts = new JComboBox<>(); private final JComboBox<String> comboPorts = new JComboBox<>();
@NotNull
private List<String> currentlyDisplayedPorts = new ArrayList<>();
private boolean isFirstTimeApplyingPorts = true;
private final JPanel leftPanel = new JPanel(new VerticalFlowLayout()); private final JPanel leftPanel = new JPanel(new VerticalFlowLayout());
private final JPanel realHardwarePanel = new JPanel(new MigLayout()); private final JPanel realHardwarePanel = new JPanel(new MigLayout());
@ -93,7 +90,6 @@ public class StartupFrame {
} }
}); });
AutoupdateUtil.setAppIcon(frame); AutoupdateUtil.setAppIcon(frame);
SerialPortScanner.INSTANCE.startTimer();
} }
@NotNull @NotNull
@ -122,6 +118,7 @@ public class StartupFrame {
//connectButton.setBackground(new Color(RUSEFI_ORANGE)); // custom orange //connectButton.setBackground(new Color(RUSEFI_ORANGE)); // custom orange
setToolTip(connectButton, "Connect to real hardware"); setToolTip(connectButton, "Connect to real hardware");
connectPanel.add(connectButton); connectPanel.add(connectButton);
connectPanel.setVisible(false);
frame.getRootPane().setDefaultButton(connectButton); frame.getRootPane().setDefaultButton(connectButton);
connectButton.addKeyListener(new KeyAdapter() { connectButton.addKeyListener(new KeyAdapter() {
@ -149,10 +146,11 @@ public class StartupFrame {
realHardwarePanel.add(noPortsMessage, "right, wrap"); realHardwarePanel.add(noPortsMessage, "right, wrap");
installMessage(noPortsMessage, "Check you cables. Check your drivers. Do you want to start simulator maybe?"); installMessage(noPortsMessage, "Check you cables. Check your drivers. Do you want to start simulator maybe?");
ProgramSelector selector = new ProgramSelector(comboPorts);
if (FileLog.isWindows()) { if (FileLog.isWindows()) {
realHardwarePanel.add(new HorizontalLine(), "right, wrap"); realHardwarePanel.add(new HorizontalLine(), "right, wrap");
ProgramSelector selector = new ProgramSelector(comboPorts);
realHardwarePanel.add(selector.getControl(), "right, wrap"); realHardwarePanel.add(selector.getControl(), "right, wrap");
// for F7 builds we just build one file at the moment // for F7 builds we just build one file at the moment
@ -170,7 +168,11 @@ public class StartupFrame {
//realHardwarePanel.add(new EraseChip().getButton(), "right, wrap"); //realHardwarePanel.add(new EraseChip().getButton(), "right, wrap");
} }
SerialPortScanner.INSTANCE.listeners.add(() -> SwingUtilities.invokeLater(this::applyKnownPorts)); SerialPortScanner.INSTANCE.addListener(currentHardware -> SwingUtilities.invokeLater(() -> {
selector.apply(currentHardware);
applyKnownPorts(currentHardware);
frame.pack();
}));
final JButton buttonLogViewer = new JButton(); final JButton buttonLogViewer = new JButton();
buttonLogViewer.setText("Start " + LinkManager.LOG_VIEWER); buttonLogViewer.setText("Start " + LinkManager.LOG_VIEWER);
@ -226,19 +228,14 @@ public class StartupFrame {
} }
} }
private void applyKnownPorts() { private void applyKnownPorts(SerialPortScanner.AvailableHardware currentHardware) {
List<String> ports = SerialPortScanner.INSTANCE.getKnownPorts(); List<String> ports = currentHardware.getKnownPorts();
if (!currentlyDisplayedPorts.equals(ports) || isFirstTimeApplyingPorts) {
log.info("Rendering available ports: " + ports); log.info("Rendering available ports: " + ports);
isFirstTimeApplyingPorts = false;
connectPanel.setVisible(!ports.isEmpty()); connectPanel.setVisible(!ports.isEmpty());
noPortsMessage.setVisible(ports.isEmpty()); noPortsMessage.setVisible(ports.isEmpty());
applyPortSelectionToUIcontrol(ports); applyPortSelectionToUIcontrol(ports);
currentlyDisplayedPorts = ports;
UiUtils.trueLayout(connectPanel); UiUtils.trueLayout(connectPanel);
frame.pack();
}
} }
public static void setFrameIcon(Frame frame) { public static void setFrameIcon(Frame frame) {

View File

@ -1,10 +1,12 @@
package com.rusefi.maintenance; package com.rusefi.maintenance;
import com.rusefi.Launcher; import com.rusefi.Launcher;
import com.rusefi.SerialPortScanner;
import com.rusefi.autodetect.PortDetector; import com.rusefi.autodetect.PortDetector;
import com.rusefi.autoupdate.AutoupdateUtil; import com.rusefi.autoupdate.AutoupdateUtil;
import com.rusefi.ui.StatusWindow; import com.rusefi.ui.StatusWindow;
import com.rusefi.ui.util.URLLabel; import com.rusefi.ui.util.URLLabel;
import com.rusefi.ui.util.UiUtils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import javax.swing.*; import javax.swing.*;
@ -17,6 +19,7 @@ import java.util.Objects;
import static com.rusefi.StartupFrame.appendBundleName; import static com.rusefi.StartupFrame.appendBundleName;
import static com.rusefi.ui.storage.PersistentConfiguration.getConfig; import static com.rusefi.ui.storage.PersistentConfiguration.getConfig;
import static com.rusefi.ui.util.UiUtils.trueLayout;
public class ProgramSelector { public class ProgramSelector {
@ -33,22 +36,16 @@ public class ProgramSelector {
public static final String BOOT_COMMANDER_EXE = "BootCommander.exe"; public static final String BOOT_COMMANDER_EXE = "BootCommander.exe";
public static final String OPENBLT_BINARY_LOCATION = Launcher.TOOLS_PATH + File.separator + "openblt"; public static final String OPENBLT_BINARY_LOCATION = Launcher.TOOLS_PATH + File.separator + "openblt";
private final JPanel content = new JPanel(new BorderLayout());
private final JLabel noHardware = new JLabel("Nothing detected");
private final JPanel controls = new JPanel(new FlowLayout()); private final JPanel controls = new JPanel(new FlowLayout());
private final JComboBox<String> mode = new JComboBox<>(); private final JComboBox<String> mode = new JComboBox<>();
public ProgramSelector(JComboBox<String> comboPorts) { public ProgramSelector(JComboBox<String> comboPorts) {
/* content.add(controls, BorderLayout.NORTH);
* todo: add FULL AUTO mode which would fire up DFU and ST-LINK in parallel hoping that one of those would work? content.add(noHardware, BorderLayout.SOUTH);
*/ controls.setVisible(false);
if (IS_WIN) {
mode.addItem(AUTO_DFU);
mode.addItem(MANUAL_DFU);
mode.addItem(DFU_ERASE);
mode.addItem(ST_LINK);
mode.addItem(OPENBLT_CAN);
}
mode.addItem(DFU_SWITCH);
controls.add(mode); controls.add(mode);
String persistedMode = getConfig().getRoot().getProperty(getClass().getSimpleName()); String persistedMode = getConfig().getRoot().getProperty(getClass().getSimpleName());
@ -117,6 +114,28 @@ public class ProgramSelector {
} }
public JPanel getControl() { public JPanel getControl() {
return controls; return content;
}
public void apply(SerialPortScanner.AvailableHardware currentHardware) {
noHardware.setVisible(currentHardware.isEmpty());
controls.setVisible(!currentHardware.isEmpty());
mode.removeAllItems();
if (IS_WIN) {
if (!currentHardware.getKnownPorts().isEmpty())
mode.addItem(AUTO_DFU);
if (currentHardware.isDfuFound()) {
mode.addItem(MANUAL_DFU);
mode.addItem(DFU_ERASE);
}
if (currentHardware.isStLinkConnected())
mode.addItem(ST_LINK);
// todo: detect PCAN mode.addItem(OPENBLT_CAN);
}
if (!currentHardware.getKnownPorts().isEmpty())
mode.addItem(DFU_SWITCH);
trueLayout(mode);
UiUtils.trueLayout(content);
} }
} }