This one returns all the numbers from 0-23 but I only want the numbers where the prompt tag is higher then 0
Oops! That's always checking the first value. Try,
if tag_values[i].value:
Almost, but I fixed it my self a bit:
def find_activeAlarm_tags():
# Initialize an empty list to store matching tag paths
tagPaths = []
tagNrPaths = []
Alarm_tags = []
# Define the range of tag names
for i in range(24):
action_tag = "Action" + str(i)
# Create a tag path for the current tag
tagPaths.append("[Test SCADA Ignition]Action/{}/hmi/prompt".format(action_tag))
# Get the tag values
tag_values = system.tag.readBlocking(tagPaths)
for i in range(24):
# Check if the prompt value is greater than 0
if tag_values[i].value > 0:
# Add the tag path to the list if the condition is met
Alarm_tags.append(i)
# Return the list of matching tag paths
return Alarm_tags
I have changed the readblocking to only 1 and you missed the comparing of the tag_values:
if tag_values[i].value > 0:
if tag_values[i].value:
will return true for all non-zero values. You only need > 0
if you want to exclude negative values.
Is it all working faster now? How much faster? (I'll fix my original script.)
this returned all values that why i did > 0.
and it is a bit faster but not that much. Still takes a good second to load.
Current state explaned
the operator screen gets its text/values from the following expression:
stringFormat(
lookup({[client]operatorTextlist},
{fpOperatorInteraction.Group 1.Label.Prompt},
'',"Value","Text"),
{fpOperatorInteraction.Group 1.Label.setpoint},
{fpOperatorInteraction.Group 1.Label.actual},
{fpOperatorInteraction.Group 1.Label.engunit},
{fpOperatorInteraction.Group 1.Label.tolMin},
{fpOperatorInteraction.Group 1.Label.tolPlus}
)
The values that are passed are different based on a opc tag that comes from my plc and is named 'operatorIndex'.
The buttons of my screen:
make it possible to switch the operatorScreen text when there is more than one alarm.
I currently made it this way:
result = find_activeAlarm_tags.find_activeAlarm_tags()
array_len = len(result)
i = array_len - 1
system.tag.writeBlocking('[Test SCADA Ignition]operatorIndex', result[i])
The function we just optimised returns al the prompt texts(alarms) that are active(higher then 0) and puts them in an array.
The button just selects the other operatorIndex in the array so that a different operator text is being displayed.
But it is stil very slow
This is just to make the problem clear
Yes sorry, I forgot to extract the value out of the qualified values returned by readBlocking
.
Here's the proper code:
from itertools import chain
tags_paths = list(chain.from_iterable(
(
"[Test SCADA Ignition]Action/Action{}/hmi/prompt".format(n),
"[Test SCADA Ignition]Action/Action{}/obj/nr".format(n)
) for n in xrange(24)
))
qvals = system.tag.readBlocking(tags_paths)
tags_values = [qval.value for qval in qvals[::2]]
tags_nrs = [qval.value for qval in qvals[1::2]]
return [nr for val, nr in zip(tags_values, tags_nrs) if val > 0]
This works too, but is not exactly quicker than the one I just posted.
Is there anything else triggered by the button click ?
This shouldn't take any noticeable amount of time.
No only this:
So, let me get things straight.
The function above is NOT called when the button is clicked ?
Well then, what's the code in that function call ? find_activeAlarm_tags.find_activeAlarm_tags()
I get the feeling this is what's taking long.
It is called when the button is clicked.
I press the button and then it is doing the function and writes the result of the function to my OPC tag OperatorIndex so that it wil pass the correct Prompt value.
This is the code you just made
from itertools import chain
def find_activeAlarm_tags():
tags_paths = list(chain.from_iterable(
(
"[Test SCADA Ignition]Action/Action{}/hmi/prompt".format(n),
"[Test SCADA Ignition]Action/Action{}/obj/nr".format(n)
) for n in xrange(24)
))
qvals = system.tag.readBlocking(tags_paths)
tags_values = [qval.value for qval in qvals[::2]]
tags_nrs = [qval.value for qval in qvals[1::2]]
return [nr for val, nr in zip(tags_values, tags_nrs) if val > 0]
Don't call it on every button click, there's no need. Build the list of values once, then iterate through it when a user clicks.
Maybe update it once in a while, or on some condition, but not on every click.
Maybe it is a good idea to make it a gateway script that operates when my operator Index is changed. so a gateway script based on a changed tag value? then it only runs the script when the value is changed. Is that a option?
It is, you can use a gateway tag change event, or a change event directly on the tag.
What's the role of the operator index in all this ?
The PLC program of the company that I'm doing this all for writes in Tia Portal a HMI tag that pointed to Prompt value in Tia portal. Now I needed that value to make texts appear in Ignition so I added the PLC tag that reads from that HMI tag in the OPC server and now I can use that to point to different prompt values in Ignition
al these action datatypes have a prompt tag in them and the operator Index is pointing to the correct Prompt value that are higher then 0
those prompt value that are higher then 0 have text that needs to be displayed on the operator screen
the text are they getting from a vision client tag with a dataset that has a value combined to a text.
I have the feeling that it has to do with the OperatorIndex. When I do something in my HMI what triggers a alarm it takes some time before the OperatorIndex changes value. Like I sad earlier the operatorIndex comes from the PLC. It is a 1500 Siemens PLC and I already have the fastest OPC subscribtion setting cause they are set to 10ms. So if it has to do with the processing I think it cannot be quicker maybe.
That sounds way too fast. 100 ms would generally be acceptable for a HMI on the same local network as the PLC.
Is your gateway on the same network as the PLC? Or does it have to go through some routers on the way?
gateway is on the same network as the PLC.
no