REO progress

token setup usability
This commit is contained in:
rusefi 2020-06-22 19:52:40 -04:00
parent b07ee61699
commit a48513cc1e
13 changed files with 210 additions and 100 deletions

View File

@ -19,6 +19,8 @@ public class AutoupdateUtil {
private static final int BUFFER_SIZE = 32 * 1024; private static final int BUFFER_SIZE = 32 * 1024;
private static final int STEPS = 1000; 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 { public static void downloadAutoupdateFile(String localZipFileName, ConnectionAndMeta connectionAndMeta, String title) throws IOException {
HttpURLConnection httpConnection = connectionAndMeta.httpConnection; 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 { public static class ConnectionAndMeta {
private String zipFileName; private String zipFileName;
private HttpURLConnection httpConnection; private HttpURLConnection httpConnection;

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -4,6 +4,7 @@
<exclude-output /> <exclude-output />
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />

View File

@ -98,7 +98,7 @@ public class AuthTokenPanel {
try { try {
String data = (String) clipboard.getData(DataFlavor.stringFlavor); String data = (String) clipboard.getData(DataFlavor.stringFlavor);
paste.setEnabled(AutoTokenUtil.isToken(data)); paste.setEnabled(AutoTokenUtil.isToken(data));
} catch (IOException | UnsupportedFlavorException ex) { } catch (IOException | IllegalStateException | UnsupportedFlavorException ex) {
// ignoring this exception // ignoring this exception
} }
} }

View File

@ -1,6 +1,7 @@
package com.rusefi; package com.rusefi;
import com.rusefi.autodetect.PortDetector; import com.rusefi.autodetect.PortDetector;
import com.rusefi.autoupdate.AutoupdateUtil;
import com.rusefi.config.generated.Fields; import com.rusefi.config.generated.Fields;
import com.rusefi.core.MessagesCentral; import com.rusefi.core.MessagesCentral;
import com.rusefi.core.Sensor; 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); mainFrame.getFrame().showFrame(tabbedPane.tabbedPane);
} }

View File

@ -36,8 +36,6 @@ import static javax.swing.JOptionPane.YES_NO_OPTION;
* @see FirmwareFlasher * @see FirmwareFlasher
*/ */
public class StartupFrame { 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"; private static final String LOGO = "/com/rusefi/logo.gif";
public static final String LINK_TEXT = "rusEFI (c) 2012-2020"; public static final String LINK_TEXT = "rusEFI (c) 2012-2020";
private static final String URI = "http://rusefi.com/?java_console"; 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(); SerialPortScanner.INSTANCE.startTimer();
} }
public static void setAppIcon(JFrame frame) {
ImageIcon icon = AutoupdateUtil.loadIcon(APPICON);
if (icon != null)
frame.setIconImage(icon.getImage());
}
public void chooseSerialPort() { public void chooseSerialPort() {
realHardwarePanel.setBorder(new TitledBorder(BorderFactory.createLineBorder(Color.darkGray), "Real stm32")); realHardwarePanel.setBorder(new TitledBorder(BorderFactory.createLineBorder(Color.darkGray), "Real stm32"));
miscPanel.setBorder(new TitledBorder(BorderFactory.createLineBorder(Color.darkGray), "Miscellaneous")); miscPanel.setBorder(new TitledBorder(BorderFactory.createLineBorder(Color.darkGray), "Miscellaneous"));

View File

@ -32,6 +32,7 @@
<copy todir="build/classes"> <copy todir="build/classes">
<fileset dir="../ts_plugin_launcher/resources" includes="**/*.png"/> <fileset dir="../ts_plugin_launcher/resources" includes="**/*.png"/>
<fileset dir="${console_path}/shared_ui/resources" includes="**/*.png"/>
</copy> </copy>
<tstamp> <tstamp>

View File

@ -1,12 +1,20 @@
package com.rusefi.ts_plugin; package com.rusefi.ts_plugin;
import com.efiAnalytics.plugin.ecu.ControllerAccess;
import com.rusefi.ui.util.FrameHelper; import com.rusefi.ui.util.FrameHelper;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/** /**
* @see PluginLauncherSandbox * @see PluginLauncherSandbox
*/ */
public class PluginBodySandbox { public class PluginBodySandbox {
public static void main(String[] args) { 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());
} }
} }

View File

@ -1,10 +1,6 @@
package com.rusefi.ts_plugin; package com.rusefi.ts_plugin;
import com.efiAnalytics.plugin.ecu.ControllerAccess; 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.autoupdate.AutoupdateUtil;
import com.rusefi.tools.online.Online; import com.rusefi.tools.online.Online;
import com.rusefi.tune.xml.Constant; import com.rusefi.tune.xml.Constant;
@ -16,12 +12,12 @@ import org.jetbrains.annotations.NotNull;
import org.putgemin.VerticalFlowLayout; import org.putgemin.VerticalFlowLayout;
import javax.swing.*; import javax.swing.*;
import javax.xml.bind.JAXBException; import java.awt.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.function.Supplier;
import java.util.jar.Attributes; import java.util.jar.Attributes;
import java.util.jar.Manifest; 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 static final ImageIcon LOGO = AutoupdateUtil.loadIcon("/rusefi_online_color_300.png");
private final JButton upload = new JButton("Upload Current Tune"); 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<ControllerAccess> controllerAccessSupplier;
private String currentConfiguration;
private boolean tuneIsOk;
private boolean projectIsOk;
/**
* the real constructor - this one is invoked via reflection
*/
public PluginEntry() { public PluginEntry() {
this(ControllerAccess::getInstance);
}
public PluginEntry(Supplier<ControllerAccess> controllerAccessSupplier) {
this.controllerAccessSupplier = controllerAccessSupplier;
upload.setBackground(new Color(0x90EE90));
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
while (true) { 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() { SwingUtilities.invokeLater(new Runnable() {
@Override @Override
public void run() { public void run() {
warning.setVisible(!isProjectActive); projectWarning.setVisible(!isProjectActive);
upload.setEnabled(isProjectActive); projectIsOk = isProjectActive;
updateUploadEnabled();
} }
}); });
@ -76,7 +94,7 @@ public class PluginEntry implements TsPluginBody {
return; return;
} }
Msq tune = writeCurrentTune(ControllerAccess.getInstance(), configurationName); Msq tune = TuneUploder.writeCurrentTune(ControllerAccess.getInstance(), configurationName);
Online.uploadTune(tune, tokenPanel, content); 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(getAttribute(BUILT_TIMESTAMP)));
// content.add(new JLabel("Active project: " + getConfigurationName())); // content.add(new JLabel("Active project: " + getConfigurationName()));
content.add(warning); content.add(projectWarning);
content.add(tuneWarning);
content.add(upload); content.add(upload);
content.add(new JLabel(LOGO)); content.add(new JLabel(LOGO));
content.add(tokenPanel.getContent()); content.add(tokenPanel.getContent());
content.add(new URLLabel(REO)); content.add(new URLLabel(REO));
} }
private void handleConfigurationChange(String configurationName) {
Map<String, Constant> 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("<html>Please set " + warning + " on Base Settings tab<br>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 @Override
public JComponent getContent() { public JComponent getContent() {
return content; return content;
@ -106,23 +162,8 @@ public class PluginEntry implements TsPluginBody {
} }
} }
private static String getArrayValue(double[][] arrayValues) { private String getConfigurationName() {
StringBuilder sb = new StringBuilder(); ControllerAccess controllerAccess = controllerAccessSupplier.get();
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();
if (controllerAccess == null) { if (controllerAccess == null) {
System.out.println("No ControllerAccess"); System.out.println("No ControllerAccess");
return null; return null;
@ -133,65 +174,6 @@ public class PluginEntry implements TsPluginBody {
return configurationNames[0]; 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<String, Constant> 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 * this method is invoked by refection
* *

View File

@ -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<String, Constant> 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<String, Constant> getFileSystemValues(String configurationName) {
if (configurationName == null)
return Collections.emptyMap();
Msq tsTune = TsTuneReader.readTsTune(configurationName);
Map<String, Constant> 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<String, Constant> 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);
}
}

View File

@ -11,5 +11,6 @@
<orderEntry type="module" module-name="shared_ui" /> <orderEntry type="module" module-name="shared_ui" />
<orderEntry type="library" name="TunerStudioPluginAPI" level="project" /> <orderEntry type="library" name="TunerStudioPluginAPI" level="project" />
<orderEntry type="module" module-name="ts_plugin_launcher" /> <orderEntry type="module" module-name="ts_plugin_launcher" />
<orderEntry type="library" name="org.mockito:mockito-all:1.10.19" level="project" />
</component> </component>
</module> </module>

View File

@ -0,0 +1,10 @@
<component name="libraryTable">
<library name="org.mockito:mockito-all:1.10.19" type="repository">
<properties maven-id="org.mockito:mockito-all:1.10.19" />
<CLASSES>
<root url="jar://$USER_HOME$/.m2/repository/org/mockito/mockito-all/1.10.19/mockito-all-1.10.19.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -5,6 +5,7 @@ import com.rusefi.ui.storage.PersistentConfiguration;
import org.putgemin.VerticalFlowLayout; import org.putgemin.VerticalFlowLayout;
import javax.swing.*; import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.io.File; import java.io.File;
@ -61,6 +62,7 @@ public class Updater {
JButton download = new JButton("Update plugin"); JButton download = new JButton("Update plugin");
if (version != null) { if (version != null) {
JButton run = new JButton("Run Version " + version); JButton run = new JButton("Run Version " + version);
run.setBackground(new Color(0x90EE90));
run.addActionListener(new AbstractAction() { run.addActionListener(new AbstractAction() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {