2 byte checksum in python for iridium SBD

1.1k Views Asked by At

I need to calculate the least significant 2 bytes of the checksum of a message (in bytes) received from an Iridium module (Short Burst Data).

The code I am using works in most cases but it doesn't for the example below.

my code is:

z=b"AT+SBDRB\r\x00\x18this is a random message\x08\xdb"#message received from Iridium module
msg=z[11:-2]
print(msg)
checksum_received = z[-2:]
checksum = 0
check_it = False

for c in msg:
    checksum = checksum + c #msg is a byte type

a=chr( checksum >> 8 ) 
b=chr( checksum & 0xFF )
c=a.encode()
d=b.encode()
checksum = c + d

print(c.hex())
print(d.hex())
print(checksum.hex())
print(checksum_received.hex())
print(checksum == checksum_received)

In the case above the checksum is different than the checksum I receive (I tried to send the message multiple times to ensure I wasn't indeed getting a trasmission error).

I have tested the code with the following messages and the two checksums are the same:

z=b"AT+SBDRB\r\x00\x05hello\x02\x14"
z=b"AT+SBDRB\r\x00\x14thisisarandommessage\x08["
z=b"AT+SBDRB\r\x00\x15this isarandommessage\x08{"

The only information given in the Iridium SBDS manual is:

The checksum is the least significant 2-bytes of the summation of the entire SBD message. The high order byte must be sent first. For example if the FA sends the word “hello” encoded in ASCII to the ISU the binary stream would be hex 68 65 6c 6c 6f 02 14.

2

There are 2 best solutions below

0
quamrana On

You seem to be converting the checksum that you calculate into two separate chr() values, and then encode them.

Its more simple:

z=b"AT+SBDRB\r\x00\x18this is a random message\x08\xdb"#message received from Iridium module
msg=z[11:-2]
print(msg)
checksum_received = z[-2:]

# checksum = 0
# for c in msg:
#     checksum = checksum + c #msg is a byte type
checksum = sum(msg)

# checksum is the correct value here
print(hex(checksum))
a = checksum >> 8 
b = checksum & 0xFF

# Now convert checksum back into a bytes object just like z[-2:] above
checksum = bytes([a,b])
print(checksum.hex())
print(checksum_received.hex())

# now these two are the same
print(checksum == checksum_received)
0
Stefan Ziegler On

I've looked into the code which Virtenio uses on it's Iridium Gateway and seems that quamrana is right. I can provide the following Java function to calculate the checksum. Java because Virtenio has the PreonVM for embedded systems, which can be programmed in JAVA. Here is the code:

int calcChecksum(byte[] data, int length) {
    int checkSum = 0;
    for (int i = 0; i < length; i++) {
        checkSum += data[i] & 0xFF;
    }
    return checkSum & 0xFFFF;
}

Then you have to compare the calculated checksum with the received one and if they match, the received data is valid. The checksum is simply calculated by summing up all the bytes of the data. The checksum is two bytes long and therefore you only need the lower two bytes of the sum.