From 9dfe9cde8ddfae52f019681d53e5188819e002d7 Mon Sep 17 00:00:00 2001 From: rusefillc Date: Thu, 3 Feb 2022 00:03:56 -0500 Subject: [PATCH] packet decoding --- src/main/java/com/rusefi/can/CANPacket.java | 8 ++++ .../java/com/rusefi/can/PacketPayload.java | 20 ++++++++++ src/main/java/com/rusefi/can/SensorType.java | 9 +++++ src/main/java/com/rusefi/can/SensorValue.java | 19 ++++++++++ .../can/decoders/AbstractPacketDecoder.java | 14 +++++++ .../rusefi/can/decoders/PacketDecoder.java | 10 +++++ .../com/rusefi/can/decoders/bmw/Bmw0AA.java | 21 +++++++++++ .../com/rusefi/can/decoders/bmw/Bmw1D0.java | 21 +++++++++++ .../rusefi/can/decoders/bmw/BmwRegistry.java | 22 +++++++++++ .../com/rusefi/can/BmwE65DecoderTest.java | 37 +++++++++++++++++++ 10 files changed, 181 insertions(+) create mode 100644 src/main/java/com/rusefi/can/PacketPayload.java create mode 100644 src/main/java/com/rusefi/can/SensorType.java create mode 100644 src/main/java/com/rusefi/can/SensorValue.java create mode 100644 src/main/java/com/rusefi/can/decoders/AbstractPacketDecoder.java create mode 100644 src/main/java/com/rusefi/can/decoders/PacketDecoder.java create mode 100644 src/main/java/com/rusefi/can/decoders/bmw/Bmw0AA.java create mode 100644 src/main/java/com/rusefi/can/decoders/bmw/Bmw1D0.java create mode 100644 src/main/java/com/rusefi/can/decoders/bmw/BmwRegistry.java create mode 100644 src/test/java/com/rusefi/can/BmwE65DecoderTest.java diff --git a/src/main/java/com/rusefi/can/CANPacket.java b/src/main/java/com/rusefi/can/CANPacket.java index 944ce88..2ea63b1 100644 --- a/src/main/java/com/rusefi/can/CANPacket.java +++ b/src/main/java/com/rusefi/can/CANPacket.java @@ -11,6 +11,10 @@ public class CANPacket { this.data = data; } + public int getTwoBytes(int index) { + return getUnsigned(index + 1) * 256 + getUnsigned(index); + } + public double getTimeStamp() { return timeStamp; } @@ -22,4 +26,8 @@ public class CANPacket { public byte[] getData() { return data; } + + public int getUnsigned(int i) { + return Byte.toUnsignedInt(data[i]); + } } diff --git a/src/main/java/com/rusefi/can/PacketPayload.java b/src/main/java/com/rusefi/can/PacketPayload.java new file mode 100644 index 0000000..6611df5 --- /dev/null +++ b/src/main/java/com/rusefi/can/PacketPayload.java @@ -0,0 +1,20 @@ +package com.rusefi.can; + +public class PacketPayload { + + private final double timeStamp; + private final SensorValue[] values; + + public PacketPayload(double timeStamp, SensorValue... values) { + this.timeStamp = timeStamp; + this.values = values; + } + + public double getTimeStamp() { + return timeStamp; + } + + public SensorValue[] getValues() { + return values; + } +} diff --git a/src/main/java/com/rusefi/can/SensorType.java b/src/main/java/com/rusefi/can/SensorType.java new file mode 100644 index 0000000..1cf5874 --- /dev/null +++ b/src/main/java/com/rusefi/can/SensorType.java @@ -0,0 +1,9 @@ +package com.rusefi.can; + +public enum SensorType { + RPM, + CLT, + PPS, + MAP, + FUEL_AMOUNT, +} diff --git a/src/main/java/com/rusefi/can/SensorValue.java b/src/main/java/com/rusefi/can/SensorValue.java new file mode 100644 index 0000000..cbf3ca1 --- /dev/null +++ b/src/main/java/com/rusefi/can/SensorValue.java @@ -0,0 +1,19 @@ +package com.rusefi.can; + +public class SensorValue { + private final SensorType type; + private final double value; + + public SensorValue(SensorType type, double value) { + this.type = type; + this.value = value; + } + + public SensorType getType() { + return type; + } + + public double getValue() { + return value; + } +} diff --git a/src/main/java/com/rusefi/can/decoders/AbstractPacketDecoder.java b/src/main/java/com/rusefi/can/decoders/AbstractPacketDecoder.java new file mode 100644 index 0000000..48cd38f --- /dev/null +++ b/src/main/java/com/rusefi/can/decoders/AbstractPacketDecoder.java @@ -0,0 +1,14 @@ +package com.rusefi.can.decoders; + +public abstract class AbstractPacketDecoder implements PacketDecoder { + private final int id; + + public AbstractPacketDecoder(int id) { + this.id = id; + } + + @Override + public int getId() { + return id; + } +} diff --git a/src/main/java/com/rusefi/can/decoders/PacketDecoder.java b/src/main/java/com/rusefi/can/decoders/PacketDecoder.java new file mode 100644 index 0000000..da54d95 --- /dev/null +++ b/src/main/java/com/rusefi/can/decoders/PacketDecoder.java @@ -0,0 +1,10 @@ +package com.rusefi.can.decoders; + +import com.rusefi.can.CANPacket; +import com.rusefi.can.PacketPayload; + +public interface PacketDecoder { + PacketPayload decode(CANPacket packet); + + int getId(); +} diff --git a/src/main/java/com/rusefi/can/decoders/bmw/Bmw0AA.java b/src/main/java/com/rusefi/can/decoders/bmw/Bmw0AA.java new file mode 100644 index 0000000..231e99f --- /dev/null +++ b/src/main/java/com/rusefi/can/decoders/bmw/Bmw0AA.java @@ -0,0 +1,21 @@ +package com.rusefi.can.decoders.bmw; + +import com.rusefi.can.CANPacket; +import com.rusefi.can.PacketPayload; +import com.rusefi.can.SensorType; +import com.rusefi.can.SensorValue; +import com.rusefi.can.decoders.AbstractPacketDecoder; + +public class Bmw0AA extends AbstractPacketDecoder { + public Bmw0AA() { + super(0xAA); + } + + @Override + public PacketPayload decode(CANPacket packet) { + SensorValue pedal = new SensorValue(SensorType.PPS, packet.getUnsigned(3) * 0.39063); + SensorValue rpm = new SensorValue(SensorType.RPM, packet.getTwoBytes(4) * 0.25); + return new PacketPayload(packet.getTimeStamp(), pedal, rpm); + } + +} diff --git a/src/main/java/com/rusefi/can/decoders/bmw/Bmw1D0.java b/src/main/java/com/rusefi/can/decoders/bmw/Bmw1D0.java new file mode 100644 index 0000000..377ac9b --- /dev/null +++ b/src/main/java/com/rusefi/can/decoders/bmw/Bmw1D0.java @@ -0,0 +1,21 @@ +package com.rusefi.can.decoders.bmw; + +import com.rusefi.can.CANPacket; +import com.rusefi.can.PacketPayload; +import com.rusefi.can.SensorType; +import com.rusefi.can.SensorValue; +import com.rusefi.can.decoders.AbstractPacketDecoder; + +public class Bmw1D0 extends AbstractPacketDecoder { + public Bmw1D0() { + super(0x1d0); + } + + @Override + public PacketPayload decode(CANPacket packet) { + SensorValue clt = new SensorValue(SensorType.CLT, packet.getUnsigned(0) - 48); + SensorValue map = new SensorValue(SensorType.MAP, packet.getUnsigned(3) * 0.2 + 59.8); + SensorValue fuel = new SensorValue(SensorType.FUEL_AMOUNT, packet.getTwoBytes(4)); + return new PacketPayload(packet.getTimeStamp(), clt, map, fuel); + } +} diff --git a/src/main/java/com/rusefi/can/decoders/bmw/BmwRegistry.java b/src/main/java/com/rusefi/can/decoders/bmw/BmwRegistry.java new file mode 100644 index 0000000..72b5715 --- /dev/null +++ b/src/main/java/com/rusefi/can/decoders/bmw/BmwRegistry.java @@ -0,0 +1,22 @@ +package com.rusefi.can.decoders.bmw; + +import com.rusefi.can.decoders.PacketDecoder; + +import java.util.HashMap; +import java.util.Map; + +public class BmwRegistry { + BmwRegistry INSTANCE = new BmwRegistry(); + + public Map decoderMap = new HashMap<>(); + + public BmwRegistry() { + register(new Bmw0AA()); + register(new Bmw1D0()); + } + + private void register(PacketDecoder decoder) { + decoderMap.put(decoder.getId(), decoder); + } + +} diff --git a/src/test/java/com/rusefi/can/BmwE65DecoderTest.java b/src/test/java/com/rusefi/can/BmwE65DecoderTest.java new file mode 100644 index 0000000..a9ec549 --- /dev/null +++ b/src/test/java/com/rusefi/can/BmwE65DecoderTest.java @@ -0,0 +1,37 @@ +package com.rusefi.can; + +import com.rusefi.can.decoders.bmw.Bmw0AA; +import com.rusefi.can.decoders.bmw.Bmw1D0; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class BmwE65DecoderTest { + @Test + public void decodeRpm() { + CANPacket packetAA = new CANPacket(1, + 0xAA, + new byte[]{0x39, 0x47, 0x02, 0x00, (byte) 0x87, 0x0A, (byte) 0x80, 0x33}); + + PacketPayload payload = new Bmw0AA().decode(packetAA); + assertEquals(2, payload.getValues().length); + assertValue(SensorType.PPS, 0.0, payload.getValues()[0]); + assertValue(SensorType.RPM, 673.75, payload.getValues()[1]); + } + + @Test + public void decodeClt() { + CANPacket packet1D0 = new CANPacket(1, + 0x1D0, new byte[]{0x62, 0x41, (byte) 0xBB, (byte) 0xC6, 0x7B, 0x5F, 0x3D, (byte) 0x88}); + PacketPayload payload = new Bmw1D0().decode(packet1D0); + assertEquals(3, payload.getValues().length); + assertValue(SensorType.CLT, 50.0, payload.getValues()[0]); + assertValue(SensorType.MAP, 99.4, payload.getValues()[1]); + assertValue(SensorType.FUEL_AMOUNT, 24443, payload.getValues()[2]); + } + + private void assertValue(SensorType expectedType, double v, SensorValue value) { + assertEquals(expectedType, value.getType()); + assertEquals(v, value.getValue(), 0.01); + } +}