2022-11-12 09:29:20 -08:00
|
|
|
package com.rusefi.can.analysis;
|
2022-11-10 15:12:02 -08:00
|
|
|
|
2022-11-12 09:29:20 -08:00
|
|
|
import com.rusefi.can.CANPacket;
|
|
|
|
import com.rusefi.mlv.LoggingContext;
|
|
|
|
import com.rusefi.mlv.LoggingStrategy;
|
2022-11-10 20:38:46 -08:00
|
|
|
import com.rusefi.sensor_logs.BinaryLogEntry;
|
|
|
|
import com.rusefi.sensor_logs.BinarySensorLog;
|
2022-11-10 15:12:02 -08:00
|
|
|
|
2022-11-12 20:00:51 -08:00
|
|
|
import java.io.*;
|
2022-11-10 15:12:02 -08:00
|
|
|
import java.util.*;
|
|
|
|
|
|
|
|
public class ByteRateOfChange {
|
|
|
|
|
2022-11-12 18:12:54 -08:00
|
|
|
static class TraceFileMetaIndex {
|
|
|
|
HashMap<ByteId, ByteStatistics> statistics = new HashMap<>();
|
2022-11-10 15:12:02 -08:00
|
|
|
|
2022-11-12 18:12:54 -08:00
|
|
|
Set<Integer> SIDs = new HashSet<>();
|
|
|
|
}
|
2022-11-12 10:07:13 -08:00
|
|
|
|
2022-11-12 18:12:54 -08:00
|
|
|
public static TraceReport process(String reportDestinationFolder, String simpleFileName, List<CANPacket> packets) throws IOException {
|
2022-11-12 10:07:13 -08:00
|
|
|
|
2022-11-12 18:12:54 -08:00
|
|
|
PerSidDump.handle(packets, simpleFileName);
|
2022-11-10 15:12:02 -08:00
|
|
|
|
2022-11-12 20:00:51 -08:00
|
|
|
CounterScanner.scanForCounters(packets);
|
2022-11-10 15:12:02 -08:00
|
|
|
|
2022-11-12 18:12:54 -08:00
|
|
|
TraceFileMetaIndex traceFileMetaIndex = calculateByteStatistics(packets);
|
|
|
|
|
2022-11-12 20:00:51 -08:00
|
|
|
writeByteReport(reportDestinationFolder, simpleFileName, traceFileMetaIndex);
|
|
|
|
|
|
|
|
TraceReport traceReport = new TraceReport(packets, simpleFileName, traceFileMetaIndex.statistics);
|
2022-11-14 19:03:41 -08:00
|
|
|
traceReport.createMegaLogViewer(traceFileMetaIndex.SIDs);
|
2022-11-12 20:00:51 -08:00
|
|
|
return traceReport;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void writeByteReport(String reportDestinationFolder, String simpleFileName, TraceFileMetaIndex traceFileMetaIndex) throws FileNotFoundException {
|
2022-11-12 18:12:54 -08:00
|
|
|
List<ByteStatistics> allStats = new ArrayList<>(traceFileMetaIndex.statistics.values());
|
2022-11-10 15:12:02 -08:00
|
|
|
allStats.sort((o1, o2) -> o2.getUniqueValues() - o1.getUniqueValues());
|
|
|
|
|
2022-11-12 20:00:51 -08:00
|
|
|
// System.out.println(allStats);
|
2022-11-10 15:12:02 -08:00
|
|
|
|
2022-11-12 20:00:51 -08:00
|
|
|
writeByteReport(reportDestinationFolder, simpleFileName, allStats);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void writeByteReport(String reportDestinationFolder, String simpleFileName, List<ByteStatistics> allStats) throws FileNotFoundException {
|
|
|
|
String outputFileName = reportDestinationFolder + File.separator + simpleFileName + ".txt";
|
|
|
|
System.out.println("Wring byte report to " + outputFileName);
|
|
|
|
PrintStream ps = new PrintStream(new FileOutputStream(outputFileName, false));
|
2022-11-10 15:12:02 -08:00
|
|
|
|
|
|
|
for (ByteStatistics byteStatistics : allStats) {
|
|
|
|
ByteId key = byteStatistics.key;
|
2022-11-12 20:00:51 -08:00
|
|
|
ps.println(dualSid(key.sid) + " byte " + key.index + " has " + byteStatistics.getUniqueValues() + " unique value(s)");
|
2022-11-10 15:12:02 -08:00
|
|
|
}
|
|
|
|
|
2022-11-10 16:23:51 -08:00
|
|
|
ps.close();
|
2022-11-10 15:12:02 -08:00
|
|
|
}
|
|
|
|
|
2022-11-12 18:12:54 -08:00
|
|
|
private static TraceFileMetaIndex calculateByteStatistics(List<CANPacket> packets) {
|
|
|
|
TraceFileMetaIndex traceFileMetaIndex = new TraceFileMetaIndex();
|
|
|
|
|
|
|
|
for (CANPacket packet : packets) {
|
|
|
|
traceFileMetaIndex.SIDs.add(packet.getId());
|
2022-11-12 20:00:51 -08:00
|
|
|
for (int byteIndex = 0; byteIndex < packet.getData().length; byteIndex++) {
|
|
|
|
ByteId key = new ByteId(packet.getId(), byteIndex);
|
2022-11-12 18:12:54 -08:00
|
|
|
ByteStatistics stats = traceFileMetaIndex.statistics.computeIfAbsent(key, byteId -> new ByteStatistics(key));
|
2022-11-12 20:00:51 -08:00
|
|
|
stats.uniqueValues.add((int) packet.getData()[byteIndex]);
|
2022-11-12 18:12:54 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return traceFileMetaIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static double getDurationMs(List<CANPacket> packets) {
|
|
|
|
return packets.isEmpty() ? 0 : packets.get(packets.size() - 1).getTimeStamp() - packets.get(0).getTimeStamp();
|
|
|
|
}
|
|
|
|
|
2022-11-10 15:12:02 -08:00
|
|
|
public static String dualSid(int sid) {
|
2022-11-12 10:39:32 -08:00
|
|
|
return dualSid(sid, "/");
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String dualSid(int sid, String separator) {
|
|
|
|
return String.format("%d%s0x%x", sid, separator, sid);
|
2022-11-10 15:12:02 -08:00
|
|
|
}
|
|
|
|
|
2022-11-12 09:29:20 -08:00
|
|
|
public static class ByteStatistics {
|
2022-11-10 15:12:02 -08:00
|
|
|
HashSet<Integer> uniqueValues = new HashSet<>();
|
|
|
|
private final ByteId key;
|
|
|
|
|
|
|
|
public ByteStatistics(ByteId key) {
|
|
|
|
this.key = key;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getUniqueValues() {
|
|
|
|
return uniqueValues.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
return "ByteStatistics{" +
|
|
|
|
"counter=" + uniqueValues.size() +
|
|
|
|
", key=" + key +
|
|
|
|
'}';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-11-12 09:29:20 -08:00
|
|
|
public static class ByteId {
|
2022-11-10 15:12:02 -08:00
|
|
|
final int sid;
|
|
|
|
final int index;
|
|
|
|
|
|
|
|
public ByteId(int sid, int index) {
|
|
|
|
this.sid = sid;
|
|
|
|
this.index = index;
|
|
|
|
}
|
|
|
|
|
2022-11-11 22:53:31 -08:00
|
|
|
private String getLogKey() {
|
2022-11-11 23:12:28 -08:00
|
|
|
return dualSid(sid) + "_byte_" + index + "_bit_" + (index * 8);
|
2022-11-11 22:53:31 -08:00
|
|
|
}
|
|
|
|
|
2022-11-10 15:12:02 -08:00
|
|
|
@Override
|
|
|
|
public boolean equals(Object o) {
|
|
|
|
if (this == o) return true;
|
|
|
|
if (o == null || getClass() != o.getClass()) return false;
|
|
|
|
ByteId byteId = (ByteId) o;
|
|
|
|
return sid == byteId.sid && index == byteId.index;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int hashCode() {
|
|
|
|
return Objects.hash(sid, index);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String toString() {
|
2022-11-11 23:12:28 -08:00
|
|
|
return getLogKey();
|
2022-11-10 15:12:02 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-10 16:23:51 -08:00
|
|
|
public static class TraceReport extends HashMap<ByteId, ByteStatistics> {
|
2022-11-12 18:12:54 -08:00
|
|
|
private final List<CANPacket> packets;
|
2022-11-10 16:23:51 -08:00
|
|
|
private final String simpleFileName;
|
|
|
|
private final HashMap<ByteId, ByteStatistics> statistics;
|
2022-11-12 10:07:13 -08:00
|
|
|
private final double durationMs;
|
2022-11-10 16:23:51 -08:00
|
|
|
|
2022-11-12 18:12:54 -08:00
|
|
|
public TraceReport(List<CANPacket> packets, String simpleFileName, HashMap<ByteId, ByteStatistics> statistics) {
|
|
|
|
this.packets = packets;
|
2022-11-10 16:23:51 -08:00
|
|
|
this.simpleFileName = simpleFileName;
|
|
|
|
this.statistics = statistics;
|
2022-11-12 18:12:54 -08:00
|
|
|
this.durationMs = getDurationMs(packets);
|
2022-11-12 09:29:20 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
String getSummary() {
|
2022-11-12 20:00:51 -08:00
|
|
|
return getSimpleFileName() + " (duration=" + (int) (durationMs / 1000) + "secs)";
|
2022-11-10 16:23:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public String getSimpleFileName() {
|
|
|
|
return simpleFileName;
|
|
|
|
}
|
|
|
|
|
|
|
|
public HashMap<ByteId, ByteStatistics> getStatistics() {
|
|
|
|
return statistics;
|
|
|
|
}
|
2022-11-10 20:38:46 -08:00
|
|
|
|
2022-11-14 19:03:41 -08:00
|
|
|
public void createMegaLogViewer(Set<Integer> SIDs) {
|
|
|
|
List<BinaryLogEntry> entries = new ArrayList<>();
|
2022-11-10 20:38:46 -08:00
|
|
|
|
|
|
|
for (ByteId key : statistics.keySet()) {
|
2022-11-14 19:03:41 -08:00
|
|
|
entries.add(BinaryLogEntry.createFloatLogEntry(key.getLogKey(), Integer.toBinaryString(key.sid)));
|
|
|
|
}
|
|
|
|
|
|
|
|
for (Integer sid : SIDs) {
|
|
|
|
for (int i = 0; i < 7; i++) {
|
2022-11-16 22:36:47 -08:00
|
|
|
{
|
|
|
|
String twoBytesKey = getTwoBytesKeyM(sid, i);
|
|
|
|
entries.add(BinaryLogEntry.createFloatLogEntry(twoBytesKey, Integer.toBinaryString(sid)));
|
|
|
|
}
|
|
|
|
{
|
|
|
|
String twoBytesKey = getTwoBytesKeyL(sid, i);
|
|
|
|
entries.add(BinaryLogEntry.createFloatLogEntry(twoBytesKey, Integer.toBinaryString(sid)));
|
|
|
|
}
|
2022-11-14 19:03:41 -08:00
|
|
|
}
|
2022-11-10 20:38:46 -08:00
|
|
|
}
|
|
|
|
|
2022-11-11 22:53:31 -08:00
|
|
|
LoggingContext context = new LoggingContext();
|
2022-11-14 19:03:41 -08:00
|
|
|
BinarySensorLog<BinaryLogEntry> log = context.getBinaryLogEntryBinarySensorLog(entries, simpleFileName + LoggingStrategy.MLG);
|
2022-11-11 22:53:31 -08:00
|
|
|
|
|
|
|
|
2022-11-12 17:59:47 -08:00
|
|
|
context.writeLogContent(packets, log, packetContent -> {
|
2022-11-14 19:03:41 -08:00
|
|
|
byte[] bytes = packetContent.getData();
|
|
|
|
for (int i = 0; i < bytes.length; i++) {
|
|
|
|
int value = bytes[i] & 0xFF;
|
|
|
|
|
|
|
|
int sid = packetContent.getId();
|
|
|
|
{
|
|
|
|
String name = new ByteId(sid, i).getLogKey();
|
|
|
|
context.currentSnapshot.put(name, (double) value);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
if (i < bytes.length - 1) {
|
|
|
|
int value2 = bytes[i + 1] & 0xFF;
|
2022-11-16 22:36:47 -08:00
|
|
|
{
|
|
|
|
String name = getTwoBytesKeyM(sid, i);
|
|
|
|
context.currentSnapshot.put(name, (double) value2 * 256 + value);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
String name = getTwoBytesKeyL(sid, i);
|
|
|
|
context.currentSnapshot.put(name, (double) value2 + value * 256);
|
|
|
|
}
|
2022-11-14 19:03:41 -08:00
|
|
|
}
|
|
|
|
}
|
2022-11-11 22:53:31 -08:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
});
|
2022-11-10 20:38:46 -08:00
|
|
|
}
|
2022-11-10 16:23:51 -08:00
|
|
|
}
|
2022-11-14 19:03:41 -08:00
|
|
|
|
2022-11-16 22:36:47 -08:00
|
|
|
private static String getTwoBytesKeyM(Integer sid, int i) {
|
|
|
|
return dualSid(sid) + "__" + i + "_" + (i + 1);
|
2022-11-14 19:03:41 -08:00
|
|
|
}
|
2022-11-16 22:36:47 -08:00
|
|
|
|
|
|
|
private static String getTwoBytesKeyL(Integer sid, int i) {
|
|
|
|
return dualSid(sid) + "__" + (i + 1) + "_" + i;
|
|
|
|
}}
|