Calculating a Modulo 256 Checksum in NodeJS for an Access 2 Laboratory Instrument

I’ve recent­ly had to fig­ure out how to send a check­sum with my mes­sages to an Access 2 instru­ment. I did not find very many good resources for doing so, so I’m going to share what I’ve got here. I got my first clues from the exam­ples in the Access 2 LIS doc­u­men­ta­tion. Unfor­tu­nate­ly, it appears that many of the check­sums in that doc­u­men­ta­tion are incor­rect, so to be sure I got ahold of some raw mes­sages from the device and their check­sums, to check my work.

Sev­er­al of the exam­ples from the doc­u­men­ta­tion are includ­ed, com­ment­ed out, at the top. Unfor­tu­nate­ly, I’ve found that not all of the­se were cor­rect in the doc­u­men­ta­tion.

var msgs = [];
 
msgs.push({str: '1H|\\^&|||ACCESS^511550|||||LIS||P|1|20161028161600' + String.fromCharCode(13)+ String.fromCharCode(3), c1: '2', c2: '1'}); // should result in ascii [c1]=2 and [c2]=1
msgs.push({str: '1H|\\^&|||ACCESS^511550|||||LIS||P|1|20161028161524' + String.fromCharCode(13)+ String.fromCharCode(3), c1: '2', c2: '6'}); // should result in ascii [c1]=2 and [c2]=6
msgs.push({str: '1H|\\^&|||ACCESS^511550|||||LIS||P|1|20161028161412' + String.fromCharCode(13)+ String.fromCharCode(3), c1: '2', c2: '2'}); // should result in ascii [c1]=2 and [c2]=2
msgs.push({str: '1H|\\^&|||ACCESS^511550|||||LIS||P|1|20161028161300' + String.fromCharCode(13)+ String.fromCharCode(3), c1: '1', c2: 'E'}); // should result in ascii [c1]=1 and [c2]=E
msgs.push({str: '1H|\\^&|||ACCESS^511550|||||LIS||P|1|20161028161224' + String.fromCharCode(13)+ String.fromCharCode(3), c1: '2', c2: '3'}); // should result in ascii [c1]=2 and [c2]=3
msgs.push({str: '1H|\\^&|||ACCESS^511550|||||LIS||P|1|20161028161148' + String.fromCharCode(13)+ String.fromCharCode(3), c1: '2', c2: '8'}); // should result in ascii [c1]=2 and [c2]=8
msgs.push({str: '1H|\\^&|||ACCESS^511550|||||LIS||P|1|20161028161112' + String.fromCharCode(13)+ String.fromCharCode(3), c1: '1', c2: 'F'}); // should result in ascii [c1]=1 and [c2]=F
msgs.push({str: '1H|\\^&|||ACCESS^511550|||||LIS||P|1|20161028161036' + String.fromCharCode(13)+ String.fromCharCode(3), c1: '2', c2: '4'}); // should result in ascii [c1]=2 and [c2]=4
msgs.push({str: '1H|\\^&|||ACCESS^511550|||||LIS||P|1|20161028140331' + String.fromCharCode(13)+ String.fromCharCode(3), c1: '1', c2: 'F'}); // should result in ascii [c1]=1 and [c2]=F
msgs.push({str: '1H|\\^&|||ACCESS^511550|||||LIS||P|1|20161028140255' + String.fromCharCode(13)+ String.fromCharCode(3), c1: '2', c2: '4'}); // should result in ascii [c1]=2 and [c2]=4
msgs.push({str: '1H|\\^&|||ACCESS^511550|||||LIS||P|1|20161028131152' + String.fromCharCode(13)+ String.fromCharCode(3), c1: '2', c2: '0'}); // should result in ascii [c1]=2 and [c2]=0
msgs.push({str: '1H|\\^&|||ACCESS^511550|||||LIS||P|1|20161028131116' + String.fromCharCode(13)+ String.fromCharCode(3), c1: '2', c2: '0'}); // should result in ascii [c1]=2 and [c2]=0
msgs.push({str: '1H|\\^&|||ACCESS^511550|||||LIS||P|1|20161028131040' + String.fromCharCode(13)+ String.fromCharCode(3), c1: '1', c2: 'C'}); // should result in ascii [c1]=1 and [c2]=C
msgs.push({str: '1H|\\^&|||ACCESS^511550|||||LIS||P|1|20161028131004' + String.fromCharCode(13)+ String.fromCharCode(3), c1: '1', c2: 'C'}); // should result in ascii [c1]=1 and [c2]=C
msgs.push({str: '1H|\\^&|||ACCESS^511550|||||LIS||P|1|20161028130928' + String.fromCharCode(13)+ String.fromCharCode(3), c1: '2', c2: 'A'}); // should result in ascii [c1]=2 and [c2]=A
msgs.push({str: '1H|\\^&|||ACCESS^511550|||||LIS||P|1|20161024120959' + String.fromCharCode(13)+ String.fromCharCode(3), c1: '2', c2: '9'}); // should result in ascii [c1]=2 and [c2]=9
msgs.push({str: '1H|\\^&|||ACCESS^511550|||||LIS||P|1|20161024120923' + String.fromCharCode(13)+ String.fromCharCode(3), c1: '2', c2: '0'}); // should result in ascii [c1]=2 and [c2]=0
msgs.push({str: '1H|\\^&|||ACCESS^511550|||||LIS||P|1|20161024120847' + String.fromCharCode(13)+ String.fromCharCode(3), c1: '2', c2: '5'}); // should result in ascii [c1]=2 and [c2]=5
msgs.push({str: '1H|\\^&|||ACCESS^511550|||||LIS||P|1|20161024120811' + String.fromCharCode(13)+ String.fromCharCode(3), c1: '1', c2: 'C'}); // should result in ascii [c1]=1 and [c2]=C
msgs.push({str: '1H|\\^&|||ACCESS^511550|||||LIS||P|1|20161024120735' + String.fromCharCode(13)+ String.fromCharCode(3), c1: '2', c2: '1'}); // should result in ascii [c1]=2 and [c2]=1
 
for(var i = 0; i < msgs.length; i++) {
    var msg = msgs[i];
    console.log('');
    console.log(msg.str);
    var checksum = calcChecksum(msg.str);
    console.log('checksum: ' + checksum + '  expected checksum: ' + msg.c1 + msg.c2);
}
 
function calcChecksum(string) {
    var buf = new Buffer(string);
    // Calculate the modulo 256 checksum
    var sum = 0;
    for (var i = 0, l = buf.length; i < l; i++) {
 
        sum = (sum + buf[i]) % 256;
    }
 
    console.log('checksum (binary): ' + sum.toString(2));
    // Convert to a two byte uppercase hex value
    var chars = sum.toString(16).toUpperCase();
    if (chars.length == 1) chars = "0" + chars;
    return chars;
}