REO progress - binary logs

This commit is contained in:
rusefi 2020-06-14 16:19:33 -04:00
parent 8165ee016f
commit 1e240983bd
11 changed files with 126 additions and 75 deletions

View File

@ -146,13 +146,13 @@ public class Field {
*/
@NotNull
@Deprecated
public Number getValue(ConfigurationImage ci) {
public Double getValue(ConfigurationImage ci) {
return getValue(ci, 1);
}
// todo: rename to getNumberValue?
@NotNull
public Number getValue(ConfigurationImage ci, double multiplier) {
public Double getValue(ConfigurationImage ci, double multiplier) {
Objects.requireNonNull(ci);
Number value;
ByteBuffer wrapped = ci.getByteBuffer(getOffset(), type.getStorageSize());

View File

@ -239,6 +239,10 @@ public enum Sensor {
public void writeToLog(DataOutputStream dos, double value) throws IOException {
switch (type) {
case INT8:
case UINT8:
dos.write((int) value);
return;
case FLOAT:
dos.writeFloat((float) value);
return;

View File

@ -10,6 +10,7 @@ import com.rusefi.io.LinkManager;
import com.rusefi.io.serial.BaudRateHolder;
import com.rusefi.maintenance.FirmwareFlasher;
import com.rusefi.maintenance.VersionChecker;
import com.rusefi.sensor_logs.SensorLogger;
import com.rusefi.ui.*;
import com.rusefi.ui.console.MainFrame;
import com.rusefi.ui.console.TabbedPanel;
@ -135,6 +136,7 @@ public class ConsoleUI {
tabbedPane.addTab("rusEFI Online", new OnlineTab().getContent());
SensorLogger.init();
if (!LinkManager.isLogViewerMode(port)) {
int selectedIndex = getConfig().getRoot().getIntProperty(TAB_INDEX, DEFAULT_TAB_INDEX);

View File

@ -1,34 +1,46 @@
package com.rusefi.sensor_logs;
import com.rusefi.FileLog;
import com.rusefi.config.FieldType;
import com.rusefi.config.generated.Fields;
import com.rusefi.core.Sensor;
import com.rusefi.core.SensorCentral;
import com.rusefi.rusEFIVersion;
import java.io.*;
import java.util.Date;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* MLV .mlq binary log file
* </p>
* Andrey Belomutskiy, (c) 2013-2020
*/
public class BinarySensorLog extends SensorLog {
private final Function<Sensor, Double> valueProvider;
private final Sensor[] sensors;
private final Collection<Sensor> sensors;
private DataOutputStream stream;
private int counter;
public BinarySensorLog() {
this(new Function<Sensor, Double>() {
@Override
public Double apply(Sensor sensor) {
return SensorCentral.getInstance().getValue(sensor);
}
}, SensorLogger.SENSORS);
this(sensor -> SensorCentral.getInstance().getValue(sensor), SensorLogger.SENSORS);
}
public BinarySensorLog(Function<Sensor, Double> valueProvider, Sensor... sensors) {
this.valueProvider = valueProvider;
this.sensors = sensors;
this.sensors = filterOutSensorsWithoutType(Objects.requireNonNull(sensors, "sensors"));
}
private Collection<Sensor> filterOutSensorsWithoutType(Sensor[] sensors) {
return Arrays.stream(sensors).filter(new Predicate<Sensor>() {
@Override
public boolean test(Sensor sensor) {
return sensor.getType() != null;
}
}).collect(Collectors.toCollection(ArrayList::new));
}
@Override
@ -44,11 +56,11 @@ public class BinarySensorLog extends SensorLog {
try {
stream = new DataOutputStream(new FileOutputStream(fileName));
} catch (IOException e) {
writeHeader();
} catch (Throwable e) {
e.printStackTrace();
stream = null;
}
writeHeader();
}
if (stream != null) {
@ -73,69 +85,76 @@ public class BinarySensorLog extends SensorLog {
stream.write(byteArray);
stream.write(checkSum);
if (counter % 20 == 0) {
// for not flush on each block of data but still flush
stream.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void writeHeader() {
try {
private void writeHeader() throws IOException {
String headerText = "\"rusEFI " + rusEFIVersion.CONSOLE_VERSION + "\"\n" +
"\"Capture Date: " + new Date() + "\"\n";
String headerText = "\"rusEFI " + rusEFIVersion.CONSOLE_VERSION + "\"\n" +
"\"Capture Date: " + new Date() + "\"\n";
for (char c : "MLVLG\0".toCharArray()) {
stream.write(c);
}
int fieldsDataSize = 0;
for (Sensor sensor : sensors) {
fieldsDataSize += sensor.getType().getStorageSize();
}
// 0006h Format version = 01
stream.write(0);
stream.write(1);
// 0008h Timestamp
stream.writeInt(0);
// 000ch
int offsetToText = Fields.MLQ_HEADER_SIZE + Fields.MLQ_FIELD_HEADER_SIZE * sensors.length;
stream.writeShort(offsetToText);
stream.writeShort(0); // reserved?
// 0010h = offset_to_data
stream.writeShort(offsetToText + headerText.length());
// 0012h
stream.writeShort(fieldsDataSize);
// 0014h number of fields
stream.writeShort(sensors.length);
for (Sensor sensor : sensors) {
String name = SensorLogger.getSensorName(sensor, 0);
String unit = sensor.getUnits();
// 0000h
stream.write(getSensorTypeValue(sensor));
// 0001h
writeLine(stream, name, 34);
// 0023h
writeLine(stream, unit, 11);
// 002Eh scale
stream.writeFloat(1); // todo: multiplier?
// 0032h zeroes
stream.writeInt(0);
// 0036h precision
stream.write(2);
}
writeLine(stream, headerText, 0);
} catch (IOException e) {
e.printStackTrace();
for (char c : "MLVLG\0".toCharArray()) {
stream.write(c);
}
int fieldsDataSize = 0;
for (Sensor sensor : sensors) {
FieldType type = sensor.getType();
if (type == null)
throw new NullPointerException("No type for " + sensor);
fieldsDataSize += type.getStorageSize();
}
// 0006h Format version = 01
stream.write(0);
stream.write(1);
// 0008h Timestamp
stream.writeInt(0);
// 000ch
int offsetToText = Fields.MLQ_HEADER_SIZE + Fields.MLQ_FIELD_HEADER_SIZE * sensors.size();
stream.writeShort(offsetToText);
stream.writeShort(0); // reserved?
// 0010h = offset_to_data
stream.writeShort(offsetToText + headerText.length());
// 0012h
stream.writeShort(fieldsDataSize);
// 0014h number of fields
stream.writeShort(sensors.size());
for (Sensor sensor : sensors) {
String name = SensorLogger.getSensorName(sensor, 0);
String unit = sensor.getUnits();
// 0000h
stream.write(getSensorTypeValue(sensor));
// 0001h
writeLine(stream, name, 34);
// 0023h
writeLine(stream, unit, 11);
// 002Eh scale
stream.writeFloat(1); // todo: multiplier?
// 0032h zeroes
stream.writeInt(0);
// 0036h precision
stream.write(2);
}
writeLine(stream, headerText, 0);
}
private int getSensorTypeValue(Sensor sensor) {
switch (sensor.getType()) {
case UINT8:
return 0;
case INT8:
return 1;
case UINT16:
return 2;
case INT16:
@ -149,8 +168,10 @@ public class BinarySensorLog extends SensorLog {
}
}
@Override
public void close() {
close(stream);
stream = null;
}
public static void close(Closeable closeable) {

View File

@ -20,11 +20,13 @@ public class BinarySensorLogSandbox {
BinarySensorLog l = new BinarySensorLog(valueProvider,
Sensor.TIME_SECONDS,
Sensor.RPM,
Sensor.VSS,
Sensor.FIRMWARE_VERSION,
Sensor.CLT);
values.put(Sensor.TIME_SECONDS, 1.0);
values.put(Sensor.RPM, 0.0);
values.put(Sensor.VSS, 60.0);
values.put(Sensor.FIRMWARE_VERSION, 20200101.0);
values.put(Sensor.CLT, 29.0);
@ -39,6 +41,5 @@ public class BinarySensorLogSandbox {
}
l.close();
}
}

View File

@ -14,13 +14,17 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
/**
* Legacy human readable CSV log file
* </p>
* Andrey Belomutskiy, (c) 2013-2020
*/
public class PlainTextSensorLog extends SensorLog {
private Writer logFile;
private long fileStartTime;
public void startIfNeeded() {
private void startIfNeeded() {
if (logFile == null) {
/*
* we only start file header once we have first bunch of data
@ -75,7 +79,6 @@ public class PlainTextSensorLog extends SensorLog {
return msSinceFileStart / 1000.0;
}
@Override
void writeSensorLogLine() {
startIfNeeded();
@ -94,5 +97,11 @@ public class PlainTextSensorLog extends SensorLog {
logFile = null;
}
}
@Override
public void close() {
BinarySensorLog.close(logFile);
logFile = null;
}
}

View File

@ -4,4 +4,6 @@ public abstract class SensorLog {
public abstract double getSecondsSinceFileStart();
abstract void writeSensorLogLine();
public abstract void close();
}

View File

@ -5,13 +5,14 @@ import com.rusefi.core.SensorCentral;
import com.rusefi.io.ConnectionStatusLogic;
import com.rusefi.io.ConnectionStatusValue;
import java.util.Arrays;
import java.util.List;
/**
* Andrey Belomutskiy, (c) 2013-2020
* 4/15/2016.
*/
public class SensorLogger {
private static SensorLog sensorLog = new PlainTextSensorLog();
protected static Sensor[] SENSORS = {Sensor.RPM,
Sensor.INT_TEMP,
@ -79,6 +80,10 @@ public class SensorLogger {
Sensor.tuneCrc16,
};
private static List<SensorLog> sensorLogs = Arrays.asList(new PlainTextSensorLog(), new BinarySensorLog());
private static boolean isInitialized;
private SensorLogger() {
}
@ -86,19 +91,24 @@ public class SensorLogger {
init();
}
private static void init() {
public synchronized static void init() {
if (isInitialized) {
return;
}
isInitialized = true;
SensorCentral.getInstance().addListener(Sensor.TIME_SECONDS, new SensorCentral.SensorListener() {
@Override
public void onSensorUpdate(double value) {
if (ConnectionStatusLogic.INSTANCE.getValue() != ConnectionStatusValue.CONNECTED)
return;
sensorLog.writeSensorLogLine();
for (SensorLog sensorLog : sensorLogs)
sensorLog.writeSensorLogLine();
}
});
}
public static double getSecondsSinceFileStart() {
return sensorLog.getSecondsSinceFileStart();
return sensorLogs.get(0).getSecondsSinceFileStart();
}
static String getSensorName(Sensor sensor, int debugMode) {

View File

@ -210,7 +210,7 @@ public class FormulasPane {
double displacement = ConfigField.getFloatValue(ci, Fields.DISPLACEMENT);
int cylinderCount = ConfigField.getIntValue(ci, Fields.CYLINDERSCOUNT);
String cylinderDisplacement = oneDecimal(displacement / cylinderCount);
String injectorFlow = oneDecimal((float) Fields.INJECTOR_FLOW.getValue(ci));
String injectorFlow = oneDecimal((float) Fields.INJECTOR_FLOW.getValue(ci).doubleValue());
String tCharge = "$Tcharge=f(CLT=" + oneDecimal(Sensor.CLT) + "C,IAT=" + IAT
+ "C,TPS=" + tpsStr + "\\%, RPM = " + RPM + ")=" + T_CHARGE + "C$";

View File

@ -6,6 +6,7 @@ import com.rusefi.io.ConnectionStateListener;
import com.rusefi.io.ConnectionStatusLogic;
import com.rusefi.io.ConnectionWatchdog;
import com.rusefi.io.LinkManager;
import com.rusefi.sensor_logs.SensorLogger;
import com.rusefi.ui.util.FrameHelper;
import javax.swing.*;
@ -54,6 +55,7 @@ public class LightweightGUI {
ConnectionStatusLogic.INSTANCE.addListener(new ConnectionStatusLogic.Listener() {
@Override
public void onConnectionStatus(boolean isConnected) {
SensorLogger.init();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {

View File

@ -193,7 +193,7 @@ public class LiveDocPanel {
combined.put(context, new RefreshActions() {
@Override
public void refresh(BinaryProtocol bp, byte[] response) {
int value = (int) conditionField.getValue(new ConfigurationImage(response));
int value = (int) conditionField.getValue(new ConfigurationImage(response)).intValue();
conditionLabel.setText(request.getField() + " is " + (value == 1 ? "TRUE" : "FALSE"));
JPanel active;
JPanel passive;