Search code examples
javaserial-portchecksumcrc

Trying to figure out the checksum algorithm for a serial interface


I'm trying to reverse-engineer a serial interface for a blood glucose meter.. essentially trying to upload data from a java program instead of from the meter itself (allows me to upload data from different sources). There is some form of checksum on the data send and so far I have been unable to create code that re-creates the checksum digit (or digits) used.

I have a full communications trace of an upload from the meter to destination program

The two transmissions I've been using to check my work are as follows:
The Date: 06 02 30 36 31 34 31 30 30 31 36 42 04 06
... which translates to [ACK][STX]061410016B[EOT][ACK]

The pertinent part of this transmission is the string "141001".. which stands for year=14(2014), month=10 (October), day=01 (the 1st).

I'm not positive what the "06" at the begging of the string is. The "B" at the end I presume is a checksum, the "6" just before it might be part of the checksum.. but seems to stay the same despite the date transmitted.


The Time: 06 02 30 36 30 38 33 31 30 39 36 44 04 06

... which translates to [ACK][STX]060831096D[EOT][ACK]

The pertinent part of this transmission is the 083109 which stands for 8:31:09 AM....

once again the string starts with 06 and ends with 6.. but this one ends with a 'D' which is presumably the checksum.


I've tried a number of algorithms to the best of my ability with the string in various forms without the ACK, without the ACK and STX, without the ACK, STX, and 06, witout the trailing '6' and all permutations of that.

I think that the leading character may refer to the number of pertinent digits.. in the date/time each have 6 pertinent digits.
Other transmissions seem to make that hold true
06 02 30 34 30 39 31 30 36 36 04 06 [ACK][STX]04091066[EOT][ACK]
(Starts with 04.. has 4 digits then 2 trailing digits)

06 02 30 38 31 34 38 39 34 34 39 35 36 36 04 06 [ACK][STX]081489449566[EOT][ACK] (Starts with 08, has 8 digits with 2 trailing digits)

but others later don't necessarily fall in line.
02 31 32 30 31 33 32 31 31 33 37 32 35 30 39 31 34 30 30 30 30 36 31 03 [STX]1201321137250914000061[ETX]
the portions of this string that I know matter are
132: the reading
1137: 11:37 AM
250914: September 25th, 2014

so this has neither 12 digits or 120.. so that's a mystery

I've run out of ideas to try.. anyone with more experience with check digits have a guess? possibly some sort of CRC? I can provide more examples if necessary

UPDATE: The order of the characters does not seem to matter, when I send the time it accepts the time as it was sent in the original stack trace: [ACK][STX]060831096D[EOT][ACK] but it also accepts [ACK][STX]060931086D[EOT][ACK] IE, I can switch the seconds and the minutes without affecting the checksum apparently.. I think this rules out CRC as well as some other checksum standards...



changing this character does not seem to have an effect on the checksum either, as changing it to a 7 is not rejected by the other side. [ACK][STX]060831096D[EOT][ACK]



changing this character does cause the other side to reject the record.. so it's either used in the checksum or is part of the checksum.. but of the 300-400 records I saw go across it was a 6 in all of them. [ACK][STX]060831096D[EOT][ACK]


Solution

  • Looks like it was an XOR over just the meaningful part of the string. Thanks to @EJP for pointing me in the right direction.
    For the Date I send in the bolded part to the function [ACK][STX]061410016B[EOT][ACK]
    The getChecksum function returns "B"

    The function looks like this

    private static String getChecksum(String s){
        int i = 14;
        byte xorChecksum = (byte)i;
        byte[] ba = s.getBytes();
        for(int j = 0; j < ba.length; j++){  
            xorChecksum ^= ba[j];  
        }
        Byte b = new Byte(xorChecksum);
        System.out.println("i: "+i+" - "+b.intValue());
        return toHex(b.intValue());
    }