I want to have a tag structure for the factory that summarises (a dynamic number of) child tags, as you look up the tree. For example I have a "line" UDT that has multiple "cell" UDTs below it. I want the "OEE" and "Status" tags in the "line" to be expression tags that summarise the corresponding tags on the child "cell"s. An example simplified structure:
Line
-Status
-OEE
-Children (Dataset of paths to the cell tags)
Cell
-Status
-OEE
What I want is for the "line/OEE" tag to be an average of the child tags (The final implementation will pass the more data, not the top level OEE, but this is a simplified example):
Pseudo code
For the Status tag I have a feeling the business logic will get very complicated (Based off what managers want shown at their level), so for the moment I will just say that the tag should be the max (Worst case) value:
Pseudo code
I have not found a way of achieving this yet. I would prefer this is done as expressions so the code lives within the tags, but maybe this is only achievable with Python?
Thanks for the help I almost have this working, but the data from the tag seems to be imported in a java format, not a python readable format.
The function is:
def sumTags(tagArray, subTag):
tags = [str(childTag) + subTag for childTag in tagArray]
return sum([x.value for x in system.tag.readAll(tags)])
When called with a manually created object ["tag1","tag2"] it works perfectly. When a value is passed from a tag the input data is not formatted correctly (I have tried formatting the tag as both a dataset and an array).
Printing out "tagArray" I see: [[[Ljava.lang.String;@475a7e29, Good, Tue Jan 10 21:43:33 PST 2023 (1673415813054)]]
Printing "tags" from the for loop creates an output like this: ["array(java.lang.String, [u'tag1', u'tag2', u'tag3'])/OEE"]
The whole arrays seems to be seen as a single string based on the subtag text being appended to the end of the array string, not to the individual items
The two calls I am currently using (from the script console to get debugging) are: print Business_Structure.sumTags(["tag 1","tag 2"], "/OEE")
Returns the correct integer print Business_Structure.sumTags(system.tag.readBlocking("Children"), "/OEE")
Throws an error because the tags are one malformed string
The issue as I see it is a basic array is structured like this:
[
tag1,
tag2
]
The tag is theoretically structured like this:
[
[
tag1,
tag2
],
quality,
date
]
But I can't seem to iterate over the inner array. If I try to nest for-loops I get: TypeError: 'com.inductiveautomation.ignition.common.model.values.BasicQualifiedValue' object is not iterable
It seems like I need to cast that type to Python array
Note: I have simplified the tag paths for ease of reading
system.tag.readBlocking returns a list of qualified values.
It looks like from your earlier post you're passing in a string array tag qualified value as the 'list of tags to read':
[Ljava.lang.String;@475a7e29 is the default Java toString() of a string array.
The second layer of square brackets ([[Ljava.lang.String;@475a7e29, Good, Tue Jan 10 21:43:33 PST 2023 (1673415813054)]) is the toString() of the qualified value.
The last set of square brackets on the outside is indicating you've got a list of results.
You can either unpack things before you pass them in to your sumTags function (generally preferred) or you can unpack them inside the function, but you must do one or the other.
E.G: print Business_Structure.sumTags(system.tag.readBlocking("Children"), "/OEE") Should instead be: print Business_Structure.sumTags(system.tag.readBlocking("Children")[0].value, "/OEE")
You must get the first element of the list, then get the .value member, in order to reference just the string array you care about.
I type this out before you posted, so I may aswell post it:
Ok I have worked it out the value supplied by readBlocking() is an array of tags not a single tag, I need to reference the 0th item and iterate across the value property:
def sumTags(tagArray, subTag):
tags = [str(childTag) + subTag for childTag in tagArray[0].value]
return sum(x.value for x in system.tag.readBlocking(tags))
However after moving it back to the tag, it wasn;t working the value supplied by the expression {[.]Children} on the tag is just the value, not the tag, so it actually would have worked on the tag, even though it wasn't working in the scripting console, because I should have been using [0].value, when calling the method in the scripting console.
This is my first time working with Python and the weak typing here made this really hard to understand what was happening...
Not seeing the actual Python errors on the tag also made it harder.