From 965d574ac65ba179acc2e3230c7a810ef5e57110 Mon Sep 17 00:00:00 2001 From: rusefillc Date: Sat, 3 Jun 2023 01:50:55 -0400 Subject: [PATCH] IsoTp copy-paste from rusEFI --- .../com/rusefi/io/can/IsoTpConnector.java | 59 +++++++++++++++++++ .../com/rusefi/io/can/IsoTpConstants.java | 7 +++ .../com/rusefi/io/can/IsoTpConnectorTest.java | 39 ++++++++++++ src/test/java/com/rusefi/util/HexBinary.java | 29 +++++++++ 4 files changed, 134 insertions(+) create mode 100644 src/main/java/com/rusefi/io/can/IsoTpConnector.java create mode 100644 src/main/java/com/rusefi/io/can/IsoTpConstants.java create mode 100644 src/test/java/com/rusefi/io/can/IsoTpConnectorTest.java create mode 100644 src/test/java/com/rusefi/util/HexBinary.java diff --git a/src/main/java/com/rusefi/io/can/IsoTpConnector.java b/src/main/java/com/rusefi/io/can/IsoTpConnector.java new file mode 100644 index 0000000..94c0474 --- /dev/null +++ b/src/main/java/com/rusefi/io/can/IsoTpConnector.java @@ -0,0 +1,59 @@ +package com.rusefi.io.can; + +import org.jetbrains.annotations.NotNull; + +/** + * @see IsoTpCanDecoder + */ +public abstract class IsoTpConnector { + + public static void sendStrategy(byte[] bytes, IsoTpConnector connector) { +// log.info("-------sendBytesToCan " + bytes.length + " byte(s):"); + + // log.info(HexBinary.printHexBinary(bytes)); + + + // 1 frame + if (bytes.length <= 7) { + connector.sendCanFrame((IsoTpConstants.ISO_TP_FRAME_SINGLE << 4) | bytes.length, bytes, 0, bytes.length); + return; + } + + // multiple frames + // send the first header frame + connector.sendCanFrame((IsoTpConstants.ISO_TP_FRAME_FIRST << 4) | ((bytes.length >> 8) & 0x0f), bytes.length & 0xff, bytes, 0, 6); + // get a flow control frame + connector.receiveData(); + + // send the rest of the data + int idx = 1, offset = 6; + int remaining = bytes.length - 6; + while (remaining > 0) { + int len = Math.min(remaining, 7); + // send the consecutive frames + connector.sendCanFrame((IsoTpConstants.ISO_TP_FRAME_CONSECUTIVE << 4) | ((idx++) & 0x0f), bytes, offset, len); + offset += len; + remaining -= len; + } + } + + @NotNull + public static byte[] combineArrays(byte[] hdr, byte[] data, int dataOffset, int dataLength) { + byte[] total = new byte[hdr.length + dataLength]; + System.arraycopy(hdr, 0, total, 0, hdr.length); + System.arraycopy(data, dataOffset, total, hdr.length, dataLength); + return total; + } + + public void sendCanFrame(int hdr0, byte[] data, int offset, int dataLength) { + sendCanData(new byte[]{(byte) hdr0}, data, offset, dataLength); + } + + public void sendCanFrame(int hdr0, int hdr1, byte[] data, int dataOffset, int dataLength) { + sendCanData(new byte[]{(byte) hdr0, (byte) hdr1}, data, dataOffset, dataLength); + } + + public abstract void sendCanData(byte[] hdr, byte[] data, int dataOffset, int dataLength); + + public abstract void receiveData(); +} diff --git a/src/main/java/com/rusefi/io/can/IsoTpConstants.java b/src/main/java/com/rusefi/io/can/IsoTpConstants.java new file mode 100644 index 0000000..6c30d7b --- /dev/null +++ b/src/main/java/com/rusefi/io/can/IsoTpConstants.java @@ -0,0 +1,7 @@ +package com.rusefi.io.can; + +public class IsoTpConstants { + final static int ISO_TP_FRAME_SINGLE = 0; + final static int ISO_TP_FRAME_FIRST = 1; + final static int ISO_TP_FRAME_CONSECUTIVE = 2; +} diff --git a/src/test/java/com/rusefi/io/can/IsoTpConnectorTest.java b/src/test/java/com/rusefi/io/can/IsoTpConnectorTest.java new file mode 100644 index 0000000..41dd579 --- /dev/null +++ b/src/test/java/com/rusefi/io/can/IsoTpConnectorTest.java @@ -0,0 +1,39 @@ +package com.rusefi.io.can; + +import com.rusefi.util.HexBinary; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +public class IsoTpConnectorTest { + @Test + public void testConnector() { + byte[] crcWrappedCrcRequest = new byte[]{ + 0, 5, 107, 0, 0, 80, 95, 105, -81, -96, 112}; + + List packets = new ArrayList<>(); + + IsoTpConnector testConnector = new IsoTpConnector() { + @Override + public void sendCanData(byte[] hdr, byte[] data, int dataOffset, int dataLength) { + byte[] total = combineArrays(hdr, data, dataOffset, dataLength); + + String packetAsString = HexBinary.printHexBinary(total); + packets.add(packetAsString); + } + + @Override + public void receiveData() { + } + }; + + IsoTpConnector.sendStrategy(crcWrappedCrcRequest, testConnector); + + assertEquals(2, packets.size()); + assertEquals("10 0B 00 05 6B 00 00 50 ", packets.get(0)); + assertEquals("21 5F 69 AF A0 70 ", packets.get(1)); + } +} diff --git a/src/test/java/com/rusefi/util/HexBinary.java b/src/test/java/com/rusefi/util/HexBinary.java new file mode 100644 index 0000000..f0d3c1b --- /dev/null +++ b/src/test/java/com/rusefi/util/HexBinary.java @@ -0,0 +1,29 @@ +package com.rusefi.util; + +public class HexBinary { + public static String printHexBinary(byte[] data) { + if (data == null) + return "(null)"; + char[] hexCode = "0123456789ABCDEF".toCharArray(); + + StringBuilder r = new StringBuilder(data.length * 2); + for (byte b : data) { + r.append(hexCode[(b >> 4) & 0xF]); + r.append(hexCode[(b & 0xF)]); + r.append(' '); + } + return r.toString(); + } + + public static String printByteArray(byte[] data) { + StringBuilder sb = new StringBuilder(); + for (byte b : data) { + if (Character.isJavaIdentifierPart(b)) { + sb.append((char) b); + } else { + sb.append(' '); + } + } + return printHexBinary(data) + sb; + } +}