Good Morning, I’m writing a script for my OEE monitoring system to monitor the number of active and down machines for all the machines in the shop. I’m using a tag change script that executes when the boolean value of selected tags changes. The original script is below:
# Specify the paths.
paths = [
"[default]Machines/Machine_Information_Template/Machine_Activity/Down",
"[default]Machines/MT_Robot/Machine_Activity/Down"
#^add your tag path for a new machine above
]
active = 0
down = 0
# Read tags
values = system.tag.readBlocking(paths)
# Loop through results
for i in range(len(values)):
tagValue = values[i].value
if tagValue == False:
active += 1
else:
down += 1
print active
print down
system.tag.writeBlocking("[default]Main_Metrics/Overall/Active_Machines", active)
system.tag.writeBlocking("[default]Main_Metrics/Overall/Down_Machines", down)
In the first iteration, everything was working fine. I updated the code so that the paths in my machine folder associated with the "down" tag is generated automatically, eliminating the need to hardcode the tag paths for each machine.
The code still runs as expected in the Script Console, but not when triggered by the tag change event.
# Find all tags named "Down" under machine folder
def findTagsNamedDown(path):
found = []
results = system.tag.browse(path)
for r in results.getResults():
name = r["name"]
fullPath = r["fullPath"]
hasChildren = r["hasChildren"]
if name == "Down":
#Store string path
found.append(str(fullPath))
if hasChildren:
found.extend(findTagsNamedDown(fullPath))
return found
baseFolder = "[default]Machines"
#Find all Down tags
paths = findTagsNamedDown(baseFolder)
#Make sure every entry is a string
paths = [str(p) for p in paths]
#Count active vs down
active = 0
down = 0
values = system.tag.readBlocking(paths)
for v in values:
tagValue = v.value
if tagValue == False:
active += 1
else:
down += 1
print active
print down
# Write machine status values to active and down machines tags
system.tag.writeBlocking("[default]Main_Metrics/Overall/Active_Machines", active)
system.tag.writeBlocking("[default]Main_Metrics/Overall/Down_Machines", down)
I am away from my computer, but I think you’ve made this harder than it needs to be. Tag Change events have all the information you need without browsing or reading the values.
When I get back to my desk, I’ll type something up
activeMachines, downMachines = [qv.value for qv in system.tag.readBlocking(["default]Main_Metrics/Overall/Active_Machines","[default]Main_Metrics/Overall/Down_Machines"])]
if newValue.value == False and previousValue.value == True:
activeMachines += 1
downMachines -= 1
elif newValue.value == True and previousValue.value == False:
activeMachines -= 1
downMachines += 1
system.tag.writeBlocking(["[default]Main_Metrics/Overall/Active_Machines","[default]Main_Metrics/Overall/Down_Machines"], [activeMachines,downMachines]))
The tag event script will be triggered every time one of the tags included in the Tag Path(s) list is changing. So you would need to read the number of active and down machines first and then adjust the numbers based on the the specific down tag that is changing.
also for future reference, use the system.tag.query instead of system.tag.browse. You'll find it much faster, and you can do some nice pre-filtering with it, and also specify return values.
In my testing I actually found that browse was faster to execute, I don't recall by how much. I don't remember it being too significant though, just thought I'd mention.
Unless you need more that just the tag path, or to filter on more than just the few options supported by .browse(), or filter by complex combinations. system.tag.query() can return the current value and any desired current property values, in the one call. Avoiding the need for a followup system.tag.readBlocking().
My problem with this is there's a possibility it gets out of sync and then operations or upper management will blame the program for not showing correct values and questioning if they could trust it all along.
Not sure if you ever do updates to servers during operations, but if so, it will most likely get out of sync during that too.
I think you were on a better track to start with by grabbing the current status of all "down" tags using the system.tag.query function and just using that instead of incrementing/decrementing values.
Or if you wanted to keep things from ever drifting or getting out of sync, you could have a scheduled time every day where it grabs the current status and updates the values of active/down machines so that the normal tag change script can adjust it from there.
Yeah, I fully agree there is a big risk of this getting out of sync and another approach could be to run this on a schedule or a mix of the two.
I did not really take into consideration whether the approach of OP was the best or not. I just wanted to help out with the question at hand as to why the script was only working in the script console.