# Twos Complement Calculation

I am trying to send a message to my security system. It uses an RS232 protocol message format, although I am sending it over ethernet. When sending a message, I need to include a checksum at the end of the message. Here is what the documentation says about the checksum:

4.1.6 Checksum
2 ASCII characters, 2-digit checksum. This is the hexadecimal two’s complement of the modulo-256 sum of the ASCII values of all characters in the message excluding the checksum itself and the CR-LF terminator at the end of the message. Permissible characters are ASCII 0-9 and upper case A-F. When all the characters are added to the Checksum, the value should equal 0.

Yikes. I have no idea what to do with that. I have the entire message as a string (not including the checksum, of course). I could feed it into a function to calculate the checksum, but I have no idea of what to put in that function.

They did also provide some sample c code, but it didn’t help me very much:
https://pastebin.com/Je3WVxc0

Is it a fixed message, or is there some variable component you want to include?

It will be a different message each time.

I figured it out. It most certainly ain’t pretty. There’s probably a one-liner that could do this, but I couldn’t find it. At the very least, there are probably ways to make this MUCH easier.

Anyway, here’s how I did it. This code works in a rule.

``````var String messageCommand="2Edm1100000Message Here^00"

var i = 0
var thisCharVal = 0
var stringTotalVal = 0

// total up the ASCII values of everything in the command. I have a transformation
// map for all of the "regular" characters
while (i < messageCommand.length) {
thisCharVal = Integer::parseInt(transform("MAP", "ascii.map", messageCommand.mid(i,1) ))
stringTotalVal = stringTotalVal + thisCharVal
i = i + 1
}

// calculate the MOD 256. We will have a number between 0 and 255 inclusive
stringTotalVal = stringTotalVal % 256

// convert to binary, 8 bits. for example, 0100 1101
var String bin_code = String.format("%08d", Integer::parseInt(Long.toBinaryString(stringTotalVal)))

// get the ones complement. Swap all the 0's to 1's and vice versa
bin_code = bin_code.replace("0", "X")
bin_code = bin_code.replace("1", "0")
bin_code = bin_code.replace("X", "1")

// convert the ones complement back to an integer
stringTotalVal = Integer.parseInt(bin_code, 2)

That was brilliant, and works perfectly! One step and it is done. Thanks 