I have a hex string with 23 two-character hex byte representations (so 46 characters long in total).
I need to calculate a simple bitwise checksum (adding each hex byte and discarding the overflow) and add it to the end.
And good guidance on how to do this? A simple for loop iterating over the string probably won’t cut it as it may make the rule execution time too long.
Hi Dave,
If the use case allows it, I would advise using a more common checksum algorithm such as MD5, SHA1, SHA256, etc. They are fast and reliable and usually easy to integrate. Please find a JSR223 Groovy example attached:
import groovy.time.*
import org.slf4j.Logger
import org.slf4j.LoggerFactory
// init logger
Logger log = LoggerFactory.getLogger('GroovyScript')
// test value
String value = '4f70656e48414220697320617765736f6d65'
// start stopwatch
Date startTime= new Date()
// calculate check-sums and log result
log.warn('MD2: {}', value.digest('MD2'))
log.warn('MD5: {}', value.md5())
log.warn('SHA1: {}', value.digest('SHA-1'))
log.warn('SHA256: {}', value.digest('SHA-256'))
// stop stopwatch & log total execution time
TimeDuration duration = TimeCategory.minus(new Date(), startTime)
log.warn('Execution Time: {}', duration)
If you really need a custom algorithm, I would still recommend using a JSR223 rule written in JavaScript, Groovy or Python. If I understand your requirement correctly, you should not encounter performance issues.
Thanks for the reply
Actually in may case string is:
a=“85100200007F5D678ACDB2E6CC03537411AE2E95DA120161ECB6C92D5E237C67F0E8FAC29EE1419375B9E17BA6AEB147D994BF14C31D8DB7FB577A5C09767E6CC0D41AB5CF368FC592514F962E8DB171DC08E80C85DE36F690A85D34F842572DA1D246C3EC05AEC3899CE27F8C28BCB9C31191C347DD64E552AF5AFF500E6E6F39E866351D”
and it’s one’s complement checksum value should come “47”.
sure ?
I used two online checksum calculators and they state the the 2’s complement would be 0x44
The adapted script shows one’s complement to be 0x43.
2’s complement then is: 0x43 +1 => 0x44.
So I would assume that the modified script would be ok.
For a test of my script and the online checksum calculators I used your hex number.
Have to agree with Wolfgang: The one’s complement 8-bit checksum of the string given here should be 0x43.
An openHAB ECMA-11 javascript (copy this to the UI script editor in OH and press “Run now” while watching the openHAB log) to do the same calculation as Wolfgang’s shell script:
var a="85100200007F5D678ACDB2E6CC03537411AE2E95DA120161ECB6C92D5E237C67F0E8FAC29EE1419375B9E17BA6AEB147D994BF14C31D8DB7FB577A5C09767E6CC0D41AB5CF368FC592514F962E8DB171DC08E80C85DE36F690A85D34F842572DA1D246C3EC05AEC3899CE27F8C28BCB9C31191C347DD64E552AF5AFF500E6E6F39E866351D";
var sum = 0;
// Convert a hex string to bytes and calculate one's complement 8-bit checksum
for (var c = 0; c < a.length; c += 2) {
byte = parseInt(a.substr(c, 2), 16);
sum = (sum + byte);
}
sum = ~sum & 255;
console.log("Checksum: 0x" + sum.toString(16));
Thanks to all for reply
Yes sorry it was typo mistake one’s complement will be 43.
I am writing in bash script.
At below line I am not getting what to write in my string case after ‘tr’.
e=echo $d | tr "*0123456789abcdef*" "*fedcba987654321*"
$d contains the 8-bit checksum of your original hex number.
tr is being used to build the one’s complement. As the complement is the inverse ( 0 => 1; 1=> 0 ) for each single bit translate ( tr ) can be used to calculate it.
The two arguments describe how tr should do the translation.
Compare the individula positions of both arguments:
0 <=> f
1 <=> e
2 <=> d