diff --git a/java_console/io/src/main/java/com/rusefi/proxy/client/LocalApplicationProxy.java b/java_console/io/src/main/java/com/rusefi/proxy/client/LocalApplicationProxy.java index f42cf46e04..e7abe8bbf7 100644 --- a/java_console/io/src/main/java/com/rusefi/proxy/client/LocalApplicationProxy.java +++ b/java_console/io/src/main/java/com/rusefi/proxy/client/LocalApplicationProxy.java @@ -36,11 +36,17 @@ import java.util.concurrent.atomic.AtomicInteger; import static com.devexperts.logging.Logging.getLogging; import static com.rusefi.binaryprotocol.BinaryProtocol.sleep; +/** + * Remote user process which facilitates connection between local tuning application and real ECU via rusEFI proxy service + */ public class LocalApplicationProxy implements Closeable { private static final ThreadFactory THREAD_FACTORY = new NamedThreadFactory("gauge poking"); private static final Logging log = getLogging(LocalApplicationProxy.class); public static final int SERVER_PORT_FOR_APPLICATIONS = HttpUtil.getIntProperty("applications.port", 8002); private final ApplicationRequest applicationRequest; + /** + * local TCP server socket which local tuning application connects to + */ private final ServerSocketReference serverHolder; private final IoStream authenticatorToProxyStream; @@ -50,6 +56,10 @@ public class LocalApplicationProxy implements Closeable { this.authenticatorToProxyStream = authenticatorToProxyStream; } + public IoStream getAuthenticatorToProxyStream() { + return authenticatorToProxyStream; + } + public static HttpResponse requestSoftwareUpdate(int httpPort, ApplicationRequest applicationRequest, UpdateType type) throws IOException { HttpPost httpPost = new HttpPost(ProxyClient.getHttpAddress(httpPort) + ProxyClient.UPDATE_CONNECTOR_SOFTWARE); diff --git a/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/LocalSdCardReader.java b/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/LocalSdCardReader.java new file mode 100644 index 0000000000..61ee24c097 --- /dev/null +++ b/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/LocalSdCardReader.java @@ -0,0 +1,44 @@ +package com.rusefi.ts_plugin; + +import com.efiAnalytics.plugin.ecu.ControllerAccess; +import com.rusefi.io.ConnectionStateListener; +import com.rusefi.io.IoStream; + +import javax.swing.*; +import java.awt.*; +import java.util.function.Supplier; + +public class LocalSdCardReader { + private final JPanel content = new JPanel(new BorderLayout()); + + private final SdCardReaderPanel sdCardReaderPanel; + + public LocalSdCardReader(Supplier controllerAccessSupplier) { + JPanel topPanel = new JPanel(new BorderLayout()); + + ConnectPanel connectPanel = new ConnectPanel(new ConnectionStateListener() { + public void onConnectionEstablished() { + sdCardReaderPanel.onConnectionEstablished(); + } + + public void onConnectionFailed() { + } + }); + topPanel.add(connectPanel.getContent(), BorderLayout.NORTH); + sdCardReaderPanel = new SdCardReaderPanel(controllerAccessSupplier, new Supplier() { + @Override + public IoStream get() { + return connectPanel.getControllerConnector().getConnector().getBinaryProtocol().getStream(); + } + }, content.getParent()); + + content.add(topPanel, BorderLayout.NORTH); + content.add(sdCardReaderPanel.getContent(), BorderLayout.CENTER); + + content.add(new JLabel("This tab allows direct access to SD card
Please be sure to disconnect Tuner Studio from ECU while downloading files using this tab"), BorderLayout.SOUTH); + } + + public Component getContent() { + return new JScrollPane(content, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + } +} diff --git a/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/PluginEntry.java b/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/PluginEntry.java index dd6e4aac6f..2f2d7a7e79 100644 --- a/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/PluginEntry.java +++ b/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/PluginEntry.java @@ -20,10 +20,13 @@ import java.util.function.Supplier; * @see PluginBodySandbox */ public class PluginEntry implements TsPluginBody { + private static final String LOCAL_SD_CARD = "Local SD Card"; + private static final String REMOTE_SD_CARD = "Remote SD Card"; private final JPanel content = new JPanel(new BorderLayout()); static final ImageIcon LOGO = AutoupdateUtil.loadIcon("/rusefi_online_color_300.png"); + private final JTabbedPane tabbedPane = new JTabbedPane(); /** * the real constructor - this one is invoked via reflection @@ -45,15 +48,32 @@ public class PluginEntry implements TsPluginBody { TuneUploadTab tuneUploadTab = new TuneUploadTab(controllerAccessSupplier); LogUploadSelector logUploadTab = new LogUploadSelector(controllerAccessSupplier); BroadcastTab broadcastTab = new BroadcastTab(); - RemoteTab remoteTab = new RemoteTab(); + Component localSdCard = new LocalSdCardReader(controllerAccessSupplier).getContent(); + Component remoteSdCard = new RemoteSdCardReader(controllerAccessSupplier).getContent(); + RemoteTab remoteTab = new RemoteTab(new RemoteTab.Listener() { + @Override + public void onConnected() { + tabbedPane.remove(localSdCard); + tabbedPane.addTab(REMOTE_SD_CARD, remoteSdCard); + } + }); + + RemoteTabController.INSTANCE.listeners.add(new RemoteTabController.Listener() { + @Override + public void onChange(RemoteTabController.State state) { + if (state == RemoteTabController.State.NOT_CONNECTED) { + tabbedPane.remove(remoteSdCard); + tabbedPane.addTab(LOCAL_SD_CARD, localSdCard); + } + } + }); - JTabbedPane tabbedPane = new JTabbedPane(); tabbedPane.addTab("Tune Upload", tuneUploadTab.getContent()); tabbedPane.addTab("Log Upload", logUploadTab.getContent()); tabbedPane.addTab("Broadcast", broadcastTab.getContent()); tabbedPane.addTab("Remote ECU", remoteTab.getContent()); - tabbedPane.addTab("Read SD Card", new SdCardReader(controllerAccessSupplier).getContent()); - content.add(tabbedPane); + tabbedPane.addTab(LOCAL_SD_CARD, localSdCard); + this.content.add(tabbedPane); InstanceAuthContext.startup(); } diff --git a/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/RemoteSdCardReader.java b/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/RemoteSdCardReader.java new file mode 100644 index 0000000000..a65a2ccb16 --- /dev/null +++ b/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/RemoteSdCardReader.java @@ -0,0 +1,36 @@ +package com.rusefi.ts_plugin; + +import com.efiAnalytics.plugin.ecu.ControllerAccess; +import com.rusefi.io.IoStream; +import com.rusefi.proxy.client.LocalApplicationProxy; + +import javax.swing.*; +import java.awt.*; +import java.util.function.Supplier; + +public class RemoteSdCardReader { + private final JPanel content = new JPanel(new BorderLayout()); + + private final SdCardReaderPanel sdCardReaderPanel; + + public RemoteSdCardReader(Supplier controllerAccessSupplier) { + + sdCardReaderPanel = new SdCardReaderPanel(controllerAccessSupplier, new Supplier() { + @Override + public IoStream get() { + LocalApplicationProxy localApplicationProxy = RemoteTabController.INSTANCE.getLocalApplicationProxy(); + if (localApplicationProxy == null) + throw new NullPointerException("Not connected"); + return localApplicationProxy.getAuthenticatorToProxyStream(); + } + }, content.getParent()); + + content.add(sdCardReaderPanel.getContent(), BorderLayout.CENTER); + } + + public Component getContent() { + return new JScrollPane(content, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + } + + +} diff --git a/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/RemoteTab.java b/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/RemoteTab.java index 3effcea735..b7f1b399d4 100644 --- a/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/RemoteTab.java +++ b/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/RemoteTab.java @@ -61,6 +61,7 @@ public class RemoteTab { return new Dimension(100, size.height); } }; + private final Listener listener; private StreamStatusControl streamStatusControl = null; @@ -69,7 +70,8 @@ public class RemoteTab { private final Executor listDownloadExecutor = Executors.newSingleThreadExecutor(new NamedThreadFactory("online list downloader", true)); - public RemoteTab() { + public RemoteTab(Listener listener) { + this.listener = listener; JButton refresh = new JButton("Refresh Remote Controllers List"); refresh.addActionListener(e -> requestControllersList()); @@ -259,6 +261,7 @@ public class RemoteTab { streamStatusControl = new StreamStatusControl(authenticatorToProxyStream); } + listener.onConnected(); setStatus("Connected to " + userDetails.getUserName(), new JLabel("You can now connect your TunerStudio to IP address localhost and port " + getLocalPort()), new URLLabel(SignatureHelper.getUrl(controllerInfo.getSignature()).first), @@ -319,4 +322,8 @@ public class RemoteTab { public JComponent getContent() { return scroll; } + + interface Listener { + void onConnected(); + } } diff --git a/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/RemoteTabController.java b/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/RemoteTabController.java index cd89ea684d..17295fe442 100644 --- a/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/RemoteTabController.java +++ b/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/RemoteTabController.java @@ -2,6 +2,8 @@ package com.rusefi.ts_plugin; import com.rusefi.proxy.client.LocalApplicationProxy; +import java.util.concurrent.CopyOnWriteArrayList; + public enum RemoteTabController { /** * TunerStudio likes to close plugin panel, we need a singleton to preserve the state @@ -11,9 +13,15 @@ public enum RemoteTabController { private State state = State.NOT_CONNECTED; private LocalApplicationProxy localApplicationProxy; + public final CopyOnWriteArrayList listeners = new CopyOnWriteArrayList<>(); + public synchronized void setState(State state) { - this.state = state; localApplicationProxy = null; + if (state != this.state) { + this.state = state; + for (Listener listener : listeners) + listener.onChange(state); + } } public synchronized State getState() { @@ -34,4 +42,8 @@ public enum RemoteTabController { CONNECTING, CONNECTED } + + interface Listener { + void onChange(State state); + } } diff --git a/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/SdCardReader.java b/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/SdCardReaderPanel.java similarity index 85% rename from java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/SdCardReader.java rename to java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/SdCardReaderPanel.java index a3feae9e11..8b507ee1b2 100644 --- a/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/SdCardReader.java +++ b/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/SdCardReaderPanel.java @@ -4,7 +4,6 @@ import com.devexperts.logging.Logging; import com.efiAnalytics.plugin.ecu.ControllerAccess; import com.rusefi.autoupdate.AutoupdateUtil; import com.rusefi.config.generated.Fields; -import com.rusefi.io.ConnectionStateListener; import com.rusefi.io.IoStream; import org.jetbrains.annotations.NotNull; import org.putgemin.VerticalFlowLayout; @@ -25,66 +24,199 @@ import static com.devexperts.logging.Logging.getLogging; import static com.rusefi.config.generated.Fields.TS_SD_PROTOCOL_FETCH_INFO; import static com.rusefi.shared.FileUtil.close; -public class SdCardReader { - private static final Logging log = getLogging(SdCardReader.class); +public class SdCardReaderPanel { private final static int TRANSFER_HEADER_SIZE = 3; - private final JPanel content = new JPanel(new BorderLayout()); + private static final Logging log = getLogging(SdCardReaderPanel.class); private final JPanel fileList = new JPanel(new VerticalFlowLayout()); private final JLabel status = new JLabel(); - - private final ConnectPanel connectPanel = new ConnectPanel(new ConnectionStateListener() { - public void onConnectionEstablished() { - ConnectPanel.IO_THREAD.execute(() -> requestFileList()); - } - - public void onConnectionFailed() { - } - }); private final Supplier controllerAccessSupplier; + private final Supplier ioStreamSupplier; + private final Container parent; - public SdCardReader(Supplier controllerAccessSupplier) { + private final JPanel content = new JPanel(new BorderLayout()); + + public SdCardReaderPanel(Supplier controllerAccessSupplier, + Supplier ioStreamSupplier, Container parent) { this.controllerAccessSupplier = controllerAccessSupplier; + this.ioStreamSupplier = ioStreamSupplier; + this.parent = parent; JButton refresh = new JButton("Refresh"); refresh.addActionListener(e -> ConnectPanel.IO_THREAD.execute(this::requestFileList)); - JPanel topPanel = new JPanel(new BorderLayout()); - JPanel lowPanel = new JPanel(new FlowLayout()); - JButton open = new JButton("Open Destination Folder"); + JPanel lowPanel = new JPanel(new FlowLayout()); lowPanel.add(refresh); lowPanel.add(open); + JPanel topPanel = new JPanel(new BorderLayout()); + topPanel.add(status, BorderLayout.CENTER); + topPanel.add(lowPanel, BorderLayout.SOUTH); + + content.add(topPanel, BorderLayout.NORTH); + content.add(fileList, BorderLayout.CENTER); + open.addActionListener(new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { try { - String folder = getDestinationFolder(controllerAccessSupplier); + String folder = getDestinationFolder(); Runtime.getRuntime().exec("explorer.exe /select," + folder + File.separator); } catch (IOException ex) { log.error("Error", ex); } } }); + } - topPanel.add(connectPanel.getContent(), BorderLayout.NORTH); - topPanel.add(status, BorderLayout.CENTER); - topPanel.add(lowPanel, BorderLayout.SOUTH); - - content.add(topPanel, BorderLayout.NORTH); - - content.add(fileList, BorderLayout.CENTER); - - content.add(new JLabel("This tab allows direct access to SD card
Please be sure to disconnect Tuner Studio from ECU while downloading files using this tab"), BorderLayout.SOUTH); + public JPanel getContent() { + return content; } @NotNull - private String getDestinationFolder(Supplier controllerAccessSupplier) { + private byte[] getDirContent() throws IOException { + byte[] packet; + byte[] response; + IoStream stream = ioStreamSupplier.get(); + + packet = new byte[3]; + packet[0] = Fields.TS_SD_R_COMMAND; + packet[2] = Fields.TS_SD_PROTOCOL_RTC; + stream.sendPacket(packet); + response = stream.getDataBuffer().getPacket("RTC status"); + log.info("RTC response " + IoStream.printHexBinary(response)); + if (response == null) + throw new IOException("RTC No packet"); + + packet = new byte[17]; + packet[0] = Fields.TS_SD_W_COMMAND; + packet[2] = TS_SD_PROTOCOL_FETCH_INFO; + packet[6] = Fields.TS_SD_PROTOCOL_READ_DIR; + stream.sendPacket(packet); + response = stream.getDataBuffer().getPacket("read dir command"); + if (response == null) + throw new IOException("Read Dir No packet"); + log.info("read dir command " + IoStream.printHexBinary(response)); + + packet = new byte[8]; + packet[0] = Fields.TS_SD_R_COMMAND; + packet[1] = 0; + packet[2] = TS_SD_PROTOCOL_FETCH_INFO; + packet[5] = 0x02; + packet[6] = 0x02; + stream.sendPacket(packet); + response = stream.getDataBuffer().getPacket("read command", true); + if (response == null) + throw new IOException("No packet"); + log.info("read command " + IoStream.printHexBinary(response)); + return response; + } + + @NotNull + public String getDestinationFolder() { return LogUploadSelector.getLogsFolderDir(controllerAccessSupplier.get().getEcuConfigurationNames()[0]); } - public Component getContent() { - return new JScrollPane(content, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + private void downloadFile(String fileName) { + String lastFour = ConnectPanel.getLastFour(fileName); + + byte[] packet = new byte[17]; + packet[0] = Fields.TS_SD_W_COMMAND; + packet[2] = TS_SD_PROTOCOL_FETCH_INFO; + packet[6] = Fields.TS_SD_PROTOCOL_FETCH_COMPRESSED; + applyLastFour(lastFour, packet); + + IoStream stream = ioStreamSupplier.get(); + + FileOutputStream fos = null; + try { + stream.sendPacket(packet); + byte[] response = stream.getDataBuffer().getPacket("Download file"); + log.info("Download file " + IoStream.printHexBinary(response)); + setStatus("Downloading " + fileName); + + fos = new FileOutputStream(getDestinationFolder() + File.separator + fileName, false); + int chunk = 0; + int totalSize = 0; + long start = System.currentTimeMillis(); + while (true) { + packet = new byte[17]; + packet[0] = Fields.TS_SD_R_COMMAND; + packet[2] = Fields.TS_SD_PROTOCOL_FETCH_DATA; + packet[3] = (byte) chunk; + packet[4] = (byte) (chunk >> 8); + + stream.sendPacket(packet); + response = stream.getDataBuffer().getPacket("Get file", true); + + if (response == null) { + log.info("No content response"); + break; + } + + int dataBytes = response.length - TRANSFER_HEADER_SIZE; + totalSize += dataBytes; + + if (chunk % 10 == 0) + log.info("Got content package size " + response.length + "/total=" + totalSize); + + fos.write(response, TRANSFER_HEADER_SIZE, dataBytes); + + if (dataBytes != 2048) { + log.info(response.length + " must be the last packet"); + long duration = System.currentTimeMillis() - start; + setStatus(fileName + " downloaded " + humanReadableByteCountBin(totalSize) + " in " + duration + " ms"); + break; + } + if (chunk % 10 == 0) + setStatus(humanReadableByteCountBin(totalSize) + " so far"); + chunk++; + } + } catch (IOException e) { + throw new IllegalStateException(e); + } finally { + close(fos); + } + } + + private void applyLastFour(String lastFour, byte[] packet) { + for (int i = 0; i < 4; i++) + packet[7 + i] = (byte) lastFour.charAt(i); + } + + private static String humanReadableByteCountBin(long bytes) { + long absB = bytes == Long.MIN_VALUE ? Long.MAX_VALUE : Math.abs(bytes); + if (absB < 1024) { + return bytes + " B"; + } + long value = absB; + CharacterIterator ci = new StringCharacterIterator("KMGTPE"); + for (int i = 40; i >= 0 && absB > 0xfffccccccccccccL >> i; i -= 10) { + value >>= 10; + ci.next(); + } + value *= Long.signum(bytes); + return String.format("%.1f %ciB", value / 1024.0, ci.current()); + } + + private void deleteFile(String fileName) { + String lastFour = ConnectPanel.getLastFour(fileName); + + byte[] packet = new byte[17]; + packet[0] = Fields.TS_SD_W_COMMAND; + packet[2] = TS_SD_PROTOCOL_FETCH_INFO; + packet[6] = Fields.TS_SD_PROTOCOL_REMOVE_FILE; + applyLastFour(lastFour, packet); + + IoStream stream = ioStreamSupplier.get(); + + try { + stream.sendPacket(packet); + byte[] response = stream.getDataBuffer().getPacket("delete file"); + log.info("Delete file " + IoStream.printHexBinary(response)); + } catch (IOException e) { + throw new IllegalStateException(e); + } } private void requestFileList() { @@ -135,7 +267,7 @@ public class SdCardReader { log.info("Filename " + fileName + " size " + fileSize); - AutoupdateUtil.trueLayout(content.getParent()); + AutoupdateUtil.trueLayout(parent); } } catch (IOException ioException) { @@ -147,148 +279,11 @@ public class SdCardReader { } } - @NotNull - private byte[] getDirContent() throws IOException { - byte[] packet; - byte[] response; - IoStream stream = connectPanel.getControllerConnector().getConnector().getBinaryProtocol().getStream(); - - packet = new byte[3]; - packet[0] = Fields.TS_SD_R_COMMAND; - packet[2] = Fields.TS_SD_PROTOCOL_RTC; - stream.sendPacket(packet); - response = stream.getDataBuffer().getPacket("RTC status"); - log.info("RTC response " + IoStream.printHexBinary(response)); - if (response == null) - throw new IOException("RTC No packet"); - - packet = new byte[17]; - packet[0] = Fields.TS_SD_W_COMMAND; - packet[2] = TS_SD_PROTOCOL_FETCH_INFO; - packet[6] = Fields.TS_SD_PROTOCOL_READ_DIR; - stream.sendPacket(packet); - response = stream.getDataBuffer().getPacket("read dir command"); - if (response == null) - throw new IOException("Read Dir No packet"); - log.info("read dir command " + IoStream.printHexBinary(response)); - - packet = new byte[8]; - packet[0] = Fields.TS_SD_R_COMMAND; - packet[1] = 0; - packet[2] = TS_SD_PROTOCOL_FETCH_INFO; - packet[5] = 0x02; - packet[6] = 0x02; - stream.sendPacket(packet); - response = stream.getDataBuffer().getPacket("read command", true); - if (response == null) - throw new IOException("No packet"); - log.info("read command " + IoStream.printHexBinary(response)); - return response; - } - - private void downloadFile(String fileName) { - String lastFour = ConnectPanel.getLastFour(fileName); - - byte[] packet = new byte[17]; - packet[0] = Fields.TS_SD_W_COMMAND; - packet[2] = TS_SD_PROTOCOL_FETCH_INFO; - packet[6] = Fields.TS_SD_PROTOCOL_FETCH_COMPRESSED; - applyLastFour(lastFour, packet); - - IoStream stream = connectPanel.getControllerConnector().getConnector().getBinaryProtocol().getStream(); - - FileOutputStream fos = null; - try { - stream.sendPacket(packet); - byte[] response = stream.getDataBuffer().getPacket("Download file"); - log.info("Download file " + IoStream.printHexBinary(response)); - setStatus("Downloading " + fileName); - - fos = new FileOutputStream(getDestinationFolder(controllerAccessSupplier) + File.separator + fileName, false); - int chunk = 0; - int totalSize = 0; - long start = System.currentTimeMillis(); - while (true) { - packet = new byte[17]; - packet[0] = Fields.TS_SD_R_COMMAND; - packet[2] = Fields.TS_SD_PROTOCOL_FETCH_DATA; - packet[3] = (byte) chunk; - packet[4] = (byte) (chunk >> 8); - - stream.sendPacket(packet); - response = stream.getDataBuffer().getPacket("Get file", true); - - if (response == null) { - log.info("No content response"); - break; - } - - int dataBytes = response.length - TRANSFER_HEADER_SIZE; - totalSize += dataBytes; - - if (chunk % 10 == 0) - log.info("Got content package size " + response.length + "/total=" + totalSize); - - fos.write(response, TRANSFER_HEADER_SIZE, dataBytes); - - if (dataBytes != 2048) { - log.info(response.length + " must be the last packet"); - long duration = System.currentTimeMillis() - start; - setStatus(fileName + " downloaded " + humanReadableByteCountBin(totalSize) + " in " + duration + " ms"); - break; - } - if (chunk % 10 == 0) - setStatus(humanReadableByteCountBin(totalSize) + " so far"); - chunk++; - } - } catch (IOException e) { - throw new IllegalStateException(e); - } finally { - close(fos); - } - } - - private void deleteFile(String fileName) { - String lastFour = ConnectPanel.getLastFour(fileName); - - byte[] packet = new byte[17]; - packet[0] = Fields.TS_SD_W_COMMAND; - packet[2] = TS_SD_PROTOCOL_FETCH_INFO; - packet[6] = Fields.TS_SD_PROTOCOL_REMOVE_FILE; - applyLastFour(lastFour, packet); - - IoStream stream = connectPanel.getControllerConnector().getConnector().getBinaryProtocol().getStream(); - - try { - stream.sendPacket(packet); - byte[] response = stream.getDataBuffer().getPacket("delete file"); - log.info("Delete file " + IoStream.printHexBinary(response)); - } catch (IOException e) { - throw new IllegalStateException(e); - } - } - - private void applyLastFour(String lastFour, byte[] packet) { - for (int i = 0; i < 4; i++) - packet[7 + i] = (byte) lastFour.charAt(i); - } - - private void setStatus(String message) { + public void setStatus(String message) { SwingUtilities.invokeLater(() -> status.setText(message)); } - private static String humanReadableByteCountBin(long bytes) { - long absB = bytes == Long.MIN_VALUE ? Long.MAX_VALUE : Math.abs(bytes); - if (absB < 1024) { - return bytes + " B"; - } - long value = absB; - CharacterIterator ci = new StringCharacterIterator("KMGTPE"); - for (int i = 40; i >= 0 && absB > 0xfffccccccccccccL >> i; i -= 10) { - value >>= 10; - ci.next(); - } - value *= Long.signum(bytes); - return String.format("%.1f %ciB", value / 1024.0, ci.current()); + public void onConnectionEstablished() { + ConnectPanel.IO_THREAD.execute(this::requestFileList); } } diff --git a/java_tools/ts_plugin/src/test/java/com/rusefi/ts_plugin/RemoteTabSandbox.java b/java_tools/ts_plugin/src/test/java/com/rusefi/ts_plugin/RemoteTabSandbox.java index 12facbfd40..18445041cd 100644 --- a/java_tools/ts_plugin/src/test/java/com/rusefi/ts_plugin/RemoteTabSandbox.java +++ b/java_tools/ts_plugin/src/test/java/com/rusefi/ts_plugin/RemoteTabSandbox.java @@ -7,6 +7,9 @@ import com.rusefi.ui.util.FrameHelper; */ public class RemoteTabSandbox { public static void main(String[] args) { - new FrameHelper().showFrame(new RemoteTab().getContent()); + RemoteTab.Listener listener = () -> { + + }; + new FrameHelper().showFrame(new RemoteTab(listener).getContent()); } }