TLDR:
I have a UDT that I am using to write/read recipes for a process we run. Each part we make has its own recipe, and they have been manually confirming that the recipe matches our documented recipes. This has led to errors and scraped out parts. And it is surprisingly difficulted to maintain change management across 7 machines.
I would love to have some kind of checksum to compare rather than just checking by a bunch of if-then statements.
I know that Ignition has a lot of java libs built into it and callable in a script. Could one of them have a checksum or hashing ability?
If the tags are all either strings or numbers, they should be hashable.
So in theory you should be able to iterate through the master recipe, and the selected recipe, and compare the results of the python builtin hash() function. Something like this:
def chunker(seq,size):
return (seq[pos:pos + size] for pos in xrange(0,len(seq),size))
def confirmRecipe():
documnetedPaths = ["list.of.paths.to.documented.values"]
selectedPaths = ["list.of.paths.to.selected.values"]
tagPaths = documentedPaths + selectedPaths
tagValues = system.tag.readBlocking(tagPaths)
documentedValues, selectedValues = [[qv.value for qv in chunk] for chunk in chunker(tagValues,len(documentedPaths))]
for i, value in enumerate(documentedValues):
if hash(value) != hash(selectedValues[i]):
#flag as unconfirmed
return False
#if execution makes it here then recipes match
return True
import org.apache.commons.codec.digest.DigestUtils.sha256Hex as sha256Hex
segmentTagPath = ["[default]Folder/Tag_A","[default]Folder/Tag_B"]
values = system.tag.readBlocking(segmentTagPath)
valueList = ''
for x in values:
valueList + str(x.value)
print(sha256Hex(valueList))
I ended up doing something like this. The main thing is the sha256Hex function only works on strings.
So, I index into the returning array of data and pulled only the value of the tag, and nothing else as that will affect the hash. And stringify the value.
Concatenate all the values into a string and run the sha256Hex function on that.
Note: Any change of the order of the tags read will affect the hash amount.
We use DigestBuilder for this sort of task internally.
So your snippet becomes:
from com.inductiveautomation.ignition.common.util import DigestBuilder
segmentTagPath = ["[default]Folder/Tag_A","[default]Folder/Tag_B"]
values = system.tag.readBlocking(segmentTagPath)
digest = DigestBuilder.sha256()
for x in values:
digest.update(x.value)
print(digest.buildHexString())
The big advantage being the update function has overloads for common numeric types as well as direct byte arrays.
I think that PDriffith solution will work and thus he gets the solution point. Altho i might just use 16 bits to keep it short.
But then I started to wonder if sha256 was the absolute best function to use.
I went down a rabbit hole. Not knowing too much about cryptography, it took me some time to describe the things I want in a function:
Avalanche Effect: I would like it to have a drastic change if even one datapoint is off . That way operators can very easily tell if the settings are off
Short: I would like it to be less than 32 characters so we can have operators check, by hand, it to our documented procedure
Ease of Implementation: Something someone already has a lib for would be great
Reversible: I would like it to be uncompressible to see the data inside if possible
Can Be Insecure: No need for keys or security
I don't expect there to be a function/algorithm that matches all these criteria but you never know untill you ask