log upload tab

This commit is contained in:
rusefi 2020-08-12 20:37:37 -04:00
parent 794b907f62
commit 17a7a89e28
7 changed files with 149 additions and 47 deletions

View File

@ -13,6 +13,7 @@ import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody; import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody; import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultHttpClient;
import org.jetbrains.annotations.Nullable;
import org.json.simple.JSONArray; import org.json.simple.JSONArray;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import org.json.simple.parser.ParseException; import org.json.simple.parser.ParseException;
@ -76,29 +77,30 @@ public class Online {
* we are here in case of individual tune upload * we are here in case of individual tune upload
*/ */
public static BasicFuture<UploadResult> uploadTune(Msq tune, AuthTokenPanel authTokenPanel, JComponent parent, FutureCallback<UploadResult> callback) { public static BasicFuture<UploadResult> uploadTune(Msq tune, AuthTokenPanel authTokenPanel, JComponent parent, FutureCallback<UploadResult> callback) {
try {
tune.writeXmlFile(outputXmlFileName);
} catch (JAXBException | IOException e) {
throw new IllegalStateException("While writing tune", e);
}
return uploadFile(parent, callback, outputXmlFileName);
}
@Nullable
public static BasicFuture<UploadResult> uploadFile(JComponent parent, FutureCallback<UploadResult> callback, final String fileName) {
BasicFuture<UploadResult> result = new BasicFuture<>(callback); BasicFuture<UploadResult> result = new BasicFuture<>(callback);
String authToken = authTokenPanel.getToken(); String authToken = AuthTokenPanel.getAuthToken();
if (!authTokenPanel.hasToken()) { if (!AuthTokenPanel.hasToken()) {
authTokenPanel.showError(parent); AuthTokenPanel.showError(parent);
return null; return null;
} }
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
UploadResult array = doUpload(authToken, tune); UploadResult array = upload(new File(fileName), authToken);
result.completed(array); result.completed(array);
} }
}).start(); }).start();
return result; return result;
} }
private static UploadResult doUpload(String authToken, Msq tune) {
try {
tune.writeXmlFile(outputXmlFileName);
// todo: network upload should not happen on UI thread
return upload(new File(outputXmlFileName), authToken);
} catch (JAXBException | IOException ex) {
return new UploadResult(true, "IO error " + ex);
}
}
} }

View File

@ -127,15 +127,15 @@ public class AuthTokenPanel {
return content; return content;
} }
public boolean hasToken() { public static boolean hasToken() {
return AutoTokenUtil.isToken(authTokenTestField.getText()); return AutoTokenUtil.isToken(getAuthToken());
} }
public String getToken() { public String getToken() {
return authTokenTestField.getText(); return authTokenTestField.getText();
} }
public void showError(JComponent parent) { public static void showError(JComponent parent) {
JOptionPane.showMessageDialog(parent, "Does not work without auth token, see below."); JOptionPane.showMessageDialog(parent, "Does not work without auth token, see below.");
} }
} }

View File

@ -1,27 +1,125 @@
package com.rusefi.ts_plugin; package com.rusefi.ts_plugin;
import com.efiAnalytics.plugin.ecu.ControllerAccess;
import com.rusefi.TsTuneReader; import com.rusefi.TsTuneReader;
import com.rusefi.autoupdate.AutoupdateUtil;
import com.rusefi.tools.online.Online;
import com.rusefi.tools.online.UploadResult;
import com.rusefi.ui.util.FrameHelper; import com.rusefi.ui.util.FrameHelper;
import org.apache.http.concurrent.FutureCallback;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.mockito.stubbing.Answer;
import org.putgemin.VerticalFlowLayout; import org.putgemin.VerticalFlowLayout;
import javax.swing.*; import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.File; import java.io.File;
import java.util.Objects;
import java.util.function.Supplier;
import static org.mockito.Mockito.*;
public class LogUploadSelector { public class LogUploadSelector {
private final JPanel content = new JPanel(new VerticalFlowLayout()); private final JPanel content = new JPanel(new BorderLayout());
private final JLabel uploadState = new JLabel();
private final JPanel fileList = new JPanel(new VerticalFlowLayout());
public static final Answer<?> NEGATIVE_ANSWER = invocation -> {
throw new UnsupportedOperationException("Not mocked " + invocation);
};
private final Supplier<ControllerAccess> controllerAccessSupplier;
public static void main(String[] args) { public static void main(String[] args) {
new FrameHelper().showFrame(new LogUploadSelector().getContent()); String projectName = "mre_f4";
ControllerAccess controllerAccess = mock(ControllerAccess.class, NEGATIVE_ANSWER);
doReturn(new String[]{projectName}).when(controllerAccess).getEcuConfigurationNames();
new FrameHelper().showFrame(new LogUploadSelector(() -> controllerAccess).getContent());
} }
public LogUploadSelector() { public LogUploadSelector(Supplier<ControllerAccess> controllerAccessSupplier) {
String projectName = "dev"; this.controllerAccessSupplier = controllerAccessSupplier;
String folder = getLogsFolderDir(projectName);
for (String fileName : new File(folder).list((dir, name) -> name.endsWith(".mlg"))) { JButton refresh = new JButton("Refresh");
System.out.println(fileName); refresh.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
refresh();
} }
});
JPanel topPanel = new JPanel(new FlowLayout());
topPanel.add(refresh);
JPanel filePanel = new JPanel(new BorderLayout());
filePanel.add(fileList, BorderLayout.CENTER);
JScrollPane fileScroll = new JScrollPane(filePanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
content.add(topPanel, BorderLayout.NORTH);
content.add(fileScroll, BorderLayout.CENTER);
content.add(uploadState, BorderLayout.SOUTH);
refresh();
}
private void refresh() {
fileList.removeAll();
String folder = getLogsFolderDir(controllerAccessSupplier.get().getEcuConfigurationNames()[0]);
for (String fileName : Objects.requireNonNull(new File(folder).list((dir, name) -> name.endsWith(".mlg")))) {
JPanel panel = new JPanel(new FlowLayout());
JButton delete = new JButton("Delete");
JButton upload = new JButton("Upload");
final String fullFileName = folder + File.separator + fileName;
panel.add(delete);
panel.add(upload);
delete.addActionListener(new AbstractAction() {
@SuppressWarnings("ResultOfMethodCallIgnored")
@Override
public void actionPerformed(ActionEvent e) {
int result = JOptionPane.showConfirmDialog(null, "Are you sure you want to remove " + fileName,
"rusEfi", JOptionPane.YES_NO_OPTION);
if (result == JOptionPane.YES_OPTION) {
new File(fullFileName).delete();
}
}
});
upload.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
Online.uploadFile(content, new FutureCallback<UploadResult>() {
@Override
public void completed(UploadResult uploadResult) {
SwingUtilities.invokeLater(() -> UploadView.setResult(uploadResult, uploadState));
}
@Override
public void failed(Exception e) {
}
@Override
public void cancelled() {
}
}, fullFileName);
}
});
panel.add(new JLabel(fileName));
fileList.add(panel);
}
AutoupdateUtil.trueLayout(content);
} }
@NotNull @NotNull
@ -29,8 +127,7 @@ public class LogUploadSelector {
return TsTuneReader.getProjectsDir() + File.separator + projectName + File.separator + "DataLogs"; return TsTuneReader.getProjectsDir() + File.separator + projectName + File.separator + "DataLogs";
} }
private JComponent getContent() { public JComponent getContent() {
return content; return content;
} }
} }

View File

@ -12,7 +12,7 @@ import java.util.function.Supplier;
/** /**
* {@link TsPluginLauncher} creates an instance of this class via reflection. * {@link TsPluginLauncher} creates an instance of this class via reflection.
* @see UploadTab upload tune & TODO upload logs * @see TuneUploadTab upload tune & TODO upload logs
* @see RemoteTab remote ECU access & control * @see RemoteTab remote ECU access & control
* @see BroadcastTab offer your ECU for remove access & control * @see BroadcastTab offer your ECU for remove access & control
* @see PluginBodySandbox * @see PluginBodySandbox
@ -40,12 +40,14 @@ public class PluginEntry implements TsPluginBody {
return; return;
} }
UploadTab uploadTab = new UploadTab(controllerAccessSupplier); TuneUploadTab tuneUploadTab = new TuneUploadTab(controllerAccessSupplier);
LogUploadSelector logUploadTab = new LogUploadSelector(controllerAccessSupplier);
BroadcastTab broadcastTab = new BroadcastTab(); BroadcastTab broadcastTab = new BroadcastTab();
RemoteTab remoteTab = new RemoteTab(); RemoteTab remoteTab = new RemoteTab();
JTabbedPane tabbedPane = new JTabbedPane(); JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.addTab("Upload", uploadTab.getContent()); tabbedPane.addTab("Tune Upload", tuneUploadTab.getContent());
tabbedPane.addTab("Log Upload", logUploadTab.getContent());
tabbedPane.addTab("Broadcast", broadcastTab.getContent()); tabbedPane.addTab("Broadcast", broadcastTab.getContent());
tabbedPane.addTab("Remote ECU", remoteTab.getContent()); tabbedPane.addTab("Remote ECU", remoteTab.getContent());
tabbedPane.addTab("Read SD Card", new SdCardReader(controllerAccessSupplier).getContent()); tabbedPane.addTab("Read SD Card", new SdCardReader(controllerAccessSupplier).getContent());

View File

@ -23,7 +23,10 @@ import java.util.Date;
import java.util.Map; import java.util.Map;
import java.util.function.Supplier; import java.util.function.Supplier;
public class UploadTab { /**
*
*/
public class TuneUploadTab {
private final JComponent content = new JPanel(new VerticalFlowLayout()); private final JComponent content = new JPanel(new VerticalFlowLayout());
// 2 seconds aggregation by default // 2 seconds aggregation by default
private static final int AUTO_UPDATE_AGGREGATION = Integer.parseInt(System.getProperty("autoupload.aggregation", "2000")); private static final int AUTO_UPDATE_AGGREGATION = Integer.parseInt(System.getProperty("autoupload.aggregation", "2000"));
@ -54,7 +57,7 @@ public class UploadTab {
private final ControllerParameterChangeListener listener; private final ControllerParameterChangeListener listener;
public UploadTab(Supplier<ControllerAccess> controllerAccessSupplier) { public TuneUploadTab(Supplier<ControllerAccess> controllerAccessSupplier) {
this.controllerAccessSupplier = controllerAccessSupplier; this.controllerAccessSupplier = controllerAccessSupplier;
timer.stop(); timer.stop();
@ -118,7 +121,7 @@ public class UploadTab {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override @Override
public void run() { public void run() {
uploadView.setResult(array); UploadView.setResult(array, uploadView.uploadState);
} }
}); });
} }

View File

@ -39,7 +39,7 @@ public class UploadView {
return PersistentConfiguration.getConfig().getRoot().getBoolProperty(AUTO_UPLOAD, false); return PersistentConfiguration.getConfig().getRoot().getBoolProperty(AUTO_UPLOAD, false);
} }
public void setResult(UploadResult result) { public static void setResult(UploadResult result, JLabel uploadState) {
uploadState.setText(result.getFirstMessage()); uploadState.setText(result.getFirstMessage());
uploadState.setVisible(true); uploadState.setVisible(true);
} }

View File

@ -1,6 +1,7 @@
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.servers.ControllerParameterServer; import com.efiAnalytics.plugin.ecu.servers.ControllerParameterServer;
import com.opensr5.ini.IniFileModel; import com.opensr5.ini.IniFileModel;
import com.rusefi.TsTuneReader; import com.rusefi.TsTuneReader;
@ -9,9 +10,9 @@ import com.rusefi.ui.util.FrameHelper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects; import java.util.Objects;
import static com.rusefi.ts_plugin.LogUploadSelector.NEGATIVE_ANSWER;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.*;
import static org.mockito.Mockito.when;
/** /**
* Sandbox for plugin body * Sandbox for plugin body
@ -22,25 +23,22 @@ public class PluginBodySandbox {
private static final String PROJECT_NAME = "dev"; private static final String PROJECT_NAME = "dev";
public static void main(String[] args) { public static void main(String[] args) throws ControllerException {
String iniFile = TsTuneReader.getProjectModeFileName(PROJECT_NAME); String iniFile = TsTuneReader.getProjectModeFileName(PROJECT_NAME);
IniFileModel model = new IniFileModel().readIniFile(iniFile); IniFileModel model = new IniFileModel().readIniFile(iniFile);
Objects.requireNonNull(model, "model"); Objects.requireNonNull(model, "model");
java.util.List<String> fieldNamesList = new ArrayList<>(model.allIniFields.keySet()); java.util.List<String> fieldNamesList = new ArrayList<>(model.allIniFields.keySet());
String[] parameterNames = fieldNamesList.toArray(new String[0]); String[] parameterNames = fieldNamesList.toArray(new String[0]);
ControllerParameterServer controllerParameterServer = mock(ControllerParameterServer.class, NEGATIVE_ANSWER);
doReturn(parameterNames).when(controllerParameterServer).getParameterNames(any());
doNothing().when(controllerParameterServer).subscribe(any(), any(), any());
ControllerParameterServer controllerParameterServer = mock(ControllerParameterServer.class); ControllerAccess controllerAccess = mock(ControllerAccess.class, NEGATIVE_ANSWER);
when(controllerParameterServer.getParameterNames(any())).thenReturn(parameterNames); doReturn(new String[]{PROJECT_NAME}).when(controllerAccess).getEcuConfigurationNames();
doReturn(controllerParameterServer).when(controllerAccess).getControllerParameterServer();
ControllerAccess controllerAccess = mock(ControllerAccess.class); new FrameHelper().showFrame(new PluginEntry(() -> controllerAccess).getContent());
when(controllerAccess.getEcuConfigurationNames()).thenReturn(new String[]{PROJECT_NAME});
when(controllerAccess.getControllerParameterServer()).thenReturn(controllerParameterServer);
new FrameHelper().showFrame(new PluginEntry(() -> {
return controllerAccess;
}).getContent());
} }
} }