1

I have a J1939 CAN raw string in the following format:

CAN:0B00FEE99CF002000CEF02000B00FEE81A9A9F60FFFFB8570B00FEE042522500425225000B00FEE5E0530100C89F0400

This string contains a few CAN messages that are broken up into 3 parts, for example

0B 00FEE99 CF002000CEF0200

1) PGN data length in bytes 0B

2) PGN number (3 bytes in length) 0FEE99

3) PGN data CF002000CEF0200

Currently, I am using substrings in order to parse the 3 parts but I am not getting the correct values. I am thinking that I might be making a mistake because I didn't convert the string into a byte array. This is the part of my code:

int CANStrLength = 24;
int CANIndex = CANDataIndex(rawDataElements);
int CANStrIndex = rawDataElements[CANIndex].IndexOf("CAN:");
string CANmessage = rawDataElements[CANIndex].Substring(CANStrIndex + 4).Split(',').First();
Console.WriteLine("\nIn rawDataElements[{0}]: {1}\nLength of CAN data: {2}", CANIndex, CANmessage, CANmessage.Length);

int numberOfCANMessages = CANmessage.Length / CANStrLength;
Console.WriteLine("There are {0} CAN messages", numberOfCANMessages);

List<string> CANMessages = SplitIntoParts(CANmessage, CANStrLength);
for (int i = 0; i < numberOfCANMessages; i++)
{
    int pgnDataLength = Convert.ToInt32(CANMessages[i].Substring(0, 2), 16);
    int pgnNumber = Convert.ToInt32(CANMessages[i].Substring(2, 6), 16);
    long CANData = Convert.ToInt64(CANMessages[i].Substring(8), 16);
    Console.WriteLine();
    Console.WriteLine(CANMessages[i]);

    switch (pgnNumber)
    {
        // fuel consumption */
        case 65257:
            string totalFuelUsedStr = CANMessages[i].Substring(8).Substring(8, 4);
            double totalFuelUsed = Convert.ToInt32(totalFuelUsedStr, 16) * 0.5;
            Console.WriteLine("Total Fuel Used: {0}L, {1}gal", totalFuelUsed, (int)(totalFuelUsed* 0.26));
            break;
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Ko Ga
  • 856
  • 15
  • 25
  • Yes, it is maybe easier to convert into byte array (see anwers bwlow), but also your code should work. Which values are wrong? Check with debugger or program output the parts of the strings you are converting. Maybe it is misinterpretation only. In your example you say `PGN number 3 bytes` (which would be 6 chars in the string) but the string "00FEE99" is seven chars long. – H.G. Sandhagen Jan 08 '17 at 13:50
  • @H.G.Sandhagen - PGN is 6 chars long `0FEE99` – Ko Ga Jan 09 '17 at 11:18
  • @H.G.Sandhagen I am getting the data part wrong. – Ko Ga Jan 09 '17 at 11:26
  • I tried your code with the example data: Length: 1 byte 0B (11), PGN 3 bytes 00FEE9 (65257), Data 8 bytes 0:9C 1:F0 2:02 3:00 4:0C 5:EF 6:02 7:00. In the switch you find `case 65257:` and extract the data part (byte 4-5) which is 0CEF (3311) multiplied with 0.5 = 1655.5. I don't know the message specification and cannot say whether this value may be ok or not. Which value expect you? – H.G. Sandhagen Jan 09 '17 at 19:07

2 Answers2

0

You might want to check here to convert the hex string into a byte array: How can I convert a hex string to a byte array?

Then you should use a MemoryStream/BinaryReader. (Converting a hex string with an int saved as LSB, does not result in the same value as converting the hex directly into an integer, because then you'll parse it like MSB). See wiki on Endianness.

So Either you use a BinaryReader to convert the bytes into an int, or you could use the BitConverter.

You could try something like: (PSEUDO)

int pgnDataLength;
int pgnNumber;
long CANData;

// this function is found on the stackoverflow link above
byte[] data = StringToByteArray(hex);

using(memStream = new MemoryStream(data))
{
    var reader = new BinaryReader(memStream);

    pgnDataLength = reader.ReadInt32();
    pgnNumber = reader.ReadInt32();
    CANData = reader.ReadInt64();
}
Community
  • 1
  • 1
Jeroen van Langen
  • 21,446
  • 3
  • 42
  • 57
0

You are correct that you need to convert to bytes. Your indexing is off since a byte is two nibbles. See code below

            string input = "0B00FEE99CF002000CEF02000B00FEE81A9A9F60FFFFB8570B00FEE042522500425225000B00FEE5E0530100C89F0400";
            List<byte> bytes = new List<byte>();
            for (int i = 0; i < input.Length; i += 2)
            {
                byte newByte = byte.Parse(input.Substring(i,2), System.Globalization.NumberStyles.HexNumber);
                bytes.Add(newByte);

            }
jdweng
  • 33,250
  • 2
  • 15
  • 20