From 3112f4d15316015db83e50df12faf75c0629949c Mon Sep 17 00:00:00 2001 From: GitHub set-date Action Date: Mon, 27 Jul 2020 00:33:02 +0000 Subject: [PATCH 1/7] Update date --- firmware/controllers/date_stamp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/controllers/date_stamp.h b/firmware/controllers/date_stamp.h index 4d04e204fd..9444b9690d 100644 --- a/firmware/controllers/date_stamp.h +++ b/firmware/controllers/date_stamp.h @@ -1,2 +1,2 @@ #pragma once -#define VCS_DATE 20200726 +#define VCS_DATE 20200727 From a7f6fefc2f58c3e9403017e51a12f56bebfce87c Mon Sep 17 00:00:00 2001 From: rusefi Date: Sun, 26 Jul 2020 23:34:37 -0400 Subject: [PATCH 2/7] proxy progress? that should be a positive change --- .../src/main/java/com/rusefi/io/tcp/BinaryProtocolServer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java_console/io/src/main/java/com/rusefi/io/tcp/BinaryProtocolServer.java b/java_console/io/src/main/java/com/rusefi/io/tcp/BinaryProtocolServer.java index 5da1d462e3..327c519eab 100644 --- a/java_console/io/src/main/java/com/rusefi/io/tcp/BinaryProtocolServer.java +++ b/java_console/io/src/main/java/com/rusefi/io/tcp/BinaryProtocolServer.java @@ -232,7 +232,7 @@ public class BinaryProtocolServer implements BinaryProtocolCommands { int fromPacket = IoHelper.getCrc32(packet); if (crc != fromPacket) throw new IllegalStateException("CRC mismatch crc=" + Integer.toString(crc, 16) + " vs packet=" + Integer.toString(fromPacket, 16) + " len=" + packet.length + " data: " + IoStream.printHexBinary(packet)); -// todo?! in.onPacketArrived(); + in.onPacketArrived(); return new Packet(packet, crc); } From 8237e2dab9c40189505717e2b29c722cf30e419b Mon Sep 17 00:00:00 2001 From: rusefi Date: Mon, 27 Jul 2020 00:16:38 -0400 Subject: [PATCH 3/7] code comments --- .../src/main/java/com/rusefi/ts_plugin/RemoteTab.java | 2 +- .../test/java/com/rusefi/ts_plugin/PluginBodySandbox.java | 4 +++- .../test/java/com/rusefi/ts_plugin/RemoteTabSandbox.java | 3 +++ .../src/com/rusefi/ts_plugin/PluginLauncherSandbox.java | 3 +++ .../src/com/rusefi/ts_plugin/TsPluginLauncher.java | 5 +++++ .../src/com/rusefi/ts_plugin/Updater.java | 8 ++++++-- 6 files changed, 21 insertions(+), 4 deletions(-) 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 384dc59adf..8e048270b1 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 @@ -29,7 +29,7 @@ import java.util.concurrent.atomic.AtomicReference; import static com.rusefi.ui.storage.PersistentConfiguration.getConfig; /** - * see RemoteTabSandbox + * @see RemoteTabSandbox */ public class RemoteTab { private static final String APPLICATION_PORT = "application_port"; diff --git a/java_tools/ts_plugin/src/test/java/com/rusefi/ts_plugin/PluginBodySandbox.java b/java_tools/ts_plugin/src/test/java/com/rusefi/ts_plugin/PluginBodySandbox.java index aa8dc15c1b..c7fdacc9be 100644 --- a/java_tools/ts_plugin/src/test/java/com/rusefi/ts_plugin/PluginBodySandbox.java +++ b/java_tools/ts_plugin/src/test/java/com/rusefi/ts_plugin/PluginBodySandbox.java @@ -14,7 +14,9 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; /** - * @see PluginLauncherSandbox + * Sandbox for plugin body + * + * @see PluginLauncherSandbox for plugin auto-update launcher */ public class PluginBodySandbox { 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 f2f8ee4b61..12facbfd40 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 @@ -2,6 +2,9 @@ package com.rusefi.ts_plugin; import com.rusefi.ui.util.FrameHelper; +/** + * @see PluginBodySandbox + */ public class RemoteTabSandbox { public static void main(String[] args) { new FrameHelper().showFrame(new RemoteTab().getContent()); diff --git a/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/PluginLauncherSandbox.java b/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/PluginLauncherSandbox.java index 7805fbca63..61f375c8bb 100644 --- a/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/PluginLauncherSandbox.java +++ b/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/PluginLauncherSandbox.java @@ -2,6 +2,9 @@ package com.rusefi.ts_plugin; import javax.swing.*; +/** + * Sandbox for {@link TsPluginLauncher} + */ public class PluginLauncherSandbox { public static void main(String[] args) { JFrame frame = new JFrame(); diff --git a/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/TsPluginLauncher.java b/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/TsPluginLauncher.java index 0f47aca0a2..c07cab8391 100644 --- a/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/TsPluginLauncher.java +++ b/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/TsPluginLauncher.java @@ -7,7 +7,12 @@ import org.putgemin.VerticalFlowLayout; import javax.swing.*; /** + * This class is the more permanent part of the plug, it's responsible for refreshing and launcher PluginEntry via reflections. + * which downloads the main more volatile UI part (PluginEntry) + * * by the way TS installs stuff into %user%\.efianalytics\TunerStudio\plugins folder + * @see PluginLauncherSandbox sandbox for this + * see PluginEntry */ public class TsPluginLauncher implements ApplicationPlugin { public static final int BUILD_VERSION = 3; diff --git a/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/Updater.java b/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/Updater.java index 3fdb229e5d..2a91be9391 100644 --- a/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/Updater.java +++ b/java_tools/ts_plugin_launcher/src/com/rusefi/ts_plugin/Updater.java @@ -20,9 +20,13 @@ import java.util.concurrent.atomic.AtomicInteger; import static com.rusefi.ts_plugin.TsPluginLauncher.VERSION; +/** + * Download fresh copy of {@link #PLUGIN_BODY_JAR} and launch {@link #PLUGIN_ENTRY_CLASS} via reflection. + */ public class Updater { + private static final String PLUGIN_ENTRY_CLASS = "com.rusefi.ts_plugin.PluginEntry"; private static final String PLUGIN_BODY_JAR = "rusefi_plugin_body.jar"; - public static final String LOCAL_JAR_FILE_NAME = FileUtil.RUSEFI_SETTINGS_FOLDER + File.separator + PLUGIN_BODY_JAR; + private static final String LOCAL_JAR_FILE_NAME = FileUtil.RUSEFI_SETTINGS_FOLDER + File.separator + PLUGIN_BODY_JAR; private static final String TITLE = "rusEFI plugin installer " + VERSION; private final JPanel content = new JPanel(new VerticalFlowLayout()); @@ -187,7 +191,7 @@ public class Updater { private static Class getPluginClass() throws MalformedURLException, ClassNotFoundException { URLClassLoader jarClassLoader = AutoupdateUtil.getClassLoaderByJar(LOCAL_JAR_FILE_NAME); - return Class.forName("com.rusefi.ts_plugin.PluginEntry", true, jarClassLoader); + return Class.forName(PLUGIN_ENTRY_CLASS, true, jarClassLoader); } private void replaceWith(TsPluginBody instance) { From 9ff5dcca97ecf56cbd4224356df34cac960f566b Mon Sep 17 00:00:00 2001 From: rusefi Date: Mon, 27 Jul 2020 00:48:04 -0400 Subject: [PATCH 4/7] broadcast tab seems to work now?! --- .../com/rusefi/autodetect/PortDetector.java | 10 +++- .../rusefi/autodetect/SerialAutoChecker.java | 0 .../com/rusefi/proxy/NetworkConnector.java | 4 ++ .../rusefi/tools/NetworkConnectorStartup.java | 3 +- .../com/rusefi/ts_plugin/BroadcastTab.java | 58 ++++++++++++++++++- .../com/rusefi/ts_plugin/PluginEntry.java | 8 +++ .../java/com/rusefi/ts_plugin/RemoteTab.java | 6 +- .../java/com/rusefi/ts_plugin/UploadTab.java | 3 +- 8 files changed, 82 insertions(+), 10 deletions(-) rename java_console/{ui => io}/src/main/java/com/rusefi/autodetect/PortDetector.java (89%) rename java_console/{ui => io}/src/main/java/com/rusefi/autodetect/SerialAutoChecker.java (100%) diff --git a/java_console/ui/src/main/java/com/rusefi/autodetect/PortDetector.java b/java_console/io/src/main/java/com/rusefi/autodetect/PortDetector.java similarity index 89% rename from java_console/ui/src/main/java/com/rusefi/autodetect/PortDetector.java rename to java_console/io/src/main/java/com/rusefi/autodetect/PortDetector.java index f4d7778adc..d06ce4e72e 100644 --- a/java_console/ui/src/main/java/com/rusefi/autodetect/PortDetector.java +++ b/java_console/io/src/main/java/com/rusefi/autodetect/PortDetector.java @@ -1,6 +1,6 @@ package com.rusefi.autodetect; -import com.rusefi.FileLog; +import com.devexperts.logging.Logging; import com.rusefi.NamedThreadFactory; import com.rusefi.io.IoStream; import com.rusefi.io.LinkManager; @@ -19,19 +19,23 @@ import java.util.function.Function; * Andrey Belomutskiy, (c) 2013-2020 */ public class PortDetector { + private final static Logging log = Logging.getLogging(PortDetector.class); + private static final NamedThreadFactory AUTO_DETECT_PORT = new NamedThreadFactory("AutoDetectPort"); /** * Connect to all serial ports and find out which one respond first * @param callback + * @return port name on which rusEFI was detected or null if none */ + @Nullable public static String autoDetectSerial(Function callback) { String[] serialPorts = getPortNames(); if (serialPorts.length == 0) { - System.err.println("No serial ports detected"); + log.error("No serial ports detected"); return null; } - FileLog.MAIN.logLine("Trying " + Arrays.toString(serialPorts)); + log.info("Trying " + Arrays.toString(serialPorts)); List serialFinder = new ArrayList<>(); CountDownLatch portFound = new CountDownLatch(1); AtomicReference result = new AtomicReference<>(); diff --git a/java_console/ui/src/main/java/com/rusefi/autodetect/SerialAutoChecker.java b/java_console/io/src/main/java/com/rusefi/autodetect/SerialAutoChecker.java similarity index 100% rename from java_console/ui/src/main/java/com/rusefi/autodetect/SerialAutoChecker.java rename to java_console/io/src/main/java/com/rusefi/autodetect/SerialAutoChecker.java diff --git a/java_console/io/src/main/java/com/rusefi/proxy/NetworkConnector.java b/java_console/io/src/main/java/com/rusefi/proxy/NetworkConnector.java index f7d873c591..f4893a41e6 100644 --- a/java_console/io/src/main/java/com/rusefi/proxy/NetworkConnector.java +++ b/java_console/io/src/main/java/com/rusefi/proxy/NetworkConnector.java @@ -34,6 +34,10 @@ public class NetworkConnector implements Closeable { private final static Logging log = Logging.getLogging(NetworkConnector.class); private boolean isClosed; + public NetworkConnectorResult runNetworkConnector(String authToken, String controllerPort, NetworkConnectorContext context) { + return runNetworkConnector(authToken, controllerPort, context, ReconnectListener.VOID); + } + public NetworkConnectorResult runNetworkConnector(String authToken, String controllerPort, NetworkConnectorContext context, ReconnectListener reconnectListener) { LinkManager controllerConnector = new LinkManager() .setCompositeLogicEnabled(false) diff --git a/java_console/ui/src/main/java/com/rusefi/tools/NetworkConnectorStartup.java b/java_console/ui/src/main/java/com/rusefi/tools/NetworkConnectorStartup.java index 87e8fd3589..0e8d529000 100644 --- a/java_console/ui/src/main/java/com/rusefi/tools/NetworkConnectorStartup.java +++ b/java_console/ui/src/main/java/com/rusefi/tools/NetworkConnectorStartup.java @@ -5,7 +5,6 @@ import com.rusefi.auth.AutoTokenUtil; import com.rusefi.autodetect.PortDetector; import com.rusefi.proxy.NetworkConnector; import com.rusefi.proxy.NetworkConnectorContext; -import com.rusefi.tools.online.ProxyClient; import com.rusefi.ui.AuthTokenPanel; public class NetworkConnectorStartup { @@ -25,7 +24,7 @@ public class NetworkConnectorStartup { NetworkConnectorContext connectorContext = new NetworkConnectorContext(); - NetworkConnector.NetworkConnectorResult networkConnectorResult = new NetworkConnector().runNetworkConnector(authToken, autoDetectedPort, connectorContext, NetworkConnector.ReconnectListener.VOID); + NetworkConnector.NetworkConnectorResult networkConnectorResult = new NetworkConnector().runNetworkConnector(authToken, autoDetectedPort, connectorContext); log.info("Running with oneTimeToken=" + networkConnectorResult.getOneTimeToken()); } } diff --git a/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/BroadcastTab.java b/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/BroadcastTab.java index e7781fcdef..00946947bb 100644 --- a/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/BroadcastTab.java +++ b/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/BroadcastTab.java @@ -1,15 +1,69 @@ package com.rusefi.ts_plugin; +import com.rusefi.auth.AutoTokenUtil; +import com.rusefi.autodetect.PortDetector; +import com.rusefi.autoupdate.AutoupdateUtil; import com.rusefi.proxy.NetworkConnector; +import com.rusefi.proxy.NetworkConnectorContext; +import com.rusefi.ui.AuthTokenPanel; +import com.rusefi.ui.util.URLLabel; +import org.putgemin.VerticalFlowLayout; import javax.swing.*; +/** + * @see PluginEntry + */ public class BroadcastTab { - private final JComponent content = new JPanel(); + private final JComponent content = new JPanel(new VerticalFlowLayout()); + + private final JLabel help = new URLLabel(RemoteTab.HOWTO_REMOTE_TUNING); + + private final JLabel status = new JLabel(); public BroadcastTab() { -// NetworkConnector + JButton broadcast = new JButton("Broadcast"); + broadcast.addActionListener(e -> { + String authToken = AuthTokenPanel.getAuthToken(); + if (!AutoTokenUtil.isToken(authToken)) { + status.setText("Auth token is required to broadcast ECU"); + return; + } + + new Thread(() -> { + String autoDetectedPort = PortDetector.autoDetectSerial(null); + SwingUtilities.invokeLater(() -> { + startBroadcasting(authToken, autoDetectedPort); + }); + + }).start(); + }); + + content.add(broadcast); + content.add(status); + content.add(help); + content.add(new JLabel(PluginEntry.LOGO)); + + AutoupdateUtil.trueLayout(content); + } + + private void startBroadcasting(String authToken, String autoDetectedPort) { + if (autoDetectedPort == null) { + status.setText("rusEFI ECU not detected.
Please make sure that TunerStudio is currently not connected to ECU."); + } else { + status.setText("rusEFI detected at " + autoDetectedPort); + + NetworkConnectorContext connectorContext = new NetworkConnectorContext(); + + new Thread(() -> { + NetworkConnector.NetworkConnectorResult networkConnectorResult = new NetworkConnector().runNetworkConnector(authToken, autoDetectedPort, connectorContext); + + SwingUtilities.invokeLater(() -> status.setText("One time password to connect to this ECU: " + networkConnectorResult.getOneTimeToken())); + + }).start(); + } + AutoupdateUtil.trueLayout(content); } public JComponent getContent() { 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 9f9a011387..f96efc3498 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 @@ -1,6 +1,7 @@ package com.rusefi.ts_plugin; import com.efiAnalytics.plugin.ecu.ControllerAccess; +import com.rusefi.autoupdate.AutoupdateUtil; import com.rusefi.ts_plugin.util.ManifestHelper; import com.rusefi.tune.xml.Constant; @@ -11,10 +12,17 @@ import java.util.function.Supplier; /** * {@link TsPluginLauncher} creates an instance of this class via reflection. + * @see UploadTab upload tune & TODO upload logs + * @see RemoteTab remote ECU access & control + * @see BroadcastTab offer your ECU for remove access & control + * @see PluginBodySandbox */ public class PluginEntry implements TsPluginBody { private final JPanel content = new JPanel(new BorderLayout()); + static final ImageIcon LOGO = AutoupdateUtil.loadIcon("/rusefi_online_color_300.png"); + + /** * the real constructor - this one is invoked via reflection */ 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 8e048270b1..c5a1d57eb4 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 @@ -29,10 +29,14 @@ import java.util.concurrent.atomic.AtomicReference; import static com.rusefi.ui.storage.PersistentConfiguration.getConfig; /** + * remote ECU access & control + * * @see RemoteTabSandbox + * @see PluginEntry */ public class RemoteTab { private static final String APPLICATION_PORT = "application_port"; + public static final String HOWTO_REMOTE_TUNING = "https://github.com/rusefi/rusefi/wiki/HOWTO-Remote-Tuning"; private final JComponent content = new JPanel(new BorderLayout()); private final JPanel list = new JPanel(new VerticalFlowLayout()); @@ -87,7 +91,7 @@ public class RemoteTab { topPanel.add(oneTimePasswordControl); topLines.add(topPanel); - topLines.add(new URLLabel("https://github.com/rusefi/rusefi/wiki/HOWTO-Remote-Tuning")); + topLines.add(new URLLabel(HOWTO_REMOTE_TUNING)); content.add(topLines, BorderLayout.NORTH); content.add(list, BorderLayout.CENTER); diff --git a/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/UploadTab.java b/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/UploadTab.java index 9862103691..6b36fa6f75 100644 --- a/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/UploadTab.java +++ b/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/UploadTab.java @@ -142,8 +142,7 @@ public class UploadTab { content.add(uploadView.getContent()); content.add(upload); - ImageIcon LOGO = AutoupdateUtil.loadIcon("/rusefi_online_color_300.png"); - content.add(new JLabel(LOGO)); + content.add(new JLabel(PluginEntry.LOGO)); content.add(tokenPanel.getContent()); content.add(new URLLabel(REO_URL)); From 2e581ec6cd0f316c86460d2247cb586ecdf941a9 Mon Sep 17 00:00:00 2001 From: rusefi Date: Mon, 27 Jul 2020 00:54:48 -0400 Subject: [PATCH 5/7] broadcast tab seems to work now?! --- .../com/rusefi/proxy/NetworkConnector.java | 10 ++++---- .../rusefi/tools/NetworkConnectorStartup.java | 2 +- .../test/java/com/rusefi/FullServerTest.java | 2 +- .../src/test/java/com/rusefi/ServerTest.java | 5 +--- .../rusefi/proxy/NetworkConnectorTest.java | 2 +- .../com/rusefi/ts_plugin/BroadcastTab.java | 23 +++++++++++++++---- 6 files changed, 28 insertions(+), 16 deletions(-) diff --git a/java_console/io/src/main/java/com/rusefi/proxy/NetworkConnector.java b/java_console/io/src/main/java/com/rusefi/proxy/NetworkConnector.java index f4893a41e6..0c8024d606 100644 --- a/java_console/io/src/main/java/com/rusefi/proxy/NetworkConnector.java +++ b/java_console/io/src/main/java/com/rusefi/proxy/NetworkConnector.java @@ -34,11 +34,11 @@ public class NetworkConnector implements Closeable { private final static Logging log = Logging.getLogging(NetworkConnector.class); private boolean isClosed; - public NetworkConnectorResult runNetworkConnector(String authToken, String controllerPort, NetworkConnectorContext context) { - return runNetworkConnector(authToken, controllerPort, context, ReconnectListener.VOID); + public NetworkConnectorResult start(String authToken, String controllerPort, NetworkConnectorContext context) { + return start(authToken, controllerPort, context, ReconnectListener.VOID); } - public NetworkConnectorResult runNetworkConnector(String authToken, String controllerPort, NetworkConnectorContext context, ReconnectListener reconnectListener) { + public NetworkConnectorResult start(String authToken, String controllerPort, NetworkConnectorContext context, ReconnectListener reconnectListener) { LinkManager controllerConnector = new LinkManager() .setCompositeLogicEnabled(false) .setNeedPullData(false); @@ -78,7 +78,7 @@ public class NetworkConnector implements Closeable { proxyReconnectSemaphore.acquire(); try { - runNetworkConnector(context.serverPortForControllers(), controllerConnector, authToken, (String message) -> { + start(context.serverPortForControllers(), controllerConnector, authToken, (String message) -> { log.error(message + " Disconnect from proxy server detected, now sleeping " + context.reconnectDelay() + " seconds"); sleep(context.reconnectDelay() * Timeouts.SECOND); log.debug("Releasing semaphore"); @@ -98,7 +98,7 @@ public class NetworkConnector implements Closeable { } @NotNull - private static SessionDetails runNetworkConnector(int serverPortForControllers, LinkManager linkManager, String authToken, final TcpIoStream.DisconnectListener disconnectListener, int oneTimeToken, ControllerInfo controllerInfo, final NetworkConnectorContext context) throws IOException { + private static SessionDetails start(int serverPortForControllers, LinkManager linkManager, String authToken, final TcpIoStream.DisconnectListener disconnectListener, int oneTimeToken, ControllerInfo controllerInfo, final NetworkConnectorContext context) throws IOException { IoStream targetEcuSocket = linkManager.getConnector().getBinaryProtocol().getStream(); SessionDetails deviceSessionDetails = new SessionDetails(controllerInfo, authToken, oneTimeToken); diff --git a/java_console/ui/src/main/java/com/rusefi/tools/NetworkConnectorStartup.java b/java_console/ui/src/main/java/com/rusefi/tools/NetworkConnectorStartup.java index 0e8d529000..c98b29f468 100644 --- a/java_console/ui/src/main/java/com/rusefi/tools/NetworkConnectorStartup.java +++ b/java_console/ui/src/main/java/com/rusefi/tools/NetworkConnectorStartup.java @@ -24,7 +24,7 @@ public class NetworkConnectorStartup { NetworkConnectorContext connectorContext = new NetworkConnectorContext(); - NetworkConnector.NetworkConnectorResult networkConnectorResult = new NetworkConnector().runNetworkConnector(authToken, autoDetectedPort, connectorContext); + NetworkConnector.NetworkConnectorResult networkConnectorResult = new NetworkConnector().start(authToken, autoDetectedPort, connectorContext); log.info("Running with oneTimeToken=" + networkConnectorResult.getOneTimeToken()); } } diff --git a/java_console/ui/src/test/java/com/rusefi/FullServerTest.java b/java_console/ui/src/test/java/com/rusefi/FullServerTest.java index 3df6febfa4..8c57c8919a 100644 --- a/java_console/ui/src/test/java/com/rusefi/FullServerTest.java +++ b/java_console/ui/src/test/java/com/rusefi/FullServerTest.java @@ -101,7 +101,7 @@ public class FullServerTest { }; // start "rusEFI network connector" to connect controller with backend since in real life controller has only local serial port it does not have network - NetworkConnector.NetworkConnectorResult networkConnectorResult = new NetworkConnector().runNetworkConnector(TestHelper.TEST_TOKEN_1, TestHelper.LOCALHOST + ":" + controllerPort, networkConnectorContext, NetworkConnector.ReconnectListener.VOID); + NetworkConnector.NetworkConnectorResult networkConnectorResult = new NetworkConnector().start(TestHelper.TEST_TOKEN_1, TestHelper.LOCALHOST + ":" + controllerPort, networkConnectorContext, NetworkConnector.ReconnectListener.VOID); ControllerInfo controllerInfo = networkConnectorResult.getControllerInfo(); TestHelper.assertLatch("controllerRegistered", controllerRegistered); diff --git a/java_console/ui/src/test/java/com/rusefi/ServerTest.java b/java_console/ui/src/test/java/com/rusefi/ServerTest.java index df25aeacc3..39cf0ef246 100644 --- a/java_console/ui/src/test/java/com/rusefi/ServerTest.java +++ b/java_console/ui/src/test/java/com/rusefi/ServerTest.java @@ -1,6 +1,5 @@ package com.rusefi; -import com.opensr5.Logger; import com.rusefi.config.generated.Fields; import com.rusefi.io.IoStream; import com.rusefi.io.commands.GetOutputsCommand; @@ -34,8 +33,6 @@ import static org.junit.Assert.assertEquals; * https://github.com/rusefi/web_backend/blob/master/documentation/rusEFI%20remote.png */ public class ServerTest { - private final static Logger logger = Logger.CONSOLE; - @Before public void setup() throws MalformedURLException { BackendTestHelper.commonServerTest(); @@ -126,7 +123,7 @@ covered by FullServerTest TestHelper.createVirtualController(controllerPort, new ConfigurationImage(Fields.TOTAL_CONFIG_SIZE), logger); // start "rusEFI network connector" to connect controller with backend since in real life controller has only local serial port it does not have network - SessionDetails deviceSessionDetails = NetworkConnector.runNetworkConnector(MockRusEfiDevice.TEST_TOKEN_1, TestHelper.LOCALHOST + ":" + controllerPort, serverPortForControllers); + SessionDetails deviceSessionDetails = NetworkConnector.start(MockRusEfiDevice.TEST_TOKEN_1, TestHelper.LOCALHOST + ":" + controllerPort, serverPortForControllers); assertTrue(controllerRegistered.await(READ_IMAGE_TIMEOUT, TimeUnit.MILLISECONDS)); diff --git a/java_console/ui/src/test/java/com/rusefi/proxy/NetworkConnectorTest.java b/java_console/ui/src/test/java/com/rusefi/proxy/NetworkConnectorTest.java index 854b685536..19ab1938e0 100644 --- a/java_console/ui/src/test/java/com/rusefi/proxy/NetworkConnectorTest.java +++ b/java_console/ui/src/test/java/com/rusefi/proxy/NetworkConnectorTest.java @@ -75,7 +75,7 @@ public class NetworkConnectorTest { reconnectCounter.countDown(); } }; - new NetworkConnector().runNetworkConnector(TestHelper.TEST_TOKEN_1, TestHelper.LOCALHOST + ":" + controllerPort, connectorContext, reconnectListener); + new NetworkConnector().start(TestHelper.TEST_TOKEN_1, TestHelper.LOCALHOST + ":" + controllerPort, connectorContext, reconnectListener); assertLatch(reconnectCounter); diff --git a/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/BroadcastTab.java b/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/BroadcastTab.java index 00946947bb..bce97a6c7e 100644 --- a/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/BroadcastTab.java +++ b/java_tools/ts_plugin/src/main/java/com/rusefi/ts_plugin/BroadcastTab.java @@ -10,6 +10,8 @@ import com.rusefi.ui.util.URLLabel; import org.putgemin.VerticalFlowLayout; import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; /** * @see PluginEntry @@ -17,12 +19,13 @@ import javax.swing.*; public class BroadcastTab { private final JComponent content = new JPanel(new VerticalFlowLayout()); - private final JLabel help = new URLLabel(RemoteTab.HOWTO_REMOTE_TUNING); - private final JLabel status = new JLabel(); + private final JButton disconnect = new JButton("Disconnect"); + private NetworkConnector networkConnector; public BroadcastTab() { JButton broadcast = new JButton("Broadcast"); + disconnect.setEnabled(false); broadcast.addActionListener(e -> { String authToken = AuthTokenPanel.getAuthToken(); @@ -40,9 +43,18 @@ public class BroadcastTab { }).start(); }); + disconnect.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + networkConnector.close(); + disconnect.setEnabled(false); + } + }); + content.add(broadcast); content.add(status); - content.add(help); + content.add(disconnect); + content.add(new URLLabel(RemoteTab.HOWTO_REMOTE_TUNING)); content.add(new JLabel(PluginEntry.LOGO)); AutoupdateUtil.trueLayout(content); @@ -53,11 +65,14 @@ public class BroadcastTab { status.setText("rusEFI ECU not detected.
Please make sure that TunerStudio is currently not connected to ECU."); } else { status.setText("rusEFI detected at " + autoDetectedPort); + disconnect.setEnabled(true); NetworkConnectorContext connectorContext = new NetworkConnectorContext(); new Thread(() -> { - NetworkConnector.NetworkConnectorResult networkConnectorResult = new NetworkConnector().runNetworkConnector(authToken, autoDetectedPort, connectorContext); + networkConnector = new NetworkConnector(); + + NetworkConnector.NetworkConnectorResult networkConnectorResult = networkConnector.start(authToken, autoDetectedPort, connectorContext); SwingUtilities.invokeLater(() -> status.setText("One time password to connect to this ECU: " + networkConnectorResult.getOneTimeToken())); From 4b54274bb144dacdc6f9e9f3ea9581aeed8f44b1 Mon Sep 17 00:00:00 2001 From: rusefi Date: Mon, 27 Jul 2020 09:45:52 -0400 Subject: [PATCH 6/7] docs --- firmware/integration/rusefi_config.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/firmware/integration/rusefi_config.txt b/firmware/integration/rusefi_config.txt index b5690901ad..313da9ac2c 100644 --- a/firmware/integration/rusefi_config.txt +++ b/firmware/integration/rusefi_config.txt @@ -18,6 +18,9 @@ ! rename the bit or substitute unused integer with any new fields of the same size ! invoke gen_config.bat to apply the tools which would generate .h and .ini files ! +! Q: Which files to include into Pull Requests? +! A: Please only include source files (.txt and .input) into a PR, we have amazing GitHub Actions which would do the rest really +! really nicely! ! ! each field is declared as ! type name;comment From 30e70cf8b72a80c99b8e1fd5ed7998eafa9564f4 Mon Sep 17 00:00:00 2001 From: GitHub build-firmware Action Date: Mon, 27 Jul 2020 13:48:00 +0000 Subject: [PATCH 7/7] Auto-generated configs and docs --- ...ngine_configuration_generated_structures.h | 4 ++-- .../controllers/algo/rusefi_generated.h | 6 +++--- ...ngine_configuration_generated_structures.h | 4 ++-- .../generated/fsio_enums_generated.def | 2 +- .../controllers/generated/fsio_getters.def | 2 +- firmware/controllers/generated/fsio_names.def | 2 +- .../controllers/generated/fsio_strings.def | 2 +- .../controllers/generated/rusefi_generated.h | 6 +++--- .../controllers/generated/signature_all.h | 6 +++--- .../generated/signature_frankenso_na6.h | 6 +++--- .../controllers/generated/signature_kin.h | 6 +++--- .../controllers/generated/signature_mre_f4.h | 6 +++--- .../controllers/generated/signature_mre_f7.h | 6 +++--- .../generated/signature_prometheus_405.h | 6 +++--- .../generated/signature_prometheus_469.h | 6 +++--- .../generated/signature_proteus_f4.h | 6 +++--- .../generated/signature_proteus_f7.h | 6 +++--- firmware/tunerstudio/generated/cache.zip | Bin 843650 -> 844595 bytes firmware/tunerstudio/generated/rusefi.ini | 6 +++--- .../generated/rusefi_frankenso_na6.ini | 6 +++--- .../tunerstudio/generated/rusefi_kinetis.ini | 6 +++--- .../tunerstudio/generated/rusefi_mre_f4.ini | 6 +++--- .../tunerstudio/generated/rusefi_mre_f7.ini | 6 +++--- .../generated/rusefi_prometheus_405.ini | 6 +++--- .../generated/rusefi_prometheus_469.ini | 6 +++--- .../generated/rusefi_proteus_f4.ini | 6 +++--- .../generated/rusefi_proteus_f7.ini | 6 +++--- .../com/rusefi/config/generated/Fields.java | 6 +++--- java_console/rusefi.xml | 2 +- 29 files changed, 72 insertions(+), 72 deletions(-) diff --git a/firmware/config/boards/kinetis/config/controllers/algo/engine_configuration_generated_structures.h b/firmware/config/boards/kinetis/config/controllers/algo/engine_configuration_generated_structures.h index 02faa5a771..dd3fa64da6 100644 --- a/firmware/config/boards/kinetis/config/controllers/algo/engine_configuration_generated_structures.h +++ b/firmware/config/boards/kinetis/config/controllers/algo/engine_configuration_generated_structures.h @@ -1,4 +1,4 @@ -// this section was generated automatically by rusEfi tool ConfigDefinition.jar based on kinetis_gen_config.bat integration/rusefi_config.txt Sun Jul 26 19:09:03 UTC 2020 +// this section was generated automatically by rusEfi tool ConfigDefinition.jar based on kinetis_gen_config.bat integration/rusefi_config.txt Mon Jul 27 13:47:20 UTC 2020 // by class com.rusefi.output.CHeaderConsumer // begin #pragma once @@ -3533,4 +3533,4 @@ struct persistent_config_s { typedef struct persistent_config_s persistent_config_s; // end -// this section was generated automatically by rusEfi tool ConfigDefinition.jar based on kinetis_gen_config.bat integration/rusefi_config.txt Sun Jul 26 19:09:03 UTC 2020 +// this section was generated automatically by rusEfi tool ConfigDefinition.jar based on kinetis_gen_config.bat integration/rusefi_config.txt Mon Jul 27 13:47:20 UTC 2020 diff --git a/firmware/config/boards/kinetis/config/controllers/algo/rusefi_generated.h b/firmware/config/boards/kinetis/config/controllers/algo/rusefi_generated.h index 00e03a4d67..a16044703c 100644 --- a/firmware/config/boards/kinetis/config/controllers/algo/rusefi_generated.h +++ b/firmware/config/boards/kinetis/config/controllers/algo/rusefi_generated.h @@ -1075,8 +1075,8 @@ #define showHumanReadableWarning_offset 976 #define showSdCardWarning_offset 76 #define SIGNATURE_BOARD kin -#define SIGNATURE_DATE 2020.07.26 -#define SIGNATURE_HASH 2735505253 +#define SIGNATURE_DATE 2020.07.27 +#define SIGNATURE_HASH 3345389999 #define silentTriggerError_offset 1464 #define slowAdcAlpha_offset 2088 #define sparkDwellRpmBins_offset 332 @@ -1344,7 +1344,7 @@ #define ts_show_spi true #define ts_show_trigger_comparator true #define ts_show_tunerstudio_port true -#define TS_SIGNATURE "rusEFI 2020.07.26.kin.2735505253" +#define TS_SIGNATURE "rusEFI 2020.07.27.kin.3345389999" #define TS_SINGLE_WRITE_COMMAND 'W' #define tunerStudioSerialSpeed_offset 728 #define twoWireBatchIgnition_offset 1476 diff --git a/firmware/controllers/generated/engine_configuration_generated_structures.h b/firmware/controllers/generated/engine_configuration_generated_structures.h index e813ce50e5..a08202790d 100644 --- a/firmware/controllers/generated/engine_configuration_generated_structures.h +++ b/firmware/controllers/generated/engine_configuration_generated_structures.h @@ -1,4 +1,4 @@ -// this section was generated automatically by rusEfi tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt Sun Jul 26 19:08:53 UTC 2020 +// this section was generated automatically by rusEfi tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt Mon Jul 27 13:47:09 UTC 2020 // by class com.rusefi.output.CHeaderConsumer // begin #pragma once @@ -3533,4 +3533,4 @@ struct persistent_config_s { typedef struct persistent_config_s persistent_config_s; // end -// this section was generated automatically by rusEfi tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt Sun Jul 26 19:08:53 UTC 2020 +// this section was generated automatically by rusEfi tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt Mon Jul 27 13:47:09 UTC 2020 diff --git a/firmware/controllers/generated/fsio_enums_generated.def b/firmware/controllers/generated/fsio_enums_generated.def index f8061c8950..6f4c6a76e7 100644 --- a/firmware/controllers/generated/fsio_enums_generated.def +++ b/firmware/controllers/generated/fsio_enums_generated.def @@ -1,4 +1,4 @@ -// this file was generated automatically by rusEfi tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt Sun Jul 26 19:08:53 UTC 2020 +// this file was generated automatically by rusEfi tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt Mon Jul 27 13:47:09 UTC 2020 // by class com.rusefi.output.FileFsioSettingsConsumer FSIO_SETTING_FANONTEMPERATURE = 1000, diff --git a/firmware/controllers/generated/fsio_getters.def b/firmware/controllers/generated/fsio_getters.def index 2a72c4a745..04caf03810 100644 --- a/firmware/controllers/generated/fsio_getters.def +++ b/firmware/controllers/generated/fsio_getters.def @@ -1,4 +1,4 @@ -// this file was generated automatically by rusEfi tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt Sun Jul 26 19:08:53 UTC 2020 +// this file was generated automatically by rusEfi tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt Mon Jul 27 13:47:09 UTC 2020 // by class com.rusefi.output.FileFsioSettingsConsumer case FSIO_SETTING_FANONTEMPERATURE: diff --git a/firmware/controllers/generated/fsio_names.def b/firmware/controllers/generated/fsio_names.def index f46e7172d4..a6ab3fe490 100644 --- a/firmware/controllers/generated/fsio_names.def +++ b/firmware/controllers/generated/fsio_names.def @@ -1,4 +1,4 @@ -// this file was generated automatically by rusEfi tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt Sun Jul 26 19:08:53 UTC 2020 +// this file was generated automatically by rusEfi tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt Mon Jul 27 13:47:09 UTC 2020 // by class com.rusefi.output.FileFsioSettingsConsumer static LENameOrdinalPair lefanOnTemperature(FSIO_SETTING_FANONTEMPERATURE, "cfg_fanOnTemperature"); diff --git a/firmware/controllers/generated/fsio_strings.def b/firmware/controllers/generated/fsio_strings.def index 942b35e90e..9e6aed85d0 100644 --- a/firmware/controllers/generated/fsio_strings.def +++ b/firmware/controllers/generated/fsio_strings.def @@ -1,4 +1,4 @@ -// this file was generated automatically by rusEfi tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt Sun Jul 26 19:08:53 UTC 2020 +// this file was generated automatically by rusEfi tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt Mon Jul 27 13:47:09 UTC 2020 // by class com.rusefi.output.FileFsioSettingsConsumer case FSIO_SETTING_FANONTEMPERATURE: diff --git a/firmware/controllers/generated/rusefi_generated.h b/firmware/controllers/generated/rusefi_generated.h index c0d3d184cf..87cda6cf84 100644 --- a/firmware/controllers/generated/rusefi_generated.h +++ b/firmware/controllers/generated/rusefi_generated.h @@ -1075,8 +1075,8 @@ #define showHumanReadableWarning_offset 976 #define showSdCardWarning_offset 76 #define SIGNATURE_BOARD all -#define SIGNATURE_DATE 2020.07.26 -#define SIGNATURE_HASH 1848812543 +#define SIGNATURE_DATE 2020.07.27 +#define SIGNATURE_HASH 173557045 #define silentTriggerError_offset 1464 #define slowAdcAlpha_offset 2088 #define sparkDwellRpmBins_offset 332 @@ -1344,7 +1344,7 @@ #define ts_show_spi true #define ts_show_trigger_comparator false #define ts_show_tunerstudio_port true -#define TS_SIGNATURE "rusEFI 2020.07.26.all.1848812543" +#define TS_SIGNATURE "rusEFI 2020.07.27.all.173557045" #define TS_SINGLE_WRITE_COMMAND 'W' #define tunerStudioSerialSpeed_offset 728 #define twoWireBatchIgnition_offset 1476 diff --git a/firmware/controllers/generated/signature_all.h b/firmware/controllers/generated/signature_all.h index 551f4619e6..8698c1d093 100644 --- a/firmware/controllers/generated/signature_all.h +++ b/firmware/controllers/generated/signature_all.h @@ -3,6 +3,6 @@ // #define SIGNATURE_BOARD all -#define SIGNATURE_DATE 2020.07.26 -#define SIGNATURE_HASH 1848812543 -#define TS_SIGNATURE "rusEFI 2020.07.26.all.1848812543" +#define SIGNATURE_DATE 2020.07.27 +#define SIGNATURE_HASH 173557045 +#define TS_SIGNATURE "rusEFI 2020.07.27.all.173557045" diff --git a/firmware/controllers/generated/signature_frankenso_na6.h b/firmware/controllers/generated/signature_frankenso_na6.h index b39a979bc1..1dc8d1fa55 100644 --- a/firmware/controllers/generated/signature_frankenso_na6.h +++ b/firmware/controllers/generated/signature_frankenso_na6.h @@ -3,6 +3,6 @@ // #define SIGNATURE_BOARD frankenso_na6 -#define SIGNATURE_DATE 2020.07.26 -#define SIGNATURE_HASH 2964705052 -#define TS_SIGNATURE "rusEFI 2020.07.26.frankenso_na6.2964705052" +#define SIGNATURE_DATE 2020.07.27 +#define SIGNATURE_HASH 3571395030 +#define TS_SIGNATURE "rusEFI 2020.07.27.frankenso_na6.3571395030" diff --git a/firmware/controllers/generated/signature_kin.h b/firmware/controllers/generated/signature_kin.h index 7209efa488..fda207018a 100644 --- a/firmware/controllers/generated/signature_kin.h +++ b/firmware/controllers/generated/signature_kin.h @@ -3,6 +3,6 @@ // #define SIGNATURE_BOARD kin -#define SIGNATURE_DATE 2020.07.26 -#define SIGNATURE_HASH 2735505253 -#define TS_SIGNATURE "rusEFI 2020.07.26.kin.2735505253" +#define SIGNATURE_DATE 2020.07.27 +#define SIGNATURE_HASH 3345389999 +#define TS_SIGNATURE "rusEFI 2020.07.27.kin.3345389999" diff --git a/firmware/controllers/generated/signature_mre_f4.h b/firmware/controllers/generated/signature_mre_f4.h index 49d7a37413..6d3337c833 100644 --- a/firmware/controllers/generated/signature_mre_f4.h +++ b/firmware/controllers/generated/signature_mre_f4.h @@ -3,6 +3,6 @@ // #define SIGNATURE_BOARD mre_f4 -#define SIGNATURE_DATE 2020.07.26 -#define SIGNATURE_HASH 667710833 -#define TS_SIGNATURE "rusEFI 2020.07.26.mre_f4.667710833" +#define SIGNATURE_DATE 2020.07.27 +#define SIGNATURE_HASH 1134990267 +#define TS_SIGNATURE "rusEFI 2020.07.27.mre_f4.1134990267" diff --git a/firmware/controllers/generated/signature_mre_f7.h b/firmware/controllers/generated/signature_mre_f7.h index 32c51d18cc..7cede4e937 100644 --- a/firmware/controllers/generated/signature_mre_f7.h +++ b/firmware/controllers/generated/signature_mre_f7.h @@ -3,6 +3,6 @@ // #define SIGNATURE_BOARD mre_f7 -#define SIGNATURE_DATE 2020.07.26 -#define SIGNATURE_HASH 667710833 -#define TS_SIGNATURE "rusEFI 2020.07.26.mre_f7.667710833" +#define SIGNATURE_DATE 2020.07.27 +#define SIGNATURE_HASH 1134990267 +#define TS_SIGNATURE "rusEFI 2020.07.27.mre_f7.1134990267" diff --git a/firmware/controllers/generated/signature_prometheus_405.h b/firmware/controllers/generated/signature_prometheus_405.h index 350be31347..783e7cfd67 100644 --- a/firmware/controllers/generated/signature_prometheus_405.h +++ b/firmware/controllers/generated/signature_prometheus_405.h @@ -3,6 +3,6 @@ // #define SIGNATURE_BOARD prometheus_405 -#define SIGNATURE_DATE 2020.07.26 -#define SIGNATURE_HASH 2603514747 -#define TS_SIGNATURE "rusEFI 2020.07.26.prometheus_405.2603514747" +#define SIGNATURE_DATE 2020.07.27 +#define SIGNATURE_HASH 4282686897 +#define TS_SIGNATURE "rusEFI 2020.07.27.prometheus_405.4282686897" diff --git a/firmware/controllers/generated/signature_prometheus_469.h b/firmware/controllers/generated/signature_prometheus_469.h index 7d34426963..16f1fe23e3 100644 --- a/firmware/controllers/generated/signature_prometheus_469.h +++ b/firmware/controllers/generated/signature_prometheus_469.h @@ -3,6 +3,6 @@ // #define SIGNATURE_BOARD prometheus_469 -#define SIGNATURE_DATE 2020.07.26 -#define SIGNATURE_HASH 2603514747 -#define TS_SIGNATURE "rusEFI 2020.07.26.prometheus_469.2603514747" +#define SIGNATURE_DATE 2020.07.27 +#define SIGNATURE_HASH 4282686897 +#define TS_SIGNATURE "rusEFI 2020.07.27.prometheus_469.4282686897" diff --git a/firmware/controllers/generated/signature_proteus_f4.h b/firmware/controllers/generated/signature_proteus_f4.h index 808253fa23..444cc7ebef 100644 --- a/firmware/controllers/generated/signature_proteus_f4.h +++ b/firmware/controllers/generated/signature_proteus_f4.h @@ -3,6 +3,6 @@ // #define SIGNATURE_BOARD proteus_f4 -#define SIGNATURE_DATE 2020.07.26 -#define SIGNATURE_HASH 3819164208 -#define TS_SIGNATURE "rusEFI 2020.07.26.proteus_f4.3819164208" +#define SIGNATURE_DATE 2020.07.27 +#define SIGNATURE_HASH 2278110458 +#define TS_SIGNATURE "rusEFI 2020.07.27.proteus_f4.2278110458" diff --git a/firmware/controllers/generated/signature_proteus_f7.h b/firmware/controllers/generated/signature_proteus_f7.h index 57c42c4072..0f2f6705da 100644 --- a/firmware/controllers/generated/signature_proteus_f7.h +++ b/firmware/controllers/generated/signature_proteus_f7.h @@ -3,6 +3,6 @@ // #define SIGNATURE_BOARD proteus_f7 -#define SIGNATURE_DATE 2020.07.26 -#define SIGNATURE_HASH 3819164208 -#define TS_SIGNATURE "rusEFI 2020.07.26.proteus_f7.3819164208" +#define SIGNATURE_DATE 2020.07.27 +#define SIGNATURE_HASH 2278110458 +#define TS_SIGNATURE "rusEFI 2020.07.27.proteus_f7.2278110458" diff --git a/firmware/tunerstudio/generated/cache.zip b/firmware/tunerstudio/generated/cache.zip index 836de805be81598268c9d583561613d554d5e901..aee5e28c82b025ed453284cf9a09b0e6a572b44b 100644 GIT binary patch delta 236456 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 delta 235393 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 d00$YFe~l%;eq - +