java console sync

This commit is contained in:
Andrey B 2014-04-26 10:05:18 -05:00
parent de303ed994
commit 15aa5e2135
25 changed files with 578 additions and 239 deletions

View File

@ -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<WaveReport.UpDown> 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");
}
}

View File

@ -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();
}
}

View File

@ -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<String> result = new AtomicReference<String>();
@ -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();
}
}

View File

@ -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<WaveReport.UpDown> 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);
}
}

View File

@ -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) {

View File

@ -10,4 +10,6 @@ public interface LinkConnector {
void send(String command) throws InterruptedException;
void restart();
boolean hasError();
}

View File

@ -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();
}
}

View File

@ -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();

View File

@ -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);

View File

@ -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.
}

View File

@ -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;

View File

@ -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() {

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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)));
}
}

View File

@ -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);
}
}

View File

@ -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<Double> dwells = new ArrayList<Double>(MEASURES);
final List<Double> advances = new ArrayList<Double>(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) {

View File

@ -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);

View File

@ -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<String> fileListModel = new DefaultListModel<String>();
private final JList<String> fileList = new JList<String>(fileListModel);
private final JLabel fileLabel = new JLabel();
private final DefaultListModel<FIleItem> fileListModel = new DefaultListModel<FIleItem>();
private final JList<FIleItem> fileList = new JList<FIleItem>(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();
}
}

View File

@ -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();
}
}

View File

@ -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

View File

@ -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();
}
}

View File

@ -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<String> ports = new ArrayList<String>();
ports.addAll(Arrays.asList(SerialPortList.getPortNames()));
ports.addAll(TcpConnector.getAvailablePorts());
ports.add(LinkManager.LOG_VIEWER);
if (ports.size() == 0) {

View File

@ -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);
}
}