I'm having some trouble getting some component scripting to work and wanted to see if anyone can point out where my error is.
We have a large machine with many touch displays and would like to isolate the control each display has to a specific section. In other words, I don't want someone on one end of the machine to have the ability to turn off power, change the mode, or manually move components they can't even see on the other end of the machine.
The current plan is to only allow those specific buttons to work based on the client IP address. I was able to get the following code to work flawlessly.
However, what if the IP address changes down the road? It will. I don't want to have to go into every button on multiple screens and manually update the IP address. I decided to create a memory tag of type string in the default tag provider and replaced the hardcode IP with the tag value. At least I think that's what I'm doing below.
Lastly, is it possible to make this act like a momentary button? The IF statement will just permanently change the state of my tag which is why I'm using mousePressed and mouseReleased. The mouseReleased code sets the variable back to "0".
I recommend basing Vision client identity on the MAC ID of the network adapter that is used to communicate with the gateway. Works even if your IT group screws with the IP addresses. In some environments (Linux, easily), you could also use motherboard serial numbers.
See this topic for MAC ID retrieval:
You can then look up in a database (or just a list of constants) in a client startup event to drive your machine-specific permissions. (I recommend Vision Client tags to hold the resulting decision.)
Thanks Gents! Got it working. Here is what I did in case anyone else in the future wants to see.
I am planning to go back and change the following client event script to run on Startup instead of on a timer. Also planning to look at the MAC ID instead of the IP once the other touch displays arrive and know what those MAC ID's are.
I ended up just binding the enable bit of every component I want strict control on with the appropriate Booleans from the client event script. Looks like it's working perfectly!
Lastly, I was able to remove the ".value" from the tags in the IF statement section but when I tried to remove it from the "system.tag.readBlocking(" portion at the top, it seemed to stop working. Didn't spend much time trying to understand why and just reverted back to what I had before.
Also, the print command definitely helped with troubleshooting. Thanks everyone for your input and time.
Reading a tag returns a qulaified value that has three attributes: value, quality, and timestamp. You'll still need the .value to get the-- umm-- value.
Now to wax pedantic...
One thing that I would recommend to you is to learn to use list comprehensions. Since your tag naming conventions are similar, using a comprehension can shorten your code-- and keep your values in a sequnce, too.
Note that this would require changing TackSub to TackSubIP
basePathIn = '[client]HMI IP Addresses/{}IP'
basePathOut = '[client]HMI IP Addresses/{}ClientActive'
tagList = ['Finish', 'Inspection', 'Outbound', 'Subassembly', 'Tack', 'TackSub']
ClientIP = system.net.getIPAddress()
tagsIn = [basePathIn.format(tagName) for tagName in tagList]
tagsOut = [basePathOut.format(tagName) for tagName in tagList]
valuesIn = [qvalue.value for qvalue in system.tag.readBlocking[tagsIn]]
valuesOut = [ip == ClientIP for ip in valuesIn]
system.tag.writeBlocking(tagsOut, valuesOut)
Your script will break if any of those client tags are left True in the designer. You should unconditionally write every true/false expression result into the appropriate tags. (Use a list of paths and a list of values.)
I've taken to preferring this method, because I don't have to worry about the '/' in the paths. It's pretty simple. Provide a List of path parts and it constructs the path for you, maybe overkill, but I like it.
from com.inductiveautomation.ignition.common.tags.paths import BasicTagPath
basePath = BasicTagPath('Client',['HMI IP Addresses'])
tagList = ['Finish','Inspection','Outbound','Subassembly','Tack','TackSub']
clientIP = system.net.getIPAddress()
valuesIn = [qv.value for qv in system.tag.readBlocking([BasicTagPath.append(basePath, tag + 'IP').toStringFull() for tag in tagList])]
system.tag.writeBlocking([BasicTagPath.append(basePath,tag + 'ClientActive').toStringFull() for tag in tagListl],[ip == clientIP for ip in valuesIn])
Also, you missed the in in your comprehension for valuesOut.