From d0eae47a8eff2de591b87e059d4250102f678874 Mon Sep 17 00:00:00 2001 From: rusefillc Date: Fri, 19 Aug 2022 23:16:59 -0400 Subject: [PATCH] now handling comments section --- .../java/com/rusefi/can/LoggingStrategy.java | 2 +- .../com/rusefi/can/reader/dbc/DbcField.java | 12 +++- .../com/rusefi/can/reader/dbc/DbcFile.java | 52 ++++++++++---- .../com/rusefi/can/reader/dbc/DbcPacket.java | 55 +++++++++++++++ .../reader/impl/ParseDBCWithCommentTest.java | 69 +++++++++++++++++++ 5 files changed, 175 insertions(+), 15 deletions(-) create mode 100644 src/test/java/com/rusefi/can/reader/impl/ParseDBCWithCommentTest.java diff --git a/src/main/java/com/rusefi/can/LoggingStrategy.java b/src/main/java/com/rusefi/can/LoggingStrategy.java index f6f93df..d8975b3 100644 --- a/src/main/java/com/rusefi/can/LoggingStrategy.java +++ b/src/main/java/com/rusefi/can/LoggingStrategy.java @@ -17,7 +17,7 @@ import java.util.concurrent.atomic.AtomicReference; public class LoggingStrategy { public static List getFieldNameEntries(DbcFile dbc) { List entries = new ArrayList<>(); - for (DbcPacket packet : dbc.packets) { + for (DbcPacket packet : dbc.packets.values()) { for (DbcField field : packet.getFields()) { entries.add(new BinaryLogEntry() { @Override diff --git a/src/main/java/com/rusefi/can/reader/dbc/DbcField.java b/src/main/java/com/rusefi/can/reader/dbc/DbcField.java index b5ce4ab..51b4670 100644 --- a/src/main/java/com/rusefi/can/reader/dbc/DbcField.java +++ b/src/main/java/com/rusefi/can/reader/dbc/DbcField.java @@ -3,11 +3,12 @@ package com.rusefi.can.reader.dbc; import com.rusefi.can.CANPacket; public class DbcField { - private final String name; + private String name; private final int startOffset; private final int length; private final double mult; private String category; + private boolean isNiceName; public DbcField(String name, int startOffset, int length, double mult, String category) { this.name = name; @@ -21,6 +22,10 @@ public class DbcField { return category; } + public boolean isNiceName() { + return isNiceName; + } + public String getName() { return name; } @@ -67,4 +72,9 @@ public class DbcField { public double getValue(CANPacket packet) { return getBitIndex(packet.getData(), startOffset, length) * mult; } + + public void rename(String niceName) { + name = niceName; + isNiceName = true; + } } diff --git a/src/main/java/com/rusefi/can/reader/dbc/DbcFile.java b/src/main/java/com/rusefi/can/reader/dbc/DbcFile.java index f055579..01a41cf 100644 --- a/src/main/java/com/rusefi/can/reader/dbc/DbcFile.java +++ b/src/main/java/com/rusefi/can/reader/dbc/DbcFile.java @@ -4,10 +4,12 @@ import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Objects; public class DbcFile { - public final List packets = new ArrayList<>(); + public final LinkedHashMap packets = new LinkedHashMap<>(); private static final boolean debugEnabled = false; @@ -26,17 +28,26 @@ public class DbcFile { while ((line = reader.readLine()) != null) { line = line.trim(); if (line.startsWith("BO_")) { - if (currentPacket != null) - this.packets.add(currentPacket); + purgePacket(currentPacket); line = line.replaceAll(":", ""); String[] tokens = line.split(" "); int decId = Integer.parseInt(tokens[1]); String packetName = tokens[2]; currentPacket = new DbcPacket(decId, packetName); + } else if (line.startsWith("CM_")) { + purgePacket(currentPacket); + line = replaceSpecialWithSpaces(line); + String[] tokens = line.split(" "); + int id = Integer.parseInt(tokens[2]); + DbcPacket packet = packets.get(id); + Objects.requireNonNull(packet, "packet for " + id); + String originalName = tokens[3]; + String niceName = merge(tokens, 4); + packet.replaceName(originalName, niceName); + } else if (line.startsWith("SG_")) { - line = line.replaceAll("[|+@(,)\\[\\]]", " "); - line = line.replaceAll(" +", " "); + line = replaceSpecialWithSpaces(line); String[] tokens = line.split(" "); String name = tokens[1]; int index = 1; @@ -65,18 +76,33 @@ public class DbcFile { // skipping useless line } } - if (currentPacket != null) - this.packets.add(currentPacket); + purgePacket(currentPacket); System.out.println(getClass().getSimpleName() + ": Total " + packets.size() + " packets"); } - // todo: performance optimization SOON - public DbcPacket findPacket(int i) { - for (DbcPacket packet : packets) { - if (packet.getId() == i) - return packet; + private static String merge(String[] tokens, int position) { + StringBuilder sb = new StringBuilder(); + for (int i = position; i < tokens.length; i++) { + if (sb.length() > 0) + sb.append(" "); + sb.append(tokens[i]); } - return null; + return sb.toString(); + } + + private void purgePacket(DbcPacket currentPacket) { + if (currentPacket != null) + packets.put(currentPacket.getId(), currentPacket); + } + + private String replaceSpecialWithSpaces(String line) { + line = line.replaceAll("[|+@(,)\\[\\]]", " "); + line = line.replaceAll(" +", " "); + return line; + } + + public DbcPacket findPacket(int canId) { + return packets.get(canId); } } diff --git a/src/main/java/com/rusefi/can/reader/dbc/DbcPacket.java b/src/main/java/com/rusefi/can/reader/dbc/DbcPacket.java index 8dddb83..f656697 100644 --- a/src/main/java/com/rusefi/can/reader/dbc/DbcPacket.java +++ b/src/main/java/com/rusefi/can/reader/dbc/DbcPacket.java @@ -1,8 +1,13 @@ package com.rusefi.can.reader.dbc; +import javax.management.ObjectName; import java.util.ArrayList; import java.util.List; +import java.util.Objects; +/** + * Packet describes all the fields for specific can ID + */ public class DbcPacket { private final int id; private final String name; @@ -44,4 +49,54 @@ public class DbcPacket { } return null; } + + public void replaceName(String originalName, String niceName) { + if (niceName.charAt(niceName.length() - 1) == ';') + niceName = niceName.substring(0, niceName.length() - 1); + niceName = unquote(niceName); + DbcField field = find(originalName); + Objects.requireNonNull(field, "By " + originalName); + field.rename(niceName); + } + + private static String unquote(String q) { + final StringBuilder buf = new StringBuilder(); + final int len = q.length(); + if (len < 2 || q.charAt(0) != '"' || q.charAt(len - 1) != '"') + return q; + for (int i = 1; i < len - 1; i++) { + char c = q.charAt(i); + if (c == '\\') { + if (i == len - 2) + throw new IllegalArgumentException("Trailing backslash"); + c = q.charAt(++i); + switch (c) { + case 'n': + c = '\n'; + break; + case '\\': + case '\"': + case '*': + case '?': + break; + default: + throw new IllegalArgumentException( + "Bad character '" + c + "' after backslash"); + } + } else { + switch (c) { + case '*': + case '?': + case '\"': + case '\n': + throw new IllegalArgumentException( + "Invalid unescaped character '" + c + + "' in the string to unquote"); + } + } + buf.append(c); + } + return buf.toString(); + } + } diff --git a/src/test/java/com/rusefi/can/reader/impl/ParseDBCWithCommentTest.java b/src/test/java/com/rusefi/can/reader/impl/ParseDBCWithCommentTest.java new file mode 100644 index 0000000..7a814cb --- /dev/null +++ b/src/test/java/com/rusefi/can/reader/impl/ParseDBCWithCommentTest.java @@ -0,0 +1,69 @@ +package com.rusefi.can.reader.impl; + +import com.rusefi.can.reader.dbc.DbcField; +import com.rusefi.can.reader.dbc.DbcFile; +import com.rusefi.can.reader.dbc.DbcPacket; +import org.junit.Test; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; + +import static junit.framework.TestCase.*; + +public class ParseDBCWithCommentTest { + private static final String RPM_DBC = + "\n" + + "BO_ 1408 Motor_Flexia: 8 XXX\n" + + " SG_ Ansaugsystem m0 : 63|1@1+ (1,0) [0|0] \"\" XXX\n" + + " SG_ Hubraum m0 : 56|7@1+ (0.1,0) [0|12.7] \"l\" XXX\n" + + " SG_ Steigung_der_Befuellungskennlin m1 : 56|8@1+ (0.001,0) [0|0.255] \"l/mm\" XXX\n" + + " SG_ Anzahl_Zylinder m0 : 52|4@1+ (1,0) [0|15] \"Vent./Zyl.\" XXX\n" + + " SG_ Bewertungsfaktor_Russindex_Turb m1 : 50|6@1+ (0.1,0) [0|6.3] \"\" XXX\n" + + " SG_ Anzahl_Ventile m0 : 49|3@1+ (1,0) [0|7] \"Vent./Zyl.\" XXX\n" + + " SG_ Bewertungsfaktor_Verschleissind m1 : 44|6@1+ (0.1,0) [0|6.3] \"\" XXX\n" + + " SG_ Hersteller_Code m1 : 40|4@1+ (1,0) [0|15] \"\" XXX\n" + + " SG_ Motorleistung m0 : 40|9@1+ (1,0) [0|512] \"KW\" XXX\n" + + " SG_ Max_Drehmoment m0 : 32|8@1+ (10,0) [0|2550] \"Nm\" XXX\n" + + " SG_ Normierter_Verbrauch m1 : 32|8@1+ (10,0) [0|2550] \"l/Zyl.\" XXX\n" + + " SG_ Oelniveauschwelle m1 : 24|8@1+ (0.25,0) [0|63.75] \"cm\" XXX\n" + + " SG_ Drehzahl_MaxNorm m0 : 24|8@1+ (100,0) [0|25500] \"U/min\" XXX\n" + + " SG_ Verschleissindex : 16|8@1+ (1,0) [0|254] \"\" XXX\n" + + " SG_ Russindex : 8|8@1+ (1,0) [0|254] \"\" XXX\n" + + " SG_ Verbrennungsart : 7|1@1+ (1,0) [0|0] \"\" XXX\n" + + " SG_ Frei_Motor_Flexia_1 : 6|1@1+ (1,0) [0|0] \"\" XXX\n" + + " SG_ Warm_Up_Cycle : 5|1@1+ (1,0) [0|0] \"\" XXX\n" + + " SG_ Driving_Cycle : 4|1@1+ (1,0) [0|0] \"\" XXX\n" + + " SG_ Zaehler_Motor_Flexia : 1|3@1+ (1,0) [0|15] \"\" XXX\n" + + " SG_ Multiplex_Schalter_Motor_Flexia M : 0|1@1+ (1,0) [0|0] \"\" XXX\n" + + "" + + "" + + "" + + "\n" + + "\n" + + "CM_ SG_ 1408 Zaehler_Motor_Flexia \"Counter Motor_Flexia\";\n" + + "CM_ SG_ 1408 Verbrennungsart \"Type of combustion\";\n" + + "CM_ SG_ 1408 Max_Drehmoment \"Maximum torque\";\n" + + "CM_ SG_ 1408 Drehzahl_MaxNorm \"RPM of maximum torque\";\n" + + "CM_ SG_ 1408 Hubraum \"Displacement\";\n" + + "CM_ SG_ 1408 Anzahl_Zylinder \"Number of cylinders\";\n" + + "CM_ SG_ 1408 Anzahl_Ventile \"Number of valves\";\n" + + "CM_ SG_ 1408 Ansaugsystem \"Induction System\";\n" + + "CM_ SG_ 1408 Motorleistung \"Maximum engine power\";\n" + + ""; + + @Test + public void parse() throws IOException { + BufferedReader reader = new BufferedReader(new StringReader(RPM_DBC)); + + DbcFile dbc = new DbcFile(); + dbc.read(reader); + + assertEquals(dbc.packets.size(), 1); + DbcPacket packet = dbc.packets.get(1408); + DbcField field = packet.find("Number of cylinders"); + assertNotNull(field); + assertTrue(field.isNiceName()); + } +} +