diff --git a/java_console/models/src/com/rusefi/rusEFIVersion.java b/java_console/models/src/com/rusefi/rusEFIVersion.java index 87f955712e..c255db7652 100644 --- a/java_console/models/src/com/rusefi/rusEFIVersion.java +++ b/java_console/models/src/com/rusefi/rusEFIVersion.java @@ -3,6 +3,6 @@ package com.rusefi; import java.util.concurrent.atomic.AtomicReference; public class rusEFIVersion { - public static final int CONSOLE_VERSION = 20200530; + public static final int CONSOLE_VERSION = 20200531; public static AtomicReference firmwareVersion = new AtomicReference<>("N/A"); } diff --git a/java_console/ui/src/com/rusefi/Launcher.java b/java_console/ui/src/com/rusefi/Launcher.java index d046c3d724..b31dd883a8 100644 --- a/java_console/ui/src/com/rusefi/Launcher.java +++ b/java_console/ui/src/com/rusefi/Launcher.java @@ -25,6 +25,7 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.*; import java.awt.event.ActionListener; +import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; @@ -182,6 +183,9 @@ public class Launcher extends rusEFIVersion { * @see StartupFrame if no parameters specified */ public static void main(final String[] args) throws Exception { + System.out.println("rusEfi UI console " + CONSOLE_VERSION); + System.out.println("Compiled " + new Date(ConsoleTools.classBuildTimeMillis())); + System.out.println("\n\n"); if (ConsoleTools.runTool(args)) { return; @@ -189,11 +193,8 @@ public class Launcher extends rusEFIVersion { ConsoleTools.printTools(); - System.out.println("Starting rusEfi UI console " + CONSOLE_VERSION); - FileLog.MAIN.start(); - getConfig().load(); FileLog.suspendLogging = getConfig().getRoot().getBoolProperty(GaugesPanel.DISABLE_LOGS); Thread.setDefaultUncaughtExceptionHandler(new DefaultExceptionHandler()); diff --git a/java_console/ui/src/com/rusefi/tools/ConsoleTools.java b/java_console/ui/src/com/rusefi/tools/ConsoleTools.java index eedd96eef2..2e0ae1fd84 100644 --- a/java_console/ui/src/com/rusefi/tools/ConsoleTools.java +++ b/java_console/ui/src/com/rusefi/tools/ConsoleTools.java @@ -15,72 +15,59 @@ import com.rusefi.io.serial.SerialIoStreamJSerialComm; import com.rusefi.maintenance.ExecHelper; import com.rusefi.tools.online.Online; import com.rusefi.tune.xml.Msq; +import com.rusefi.ui.OnlineTab; import org.jetbrains.annotations.Nullable; import javax.xml.bind.JAXBException; import java.io.File; import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; import java.util.Arrays; import java.util.Map; -import java.util.Objects; import java.util.TreeMap; +import static com.rusefi.ui.storage.PersistentConfiguration.getConfig; + public class ConsoleTools { + public static final String SET_AUTH_TOKEN = "set_auth_token"; private static Map TOOLS = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + private static Map toolsHelp = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + static { - TOOLS.put("help", args -> printTools()); - TOOLS.put("headless", ConsoleTools::runHeadless); - TOOLS.put("compile", ConsoleTools::invokeCompileExpressionTool); - TOOLS.put("ptrace_enums", ConsoleTools::runPerfTraceTool); - TOOLS.put("save_binary_configuration", ConsoleTools::saveBinaryConfig); - TOOLS.put("functional_test", ConsoleTools::runFunctionalTest); - TOOLS.put("compile_fsio_file", ConsoleTools::runCompileTool); - TOOLS.put("firing_order", ConsoleTools::runFiringOrderTool); - TOOLS.put("convert_binary_configuration_to_xml", ConsoleTools::convertBinaryToXml); - TOOLS.put("reboot_ecu", args -> sendCommand(Fields.CMD_REBOOT)); - TOOLS.put(Fields.CMD_REBOOT_DFU, args -> sendCommand(Fields.CMD_REBOOT_DFU)); + TOOLSput("help", args -> printTools(), "Print this help."); + TOOLSput("headless", ConsoleTools::runHeadless, "Connect to rusEFI controller and start saving logs."); + + TOOLSput("ptrace_enums", ConsoleTools::runPerfTraceTool, "NOT A USER TOOL. Development tool to process pefrormance trace enums"); + TOOLSput("firing_order", ConsoleTools::runFiringOrderTool, "NOT A USER TOOL. Development tool relating to adding new firing order into rusEFI firmware."); + TOOLSput("functional_test", ConsoleTools::runFunctionalTest, "NOT A USER TOOL. Development tool related to functional testing"); + TOOLSput("convert_binary_configuration_to_xml", ConsoleTools::convertBinaryToXml, "NOT A USER TOOL. Development tool to convert binary configuration into XML form."); + + TOOLSput("compile_fsio_line", ConsoleTools::invokeCompileExpressionTool, "Convert a line to RPN form."); + TOOLSput("compile_fsio_file", ConsoleTools::runCompileTool, "Convert all lines from a file to RPN form."); + + TOOLSput("print_auth_token", args -> printAuthToken(), "Print current rusEFI Online authentication token."); + TOOLSput(SET_AUTH_TOKEN, ConsoleTools::setAuthToken, "Set rusEFI authentication token."); + + TOOLSput("reboot_ecu", args -> sendCommand(Fields.CMD_REBOOT), "Sends a command to reboot rusEFI controller."); + TOOLSput(Fields.CMD_REBOOT_DFU, args -> sendCommand(Fields.CMD_REBOOT_DFU), "Sends a command to switch rusEFI controller into DFU mode."); + } + + private static void TOOLSput(String command, ConsoleTool callback, String help) { + TOOLS.put(command, callback); + toolsHelp.put(command, help); } public static void printTools() { for (String key : TOOLS.keySet()) { System.out.println("Tool available: " + key); - } - } - - private static void saveBinaryConfig(String[] args) throws IOException { - if (args.length < 2) { - System.out.println("Please specify output file name for binary configuration"); - System.exit(-1); - } - String fileName = args[1]; - - String autoDetectedPort = autoDetectPort(); - if (autoDetectedPort == null) - return; - LinkManager.startAndConnect(autoDetectedPort, new ConnectionStateListener() { - @Override - public void onConnectionEstablished() { - BinaryProtocol binaryProtocol = LinkManager.connector.getBinaryProtocol(); - Objects.requireNonNull(binaryProtocol, "binaryProtocol"); - ConfigurationImage configurationImage = binaryProtocol.getControllerConfiguration(); - Objects.requireNonNull(configurationImage, "configurationImage"); - - try { - ConfigurationImageFile.saveToFile(configurationImage, fileName); - System.exit(0); - } catch (IOException e) { - System.out.println("While writing " + e); - System.exit(-1); - } + String help = toolsHelp.get(key); + if (help != null) { + System.out.println("\t" + help); + System.out.println("\n"); } - - @Override - public void onConnectionFailed() { - System.out.println("onConnectionFailed"); - System.exit(-1); - } - }); + } } private static void sendCommand(String command) throws IOException { @@ -106,6 +93,21 @@ public class ConsoleTools { System.exit(returnCode); } + private static void setAuthToken(String[] args) { + String newToken = args[1]; + getConfig().getRoot().setProperty(OnlineTab.AUTH_TOKEN, newToken); + } + + private static void printAuthToken() { + String authToken = getConfig().getRoot().getProperty(OnlineTab.AUTH_TOKEN); + if (authToken.trim().isEmpty()) { + System.out.println("Auth token not defined. Please use " + SET_AUTH_TOKEN + " command"); + System.out.println("\tPlease see https://github.com/rusefi/rusefi/wiki/Online"); + return; + } + System.out.println("Auth token: " + authToken); + } + private static void runFunctionalTest(String[] args) throws InterruptedException { // passing port argument if it was specified String[] toolArgs = args.length == 1 ? new String[0] : new String[]{args[1]}; @@ -214,6 +216,26 @@ public class ConsoleTools { Online.upload(new File(Msq.outputXmlFileName), "x"); } + public static long classBuildTimeMillis() throws URISyntaxException, IllegalStateException, IllegalArgumentException { + Class clazz = ConsoleTools.class; + URL resource = clazz.getResource(clazz.getSimpleName() + ".class"); + if (resource == null) { + throw new IllegalStateException("Failed to find class file for class: " + + clazz.getName()); + } + + if (resource.getProtocol().equals("file")) { + return new File(resource.toURI()).lastModified(); + } else if (resource.getProtocol().equals("jar")) { + String path = resource.getPath(); + return new File(path.substring(5, path.indexOf("!"))).lastModified(); + } else { + throw new IllegalArgumentException("Unhandled url protocol: " + + resource.getProtocol() + " for class: " + + clazz.getName() + " resource: " + resource.toString()); + } + } + interface ConsoleTool { void runTool(String args[]) throws Exception; } diff --git a/java_console/ui/src/com/rusefi/ui/OnlineTab.java b/java_console/ui/src/com/rusefi/ui/OnlineTab.java index b1cd9f1d6a..28d03eb809 100644 --- a/java_console/ui/src/com/rusefi/ui/OnlineTab.java +++ b/java_console/ui/src/com/rusefi/ui/OnlineTab.java @@ -17,7 +17,7 @@ import java.io.IOException; import static com.rusefi.ui.storage.PersistentConfiguration.getConfig; public class OnlineTab { - private static final String AUTH_TOKEN = "auth_token"; + public static final String AUTH_TOKEN = "auth_token"; private static final String TOKEN_WARNING = "Please copy token from your forum profile"; private final JPanel content = new JPanel(new VerticalFlowLayout()); diff --git a/java_console/ui/src/com/rusefi/ui/storage/Node.java b/java_console/ui/src/com/rusefi/ui/storage/Node.java index 2c8a9a7512..ad1e8a7dbb 100644 --- a/java_console/ui/src/com/rusefi/ui/storage/Node.java +++ b/java_console/ui/src/com/rusefi/ui/storage/Node.java @@ -6,6 +6,9 @@ import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.Map; +/** + * @see PersistentConfiguration + */ public class Node { private String prefix; private Map config = new HashMap<>(); diff --git a/java_console/ui/src/com/rusefi/ui/storage/PersistentConfiguration.java b/java_console/ui/src/com/rusefi/ui/storage/PersistentConfiguration.java index 2d8be05779..d6406c07f4 100644 --- a/java_console/ui/src/com/rusefi/ui/storage/PersistentConfiguration.java +++ b/java_console/ui/src/com/rusefi/ui/storage/PersistentConfiguration.java @@ -13,34 +13,50 @@ public class PersistentConfiguration { private static final String CONFIG_FILE_NAME = "rusefi_console_properties.xml"; private Map config = new HashMap<>(); + private boolean isLoaded; public static PersistentConfiguration getConfig() { return INSTANCE; } + private PersistentConfiguration() { + Runtime.getRuntime().addShutdownHook(new Thread(() -> getConfig().save())); + } + @SuppressWarnings("unchecked") public void load() { try { XMLDecoder e = new XMLDecoder(new BufferedInputStream(new FileInputStream(CONFIG_FILE_NAME))); config = (Map) e.readObject(); e.close(); + System.out.println("Got configuration from " + CONFIG_FILE_NAME); } catch (Throwable e) { FileLog.MAIN.logLine("Console configuration not found " + CONFIG_FILE_NAME + ", using defaults"); } + isLoaded = true; } + /** + * todo: maybe the shutdown hook is the only place where this method should be invoked? + */ public void save() { + if (!isLoaded) { + // settings not loaded, nothing to save + return; + } try { XMLEncoder e = new XMLEncoder(new BufferedOutputStream(new FileOutputStream(CONFIG_FILE_NAME))); e.writeObject(config); e.close(); - System.out.println("Saved to " + CONFIG_FILE_NAME); + System.out.println("Saved settings to " + CONFIG_FILE_NAME); } catch (FileNotFoundException e1) { FileLog.MAIN.logLine("Error saving " + CONFIG_FILE_NAME); } } public Node getRoot() { + if (!isLoaded) + load(); return new Node("root", config); } } \ No newline at end of file