diff --git a/java_console/autoupdate/src/com/rusefi/autoupdate/AutoupdateUtil.java b/java_console/autoupdate/src/com/rusefi/autoupdate/AutoupdateUtil.java index f863098194..0c4a2062bd 100644 --- a/java_console/autoupdate/src/com/rusefi/autoupdate/AutoupdateUtil.java +++ b/java_console/autoupdate/src/com/rusefi/autoupdate/AutoupdateUtil.java @@ -19,6 +19,8 @@ public class AutoupdateUtil { private static final int BUFFER_SIZE = 32 * 1024; private static final int STEPS = 1000; + // todo: figure out a better way to work with absolute path + private static final String APPICON = "/appicon.png"; public static void downloadAutoupdateFile(String localZipFileName, ConnectionAndMeta connectionAndMeta, String title) throws IOException { HttpURLConnection httpConnection = connectionAndMeta.httpConnection; @@ -103,6 +105,12 @@ public class AutoupdateUtil { } } + public static void setAppIcon(JFrame frame) { + ImageIcon icon = loadIcon(APPICON); + if (icon != null) + frame.setIconImage(icon.getImage()); + } + public static class ConnectionAndMeta { private String zipFileName; private HttpURLConnection httpConnection; diff --git a/java_console/ui/resources/com/rusefi/appicon.png b/java_console/shared_ui/resources/com/rusefi/appicon.png similarity index 100% rename from java_console/ui/resources/com/rusefi/appicon.png rename to java_console/shared_ui/resources/com/rusefi/appicon.png diff --git a/java_console/shared_ui/shared_ui.iml b/java_console/shared_ui/shared_ui.iml index c51500b928..c258fee90d 100644 --- a/java_console/shared_ui/shared_ui.iml +++ b/java_console/shared_ui/shared_ui.iml @@ -4,6 +4,7 @@ + diff --git a/java_console/shared_ui/src/com/rusefi/ui/AuthTokenPanel.java b/java_console/shared_ui/src/com/rusefi/ui/AuthTokenPanel.java index 3fe694c8ef..59f556f884 100644 --- a/java_console/shared_ui/src/com/rusefi/ui/AuthTokenPanel.java +++ b/java_console/shared_ui/src/com/rusefi/ui/AuthTokenPanel.java @@ -98,7 +98,7 @@ public class AuthTokenPanel { try { String data = (String) clipboard.getData(DataFlavor.stringFlavor); paste.setEnabled(AutoTokenUtil.isToken(data)); - } catch (IOException | UnsupportedFlavorException ex) { + } catch (IOException | IllegalStateException | UnsupportedFlavorException ex) { // ignoring this exception } } diff --git a/java_console/ui/src/main/java/com/rusefi/ConsoleUI.java b/java_console/ui/src/main/java/com/rusefi/ConsoleUI.java index 43cf3ce46e..b3b1c20188 100644 --- a/java_console/ui/src/main/java/com/rusefi/ConsoleUI.java +++ b/java_console/ui/src/main/java/com/rusefi/ConsoleUI.java @@ -1,6 +1,7 @@ package com.rusefi; import com.rusefi.autodetect.PortDetector; +import com.rusefi.autoupdate.AutoupdateUtil; import com.rusefi.config.generated.Fields; import com.rusefi.core.MessagesCentral; import com.rusefi.core.Sensor; @@ -158,7 +159,7 @@ public class ConsoleUI { } }); - StartupFrame.setAppIcon(mainFrame.getFrame().getFrame()); + AutoupdateUtil.setAppIcon(mainFrame.getFrame().getFrame()); mainFrame.getFrame().showFrame(tabbedPane.tabbedPane); } diff --git a/java_console/ui/src/main/java/com/rusefi/StartupFrame.java b/java_console/ui/src/main/java/com/rusefi/StartupFrame.java index 1f6e646d23..b0a75ee4bf 100644 --- a/java_console/ui/src/main/java/com/rusefi/StartupFrame.java +++ b/java_console/ui/src/main/java/com/rusefi/StartupFrame.java @@ -36,8 +36,6 @@ import static javax.swing.JOptionPane.YES_NO_OPTION; * @see FirmwareFlasher */ public class StartupFrame { - // todo: figure out a better way to work with absolute path - private static final String APPICON = "/appicon.png"; private static final String LOGO = "/com/rusefi/logo.gif"; public static final String LINK_TEXT = "rusEFI (c) 2012-2020"; private static final String URI = "http://rusefi.com/?java_console"; @@ -80,16 +78,10 @@ public class StartupFrame { } } }); - setAppIcon(frame); + AutoupdateUtil.setAppIcon(frame); SerialPortScanner.INSTANCE.startTimer(); } - public static void setAppIcon(JFrame frame) { - ImageIcon icon = AutoupdateUtil.loadIcon(APPICON); - if (icon != null) - frame.setIconImage(icon.getImage()); - } - public void chooseSerialPort() { realHardwarePanel.setBorder(new TitledBorder(BorderFactory.createLineBorder(Color.darkGray), "Real stm32")); miscPanel.setBorder(new TitledBorder(BorderFactory.createLineBorder(Color.darkGray), "Miscellaneous")); diff --git a/java_tools/ts_plugin/build.xml b/java_tools/ts_plugin/build.xml index 0cc26e482b..45c94c7388 100644 --- a/java_tools/ts_plugin/build.xml +++ b/java_tools/ts_plugin/build.xml @@ -32,6 +32,7 @@ + diff --git a/java_tools/ts_plugin/src/com/rusefi/ts_plugin/PluginBodySandbox.java b/java_tools/ts_plugin/src/com/rusefi/ts_plugin/PluginBodySandbox.java index a402f4ebcb..086951bc45 100644 --- a/java_tools/ts_plugin/src/com/rusefi/ts_plugin/PluginBodySandbox.java +++ b/java_tools/ts_plugin/src/com/rusefi/ts_plugin/PluginBodySandbox.java @@ -1,12 +1,20 @@ package com.rusefi.ts_plugin; +import com.efiAnalytics.plugin.ecu.ControllerAccess; import com.rusefi.ui.util.FrameHelper; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + /** * @see PluginLauncherSandbox */ public class PluginBodySandbox { public static void main(String[] args) { - new FrameHelper().showFrame(new PluginEntry().getContent()); + new FrameHelper().showFrame(new PluginEntry(() -> { + ControllerAccess controllerAccess = mock(ControllerAccess.class); + when(controllerAccess.getEcuConfigurationNames()).thenReturn(new String[]{"dev"}); + return controllerAccess; + }).getContent()); } } diff --git a/java_tools/ts_plugin/src/com/rusefi/ts_plugin/PluginEntry.java b/java_tools/ts_plugin/src/com/rusefi/ts_plugin/PluginEntry.java index 48466e7d4d..b7540d04f9 100644 --- a/java_tools/ts_plugin/src/com/rusefi/ts_plugin/PluginEntry.java +++ b/java_tools/ts_plugin/src/com/rusefi/ts_plugin/PluginEntry.java @@ -1,10 +1,6 @@ package com.rusefi.ts_plugin; import com.efiAnalytics.plugin.ecu.ControllerAccess; -import com.efiAnalytics.plugin.ecu.ControllerException; -import com.efiAnalytics.plugin.ecu.ControllerParameter; -import com.efiAnalytics.plugin.ecu.servers.ControllerParameterServer; -import com.rusefi.TsTuneReader; import com.rusefi.autoupdate.AutoupdateUtil; import com.rusefi.tools.online.Online; import com.rusefi.tune.xml.Constant; @@ -16,12 +12,12 @@ import org.jetbrains.annotations.NotNull; import org.putgemin.VerticalFlowLayout; import javax.swing.*; -import javax.xml.bind.JAXBException; +import java.awt.*; import java.awt.event.ActionEvent; import java.io.IOException; import java.net.URL; import java.util.Map; -import java.util.TreeMap; +import java.util.function.Supplier; import java.util.jar.Attributes; import java.util.jar.Manifest; @@ -37,20 +33,42 @@ public class PluginEntry implements TsPluginBody { private static final ImageIcon LOGO = AutoupdateUtil.loadIcon("/rusefi_online_color_300.png"); private final JButton upload = new JButton("Upload Current Tune"); - private static final JLabel warning = new JLabel("Please open project"); + private static final JLabel projectWarning = new JLabel("Please open project"); + private static final JLabel tuneWarning = new JLabel(); + private final Supplier controllerAccessSupplier; + private String currentConfiguration; + private boolean tuneIsOk; + private boolean projectIsOk; + + /** + * the real constructor - this one is invoked via reflection + */ public PluginEntry() { + this(ControllerAccess::getInstance); + } + + public PluginEntry(Supplier controllerAccessSupplier) { + this.controllerAccessSupplier = controllerAccessSupplier; + upload.setBackground(new Color(0x90EE90)); new Thread(new Runnable() { @Override public void run() { while (true) { - boolean isProjectActive = getConfigurationName() != null; + String configurationName = getConfigurationName(); + if ((currentConfiguration == null && configurationName != null) + || !currentConfiguration.equals(configurationName)) { + handleConfigurationChange(configurationName); + } + + boolean isProjectActive = configurationName != null; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - warning.setVisible(!isProjectActive); - upload.setEnabled(isProjectActive); + projectWarning.setVisible(!isProjectActive); + projectIsOk = isProjectActive; + updateUploadEnabled(); } }); @@ -76,7 +94,7 @@ public class PluginEntry implements TsPluginBody { return; } - Msq tune = writeCurrentTune(ControllerAccess.getInstance(), configurationName); + Msq tune = TuneUploder.writeCurrentTune(ControllerAccess.getInstance(), configurationName); Online.uploadTune(tune, tokenPanel, content); } }); @@ -84,13 +102,51 @@ public class PluginEntry implements TsPluginBody { content.add(new JLabel(getAttribute(BUILT_TIMESTAMP))); // content.add(new JLabel("Active project: " + getConfigurationName())); - content.add(warning); + content.add(projectWarning); + content.add(tuneWarning); content.add(upload); content.add(new JLabel(LOGO)); content.add(tokenPanel.getContent()); content.add(new URLLabel(REO)); } + private void handleConfigurationChange(String configurationName) { + Map fileSystemValues = TuneUploder.getFileSystemValues(configurationName); + Constant engineMake = fileSystemValues.get("enginemake"); + Constant engineCode = fileSystemValues.get("enginecode"); + Constant vehicleName = fileSystemValues.get("VEHICLENAME"); + String warning = ""; + if (isEmpty(engineMake.getValue())) { + warning += " engine make"; + } + if (isEmpty(engineCode.getValue())) { + warning += " engine code"; + } + if (isEmpty(vehicleName.getValue())) { + warning += " vehicle name"; + } + if (warning.isEmpty()) { + tuneWarning.setVisible(false); + tuneIsOk = true; + updateUploadEnabled(); + } else { + tuneWarning.setText("Please set " + warning + " on Base Settings tab
and reopen Project"); + tuneWarning.setForeground(Color.red); + tuneWarning.setVisible(true); + tuneIsOk = false; + updateUploadEnabled(); + } + currentConfiguration = configurationName; + } + + private void updateUploadEnabled() { + upload.setEnabled(tuneIsOk && projectIsOk); + } + + private boolean isEmpty(String engineCode) { + return engineCode == null || engineCode.trim().length() == 0; + } + @Override public JComponent getContent() { return content; @@ -106,23 +162,8 @@ public class PluginEntry implements TsPluginBody { } } - private static String getArrayValue(double[][] arrayValues) { - StringBuilder sb = new StringBuilder(); - for (int rowIndex = 0; rowIndex < arrayValues.length; rowIndex++) { - double[] array = arrayValues[rowIndex]; - sb.append("\n\t"); - for (int colIndex = 0; colIndex < array.length; colIndex++) { - double value = array[colIndex]; - sb.append(' '); - sb.append(value); - } - } - sb.append("\n"); - return sb.toString(); - } - - public static String getConfigurationName() { - ControllerAccess controllerAccess = ControllerAccess.getInstance(); + private String getConfigurationName() { + ControllerAccess controllerAccess = controllerAccessSupplier.get(); if (controllerAccess == null) { System.out.println("No ControllerAccess"); return null; @@ -133,65 +174,6 @@ public class PluginEntry implements TsPluginBody { return configurationNames[0]; } - private static String toString(double scalarValue, int decimalPlaces) { - // todo: start using decimalPlaces parameter! - return Double.toString(scalarValue); - } - - private static Msq writeCurrentTune(ControllerAccess controllerAccess, String configurationName) { - Msq msq = new Msq(); - ControllerParameterServer controllerParameterServer = controllerAccess.getControllerParameterServer(); - - Msq tsTune = TsTuneReader.readTsTune(configurationName); - Map byName = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - for (Constant c : tsTune.findPage().constant) { - byName.put(c.getName(), c); - } - - try { - String[] parameterNames = controllerParameterServer.getParameterNames(configurationName); - for (String parameterName : parameterNames) { - ControllerParameter cp = controllerParameterServer.getControllerParameter(configurationName, parameterName); - String type = cp.getParamClass(); - String value; - if (ControllerParameter.PARAM_CLASS_BITS.equals(type)) { - value = cp.getStringValue(); - System.out.println("TsPlugin bits " + parameterName + ": " + value); - } else if (ControllerParameter.PARAM_CLASS_SCALAR.equals(type)) { - value = toString(cp.getScalarValue(), cp.getDecimalPlaces()); - System.out.println("TsPlugin scalar " + parameterName + ": " + cp.getScalarValue() + "/" + cp.getStringValue()); - - } else if (ControllerParameter.PARAM_CLASS_ARRAY.equals(type)) { - value = getArrayValue(cp.getArrayValues()); - } else if ("string".equals(type)) { - //value = cp.getStringValue(); - // WOW hack - // TS does not provide values for string parameters?! so we read the file directly - Constant constant = byName.get(parameterName); - if (constant == null) { - System.out.println("Not found in TS tune " + parameterName); - value = null; - } else { - value = constant.getValue(); - System.out.println("TsPlugin name=" + parameterName + " string=" + cp.getStringValue() + "/h=" + value); - } - } else { - System.out.println("TsPlugin name=" + parameterName + " unexpected type " + type + "/" + cp.getStringValue()); - value = cp.getStringValue(); - } - - msq.findPage().constant.add(new Constant(parameterName, cp.getUnits(), value)); - } - - String fileName = Msq.outputXmlFileName; - msq.writeXmlFile(fileName); - return msq; - } catch (JAXBException | IOException | ControllerException e) { - System.out.println("Error writing XML: " + e); - return null; - } - } - /** * this method is invoked by refection * diff --git a/java_tools/ts_plugin/src/com/rusefi/ts_plugin/TuneUploder.java b/java_tools/ts_plugin/src/com/rusefi/ts_plugin/TuneUploder.java new file mode 100644 index 0000000000..441e161f32 --- /dev/null +++ b/java_tools/ts_plugin/src/com/rusefi/ts_plugin/TuneUploder.java @@ -0,0 +1,104 @@ +package com.rusefi.ts_plugin; + +import com.efiAnalytics.plugin.ecu.ControllerAccess; +import com.efiAnalytics.plugin.ecu.ControllerException; +import com.efiAnalytics.plugin.ecu.ControllerParameter; +import com.efiAnalytics.plugin.ecu.servers.ControllerParameterServer; +import com.rusefi.TsTuneReader; +import com.rusefi.tune.xml.Constant; +import com.rusefi.tune.xml.Msq; +import org.jetbrains.annotations.NotNull; + +import javax.xml.bind.JAXBException; +import java.io.IOException; +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; + +public class TuneUploder { + static Msq writeCurrentTune(ControllerAccess controllerAccess, String configurationName) { + Msq msq = new Msq(); + ControllerParameterServer controllerParameterServer = controllerAccess.getControllerParameterServer(); + + Map fileSystemValues = getFileSystemValues(configurationName); + + try { + String[] parameterNames = controllerParameterServer.getParameterNames(configurationName); + for (String parameterName : parameterNames) { + handleParameter(configurationName, msq, controllerParameterServer, fileSystemValues, parameterName); + } + + String fileName = Msq.outputXmlFileName; + msq.writeXmlFile(fileName); + return msq; + } catch (JAXBException | IOException | ControllerException e) { + System.out.println("Error writing XML: " + e); + return null; + } + } + + @NotNull + static Map getFileSystemValues(String configurationName) { + if (configurationName == null) + return Collections.emptyMap(); + Msq tsTune = TsTuneReader.readTsTune(configurationName); + Map byName = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + for (Constant c : tsTune.findPage().constant) { + byName.put(c.getName(), c); + } + return byName; + } + + private static void handleParameter(String configurationName, Msq msq, ControllerParameterServer controllerParameterServer, Map byName, String parameterName) throws ControllerException { + ControllerParameter cp = controllerParameterServer.getControllerParameter(configurationName, parameterName); + String type = cp.getParamClass(); + String value; + if (ControllerParameter.PARAM_CLASS_BITS.equals(type)) { + value = cp.getStringValue(); + System.out.println("TsPlugin bits " + parameterName + ": " + value); + } else if (ControllerParameter.PARAM_CLASS_SCALAR.equals(type)) { + value = toString(cp.getScalarValue(), cp.getDecimalPlaces()); + System.out.println("TsPlugin scalar " + parameterName + ": " + cp.getScalarValue() + "/" + cp.getStringValue()); + + } else if (ControllerParameter.PARAM_CLASS_ARRAY.equals(type)) { + value = getArrayValue(cp.getArrayValues()); + } else if ("string".equals(type)) { + //value = cp.getStringValue(); + // WOW hack + // TS does not provide values for string parameters?! so we read the file directly + Constant constant = byName.get(parameterName); + if (constant == null) { + System.out.println("Not found in TS tune " + parameterName); + value = null; + } else { + value = constant.getValue(); + System.out.println("TsPlugin name=" + parameterName + " string=" + cp.getStringValue() + "/h=" + value); + } + } else { + System.out.println("TsPlugin name=" + parameterName + " unexpected type " + type + "/" + cp.getStringValue()); + value = cp.getStringValue(); + } + + msq.findPage().constant.add(new Constant(parameterName, cp.getUnits(), value)); + } + + private static String getArrayValue(double[][] arrayValues) { + StringBuilder sb = new StringBuilder(); + for (int rowIndex = 0; rowIndex < arrayValues.length; rowIndex++) { + double[] array = arrayValues[rowIndex]; + sb.append("\n\t"); + for (int colIndex = 0; colIndex < array.length; colIndex++) { + double value = array[colIndex]; + sb.append(' '); + sb.append(value); + } + } + sb.append("\n"); + return sb.toString(); + } + + private static String toString(double scalarValue, int decimalPlaces) { + // todo: start using decimalPlaces parameter! + return Double.toString(scalarValue); + } +} diff --git a/java_tools/ts_plugin/ts_plugin.iml b/java_tools/ts_plugin/ts_plugin.iml index 37589882cd..9d813fb42d 100644 --- a/java_tools/ts_plugin/ts_plugin.iml +++ b/java_tools/ts_plugin/ts_plugin.iml @@ -11,5 +11,6 @@ + \ No newline at end of file diff --git a/java_tools/ts_plugin_launcher/.idea/libraries/org_mockito_mockito_all_1_10_19.xml b/java_tools/ts_plugin_launcher/.idea/libraries/org_mockito_mockito_all_1_10_19.xml new file mode 100644 index 0000000000..403be5147c --- /dev/null +++ b/java_tools/ts_plugin_launcher/.idea/libraries/org_mockito_mockito_all_1_10_19.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file 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 a1e303ea1e..9382f106f4 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 @@ -5,6 +5,7 @@ import com.rusefi.ui.storage.PersistentConfiguration; import org.putgemin.VerticalFlowLayout; import javax.swing.*; +import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; @@ -61,6 +62,7 @@ public class Updater { JButton download = new JButton("Update plugin"); if (version != null) { JButton run = new JButton("Run Version " + version); + run.setBackground(new Color(0x90EE90)); run.addActionListener(new AbstractAction() { @Override public void actionPerformed(ActionEvent e) {