diff --git a/java_console/autotest/src/com/rusefi/AutoTest.java b/java_console/autotest/src/com/rusefi/AutoTest.java index be9a7c5d9c..5ee8be0136 100644 --- a/java_console/autotest/src/com/rusefi/AutoTest.java +++ b/java_console/autotest/src/com/rusefi/AutoTest.java @@ -2,22 +2,12 @@ package com.rusefi; import com.irnems.FileLog; -import com.irnems.core.Sensor; -import com.irnems.core.SensorCentral; -import com.rusefi.io.LinkManager; -import com.rusefi.io.tcp.TcpConnector; -import com.rusefi.waves.RevolutionLog; import com.rusefi.waves.WaveChart; -import com.rusefi.waves.WaveChartParser; -import com.rusefi.waves.WaveReport; -import java.util.List; -import java.util.concurrent.*; - -import static com.rusefi.IoUtil.*; -import static com.rusefi.TestingUtils.assertCloseEnough; -import static com.rusefi.TestingUtils.assertTrue; -import static com.rusefi.waves.WaveReport.isCloseEnough; +import static com.rusefi.IoUtil.nextChart; +import static com.rusefi.IoUtil.sendCommand; +import static com.rusefi.TestingUtils.assertNull; +import static com.rusefi.TestingUtils.assertWave; /** * rusEfi firmware simulator functional test suite @@ -28,123 +18,167 @@ import static com.rusefi.waves.WaveReport.isCloseEnough; * 3/5/14 */ public class AutoTest { + private static void mainTestBody() { + testFordAspire(); + + sendCommand("set_engine_type 2"); + testDodgeNeon(); + +// todo: uncomment once we resolve the RAM issue & OUTPUT_SIGNAL_MAX_SIZE gets back to 60 +// sendCommand("set_engine_type 7"); +// testFord6(); + + sendCommand("set_engine_type 4"); + testFordFiesta(); + } + + private static void testDodgeNeon() { + WaveChart chart; + IoUtil.changeRpm(2000); + sendCommand("set_ignition_mode 1"); + chart = nextChart(); + + String msg = "Neon"; + float x = 110; + assertWave(msg, chart, WaveChart.INJECTOR_4, 0.1, x + 540); + assertWave(msg, chart, WaveChart.INJECTOR_2, 0.1, x); + assertWave(msg, chart, WaveChart.INJECTOR_1, 0.1, x + 180); + assertWave(msg, chart, WaveChart.INJECTOR_3, 0.1, x + 360); + + x = 122; + assertWave(msg, chart, WaveChart.SPARK_4, 0.13333, x + 540); + assertWave(msg, chart, WaveChart.SPARK_2, 0.13333, x); + assertWave(msg, chart, WaveChart.SPARK_1, 0.13333, x + 180); + assertWave(msg, chart, WaveChart.SPARK_3, 0.13333, x + 360); + } + + private static void testFordFiesta() { +// WaveChart chart; +// changeRpm(2000); +// chart = nextChart(); + } + + private static void testFord6() { + WaveChart chart; + IoUtil.changeRpm(2000); + chart = nextChart(); + + int x = 7; + assertWave("ford 6", chart, WaveChart.SPARK_1, 0.01666, x, x + 120, x + 240, x + 360, x + 480, x + 600); + + } + + private static void testFordAspire() { + WaveChart chart; + // todo: interesting changeRpm(100); + sendCommand("set_cranking_rpm 500"); + IoUtil.changeRpm(200); + + float x; + chart = nextChart(); + x = 55; + assertWave("aspire default cranking ", chart, WaveChart.SPARK_1, 0.1944, x, x + 180, x + 360, x + 540); + + + IoUtil.changeRpm(600); + chart = nextChart(); + x = 76; + assertWave("aspire default runnint ", chart, WaveChart.SPARK_1, 0.04, x, x + 180, x + 360, x + 540); + + IoUtil.changeRpm(200); + + sendCommand("set_cranking_charge_angle 65"); + sendCommand("set_cranking_timing_angle 31"); + + chart = nextChart(); + x = 55; + assertWave("aspire", chart, WaveChart.SPARK_1, 0.18, x, x + 180, x + 360, x + 540); + + sendCommand("set_cranking_timing_angle 40"); + chart = nextChart(); + x = 64; + assertWave("aspire", chart, WaveChart.SPARK_1, 0.18, x, x + 180, x + 360, x + 540); + sendCommand("set_cranking_timing_angle -149"); + + sendCommand("set_cranking_charge_angle 40"); + chart = nextChart(); + x = 80; + assertWave("aspire", chart, WaveChart.SPARK_1, 40.0 / 360, x, x + 180, x + 360, x + 540); + sendCommand("set_cranking_charge_angle 65"); + + IoUtil.changeRpm(600); + sendCommand("set_cranking_rpm 700"); + chart = nextChart(); + x = 55; + assertWave("cranking@600", chart, WaveChart.SPARK_1, 0.18, x, x + 180, x + 360, x + 540); + + IoUtil.changeRpm(2000); + sendCommand("set_whole_fuel_map 1.57"); + + chart = nextChart(); + + assertWave(chart, WaveChart.INJECTOR_1, 0.051, 238.75); + assertWave(chart, WaveChart.INJECTOR_2, 0.051, 53.04); + assertWave(chart, WaveChart.INJECTOR_3, 0.051, 417.04); + assertWave(chart, WaveChart.INJECTOR_4, 0.051, 594.04); + + x = 22; + assertWave(chart, WaveChart.SPARK_1, 0.133, x, x + 180, x + 360, x + 540); + + sendCommand("set_fuel_map 2200 4 15.66"); + sendCommand("set_fuel_map 2000 4 15.66"); + sendCommand("set_fuel_map 2200 4.2 15.66"); + sendCommand("set_fuel_map 2000 4.2 15.66"); + // fake 2 means 4 on the gauge because of the divider. should we simplify this? + sendCommand("set_fake_maf_voltage 2"); + sendCommand("set_global_trigger_offset_angle 175"); + chart = nextChart(); + + assertWave(chart, WaveChart.INJECTOR_1, 0.522, 238.75); + assertWave(chart, WaveChart.INJECTOR_2, 0.522, 53.04); + assertWave(chart, WaveChart.INJECTOR_3, 0.522, 417.04); + assertWave(chart, WaveChart.INJECTOR_4, 0.522, 594.04); + + x = 41; + assertWave(chart, WaveChart.SPARK_1, 0.133, x, x + 180, x + 360, x + 540); + assertNull("chart for " + WaveChart.SPARK_2, chart.get(WaveChart.SPARK_2)); + + sendCommand("set_global_trigger_offset_angle 130"); + chart = nextChart(); + x = 580; + assertWave(chart, WaveChart.SPARK_1, 0.133, x, x + 180, x + 360, x + 540); + + // let's enable more channels dynamically + sendCommand("set_ignition_mode 1"); + chart = nextChart(); + assertWave(chart, WaveChart.SPARK_2, 0.133, x); + assertWave(chart, WaveChart.SPARK_3, 0.133, x + 360); + + sendCommand("set_whole_timing_map 200"); + chart = nextChart(); + x = 59; + assertWave(chart, WaveChart.SPARK_2, 0.133, x); + } + public static void main(String[] args) throws InterruptedException { FileLog.SIMULATOR_CONSOLE.start(); FileLog.MAIN.start(); + boolean failed = false; try { - runTest(); + IoUtil.launchSimulator(); + mainTestBody(); + } catch (Throwable e) { + e.printStackTrace(); + failed = true; } finally { ExecHelper.destroy(); } + if (failed) + System.exit(-1); FileLog.MAIN.logLine("*******************************************************************************"); FileLog.MAIN.logLine("************************************ Looks good! *****************************"); FileLog.MAIN.logLine("*******************************************************************************"); - System.exit(0); + System.exit(0); // this is a safer method eliminating the issue of non-daemon threads } - - private static void runTest() throws InterruptedException { - if (!TcpConnector.getAvailablePorts().isEmpty()) - throw new IllegalStateException("Port already binded on startup?"); - - ExecHelper.startSimulator(); - - -// FileLog.rlog("Waiting for TCP port..."); -// for (int i = 0; i < 180; i++) { -// if (!TcpConnector.getAvailablePorts().isEmpty()) -// break; -// Thread.sleep(1000); -// } -// if (TcpConnector.getAvailablePorts().isEmpty()) -// throw new IllegalStateException("Did we start it?"); -// /** -// * If we open a connection just to validate that the process has started, we are getting -// * weird issues with the second - actual connection -// */ -// FileLog.rlog("Time for simulator to close the port..."); -// Thread.sleep(3000); -// -// FileLog.rlog("Got a TCP port! Connecting..."); - LinkManager.start("" + TcpConnector.DEFAULT_PORT); - /** - * TCP connector is blocking - */ - LinkManager.open(); - - FileLog.rlog("Let's give it some time to start..."); - - final CountDownLatch startup = new CountDownLatch(1); - SensorCentral.AdcListener listener = new SensorCentral.AdcListener() { - @Override - public void onAdcUpdate(SensorCentral model, double value) { - startup.countDown(); - } - }; - long waitStart = System.currentTimeMillis(); - SensorCentral.getInstance().addListener(Sensor.RPM, listener); - startup.await(5, TimeUnit.SECONDS); - SensorCentral.getInstance().removeListener(Sensor.RPM, listener); - FileLog.MAIN.logLine("Got first signal in " + (System.currentTimeMillis() - waitStart)); - - mainTestBody(); - } - - private static void mainTestBody() throws InterruptedException { - changeRpm(500); - changeRpm(2000); - - String chartLine = getNextWaveChart(); - - - WaveChart chart = WaveChartParser.unpackToMap(chartLine); - - StringBuilder revolutions = chart.get(RevolutionLog.TOP_DEAD_CENTER_MESSAGE); - if (revolutions.length() == 0) - throw new IllegalStateException("Empty revolutions in " + chartLine); - - RevolutionLog revolutionLog = RevolutionLog.parseRevolutions(revolutions); - assertWave(chart, revolutionLog, WaveChart.INJECTOR_1, 0.33, 238.75); - assertWave(chart, revolutionLog, WaveChart.INJECTOR_2, 0.33, 53.04); - assertWave(chart, revolutionLog, WaveChart.INJECTOR_3, 0.33, 417.04); - assertWave(chart, revolutionLog, WaveChart.INJECTOR_4, 0.33, 594.04); - - assertWave(chart, revolutionLog, WaveChart.SPARK_1, 0.41, 53.05, 238.75, 417.72, 594.84); - } - - private static void assertWave(WaveChart chart, RevolutionLog revolutionLog, String key, double width, double... expectedAngles) { - StringBuilder events = chart.get(key); - assertTrue("Events not null for " + key, events != null); - List wr = WaveReport.parse(events.toString()); - assertTrue("waves for " + key, !wr.isEmpty()); - for (WaveReport.UpDown ud : wr) { - double angleByTime = revolutionLog.getCrankAngleByTime(ud.upTime); - assertCloseEnough("angle for " + key, angleByTime, expectedAngles); - - assertCloseEnough("width for " + key, ud.getDutyCycle(revolutionLog), width); - } - } - - private static void changeRpm(final int rpm) throws InterruptedException { - sendCommand("rpm " + rpm); - - final CountDownLatch rpmLatch = new CountDownLatch(1); - SensorCentral.AdcListener listener = new SensorCentral.AdcListener() { - @Override - public void onAdcUpdate(SensorCentral model, double value) { - double actualRpm = SensorCentral.getInstance().getValue(Sensor.RPM); - if (isCloseEnough(rpm, actualRpm)) - rpmLatch.countDown(); - } - }; - SensorCentral.getInstance().addListener(Sensor.RPM, listener); - rpmLatch.await(5, TimeUnit.SECONDS); - SensorCentral.getInstance().removeListener(Sensor.RPM, listener); - - double actualRpm = SensorCentral.getInstance().getValue(Sensor.RPM); - - if (!isCloseEnough(rpm, actualRpm)) - throw new IllegalStateException("rpm change did not happen"); - } - } diff --git a/java_console/autotest/src/com/rusefi/ExecHelper.java b/java_console/autotest/src/com/rusefi/ExecHelper.java index dcc5315904..845195fd0e 100644 --- a/java_console/autotest/src/com/rusefi/ExecHelper.java +++ b/java_console/autotest/src/com/rusefi/ExecHelper.java @@ -19,11 +19,11 @@ public class ExecHelper { Thread.currentThread().setName("Main simulation"); try { - FileLog.rlog("Binary size: " + new File(SIMULATOR_COMMAND).length()); + FileLog.MAIN.logLine("Binary size: " + new File(SIMULATOR_COMMAND).length()); - FileLog.rlog("Executing " + SIMULATOR_COMMAND); + FileLog.MAIN.logLine("Executing " + SIMULATOR_COMMAND); ExecHelper.simulatorProcess = Runtime.getRuntime().exec(SIMULATOR_COMMAND); - FileLog.rlog("simulatorProcess: " + ExecHelper.simulatorProcess); + FileLog.MAIN.logLine("simulatorProcess: " + ExecHelper.simulatorProcess); BufferedReader input = new BufferedReader(new InputStreamReader(ExecHelper.simulatorProcess.getInputStream())); @@ -35,7 +35,7 @@ public class ExecHelper { FileLog.SIMULATOR_CONSOLE.logLine(line); } - FileLog.rlog("exitValue: " + simulatorProcess.exitValue()); + FileLog.MAIN.logLine("exitValue: " + simulatorProcess.exitValue()); System.out.println("end of console"); input.close(); @@ -65,7 +65,7 @@ public class ExecHelper { static void destroy() { if (simulatorProcess != null) { - FileLog.rlog("Destroying sub-process..."); + FileLog.MAIN.logLine("Destroying sub-process..."); simulatorProcess.destroy(); } } diff --git a/java_console/autotest/src/com/rusefi/IoUtil.java b/java_console/autotest/src/com/rusefi/IoUtil.java index 7e499329bf..f6fccfaa44 100644 --- a/java_console/autotest/src/com/rusefi/IoUtil.java +++ b/java_console/autotest/src/com/rusefi/IoUtil.java @@ -1,38 +1,66 @@ package com.rusefi; +import com.irnems.FileLog; import com.irnems.core.EngineState; +import com.irnems.core.Sensor; +import com.irnems.core.SensorCentral; import com.rusefi.io.CommandQueue; import com.rusefi.io.InvocationConfirmationListener; import com.rusefi.io.LinkManager; +import com.rusefi.io.tcp.TcpConnector; +import com.rusefi.waves.WaveChart; +import com.rusefi.waves.WaveChartParser; import com.rusefi.waves.WaveReport; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import static com.rusefi.waves.WaveReport.isCloseEnough; + /** * @author Andrey Belomutskiy * 3/19/14. */ public class IoUtil { - static void sendCommand(String command) throws InterruptedException { + static void sendCommand(String command) { final CountDownLatch responseLatch = new CountDownLatch(1); + long time = System.currentTimeMillis(); + if (LinkManager.hasError()) + throw new IllegalStateException("IO error"); + FileLog.MAIN.logLine("Sending command [" + command + "]"); CommandQueue.getInstance().write(command, CommandQueue.DEFAULT_TIMEOUT, new InvocationConfirmationListener() { @Override public void onCommandConfirmation() { responseLatch.countDown(); } }); - responseLatch.await(20, TimeUnit.SECONDS); + wait(responseLatch, 20); + if (LinkManager.hasError()) + throw new IllegalStateException("IO error"); + FileLog.MAIN.logLine("Command [" + command + "] executed in " + (System.currentTimeMillis() - time)); } - static String getNextWaveChart() throws InterruptedException { + private static void wait(CountDownLatch responseLatch, int seconds) { + try { + responseLatch.await(seconds, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } + } + + static String getNextWaveChart() { + // we need to skip TWO because spark could have been scheduled a while ago and happen now + // todo: improve this logic, compare times + getWaveChart(); getWaveChart(); // we want to wait for the 2nd chart to see same same RPM across the whole chart - return getWaveChart(); + String result = getWaveChart(); + FileLog.MAIN.logLine("current chart: " + result); + return result; } - private static String getWaveChart() throws InterruptedException { + private static String getWaveChart() { final CountDownLatch waveChartLatch = new CountDownLatch(1); final AtomicReference result = new AtomicReference(); @@ -44,8 +72,91 @@ public class IoUtil { result.set(value); } }); - waveChartLatch.await(5, TimeUnit.SECONDS); + int timeout = 15; + wait(waveChartLatch, timeout); LinkManager.engineState.removeAction(WaveReport.WAVE_CHART); + if (result.get() == null) + throw new IllegalStateException("Did not receive chart in " + timeout); return result.get(); } + + static WaveChart nextChart() { + return WaveChartParser.unpackToMap(getNextWaveChart()); + } + + static void changeRpm(final int rpm) { + sendCommand("rpm " + rpm); + long time = System.currentTimeMillis(); + + final CountDownLatch rpmLatch = new CountDownLatch(1); + SensorCentral.AdcListener listener = new SensorCentral.AdcListener() { + @Override + public void onAdcUpdate(SensorCentral model, double value) { + double actualRpm = SensorCentral.getInstance().getValue(Sensor.RPM); + if (isCloseEnough(rpm, actualRpm)) + rpmLatch.countDown(); + } + }; + SensorCentral.getInstance().addListener(Sensor.RPM, listener); + try { + rpmLatch.await(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new IllegalStateException(e); + } + FileLog.MAIN.logLine("RPM change [" + rpm + "] executed in " + (System.currentTimeMillis() - time)); + SensorCentral.getInstance().removeListener(Sensor.RPM, listener); + + double actualRpm = SensorCentral.getInstance().getValue(Sensor.RPM); + + if (!isCloseEnough(rpm, actualRpm)) + throw new IllegalStateException("rpm change did not happen: " + rpm + ", actual " + actualRpm); + } + + static void waitForFirstResponse() throws InterruptedException { + FileLog.MAIN.logLine("Let's give it some time to start..."); + final CountDownLatch startup = new CountDownLatch(1); + SensorCentral.AdcListener listener = new SensorCentral.AdcListener() { + @Override + public void onAdcUpdate(SensorCentral model, double value) { + startup.countDown(); + } + }; + long waitStart = System.currentTimeMillis(); + SensorCentral.getInstance().addListener(Sensor.RPM, listener); + startup.await(5, TimeUnit.SECONDS); + SensorCentral.getInstance().removeListener(Sensor.RPM, listener); + FileLog.MAIN.logLine("Got first signal in " + (System.currentTimeMillis() - waitStart)); + } + + static void launchSimulator() throws InterruptedException { + if (!TcpConnector.getAvailablePorts().isEmpty()) + throw new IllegalStateException("Port already binded on startup?"); + + ExecHelper.startSimulator(); + + +// FileLog.rlog("Waiting for TCP port..."); +// for (int i = 0; i < 180; i++) { +// if (!TcpConnector.getAvailablePorts().isEmpty()) +// break; +// Thread.sleep(1000); +// } +// if (TcpConnector.getAvailablePorts().isEmpty()) +// throw new IllegalStateException("Did we start it?"); +// /** +// * If we open a connection just to validate that the process has started, we are getting +// * weird issues with the second - actual connection +// */ +// FileLog.rlog("Time for simulator to close the port..."); +// Thread.sleep(3000); +// +// FileLog.rlog("Got a TCP port! Connecting..."); + LinkManager.start("" + TcpConnector.DEFAULT_PORT); + /** + * TCP connector is blocking + */ + LinkManager.open(); + + waitForFirstResponse(); + } } diff --git a/java_console/autotest/src/com/rusefi/TestingUtils.java b/java_console/autotest/src/com/rusefi/TestingUtils.java index bad0f0977e..714e0fc89f 100644 --- a/java_console/autotest/src/com/rusefi/TestingUtils.java +++ b/java_console/autotest/src/com/rusefi/TestingUtils.java @@ -1,6 +1,12 @@ package com.rusefi; +import com.irnems.FileLog; +import com.rusefi.waves.RevolutionLog; +import com.rusefi.waves.WaveChart; +import com.rusefi.waves.WaveReport; + import java.util.Arrays; +import java.util.List; import static com.rusefi.waves.WaveReport.isCloseEnough; @@ -11,19 +17,55 @@ import static com.rusefi.waves.WaveReport.isCloseEnough; public class TestingUtils { static void assertTrue(String msg, boolean b) { if (!b) - throw new IllegalStateException("Not true: " + msg); + fail("Not true: " + msg); } static void assertCloseEnough(String msg, double current, double... expectations) { for (double expected : expectations) { - if (isCloseEnough(expected, current)) + if (isCloseEnough(fixAngle(expected), current)) return; } - throw new IllegalStateException(msg + ": Got " + current + " while expecting " + Arrays.toString(expectations)); + fail(msg + ": Got " + current + " while expecting " + Arrays.toString(expectations)); + } + + private static double fixAngle(double angle) { + while (angle > 720) + angle -= 720; + return angle; + } + + private static void fail(String message) { + FileLog.MAIN.logLine("FAILURE: " + message); + throw new IllegalStateException(message); } static void assertTrue(boolean b) { if (!b) - throw new IllegalStateException("Not true"); + fail("Not true"); + } + + static void assertWave(WaveChart chart, String key, double width, double... expectedAngles) { + assertWave("", chart, key, width, expectedAngles); + } + + static void assertWave(String msg, WaveChart chart, String key, double width, double... expectedAngles) { + RevolutionLog revolutionLog = chart.getRevolutionsLog(); + if (revolutionLog.keySet().isEmpty()) + throw new IllegalStateException(msg + " Empty revolutions in " + chart); + + StringBuilder events = chart.get(key); + assertTrue(msg + " Events not null for " + key, events != null); + List wr = WaveReport.parse(events.toString()); + assertTrue(msg + " waves for " + key, !wr.isEmpty()); + for (WaveReport.UpDown ud : wr) { + double angleByTime = revolutionLog.getCrankAngleByTime(ud.upTime); + assertCloseEnough(msg + " angle for " + key + "@" + ud.upTime, angleByTime, expectedAngles); + + assertCloseEnough(msg + "width for " + key, ud.getDutyCycle(revolutionLog), width); + } + } + + static void assertNull(String msg, Object value) { + assertTrue(msg, value == null); } } diff --git a/java_console/io/src/com/irnems/FileLog.java b/java_console/io/src/com/irnems/FileLog.java index 697789a13a..6174b8eca3 100644 --- a/java_console/io/src/com/irnems/FileLog.java +++ b/java_console/io/src/com/irnems/FileLog.java @@ -58,7 +58,7 @@ public enum FileLog { if (fileLog == null) return; try { - fileLog.write((fullLine + "\r\n").getBytes()); + fileLog.write((new Date() + ": " + fullLine + "\r\n").getBytes()); fileLog.flush(); System.out.println(fullLine); } catch (IOException e) { diff --git a/java_console/io/src/com/rusefi/io/LinkConnector.java b/java_console/io/src/com/rusefi/io/LinkConnector.java index 60954c9939..e6aa7e717c 100644 --- a/java_console/io/src/com/rusefi/io/LinkConnector.java +++ b/java_console/io/src/com/rusefi/io/LinkConnector.java @@ -10,4 +10,6 @@ public interface LinkConnector { void send(String command) throws InterruptedException; void restart(); + + boolean hasError(); } diff --git a/java_console/io/src/com/rusefi/io/LinkManager.java b/java_console/io/src/com/rusefi/io/LinkManager.java index 61c4044388..2085dbe912 100644 --- a/java_console/io/src/com/rusefi/io/LinkManager.java +++ b/java_console/io/src/com/rusefi/io/LinkManager.java @@ -23,24 +23,50 @@ public class LinkManager { return t; } }); + public static final String LOG_VIEWER = "log viewer"; + private static final LinkConnector VOID = new LinkConnector() { + @Override + public void connect() { + } + + @Override + public void send(String command) throws InterruptedException { + } + + @Override + public void restart() { + } + + @Override + public boolean hasError() { + return false; + } + }; public static EngineState engineState = new EngineState(new EngineState.EngineStateListenerImpl() { @Override public void beforeLine(String fullLine) { - FileLog.rlog("SerialManager.beforeLine: " + fullLine); FileLog.MAIN.logLine(fullLine); } }); public static boolean onlyUI = false; private static LinkConnector connector; + private static String port; public static void start(String port) { - if (TcpConnector.isTcpPort(port)) { + LinkManager.port = port; + if (port.equals(LOG_VIEWER)) { + connector = LinkManager.VOID; + } else if (TcpConnector.isTcpPort(port)) { connector = new TcpConnector(port); } else { connector = new SerialConnector(port); } } + public static boolean isLogViewer() { + return connector == LinkManager.VOID; + } + public static void open() { if (connector == null) throw new NullPointerException("connector"); @@ -64,4 +90,8 @@ public class LinkManager { public static void restart() { connector.restart(); } + + public static boolean hasError() { + return connector.hasError(); + } } diff --git a/java_console/io/src/com/rusefi/io/serial/PortHolder.java b/java_console/io/src/com/rusefi/io/serial/PortHolder.java index dc4bd41728..97e9cd94f3 100644 --- a/java_console/io/src/com/rusefi/io/serial/PortHolder.java +++ b/java_console/io/src/com/rusefi/io/serial/PortHolder.java @@ -47,10 +47,10 @@ class PortHolder { public boolean open(String port, DataListener listener) { SerialPort serialPort = new SerialPort(port); try { - FileLog.rlog("Opening " + port + " @ " + BAUD_RATE); + FileLog.MAIN.logLine("Opening " + port + " @ " + BAUD_RATE); boolean opened = serialPort.openPort();//Open serial port if (!opened) - FileLog.rlog("opened: " + opened); + FileLog.MAIN.logLine("opened: " + opened); serialPort.setParams(BAUD_RATE, 8, 1, 0);//Set params. int mask = SerialPort.MASK_RXCHAR; //Set the prepared mask @@ -81,7 +81,7 @@ class PortHolder { serialPort.closePort(); serialPort = null; } catch (SerialPortException e) { - FileLog.rlog("Error while closing: " + e); + FileLog.MAIN.logLine("Error while closing: " + e); } finally { portLock.notifyAll(); } @@ -93,7 +93,7 @@ class PortHolder { * this method blocks till a connection is available */ public void packAndSend(String command) throws InterruptedException { - FileLog.rlog("Sending [" + command + "]"); + FileLog.MAIN.logLine("Sending [" + command + "]"); MessagesCentral.getInstance().postMessage(CommandQueue.class, "Sending [" + command + "]"); long now = System.currentTimeMillis(); diff --git a/java_console/io/src/com/rusefi/io/serial/SerialConnector.java b/java_console/io/src/com/rusefi/io/serial/SerialConnector.java index 7d5683469a..3f65d192df 100644 --- a/java_console/io/src/com/rusefi/io/serial/SerialConnector.java +++ b/java_console/io/src/com/rusefi/io/serial/SerialConnector.java @@ -21,6 +21,11 @@ public class SerialConnector implements LinkConnector { SerialManager.restart(); } + @Override + public boolean hasError() { + return false; + } + @Override public void send(String command) throws InterruptedException { PortHolder.getInstance().packAndSend(command); diff --git a/java_console/io/src/com/rusefi/io/tcp/TcpConnector.java b/java_console/io/src/com/rusefi/io/tcp/TcpConnector.java index fd4bea3bf7..358759bb8f 100644 --- a/java_console/io/src/com/rusefi/io/tcp/TcpConnector.java +++ b/java_console/io/src/com/rusefi/io/tcp/TcpConnector.java @@ -18,6 +18,7 @@ public class TcpConnector implements LinkConnector { public static final String LOCALHOST = "localhost"; private final int port; private BufferedWriter writer; + private boolean withError; public TcpConnector(String port) { this.port = getTcpPort(port); @@ -77,6 +78,11 @@ public class TcpConnector implements LinkConnector { // FileLog.rlog("Restarting on " + port); } + @Override + public boolean hasError() { + return withError; + } + @Override public void send(String command) throws InterruptedException { FileLog.rlog("Writing " + command); @@ -84,6 +90,7 @@ public class TcpConnector implements LinkConnector { writer.write(command + "\r\n"); writer.flush(); } catch (IOException e) { + withError = true; System.err.println("err in send"); e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } diff --git a/java_console/models/src/com/irnems/core/EngineState.java b/java_console/models/src/com/irnems/core/EngineState.java index e76b653795..d8673daa8a 100644 --- a/java_console/models/src/com/irnems/core/EngineState.java +++ b/java_console/models/src/com/irnems/core/EngineState.java @@ -49,6 +49,10 @@ public class EngineState { public void onResponse(String message) { String response = unpackString(message); if (response != null) { + // todo: improve this hack + int i = response.indexOf("2014: "); + if (i != -1) + response = response.substring(i + 6); String copy = response; listener.beforeLine(response); while (!response.isEmpty()) @@ -196,13 +200,13 @@ public class EngineState { public static String unpackString(String message) { String prefix = "line" + PACKING_DELIMITER; if (!message.startsWith(prefix)) { - FileLog.rlog("EngineState: unexpected header: " + message); + FileLog.MAIN.logLine("EngineState: unexpected header: " + message); return null; } message = message.substring(prefix.length()); int delimiterIndex = message.indexOf(PACKING_DELIMITER); if (delimiterIndex == -1) { - FileLog.rlog("Delimiter not found in: " + message); + FileLog.MAIN.logLine("Delimiter not found in: " + message); return null; } String lengthToken = message.substring(0, delimiterIndex); @@ -210,13 +214,13 @@ public class EngineState { try { expectedLen = Integer.parseInt(lengthToken); } catch (NumberFormatException e) { - FileLog.rlog("invalid len: " + lengthToken); + FileLog.MAIN.logLine("invalid len: " + lengthToken); return null; } String response = message.substring(delimiterIndex + 1); if (response.length() != expectedLen) { - FileLog.rlog("message len does not match header: " + message); + FileLog.MAIN.logLine("message len does not match header: " + message); response = null; } return response; diff --git a/java_console/models/src/com/irnems/core/MessagesCentral.java b/java_console/models/src/com/irnems/core/MessagesCentral.java index a29b3f0419..8ef06e6c99 100644 --- a/java_console/models/src/com/irnems/core/MessagesCentral.java +++ b/java_console/models/src/com/irnems/core/MessagesCentral.java @@ -26,7 +26,7 @@ public class MessagesCentral { } public void postMessage(final Class clazz, final String message) { - FileLog.rlog("postMessage " + clazz.getSimpleName() + ": " + message); + FileLog.MAIN.logLine("postMessage " + clazz.getSimpleName() + ": " + message); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { diff --git a/java_console/models/src/com/rusefi/waves/WaveChart.java b/java_console/models/src/com/rusefi/waves/WaveChart.java index 0dea8b1415..6e1aece866 100644 --- a/java_console/models/src/com/rusefi/waves/WaveChart.java +++ b/java_console/models/src/com/rusefi/waves/WaveChart.java @@ -17,6 +17,8 @@ public class WaveChart { public static final String INJECTOR_2 = "Injector 2"; public static final String INJECTOR_3 = "Injector 3"; public static final String INJECTOR_4 = "Injector 4"; + public static final String INJECTOR_5 = "Injector 5"; + public static final String INJECTOR_6 = "Injector 6"; public static final String SPARK_1 = "Spark 1"; public static final String SPARK_2 = "Spark 2"; public static final String SPARK_3 = "Spark 3"; @@ -28,6 +30,11 @@ public class WaveChart { this.map = map; } + public RevolutionLog getRevolutionsLog() { + StringBuilder revolutions = get(RevolutionLog.TOP_DEAD_CENTER_MESSAGE); + return RevolutionLog.parseRevolutions(revolutions); + } + public StringBuilder get(String key) { return map.get(key); } diff --git a/java_console/models/src/com/rusefi/waves/WaveChartParser.java b/java_console/models/src/com/rusefi/waves/WaveChartParser.java index 3011eaf41a..8cb5b2da9e 100644 --- a/java_console/models/src/com/rusefi/waves/WaveChartParser.java +++ b/java_console/models/src/com/rusefi/waves/WaveChartParser.java @@ -16,6 +16,8 @@ public class WaveChartParser { * This method unpacks a mixed-key message into a Map of messages by key */ public static WaveChart unpackToMap(String value) { + if (value == null) + throw new NullPointerException("value"); FileLog.rlog(": " + value); String[] array = value.split(DELI); diff --git a/java_console/models/src/com/rusefi/waves/WaveReport.java b/java_console/models/src/com/rusefi/waves/WaveReport.java index ecab46ce4a..b102f031aa 100644 --- a/java_console/models/src/com/rusefi/waves/WaveReport.java +++ b/java_console/models/src/com/rusefi/waves/WaveReport.java @@ -159,7 +159,9 @@ public class WaveReport implements TimeAxisTranslator { } public double getDutyCycle(RevolutionLog rl) { - double angleDuration = (rl.getCrankAngleByTime(downTime) + 360 - rl.getCrankAngleByTime(upTime)) % 260; + double angleDuration = (rl.getCrankAngleByTime(downTime) + 720 - rl.getCrankAngleByTime(upTime)) % 360; + if (angleDuration < 0) + throw new IllegalStateException("Negative width: " + angleDuration); return angleDuration / 360; } } diff --git a/java_console/models/src/com/rusefi/waves/test/WaveChartParserTest.java b/java_console/models/src/com/rusefi/waves/test/WaveChartParserTest.java index f5d1c0d6c4..e41b5d8bfa 100644 --- a/java_console/models/src/com/rusefi/waves/test/WaveChartParserTest.java +++ b/java_console/models/src/com/rusefi/waves/test/WaveChartParserTest.java @@ -52,7 +52,7 @@ public class WaveChartParserTest { for (WaveReport.UpDown ud : wr.getList()) { assertTrue(isCloseEnough(238.75, rl.getCrankAngleByTime(ud.upTime))); - assertTrue(isCloseEnough(0.308, ud.getDutyCycle(rl))); + assertTrue(ud.getDutyCycle(rl) + "", isCloseEnough(0.0307, ud.getDutyCycle(rl))); } } diff --git a/java_console/ui/src/com/irnems/ChartRepository.java b/java_console/ui/src/com/irnems/ChartRepository.java index 1adb0507e1..f0f919bfd9 100644 --- a/java_console/ui/src/com/irnems/ChartRepository.java +++ b/java_console/ui/src/com/irnems/ChartRepository.java @@ -1,12 +1,9 @@ package com.irnems; -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; +import com.rusefi.ui.ChartScrollControl; + import java.util.ArrayList; import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; /** * 7/27/13 @@ -44,50 +41,7 @@ public class ChartRepository { public void onDigitalChart(String chart); } - public JComponent createControls(final CRListener listener) { - - final AtomicInteger index = new AtomicInteger(); - - JPanel result = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 0)); - result.setBorder(BorderFactory.createLineBorder(Color.red)); - - final JLabel info = new JLabel(); - - setInfoText(index, info); - - JButton prev = new JButton("<"); - prev.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (index.intValue() > 0) { - index.decrementAndGet(); - listener.onDigitalChart(charts.get(index.get())); - setInfoText(index, info); - } - } - }); - - - JButton next = new JButton(">"); - next.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (index.intValue() < getSize() - 1) { - index.incrementAndGet(); - listener.onDigitalChart(charts.get(index.get())); - setInfoText(index, info); - } - } - }); - - result.add(prev); - result.add(info); - result.add(next); - - return result; - } - - private void setInfoText(AtomicInteger index, JLabel info) { - info.setText(index.get() + "/" + getSize()); + public ChartScrollControl createControls(final CRListener listener) { + return new ChartScrollControl(listener); } } diff --git a/java_console/ui/src/com/irnems/EcuStimulator.java b/java_console/ui/src/com/irnems/EcuStimulator.java index 0c5c51cc63..bed82cb177 100644 --- a/java_console/ui/src/com/irnems/EcuStimulator.java +++ b/java_console/ui/src/com/irnems/EcuStimulator.java @@ -40,7 +40,7 @@ public class EcuStimulator { private static final int RPM_MIN = 400; private static final int RPM_MAX = 6000; private static final int RPM_INCREMENT = 250; - private static final Sensor DWELL_SENSOR = Sensor.DWELL1; + private static final Sensor DWELL_SENSOR = Sensor.DWELL0; private static final String TABLE_FILE_NAME = "table" + RPM_INCREMENT + "_" + MAF_INCREMENT + ".csv"; @@ -111,10 +111,14 @@ public class EcuStimulator { private static void runSimulation(int rpm, ResultListener resultListener, final Sensor dwellSensor) { for (double maf = MAF_MIN; maf <= MAF_MAX; maf += MAF_INCREMENT) { - setPotVoltage(maf, Sensor.MAF); + //setPotVoltage(maf, Sensor.MAF); + setPotVoltage(maf, null); setRpm(rpm); sleepRuntime(SLEEP_TIME); + /** + * We are making a number of measurements and then we take the middle one + */ final List dwells = new ArrayList(MEASURES); final List advances = new ArrayList(MEASURES); @@ -125,9 +129,9 @@ public class EcuStimulator { public void onTime(double time) { if (latch.getCount() == 0) return; - double dwell0 = getValue(dwellSensor); + double dwell = getValue(dwellSensor); double advance = 0;//getValue(Sensor.ADVANCE0); - dwells.add(dwell0); + dwells.add(dwell); advances.add(advance); latch.countDown(); } @@ -148,7 +152,6 @@ public class EcuStimulator { if (dwellDiff > 1) System.out.println("dwells " + dwells); - double dwell = dwells.get(MEASURES / 2); double advance = advances.get(MEASURES / 2); @@ -188,23 +191,32 @@ public class EcuStimulator { log("Result: " + actual + " while setting " + rpm); } - public static void setPotVoltage(double voltage, Sensor sensor) { - log("Current voltage: " + getValue(sensor) + ", setting " + voltage); + public static void setPotVoltage(double targetVoltage, Sensor sensor) { + if (sensor != null) + log("Current targetVoltage: " + getValue(sensor) + ", setting " + targetVoltage); int attempt = 0; - int resistance = PotCommand.getPotResistance(voltage); + //double vRef = SensorCentral.getInstance().getValue(Sensor.VREF) * PotCommand.VOLTAGE_CORRECTION; + double vRef = 4.7; + int resistance = PotCommand.getPotResistance(targetVoltage, vRef); if (resistance <= 0) { - log("Invalid resistance " + resistance + ". Invalid voltage " + voltage + "?"); + log("Invalid resistance " + resistance + ". Invalid targetVoltage " + targetVoltage + "?"); return; } - double actual; - do { + if (sensor == null) { PotCommand.requestPotChange(1, resistance); - sleepRuntime(50); - actual = getValue(sensor); - log("Got: " + actual + " on attempt=" + attempt + " while setting " + voltage + " for " + sensor); - } while (attempt++ < 10 && Math.abs(voltage - actual) > 0.2); - log("Result: " + actual + " while setting " + voltage); + sleepRuntime(1000); + } else { + + double actual; + do { + PotCommand.requestPotChange(1, resistance); + sleepRuntime(50); + actual = getValue(sensor); + log("Got: " + actual + " on attempt=" + attempt + " while setting " + targetVoltage + " for " + sensor); + } while (attempt++ < 10 && Math.abs(targetVoltage - actual) > 0.2); + log("Result: " + actual + " while setting " + targetVoltage); + } } private static void log(String message) { diff --git a/java_console/ui/src/com/irnems/Launcher.java b/java_console/ui/src/com/irnems/Launcher.java index 0c5aa6105b..b4a3120f70 100644 --- a/java_console/ui/src/com/irnems/Launcher.java +++ b/java_console/ui/src/com/irnems/Launcher.java @@ -20,7 +20,7 @@ import javax.swing.*; * @see WavePanel */ public class Launcher extends FrameHelper { - private static final Object CONSOLE_VERSION = "20140304"; + private static final Object CONSOLE_VERSION = "20140407"; public Launcher(String port) { FileLog.MAIN.start(); @@ -40,7 +40,7 @@ public class Launcher extends FrameHelper { // tabbedPane.addTab("live map adjustment", new Live3DReport().getControl()); tabbedPane.add("MessagesCentral", new MsgPanel(true)); -// tabbedPane.add("Log Viewer", new LogViewer()); + tabbedPane.add("Log Viewer", new LogViewer()); tabbedPane.setSelectedIndex(2); // tabbedPane.setSelectedIndex(5); diff --git a/java_console/ui/src/com/irnems/LogViewer.java b/java_console/ui/src/com/irnems/LogViewer.java index 97aebe6171..0f3bd1304e 100644 --- a/java_console/ui/src/com/irnems/LogViewer.java +++ b/java_console/ui/src/com/irnems/LogViewer.java @@ -3,11 +3,16 @@ package com.irnems; import com.irnems.core.EngineState; import com.irnems.file.FileUtils; import com.irnems.ui.WavePanel; +import com.irnems.ui.widgets.UpDownImage; +import com.rusefi.FIleItem; +import com.rusefi.io.LinkManager; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.io.File; import java.io.FileFilter; @@ -19,13 +24,15 @@ public class LogViewer extends JPanel { public static final FileFilter FILE_FILTER = new FileFilter() { @Override public boolean accept(File pathname) { - return pathname.getName().startsWith("rfi_report"); + return pathname.getName().contains("MAIN_rfi_report"); } }; private final JLabel folderLabel = new JLabel(); - private final DefaultListModel fileListModel = new DefaultListModel(); - private final JList fileList = new JList(fileListModel); + private final JLabel fileLabel = new JLabel(); + private final DefaultListModel fileListModel = new DefaultListModel(); + private final JList fileList = new JList(fileListModel); private String currentFolder; + private static JPanel descPanel = new JPanel(); // int currentChartIndex = 0; @@ -54,30 +61,44 @@ public class LogViewer extends JPanel { folderPanel.add(folderButton); folderPanel.add(folderLabel); + folderPanel.add(fileLabel); - folderPanel.setBackground(Color.red); + //folderPanel.setBackground(Color.red); add(folderPanel, BorderLayout.NORTH); - - JPanel descPanel = new JPanel(); - descPanel.add(new JLabel("Total digital charts: ")); - descPanel.add(new JLabel("" + ChartRepository.getInstance().getSize())); - + refreshCountPanel(); JPanel boxPanel = new JPanel(); boxPanel.setLayout(new BoxLayout(boxPanel, BoxLayout.X_AXIS)); boxPanel.setBorder(BorderFactory.createLineBorder(Color.cyan)); - boxPanel.add(fileList); - boxPanel.add(descPanel); + fileList.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + FIleItem selectedItem = fileList.getSelectedValue(); + openFile(selectedItem.getFile()); + } + } + }); + JScrollPane scrollPane = new JScrollPane(fileList); + boxPanel.add(scrollPane); + boxPanel.add(descPanel); add(boxPanel); } + private void refreshCountPanel() { + descPanel.removeAll(); + descPanel.add(new JLabel("Total digital charts: ")); + descPanel.add(new JLabel("" + ChartRepository.getInstance().getSize())); + UpDownImage.trueRepaint(descPanel); + } + private void openFolder(String folderName) { - folderLabel.setText(folderName); + folderLabel.setText("Current folder: " + folderName); currentFolder = folderName; File folder = new File(folderName); @@ -89,13 +110,13 @@ public class LogViewer extends JPanel { for (File file : files) fileListModel.addElement(getFileDesc(file)); - if (files.length > 0) + if (files.length > 0 && LinkManager.isLogViewer()) openFile(files[0]); } - private String getFileDesc(File file) { - return file.getName() + " " + file.getUsableSpace(); + private FIleItem getFileDesc(File file) { + return new FIleItem(file); } @@ -127,6 +148,7 @@ public class LogViewer extends JPanel { // // private void openFile(File file) { + fileLabel.setText("Current file: " + file.getName()); String filename = file.getAbsolutePath(); EngineState.EngineStateListener listener = new EngineState.EngineStateListenerImpl() { }; @@ -145,6 +167,7 @@ public class LogViewer extends JPanel { FileUtils.readFile2(filename, engineState); if (ChartRepository.getInstance().getSize() > 0) - WavePanel.getInstance().displayChart(ChartRepository.getInstance().getChart(0)); + WavePanel.getInstance().reloadFile(); + refreshCountPanel(); } } \ No newline at end of file diff --git a/java_console/ui/src/com/irnems/ui/WavePanel.java b/java_console/ui/src/com/irnems/ui/WavePanel.java index 5729f4f525..d27ce3fa44 100644 --- a/java_console/ui/src/com/irnems/ui/WavePanel.java +++ b/java_console/ui/src/com/irnems/ui/WavePanel.java @@ -8,6 +8,7 @@ import com.irnems.core.SensorCentral; import com.irnems.ui.widgets.AnyCommand; import com.irnems.ui.widgets.UpDownImage; import com.rusefi.io.LinkManager; +import com.rusefi.ui.ChartScrollControl; import com.rusefi.waves.RevolutionLog; import com.rusefi.waves.WaveChart; import com.rusefi.waves.WaveChartParser; @@ -38,6 +39,7 @@ public class WavePanel extends JPanel { private final ZoomControl zoomControl = new ZoomControl(); private final ChartStatusPanel statusPanel = new ChartStatusPanel(zoomControl); private final UpDownImage crank = register("crank"); + private ChartScrollControl scrollControl; private boolean isPaused; @@ -86,12 +88,13 @@ public class WavePanel extends JPanel { buttonPanel.add(zoomControl); - buttonPanel.add(ChartRepository.getInstance().createControls(new ChartRepository.CRListener() { + scrollControl = ChartRepository.getInstance().createControls(new ChartRepository.CRListener() { @Override public void onDigitalChart(String chart) { displayChart(chart); } - })); + }); + buttonPanel.add(scrollControl.getContent()); add(buttonPanel, BorderLayout.NORTH); add(imagePanel, BorderLayout.CENTER); @@ -181,4 +184,9 @@ public class WavePanel extends JPanel { images.put(name, image); return image; } + + public void reloadFile() { + displayChart(ChartRepository.getInstance().getChart(0)); + scrollControl.reset(); + } } diff --git a/java_console/ui/src/com/irnems/ui/widgets/PotCommand.java b/java_console/ui/src/com/irnems/ui/widgets/PotCommand.java index 724ffcfc10..b39203d5e7 100644 --- a/java_console/ui/src/com/irnems/ui/widgets/PotCommand.java +++ b/java_console/ui/src/com/irnems/ui/widgets/PotCommand.java @@ -36,7 +36,7 @@ public class PotCommand { @Override public void stateChanged(ChangeEvent e) { Double Vout = (Double) voltageSpinner.getValue(); - int d = getPotResistance(Vout); + int d = getPotResistance(Vout, SensorCentral.getInstance().getValue(Sensor.VREF) * VOLTAGE_CORRECTION); potSpinner.setValue(d); } }); @@ -86,8 +86,7 @@ public class PotCommand { CommandQueue.getInstance().write("pot" + channel + " " + resistance); } - public static int getPotResistance(Double vout) { - double vRef = SensorCentral.getInstance().getValue(Sensor.VREF) * VOLTAGE_CORRECTION; + public static int getPotResistance(Double vout, double vRef) { double r = getR1InVoltageDividor3(vout, vRef, MAF_CHANNEL_ECU_INTERNAL_RESISTANCE); MessagesCentral.getInstance().postMessage(PotCommand.class, "VRef=" + vRef + ", needed resistance: " + r); // pot command accept resistance and does the conversion itself diff --git a/java_console/ui/src/com/rusefi/FIleItem.java b/java_console/ui/src/com/rusefi/FIleItem.java new file mode 100644 index 0000000000..9a1fd3571f --- /dev/null +++ b/java_console/ui/src/com/rusefi/FIleItem.java @@ -0,0 +1,24 @@ +package com.rusefi; + +import java.io.File; + +/** + * 4/7/14 + * (c) Andrey Belomutskiy + */ +public class FIleItem { + private final File file; + + public FIleItem(File file) { + this.file = file; + } + + public File getFile() { + return file; + } + + @Override + public String toString() { + return file.getName() + " " + file.length(); + } +} diff --git a/java_console/ui/src/com/rusefi/PortLookupFrame.java b/java_console/ui/src/com/rusefi/PortLookupFrame.java index e239d9ddb8..df809e9ca0 100644 --- a/java_console/ui/src/com/rusefi/PortLookupFrame.java +++ b/java_console/ui/src/com/rusefi/PortLookupFrame.java @@ -1,6 +1,7 @@ package com.rusefi; import com.irnems.Launcher; +import com.rusefi.io.LinkManager; import com.rusefi.io.tcp.TcpConnector; import jssc.SerialPortList; @@ -22,6 +23,7 @@ public class PortLookupFrame { java.util.List ports = new ArrayList(); ports.addAll(Arrays.asList(SerialPortList.getPortNames())); ports.addAll(TcpConnector.getAvailablePorts()); + ports.add(LinkManager.LOG_VIEWER); if (ports.size() == 0) { diff --git a/java_console/ui/src/com/rusefi/ui/ChartScrollControl.java b/java_console/ui/src/com/rusefi/ui/ChartScrollControl.java new file mode 100644 index 0000000000..65f0d6facc --- /dev/null +++ b/java_console/ui/src/com/rusefi/ui/ChartScrollControl.java @@ -0,0 +1,71 @@ +package com.rusefi.ui; + +import com.irnems.ChartRepository; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * 4/7/14 + * (c) Andrey Belomutskiy + */ +public class ChartScrollControl { + private final JPanel content = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 0)); + private final AtomicInteger index = new AtomicInteger(); + private static final JLabel info = new JLabel(); + + public ChartScrollControl(final ChartRepository.CRListener listener) { + + content.setBorder(BorderFactory.createLineBorder(Color.red)); + + + setInfoText(index); + + JButton prev = new JButton("<"); + prev.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (index.intValue() > 0) { + index.decrementAndGet(); + listener.onDigitalChart(ChartRepository.getInstance().getChart(index.get())); + setInfoText(index); + } + } + }); + + + JButton next = new JButton(">"); + next.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (index.intValue() < ChartRepository.getInstance().getSize() - 1) { + index.incrementAndGet(); + listener.onDigitalChart(ChartRepository.getInstance().getChart(index.get())); + setInfoText(index); + } + } + }); + + content.add(prev); + content.add(info); + content.add(next); + + } + + public JPanel getContent() { + return content; + } + + private void setInfoText(AtomicInteger index) { + info.setText(index.get() + "/" + ChartRepository.getInstance().getSize()); + } + + public void reset() { + index.set(0); + setInfoText(index); + } +} +