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.tcp.TcpConnector;
import com.rusefi.maintenance.DfuFlasher;
import com.rusefi.ui.StatusConsumer;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import static com.rusefi.FileLog.isLinux;
@ -23,54 +23,66 @@ public enum SerialPortScanner {
private static final boolean SHOW_SOCKETCAN = isLinux();
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
*/
private void findAllAvailablePorts(boolean includeSlowTcpLookup) {
List<String> ports = new ArrayList<>();
boolean dfuConnected;
boolean stLinkConnected;
String[] serialPorts = LinkManager.getCommPorts();
if (serialPorts.length > 0)
ports.add(AUTO_SERIAL);
ports.addAll(Arrays.asList(serialPorts));
if (includeSlowTcpLookup)
if (includeSlowTcpLookup) {
ports.addAll(TcpConnector.getAvailablePorts());
dfuConnected = DfuFlasher.detectSTM32BootloaderDriverState(StatusConsumer.VOID);
stLinkConnected = DfuFlasher.detectStLink(StatusConsumer.VOID);
} else {
dfuConnected = false;
stLinkConnected = false;
}
if (SHOW_PCAN)
ports.add(LinkManager.PCAN);
if (SHOW_SOCKETCAN)
ports.add(LinkManager.SOCKET_CAN);
boolean isListUpdated;
synchronized (knownPorts) {
isListUpdated = knownPorts.equals(ports);
knownPorts.clear();
knownPorts.addAll(ports);
AvailableHardware currentHardware = new AvailableHardware(ports, dfuConnected, stLinkConnected);
synchronized (lock) {
isListUpdated = !knownHardware.equals(currentHardware);
knownHardware = currentHardware;
}
if (isListUpdated) {
for (Listener listener : listeners)
listener.onChange();
listener.onChange(currentHardware);
}
}
@NotNull
public List<String> getKnownPorts() {
synchronized (knownPorts) {
return new ArrayList<>(knownPorts);
}
}
public void startTimer() {
private void startTimer() {
Thread portsScanner = new Thread(() -> {
boolean isFirstTime = true;
while (isRunning) {
findAllAvailablePorts(!isFirstTime);
isFirstTime = false;
try {
Thread.sleep(1000);
Thread.sleep(300);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
@ -86,6 +98,44 @@ public enum SerialPortScanner {
}
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());
// todo: move this line to the connectPanel
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 realHardwarePanel = new JPanel(new MigLayout());
@ -93,7 +90,6 @@ public class StartupFrame {
}
});
AutoupdateUtil.setAppIcon(frame);
SerialPortScanner.INSTANCE.startTimer();
}
@NotNull
@ -122,6 +118,7 @@ public class StartupFrame {
//connectButton.setBackground(new Color(RUSEFI_ORANGE)); // custom orange
setToolTip(connectButton, "Connect to real hardware");
connectPanel.add(connectButton);
connectPanel.setVisible(false);
frame.getRootPane().setDefaultButton(connectButton);
connectButton.addKeyListener(new KeyAdapter() {
@ -149,10 +146,11 @@ public class StartupFrame {
realHardwarePanel.add(noPortsMessage, "right, wrap");
installMessage(noPortsMessage, "Check you cables. Check your drivers. Do you want to start simulator maybe?");
ProgramSelector selector = new ProgramSelector(comboPorts);
if (FileLog.isWindows()) {
realHardwarePanel.add(new HorizontalLine(), "right, wrap");
ProgramSelector selector = new ProgramSelector(comboPorts);
realHardwarePanel.add(selector.getControl(), "right, wrap");
// 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");
}
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();
buttonLogViewer.setText("Start " + LinkManager.LOG_VIEWER);
@ -226,19 +228,14 @@ public class StartupFrame {
}
}
private void applyKnownPorts() {
List<String> ports = SerialPortScanner.INSTANCE.getKnownPorts();
if (!currentlyDisplayedPorts.equals(ports) || isFirstTimeApplyingPorts) {
private void applyKnownPorts(SerialPortScanner.AvailableHardware currentHardware) {
List<String> ports = currentHardware.getKnownPorts();
log.info("Rendering available ports: " + ports);
isFirstTimeApplyingPorts = false;
connectPanel.setVisible(!ports.isEmpty());
noPortsMessage.setVisible(ports.isEmpty());
applyPortSelectionToUIcontrol(ports);
currentlyDisplayedPorts = ports;
UiUtils.trueLayout(connectPanel);
frame.pack();
}
}
public static void setFrameIcon(Frame frame) {

View File

@ -1,10 +1,12 @@
package com.rusefi.maintenance;
import com.rusefi.Launcher;
import com.rusefi.SerialPortScanner;
import com.rusefi.autodetect.PortDetector;
import com.rusefi.autoupdate.AutoupdateUtil;
import com.rusefi.ui.StatusWindow;
import com.rusefi.ui.util.URLLabel;
import com.rusefi.ui.util.UiUtils;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@ -17,6 +19,7 @@ import java.util.Objects;
import static com.rusefi.StartupFrame.appendBundleName;
import static com.rusefi.ui.storage.PersistentConfiguration.getConfig;
import static com.rusefi.ui.util.UiUtils.trueLayout;
public class ProgramSelector {
@ -33,22 +36,16 @@ public class ProgramSelector {
public static final String BOOT_COMMANDER_EXE = "BootCommander.exe";
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 JComboBox<String> mode = new JComboBox<>();
public ProgramSelector(JComboBox<String> comboPorts) {
/*
* todo: add FULL AUTO mode which would fire up DFU and ST-LINK in parallel hoping that one of those would work?
*/
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);
content.add(controls, BorderLayout.NORTH);
content.add(noHardware, BorderLayout.SOUTH);
controls.setVisible(false);
controls.add(mode);
String persistedMode = getConfig().getRoot().getProperty(getClass().getSimpleName());
@ -117,6 +114,28 @@ public class ProgramSelector {
}
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);
}
}