1
votes

I have an Avl Packet that I'm recieving through GPRS from a Device.

The protocol manual says the packet has a 16bit CRC on the last 4 bytes and a source code for CRC calculation is given:

public static int getCrc16(Byte[] buffer) {
    return getCrc16(buffer, 0, buffer.length, 0xA001, 0);
    }

public synchronized static int getCrc16(Byte[] buffer, int offset, int bufLen, int polynom, int preset) {
    preset &= 0xFFFF;
    polynom &= 0xFFFF;
    int crc = preset;
    for (int i = 0; i < bufLen; i++) {
        int data = buffer[i + offset] & 0xFF;
        crc ^= data;
        for (int j = 0; j < 8; j++) {
            if ((crc & 0x0001) != 0) {
                crc = (crc >> 1) ^ polynom;
            } else {
                crc = crc >> 1;
            }
        }
    }
    return crc & 0xFFFF;
}

So I get the CRC number the packet sends me,then I call getCrc16 for the Byte array in which I have stored the packet and then compare the two numbers right??

Here is the code I use inside my program:

public static String toBinaryString(byte n) {
    StringBuilder sb = new StringBuilder("00000000");
    for (int bit = 0; bit < 8; bit++) {
        if (((n >> bit) & 1) > 0) {
            sb.setCharAt(7 - bit, '1');
        }
    }
    return sb.toString();
}

    int CalculatedCRC = getCrc16(AvlPacket);
    System.out.println("Calculated CRC= " + CalculatedCRC);

    int index = (AvlPacket.length)-4;
    String BinaryRecievedCRC = "";

    for (int j = 0; j < 4; j++) {
        BinaryRecievedCRC+= toBinaryString(AvlPacket[index]);
        index+=1;
    }

    int RecievedCRC = Integer.parseInt(BinaryRecievedCRC, 2);
    System.out.println("Recieved CRC= " + RecievedCRC);

toBinaryString() converts a byte to it's binary from and puts it into a string!

So I calculate the CRC through getCrc16() given to me from the manual.Then take an index 4 bytes before the end of the packet so I can read the last 4 bytes and get the CRC sent with the packet!

The for loop takes each of the last bytes and with toBinaryString() combines all them in binary form and into a String!So I got something like 0000000000000000101011011101001 (The manual states that first two bytes are always zeroes because its a 16bit CRC)

So I just parse the Binary String into a signed int and Compare the two CRCs...!

Yet I get Results like :

Calculated CRC= 21395 -----Recieved CRC= 30416

or

Calculated CRC= 56084 -----Recieved CRC= 10504

I've tested with many packets and they can't all have loss of data..And I'm parsing the data too so I know that the data I get is correct!

What am I missing in all this??

3

3 Answers

0
votes

There is probably something wrong with the documentation wording (or your understanding of it). If there is a 16-Bit CRC in a packet, its most likely occupying two bytes, not four (in binary form). If it were a decimal, even four bytes wouldn't suffice (you would need 5 didgts to store it as unsigned decimal string).

Your code shows you do conversions (but I can't see what kind of conversion its supposed to do):

BinaryRecievedCRC+= toBinaryString(AvlPacket[index]);

I would expect the CRC to be store in the data in binary form, so I assume the only thing you need to figure out are which endianess is used and where the CRC is stored in the data.

Edit: Judging from your comment you would need to extract the CRC like this:

public int getCRC(byte[] data, int index) {
    return ((data[index] & 0xFF) << 8)) | (data[index + 1] & 0xFF);
}
0
votes

So I get the CRC number the packet sends me,then I call getCrc16 for the Byte array in which I have stored the packet and then compare the two numbers right??

Wrong. You calculate the CRC over the entire message, including the CRC bytes, and the result should be zero.

0
votes

Problem Solved!

The problem was that the Packet had 8 other bytes before getting into the Data part! So I had to exclude those first 8 bytes along with the last 4 bytes of the sent CRC before calculating the CRC!

Now the numbers agree and the above code is correct with the exception that the for loop in the getCrc16 function starts from i=8 (so as to skip the first 8 bytes of the packet which do no belong to the Data part!)

Thank you all for your time!