Read a Folder Full of Tags via Script

Hi, teh question is quite easy, how could I read a folder full of tags?

I have a folder [default]TestAlarms inside of it I have something liket his:
[default]TestAlarms/tag_1
[default]TestAlarms/alarm
[default]TestAlarms/test_8
[...]
Can I do something like this system.tag.readBlocking(["[default]TestAlarms/*"])? I'm having no luck.

Thx in advance!

No, but you can use system.tag.browse to get your tag paths to supply to readBlocking

Eg

tagPaths = [str(tag["fullPath"]) for tag in system.tag.browse("TestAlarms", filter={"tagType": "AtomicTag"})]

system.tag.readBlocking(tagPaths)
2 Likes

Just to leave it here. My original objective was to see if any of those tags is set to True.
I think I'm simply gonna use a system.tag.query()

Code
provider = 'default'
limit = 100

query = {
  "options": {
    "includeUdtMembers": True,
    "includeUdtDefinitions": False
  },
  "condition": {
    "path": "TestAlarms/*",
    "attributes": {
      "values": [],
      "requireAll": True
    },
    "properties": {
      "op": "Or",
      "conditions": [
        {
          "op": "And",
          "conditions": [
            {
              "prop": "value",
              "comp": "Equal",
              "value": "True"
            }
          ]
        }
      ]
    }
  },
  "returnProperties": [
    "tagType",
    "quality"
  ]
}

results = system.tag.query(provider, query, limit)

You can certainly use system.tag.query() if you want, but it isn't too much of a strech to take Nick's code and return only the paths with true values.

tagPaths = [tag['fullPath'].toStringFull() for tag in system.tag.browse('TestAlarms',filter={'tagType':'AtomicTag','dataType':'Boolean'}|)]
print [path for path,qv in zip(tagPaths, system.tag.readBlocking(tagPaths)) if qv.value]

If you need it to drill down into nested folders then you can include the recursive flag in the filter. Just be careful where you run the script if you decide to do that.

1 Like

If you only care about the value of the tags, system.tag.browse would already give you their values, so no need to do another system.tag.readBlocking. something like this would give you all the true alarms

results = system.tag.browse("[default]TestAlarms").results
activeAlarms = [tag.get('name') for tag in results if tag.get('value').value == True]

Careful, this will not work without at a minimum a filter for AtomicTags. Any nested folders or UDT's will not have the 'value' key, and so will throw an AttributeError.

Also, returning the 'name' is not a great solution here either, as it is entirely possible that some tags have the same names, you really need the full path or at least as much of the path as possible to defierintiate tags, thus the use of 'fullPath'.

3 Likes

well, tbf,

results = system.tag.browse("[default]TestAlarms").results
activeAlarms = [tag.get('name') for tag in results if tag.get('value', None).__getitem__('value', False) == True]

will work

This will be false if an atomic tag happens to have a zero value, or an empty string value, skipping those valid tags. Meh.

(Seems to have a typo, too. So no, won't work.)

i thought the intent was to get atomic tags with a value of True? good call on the typo, though

I have some personal peev's about utilizing get*() on a dictionary when you would "expect" it to have the key. Personally I find the following to be more readable, and it doesn't make my eye twitch.

results = system.tag.browse('[default]TestAlarms', filter={'tagType':'AtomicTag'}).results
activeAlarms = [tag['fullPath'] for tag in results if tag['value'].value]

Exact same functionality, no dunder methods, will work 100% of the time. A small price to pay for adding a filter IMO.

Would even be simple to parameterize it into a function, though making it robust enough to handle multiple tag types would take a bit of work.

1 Like

yeah, you're not wrong. I was tempted to try to do it with lambdas but then even my eyes started twitching

Yep, didn't test with nested folders :laughing:

I thought about fullPath, but since there's no "recursive": True in the filter, I figured name would be sufficient.

Is there any real difference (not taking count of the returned object) of using system.tag.query() or using system.tag.browse()? Wanna use the most efficient one.

I really only care if there is any true value, I don't care which tags are set to true.

Browse is faster, not significantly. More efficient would be to cache the returned tagpaths and read the cached list

2 Likes

If this is for a visualization, and inferring that the goal is to tell that an alarm is true, can you use the isAlarmActive expression?
https://www.docs.inductiveautomation.com/docs/8.1/appendix/expression-functions/alarming/isAlarmActive

1 Like

Those aren't real Ignition Alarms. Those alarms are from a machine, they send us like 100 differents tags that when true means that an alarm in the machine is on. That's why I need to check if any is on.

I guess my answer to that would be to make them ignition alarms, because once you know that there is an alarm, the next step will be wanting to know what the alarm is and be able to analyze which alarm is causing the problem.