remote tab misc progress

This commit is contained in:
rusefi 2020-08-30 00:21:34 -04:00
parent c80a03ab84
commit 24f6ead04b
19 changed files with 189 additions and 64 deletions

View File

@ -8,7 +8,7 @@ import java.util.concurrent.atomic.AtomicInteger;
public class NamedThreadFactory implements ThreadFactory { public class NamedThreadFactory implements ThreadFactory {
private final AtomicInteger counter = new AtomicInteger(); private final AtomicInteger counter = new AtomicInteger();
private String name; private final String name;
private final boolean isDaemon; private final boolean isDaemon;
public NamedThreadFactory(String name) { public NamedThreadFactory(String name) {
@ -20,7 +20,6 @@ public class NamedThreadFactory implements ThreadFactory {
this.isDaemon = isDaemon; this.isDaemon = isDaemon;
} }
@Override @Override
public Thread newThread(@NotNull Runnable r) { public Thread newThread(@NotNull Runnable r) {
Thread t = Executors.defaultThreadFactory().newThread(r); Thread t = Executors.defaultThreadFactory().newThread(r);

View File

@ -15,6 +15,7 @@ public class SessionDetails {
public static final String AUTH_TOKEN = "authToken"; public static final String AUTH_TOKEN = "authToken";
public static final String CONNECTOR_VERSION = "connectorVersion"; public static final String CONNECTOR_VERSION = "connectorVersion";
public static final String IMPLEMENTATION = "implementation"; public static final String IMPLEMENTATION = "implementation";
public static final String AGE = "age";
private static final String CONTROLLER = "controller"; private static final String CONTROLLER = "controller";
private static final String HARDCODED_ONE_TIME_CODE = System.getProperty("ONE_TIME_CODE"); private static final String HARDCODED_ONE_TIME_CODE = System.getProperty("ONE_TIME_CODE");
@ -74,11 +75,12 @@ public class SessionDetails {
JSONObject jsonObject = HttpUtil.parse(jsonString); JSONObject jsonObject = HttpUtil.parse(jsonString);
String authToken = (String) jsonObject.get(AUTH_TOKEN); String authToken = (String) jsonObject.get(AUTH_TOKEN);
long oneTimeCode = (Long)jsonObject.get(VEHICLE_TOKEN); long oneTimeCode = (Long) jsonObject.get(VEHICLE_TOKEN);
long connectorVersion = (long) jsonObject.get(CONNECTOR_VERSION); long connectorVersion = (long) jsonObject.get(CONNECTOR_VERSION);
String age = (String) jsonObject.get(AGE);
NetworkConnector.Implementation implementation = NetworkConnector.Implementation.find((String) jsonObject.get(IMPLEMENTATION)); NetworkConnector.Implementation implementation = NetworkConnector.Implementation.find((String) jsonObject.get(IMPLEMENTATION));
ControllerInfo controllerInfo = ControllerInfo.valueOf((String) jsonObject.get(CONTROLLER)); ControllerInfo controllerInfo = ControllerInfo.valueOf((String) jsonObject.get(CONTROLLER));
return new SessionDetails(implementation, controllerInfo, authToken, (int) oneTimeCode, (int) connectorVersion); return new SessionDetails(implementation, controllerInfo, authToken, (int) oneTimeCode, (int) connectorVersion);
} }

View File

@ -2,6 +2,7 @@ package com.rusefi.tools.online;
import com.rusefi.proxy.client.LocalApplicationProxy; import com.rusefi.proxy.client.LocalApplicationProxy;
import com.rusefi.server.ControllerInfo; import com.rusefi.server.ControllerInfo;
import com.rusefi.server.SessionDetails;
import com.rusefi.server.UserDetails; import com.rusefi.server.UserDetails;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.json.simple.JSONArray; import org.json.simple.JSONArray;
@ -54,7 +55,8 @@ public class ProxyClient {
UserDetails vehicleOwner = UserDetails.valueOf(element); UserDetails vehicleOwner = UserDetails.valueOf(element);
boolean isUsed = (Boolean) element.get(IS_USED); boolean isUsed = (Boolean) element.get(IS_USED);
String ownerName = (String) element.get(OWNER); String ownerName = (String) element.get(OWNER);
userLists.add(new PublicSession(vehicleOwner, ci, isUsed, ownerName)); String age = (String) element.get(SessionDetails.AGE);
userLists.add(new PublicSession(vehicleOwner, ci, isUsed, ownerName, age));
} }
System.out.println("object=" + array); System.out.println("object=" + array);

View File

@ -14,12 +14,18 @@ public class PublicSession {
* Person currently in control of tuning session * Person currently in control of tuning session
*/ */
private final String tunerName; private final String tunerName;
private final String age;
public PublicSession(UserDetails vehicleOwner, ControllerInfo controllerInfo, boolean isUsed, String tunerName) { public PublicSession(UserDetails vehicleOwner, ControllerInfo controllerInfo, boolean isUsed, String tunerName, String age) {
this.vehicleOwner = vehicleOwner; this.vehicleOwner = vehicleOwner;
this.controllerInfo = controllerInfo; this.controllerInfo = controllerInfo;
this.isUsed = isUsed; this.isUsed = isUsed;
this.tunerName = tunerName; this.tunerName = tunerName;
this.age = age;
}
public String getAge() {
return age;
} }
public UserDetails getVehicleOwner() { public UserDetails getVehicleOwner() {

View File

@ -1,5 +1,6 @@
package com.rusefi.ui; package com.rusefi.ui;
import com.devexperts.logging.Logging;
import com.rusefi.auth.AuthTokenUtil; import com.rusefi.auth.AuthTokenUtil;
import com.rusefi.ui.storage.PersistentConfiguration; import com.rusefi.ui.storage.PersistentConfiguration;
import com.rusefi.ui.util.URLLabel; import com.rusefi.ui.util.URLLabel;
@ -16,6 +17,7 @@ import java.io.IOException;
import static com.rusefi.ui.storage.PersistentConfiguration.getConfig; import static com.rusefi.ui.storage.PersistentConfiguration.getConfig;
public class AuthTokenPanel { public class AuthTokenPanel {
private final static Logging log = Logging.getLogging(AuthTokenPanel.class);
private final JPanel content = new JPanel(new BorderLayout()); private final JPanel content = new JPanel(new BorderLayout());
private final JTextField authTokenTestField = new JTextField(); private final JTextField authTokenTestField = new JTextField();
@ -105,18 +107,18 @@ public class AuthTokenPanel {
String data = (String) clipboard.getData(DataFlavor.stringFlavor); String data = (String) clipboard.getData(DataFlavor.stringFlavor);
paste.setEnabled(AuthTokenUtil.isToken(data)); paste.setEnabled(AuthTokenUtil.isToken(data));
} catch (IOException | IllegalStateException | UnsupportedFlavorException ex) { } catch (IOException | IllegalStateException | UnsupportedFlavorException ex) {
// ignoring this exception log.info("Ignoring " + ex);
} }
} }
private void grabText() { private void persistToken() {
setAuthToken(AuthTokenPanel.this.authTokenTestField.getText()); setAuthToken(AuthTokenPanel.this.authTokenTestField.getText());
PersistentConfiguration.getConfig().save(); PersistentConfiguration.getConfig().save();
} }
private void onTextChange() { private void onTextChange() {
if (AuthTokenUtil.isToken(authTokenTestField.getText())) { if (AuthTokenUtil.isToken(authTokenTestField.getText())) {
grabText(); persistToken();
} }
} }

View File

@ -116,7 +116,7 @@ public class FullServerTest {
TestHelper.assertLatch("controllerRegistered", controllerRegistered); TestHelper.assertLatch("controllerRegistered", controllerRegistered);
SessionDetails authenticatorSessionDetails = new SessionDetails(NetworkConnector.Implementation.Unknown, controllerInfo, TEST_TOKEN_3, networkConnectorResult.getOneTimeToken(), rusEFIVersion.CONSOLE_VERSION); SessionDetails authenticatorSessionDetails = new SessionDetails(NetworkConnector.Implementation.Unknown, controllerInfo, TEST_TOKEN_3, networkConnectorResult.getOneTimeToken(), rusEFIVersion.CONSOLE_VERSION, "");
ApplicationRequest applicationRequest = new ApplicationRequest(authenticatorSessionDetails, userDetailsResolver.apply(TestHelper.TEST_TOKEN_1)); ApplicationRequest applicationRequest = new ApplicationRequest(authenticatorSessionDetails, userDetailsResolver.apply(TestHelper.TEST_TOKEN_1));
// start authenticator // start authenticator

View File

@ -59,7 +59,6 @@ public class Backend implements Closeable {
* @see BinaryProtocolProxy#USER_IO_TIMEOUT * @see BinaryProtocolProxy#USER_IO_TIMEOUT
*/ */
private static final int APPLICATION_INACTIVITY_TIMEOUT = 3 * Timeouts.MINUTE; private static final int APPLICATION_INACTIVITY_TIMEOUT = 3 * Timeouts.MINUTE;
static final String AGE = "age";
private static final ThreadFactory APPLICATION_CONNECTION_CLEANUP = new NamedThreadFactory("rusEFI Application connections Cleanup"); private static final ThreadFactory APPLICATION_CONNECTION_CLEANUP = new NamedThreadFactory("rusEFI Application connections Cleanup");
private static final ThreadFactory GAUGE_POKER = new NamedThreadFactory("rusEFI gauge poker"); private static final ThreadFactory GAUGE_POKER = new NamedThreadFactory("rusEFI gauge poker");
@ -277,7 +276,7 @@ public class Backend implements Closeable {
JsonObjectBuilder b = Json.createObjectBuilder() JsonObjectBuilder b = Json.createObjectBuilder()
.add(UserDetails.USER_ID, application.getUserDetails().getUserId()) .add(UserDetails.USER_ID, application.getUserDetails().getUserId())
.add(UserDetails.USERNAME, application.getUserDetails().getUserName()) .add(UserDetails.USERNAME, application.getUserDetails().getUserName())
.add(AGE, application.getBirthday().getDuration()) .add(SessionDetails.AGE, application.getBirthday().getDuration())
; ;
JsonObject applicationObject = addStreamStats(b, application.getClientStream()) JsonObject applicationObject = addStreamStats(b, application.getClientStream())
.build(); .build();
@ -308,7 +307,7 @@ public class Backend implements Closeable {
JsonObjectBuilder objectBuilder = Json.createObjectBuilder() JsonObjectBuilder objectBuilder = Json.createObjectBuilder()
.add(UserDetails.USER_ID, client.getUserDetails().getUserId()) .add(UserDetails.USER_ID, client.getUserDetails().getUserId())
.add(UserDetails.USERNAME, client.getUserDetails().getUserName()) .add(UserDetails.USERNAME, client.getUserDetails().getUserName())
.add(AGE, client.getBirthday().getDuration()) .add(SessionDetails.AGE, client.getBirthday().getDuration())
.add("OUTPUT_ROUND_TRIP", client.getOutputRoundAroundDuration()) .add("OUTPUT_ROUND_TRIP", client.getOutputRoundAroundDuration())
.add(ProxyClient.IS_USED, client.getTwoKindSemaphore().isUsed()) .add(ProxyClient.IS_USED, client.getTwoKindSemaphore().isUsed())
.add(ControllerStateDetails.RPM, rpm) .add(ControllerStateDetails.RPM, rpm)

View File

@ -74,7 +74,7 @@ public class Monitoring {
builder.add("framework version", rusEFIVersion.CONSOLE_VERSION); builder.add("framework version", rusEFIVersion.CONSOLE_VERSION);
builder.add("compiled", new Date(rusEFIVersion.classBuildTimeMillis()).toString()); builder.add("compiled", new Date(rusEFIVersion.classBuildTimeMillis()).toString());
builder.add("now", System.currentTimeMillis()); builder.add("now", System.currentTimeMillis());
builder.add(Backend.AGE, birthday.getDuration()); builder.add(SessionDetails.AGE, birthday.getDuration());
return new RsJson(builder.build()); return new RsJson(builder.build());
} }

View File

@ -11,7 +11,7 @@ public class SessionDetailsTest {
@Test @Test
public void testSerialization() { public void testSerialization() {
SessionDetails sd = new SessionDetails(NetworkConnector.Implementation.Unknown, TestHelper.CONTROLLER_INFO, "auth", 123, rusEFIVersion.CONSOLE_VERSION); SessionDetails sd = new SessionDetails(NetworkConnector.Implementation.Unknown, TestHelper.CONTROLLER_INFO, "auth", 123, rusEFIVersion.CONSOLE_VERSION, "");
String json = sd.toJson(); String json = sd.toJson();
SessionDetails fromJson = SessionDetails.valueOf(json); SessionDetails fromJson = SessionDetails.valueOf(json);
@ -20,7 +20,7 @@ public class SessionDetailsTest {
@Test @Test
public void testApplicationRequest() { public void testApplicationRequest() {
SessionDetails sd = new SessionDetails(NetworkConnector.Implementation.Unknown, TestHelper.CONTROLLER_INFO, "auth", 123, rusEFIVersion.CONSOLE_VERSION); SessionDetails sd = new SessionDetails(NetworkConnector.Implementation.Unknown, TestHelper.CONTROLLER_INFO, "auth", 123, rusEFIVersion.CONSOLE_VERSION, "");
ApplicationRequest ar = new ApplicationRequest(sd, new UserDetails("", 321)); ApplicationRequest ar = new ApplicationRequest(sd, new UserDetails("", 321));
String json = ar.toJson(); String json = ar.toJson();

View File

@ -1,10 +1,13 @@
package com.rusefi; package com.rusefi;
import com.rusefi.core.Pair;
public class SignatureHelper { public class SignatureHelper {
public static final String PREFIX = "rusEFI "; public static final String PREFIX = "rusEFI ";
public static final char SLASH = '/';
public static String getUrl(String signature) { public static Pair<String, String> getUrl(String signature) {
if (!signature.startsWith(PREFIX)) if (!signature.startsWith(PREFIX))
return null; return null;
signature = signature.substring(PREFIX.length()).trim(); signature = signature.substring(PREFIX.length()).trim();
@ -18,6 +21,7 @@ public class SignatureHelper {
String bundle = elements[3]; String bundle = elements[3];
String hash = elements[4]; String hash = elements[4];
return "https://rusefi.com/online/ini/rusefi/" + year + "/" + month + "/" + day + "/" + bundle + "/" + hash + ".ini"; String fileName = hash + ".ini";
return new Pair("https://rusefi.com/online/ini/rusefi/" + year + SLASH + month + SLASH + day + SLASH + bundle + SLASH + fileName, fileName);
} }
} }

View File

@ -2,6 +2,7 @@ package com.rusefi.ts_plugin;
import com.efiAnalytics.plugin.ecu.ControllerAccess; import com.efiAnalytics.plugin.ecu.ControllerAccess;
import com.rusefi.autoupdate.AutoupdateUtil; import com.rusefi.autoupdate.AutoupdateUtil;
import com.rusefi.ts_plugin.auth.InstanceAuthContext;
import com.rusefi.ts_plugin.util.ManifestHelper; import com.rusefi.ts_plugin.util.ManifestHelper;
import com.rusefi.tune.xml.Constant; import com.rusefi.tune.xml.Constant;
@ -12,6 +13,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 TuneUploadTab 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
@ -52,6 +54,18 @@ public class PluginEntry implements TsPluginBody {
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());
content.add(tabbedPane); content.add(tabbedPane);
InstanceAuthContext.startup();
}
public static String getNonDaemonThreads() {
StringBuilder sb = new StringBuilder();
for (Thread thread : Thread.getAllStackTraces().keySet()) {
// Daemon thread will not prevent the JVM from exiting
if (!thread.isDaemon())
sb.append(thread.getName() + "\n");
}
return sb.toString();
} }
private boolean isLauncherTooOld() { private boolean isLauncherTooOld() {

View File

@ -4,6 +4,7 @@ import com.rusefi.NamedThreadFactory;
import com.rusefi.SignatureHelper; import com.rusefi.SignatureHelper;
import com.rusefi.Timeouts; import com.rusefi.Timeouts;
import com.rusefi.autoupdate.AutoupdateUtil; import com.rusefi.autoupdate.AutoupdateUtil;
import com.rusefi.core.Pair;
import com.rusefi.io.serial.StreamStatistics; import com.rusefi.io.serial.StreamStatistics;
import com.rusefi.io.tcp.ServerSocketReference; import com.rusefi.io.tcp.ServerSocketReference;
import com.rusefi.io.tcp.TcpIoStream; import com.rusefi.io.tcp.TcpIoStream;
@ -18,6 +19,8 @@ import com.rusefi.server.UserDetails;
import com.rusefi.tools.online.HttpUtil; import com.rusefi.tools.online.HttpUtil;
import com.rusefi.tools.online.ProxyClient; import com.rusefi.tools.online.ProxyClient;
import com.rusefi.tools.online.PublicSession; import com.rusefi.tools.online.PublicSession;
import com.rusefi.ts_plugin.auth.InstanceAuthContext;
import com.rusefi.ts_plugin.auth.SelfInfo;
import com.rusefi.ui.AuthTokenPanel; import com.rusefi.ui.AuthTokenPanel;
import com.rusefi.ui.util.URLLabel; import com.rusefi.ui.util.URLLabel;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -45,6 +48,8 @@ public class RemoteTab {
private static final String APPLICATION_PORT = "application_port"; private static final String APPLICATION_PORT = "application_port";
public static final String HOWTO_REMOTE_TUNING = "https://github.com/rusefi/rusefi/wiki/HOWTO-Remote-Tuning"; 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 JComponent content = new JPanel(new BorderLayout());
private final JScrollPane scroll = new JScrollPane(content, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
private final JPanel list = new JPanel(new VerticalFlowLayout()); private final JPanel list = new JPanel(new VerticalFlowLayout());
private final JTextField oneTimePasswordControl = new JTextField("0") { private final JTextField oneTimePasswordControl = new JTextField("0") {
@ -61,18 +66,18 @@ public class RemoteTab {
private final JButton disconnect = new JButton("Disconnect"); private final JButton disconnect = new JButton("Disconnect");
private final Executor listDownloadExecutor = Executors.newSingleThreadExecutor(new NamedThreadFactory("online list downloader")); private final Executor listDownloadExecutor = Executors.newSingleThreadExecutor(new NamedThreadFactory("online list downloader", true));
public RemoteTab() { public RemoteTab() {
JButton refresh = new JButton("Refresh List"); JButton refresh = new JButton("Refresh Remote Controllers List");
refresh.addActionListener(e -> requestListDownload()); refresh.addActionListener(e -> requestControllersList());
disconnect.addActionListener(e -> { disconnect.addActionListener(e -> {
LocalApplicationProxy localApplicationProxy = RemoteTabController.INSTANCE.getLocalApplicationProxy(); LocalApplicationProxy localApplicationProxy = RemoteTabController.INSTANCE.getLocalApplicationProxy();
if (localApplicationProxy != null) if (localApplicationProxy != null)
localApplicationProxy.close(); localApplicationProxy.close();
RemoteTabController.INSTANCE.setState(RemoteTabController.State.NOT_CONNECTED); RemoteTabController.INSTANCE.setState(RemoteTabController.State.NOT_CONNECTED);
requestListDownload(); requestControllersList();
}); });
@ -100,24 +105,23 @@ public class RemoteTab {
JPanel topLines = new JPanel(new VerticalFlowLayout()); JPanel topLines = new JPanel(new VerticalFlowLayout());
JPanel topPanel = new JPanel(new FlowLayout());
topPanel.add(refresh);
topPanel.add(new JLabel(" Local Port: "));
topPanel.add(applicationPort);
topPanel.add(new JLabel(" One time password:"));
topPanel.add(oneTimePasswordControl);
topLines.add(topPanel);
topLines.add(new URLLabel(HOWTO_REMOTE_TUNING)); topLines.add(new URLLabel(HOWTO_REMOTE_TUNING));
topLines.add(new SelfInfo().getContent());
topLines.add(refresh);
topLines.add(new JLabel("Local Port for tuning software"));
topLines.add(applicationPort);
topLines.add(new JLabel("One time password:"));
topLines.add(oneTimePasswordControl);
content.add(topLines, BorderLayout.NORTH); content.add(topLines, BorderLayout.NORTH);
content.add(list, BorderLayout.CENTER); content.add(list, BorderLayout.CENTER);
list.add(new JLabel("Requesting list of ECUs")); list.add(new JLabel("Requesting list of ECUs"));
InstanceAuthContext.listeners.add(userDetails -> requestControllersList());
LocalApplicationProxy currentState = RemoteTabController.INSTANCE.getLocalApplicationProxy(); LocalApplicationProxy currentState = RemoteTabController.INSTANCE.getLocalApplicationProxy();
if (currentState == null) { if (currentState == null) {
requestListDownload(); requestControllersList();
} else { } else {
setConnectedStatus(currentState.getApplicationRequest().getVehicleOwner(), null, setConnectedStatus(currentState.getApplicationRequest().getVehicleOwner(), null,
currentState.getApplicationRequest().getSessionDetails().getControllerInfo()); currentState.getApplicationRequest().getSessionDetails().getControllerInfo());
@ -128,15 +132,13 @@ public class RemoteTab {
return getConfig().getRoot().getProperty(APPLICATION_PORT, "29001"); return getConfig().getRoot().getProperty(APPLICATION_PORT, "29001");
} }
private void requestListDownload() { private void requestControllersList() {
listDownloadExecutor.execute(() -> { listDownloadExecutor.execute(() -> {
List<PublicSession> userDetails;
try { try {
userDetails = ProxyClient.getOnlineApplications(HttpUtil.PROXY_JSON_API_HTTP_PORT); List<PublicSession> userDetails = ProxyClient.getOnlineApplications(HttpUtil.PROXY_JSON_API_HTTP_PORT);
SwingUtilities.invokeLater(() -> showList(userDetails)); SwingUtilities.invokeLater(() -> showList(userDetails));
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
return;
} }
}); });
} }
@ -150,20 +152,20 @@ public class RemoteTab {
} else { } else {
JPanel verticalPanel = new JPanel(new VerticalFlowLayout()); JPanel verticalPanel = new JPanel(new VerticalFlowLayout());
JScrollPane scroll = new JScrollPane(verticalPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); list.add(verticalPanel);
list.add(scroll);
for (PublicSession user : userDetails) { for (PublicSession user : userDetails) {
verticalPanel.add(createSessionControl(user)); verticalPanel.add(createControllerRow(user));
} }
} }
AutoupdateUtil.trueLayout(list); AutoupdateUtil.trueLayout(list);
} }
private JComponent createSessionControl(PublicSession publicSession) { private JComponent createControllerRow(PublicSession publicSession) {
ControllerInfo controllerInfo = publicSession.getControllerInfo();
JComponent topLine = new JPanel(new FlowLayout()); JComponent topLine = new JPanel(new FlowLayout());
topLine.add(new JLabel(publicSession.getVehicleOwner().getUserName())); topLine.add(new JLabel(publicSession.getVehicleOwner().getUserName()));
ControllerInfo controllerInfo = publicSession.getControllerInfo();
topLine.add(new JLabel(controllerInfo.getVehicleName() + " " + controllerInfo.getEngineMake() + " " + controllerInfo.getEngineCode())); topLine.add(new JLabel(controllerInfo.getVehicleName() + " " + controllerInfo.getEngineMake() + " " + controllerInfo.getEngineCode()));
JPanel bottomPanel = new JPanel(new FlowLayout()); JPanel bottomPanel = new JPanel(new FlowLayout());
@ -175,26 +177,34 @@ public class RemoteTab {
connect.addActionListener(event -> connectToProxy(publicSession)); connect.addActionListener(event -> connectToProxy(publicSession));
bottomPanel.add(connect); bottomPanel.add(connect);
JButton updateSoftware = new JButton("Update Connector"); if (InstanceAuthContext.isOurController(publicSession.getVehicleOwner().getUserId())) {
updateSoftware.addActionListener(new AbstractAction() { JButton updateSoftware = new JButton("Update Connector");
@Override updateSoftware.addActionListener(new AbstractAction() {
public void actionPerformed(ActionEvent e) { @Override
try { public void actionPerformed(ActionEvent e) {
LocalApplicationProxy.requestSoftwareUpdate(HttpUtil.PROXY_JSON_API_HTTP_PORT, try {
getApplicationRequest(publicSession)); LocalApplicationProxy.requestSoftwareUpdate(HttpUtil.PROXY_JSON_API_HTTP_PORT,
} catch (IOException ioException) { getApplicationRequest(publicSession));
ioException.printStackTrace(); } catch (IOException ioException) {
ioException.printStackTrace();
}
} }
} });
}); bottomPanel.add(updateSoftware);
bottomPanel.add(updateSoftware); }
} }
JPanel userPanel = new JPanel(new BorderLayout()); JPanel userPanel = new JPanel(new BorderLayout());
JPanel infoLine = new JPanel(new FlowLayout());
infoLine.add(new JLabel("Age " + publicSession.getAge()));
infoLine.add(getSignatureDownload(controllerInfo));
userPanel.add(topLine, BorderLayout.NORTH); userPanel.add(topLine, BorderLayout.NORTH);
userPanel.add(new URLLabel(SignatureHelper.getUrl(controllerInfo.getSignature())), BorderLayout.CENTER); userPanel.add(infoLine, BorderLayout.CENTER);
userPanel.add(bottomPanel, BorderLayout.SOUTH); userPanel.add(bottomPanel, BorderLayout.SOUTH);
userPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK)); userPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
@ -202,6 +212,13 @@ public class RemoteTab {
return userPanel; return userPanel;
} }
@NotNull
private URLLabel getSignatureDownload(ControllerInfo controllerInfo) {
Pair<String, String> url = SignatureHelper.getUrl(controllerInfo.getSignature());
return new URLLabel(url.second, url.first);
}
private void connectToProxy(PublicSession publicSession) { private void connectToProxy(PublicSession publicSession) {
RemoteTabController.INSTANCE.setState(RemoteTabController.State.CONNECTING); RemoteTabController.INSTANCE.setState(RemoteTabController.State.CONNECTING);
setStatus("Connecting to " + publicSession.getVehicleOwner().getUserName()); setStatus("Connecting to " + publicSession.getVehicleOwner().getUserName());
@ -228,7 +245,7 @@ public class RemoteTab {
setStatus("Connected to " + userDetails.getUserName(), setStatus("Connected to " + userDetails.getUserName(),
new JLabel("You can now connect your TunerStudio to IP address localhost and port " + getLocalPort()), new JLabel("You can now connect your TunerStudio to IP address localhost and port " + getLocalPort()),
new URLLabel(SignatureHelper.getUrl(controllerInfo.getSignature())), new URLLabel(SignatureHelper.getUrl(controllerInfo.getSignature()).first),
disconnect, streamStatusControl == null ? null : streamStatusControl.getContent()); disconnect, streamStatusControl == null ? null : streamStatusControl.getContent());
} }
@ -280,11 +297,10 @@ public class RemoteTab {
publicSession.getControllerInfo(), AuthTokenPanel.getAuthToken(), publicSession.getControllerInfo(), AuthTokenPanel.getAuthToken(),
Integer.parseInt(oneTimePasswordControl.getText()), rusEFIVersion.CONSOLE_VERSION); Integer.parseInt(oneTimePasswordControl.getText()), rusEFIVersion.CONSOLE_VERSION);
ApplicationRequest applicationRequest = new ApplicationRequest(sessionDetails, publicSession.getVehicleOwner()); return new ApplicationRequest(sessionDetails, publicSession.getVehicleOwner());
return applicationRequest;
} }
public JComponent getContent() { public JComponent getContent() {
return content; return scroll;
} }
} }

View File

@ -24,7 +24,7 @@ import java.util.Map;
import java.util.function.Supplier; import java.util.function.Supplier;
/** /**
* * @see PluginBodySandbox
*/ */
public class TuneUploadTab { public class TuneUploadTab {
private final JComponent content = new JPanel(new VerticalFlowLayout()); private final JComponent content = new JPanel(new VerticalFlowLayout());
@ -69,7 +69,7 @@ public class TuneUploadTab {
}; };
upload.setBackground(new Color(0x90EE90)); upload.setBackground(new Color(0x90EE90));
new Thread(new Runnable() { Thread t = new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
while (true) { while (true) {
@ -97,7 +97,9 @@ public class TuneUploadTab {
} }
} }
} }
}).start(); });
t.setDaemon(true);
t.start();
upload.addActionListener(new AbstractAction() { upload.addActionListener(new AbstractAction() {
@Override @Override

View File

@ -26,13 +26,15 @@ public class UploadQueue {
return; return;
isStarted = true; isStarted = true;
readOutbox(); readOutbox();
new Thread(() -> { Thread t = new Thread(() -> {
try { try {
uploadLoop(); uploadLoop();
} catch (InterruptedException e) { } catch (InterruptedException e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
}, "Positing Thread").start(); }, "Posting Thread");
t.setDaemon(true);
t.start();
} }
private static void readOutbox() { private static void readOutbox() {

View File

@ -0,0 +1,44 @@
package com.rusefi.ts_plugin.auth;
import com.devexperts.logging.Logging;
import com.rusefi.server.JsonUserDetailsResolver;
import com.rusefi.server.UserDetails;
import com.rusefi.ui.AuthTokenPanel;
import java.util.concurrent.CopyOnWriteArrayList;
public class InstanceAuthContext {
private final static Logging log = Logging.getLogging(InstanceAuthContext.class);
private static boolean isInitialized;
public static CopyOnWriteArrayList<Listener> listeners = new CopyOnWriteArrayList<>();
public static UserDetails self;
public synchronized static void startup() {
if (isInitialized)
return;
if (!AuthTokenPanel.hasToken()) {
// exiting without marking initialized - UI has a chance to re-start the process once token is provided
return;
}
log.info("Startup");
isInitialized = true;
new Thread(() -> {
self = new JsonUserDetailsResolver().apply(AuthTokenPanel.getAuthToken());
for (Listener listener : listeners)
listener.onUserDetails(self);
}).start();
}
public static boolean isOurController(int userId) {
if (self == null)
return false;
return self.getUserId() == userId;
}
public interface Listener {
void onUserDetails(UserDetails userDetails);
}
}

View File

@ -0,0 +1,33 @@
package com.rusefi.ts_plugin.auth;
import com.rusefi.server.UserDetails;
import javax.swing.*;
import java.awt.*;
public class SelfInfo {
private final JLabel jLabel = new JLabel();
public SelfInfo() {
InstanceAuthContext.listeners.add(new InstanceAuthContext.Listener() {
@Override
public void onUserDetails(UserDetails userDetails) {
setInfo();
}
});
setInfo();
}
private void setInfo() {
UserDetails userDetails = InstanceAuthContext.self;
if (userDetails == null) {
jLabel.setText("Authorizing...");
} else {
jLabel.setText("Logged in as " + userDetails.getUserName());
}
}
public Component getContent() {
return jLabel;
}
}

View File

@ -7,7 +7,7 @@ import static org.junit.Assert.assertEquals;
public class SignatureHelperTest { public class SignatureHelperTest {
@Test @Test
public void test() { public void test() {
String url = SignatureHelper.getUrl("rusEFI 2020.07.06.frankenso_na6.2468827536"); String url = SignatureHelper.getUrl("rusEFI 2020.07.06.frankenso_na6.2468827536").first;
assertEquals("https://rusefi.com/online/ini/rusefi/2020/07/06/frankenso_na6/2468827536.ini", url); assertEquals("https://rusefi.com/online/ini/rusefi/2020/07/06/frankenso_na6/2468827536.ini", url);
} }
} }