# UDT Quality for its children

**URL:** <https://forum.inductiveautomation.com/t/udt-quality-for-its-children/82162>\
**Category:** Ignition\
**Tags:** ignition81\
**Created:** [November 20, 2023, 10:15pm UTC](https://forum.inductiveautomation.com/t/udt-quality-for-its-children/82162 "2023-11-20T22:15:57Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![gdube](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/gdube/32/41701_2.png) [@gdube](https://forum.inductiveautomation.com/u/gdube)\
**Post date:** [November 20, 2023, 10:15pm UTC](https://forum.inductiveautomation.com/t/udt-quality-for-its-children/82162/1 "2023-11-20T22:15:57Z")

</div>

Hi guys, I noticed that we can read a whole UDT instance (with its children) in a single system.tag.readBlocking() call, but the quality code is always good even though the quality of its children may not be.

Did anyone figure a good way to deal with that?

Within the UDT, I created an expression tag that was basically "isGood(childA) && isGood(childB) && ....", but it seems a bit fragile.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [November 20, 2023, 10:50pm UTC](https://forum.inductiveautomation.com/t/udt-quality-for-its-children/82162/2 "2023-11-20T22:50:28Z")

</div>

Show your code, please.

---

<div class="post-metadata">

**Author:** ![gdube](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/gdube/32/41701_2.png) [@gdube](https://forum.inductiveautomation.com/u/gdube)\
**Post date:** [November 20, 2023, 11:10pm UTC](https://forum.inductiveautomation.com/t/udt-quality-for-its-children/82162/3 "2023-11-20T23:10:47Z")

</div>

I wanted to check the quality of the children of the UDT since I wanted to add tags from other OPC sources, but right now they all come from Kepware.

Wec (aka. wind energy converter)

```auto
class Wec:
	def __init__ (self, identifier, wind_speed_average, status, rbh_raw_value):
		self.identifier = identifier 
		self.wind_speed_average= wind_speed_average
		self.status = status
		self.rbh = Rbh(rbh_raw_value)

```

Initialize WECs

```auto
def initializeWECs():
	results = system.tag.browse('[default]Wec')
	paths = []
	for x in results:
		paths.append(str(x['fullPath']))
	qValues = system.tag.readBlocking(paths)
	wecList = []
	for qValue in qValues:
		value = qValue.value
		identifier = value['Identifier']
		goodQuality = qValue.quality.isGood() and value['IsGood']
		if not goodQuality: 
			continue
		wec = Wec(
			identifier, 
			value['WindSpeedAverage'], 
			value['Status'], 
			value['Ctrl']['Rbh']
		)
		wecList.append(wec)
	return wecList

```

UDT

```auto
{
  "name": "Wec",
  "parameters": {
    "ID": {
      "dataType": "Integer",
      "value": 0
    }
  },
  "tagType": "UdtType",
  "tags": [
    {
      "valueSource": "expr",
      "expression": "{ID}",
      "name": "Identifier",
      "tagType": "AtomicTag"
    },
    {
      "opcItemPath": {
        "bindType": "parameter",
        "binding": "nsu\u003dKEPServerEX;s\u003dEnercon.Main.Loc.Wec.Plant{ID}.Status.St"
      },
      "valueSource": "opc",
      "dataType": "Int4Array",
      "name": "Status",
      "tagType": "AtomicTag",
      "opcServer": "KEPServerEX_UA"
    },
    {
      "opcItemPath": {
        "bindType": "parameter",
        "binding": "nsu\u003dKEPServerEX;s\u003dEnercon.Main.Loc.Wec.Plant{ID}.Vwind"
      },
      "valueSource": "opc",
      "dataType": "Float4",
      "name": "WindSpeed",
      "tagType": "AtomicTag",
      "opcServer": "KEPServerEX_UA"
    },
    {
      "valueSource": "expr",
      "expression": "isGood({[.]Power})\r\n\u0026\u0026 isGood({[.]Status})\r\n\u0026\u0026 isGood({[.]WindSpeed})\r\n\u0026\u0026 isGood({[.]WindSpeedAverage})\r\n\u0026\u0026 isGood({[.]Ctrl/Rbh}) ",
      "dataType": "Boolean",
      "documentation": "Indicates whether all tags in this UDT has good quality or not.",
      "name": "IsGood",
      "tagType": "AtomicTag"
    },
    {
      "name": "Ctrl",
      "tagType": "Folder",
      "tags": [
        {
          "opcItemPath": {
            "bindType": "parameter",
            "binding": "nsu\u003dKEPServerEX;s\u003dEnercon.Main.Loc.Wec.Plant{ID}.Ctrl.SessionState"
          },
          "valueSource": "opc",
          "name": "SessionState",
          "tagType": "AtomicTag",
          "opcServer": "KEPServerEX_UA"
        },
        {
          "opcItemPath": {
            "bindType": "parameter",
            "binding": "nsu\u003dKEPServerEX;s\u003dEnercon.Main.Loc.Wec.Plant{ID}.Ctrl.SessionSubmit"
          },
          "valueSource": "opc",
          "dataType": "Int8Array",
          "name": "SessionSubmit",
          "tagType": "AtomicTag",
          "opcServer": "KEPServerEX_UA"
        },
        {
          "opcItemPath": {
            "bindType": "parameter",
            "binding": "nsu\u003dKEPServerEX;s\u003dEnercon.Main.Loc.Wec.Plant{ID}.Ctrl.Rbh"
          },
          "valueSource": "opc",
          "dataType": "Int8",
          "name": "Rbh",
          "tagType": "AtomicTag",
          "opcServer": "KEPServerEX_UA"
        },
        {
          "opcItemPath": {
            "bindType": "parameter",
            "binding": "nsu\u003dKEPServerEX;s\u003dEnercon.Main.Loc.Wec.Plant{ID}.Ctrl.SessionTimeOut"
          },
          "valueSource": "opc",
          "name": "SessionTimeOut",
          "tagType": "AtomicTag",
          "opcServer": "KEPServerEX_UA"
        },
        {
          "opcItemPath": {
            "bindType": "parameter",
            "binding": "nsu\u003dKEPServerEX;s\u003dEnercon.Main.Loc.Wec.Plant{ID}.Ctrl.SessionPubKey"
          },
          "valueSource": "opc",
          "dataType": "Int8",
          "name": "SessionPubKey",
          "tagType": "AtomicTag",
          "opcServer": "KEPServerEX_UA"
        },
        {
          "opcItemPath": {
            "bindType": "parameter",
            "binding": "nsu\u003dKEPServerEX;s\u003dEnercon.Main.Loc.Wec.Plant{ID}.Ctrl.SetRbh"
          },
          "valueSource": "opc",
          "dataType": "Int8Array",
          "name": "SetRbh",
          "tagType": "AtomicTag",
          "opcServer": "KEPServerEX_UA"
        },
        {
          "opcItemPath": {
            "bindType": "parameter",
            "binding": "nsu\u003dKEPServerEX;s\u003dEnercon.Main.Loc.Wec.Plant{ID}.Ctrl.SessionRequest"
          },
          "valueSource": "opc",
          "dataType": "Int8Array",
          "name": "SessionRequest",
          "tagType": "AtomicTag",
          "opcServer": "KEPServerEX_UA"
        }
      ]
    },
    {
      "valueSource": "memory",
      "dataType": "Float4",
      "name": "WindSpeedAverage",
      "value": 0,
      "tagType": "AtomicTag"
    },
    {
      "opcItemPath": {
        "bindType": "parameter",
        "binding": "nsu\u003dKEPServerEX;s\u003dEnercon.Main.Loc.Wec.Plant{ID}.P"
      },
      "valueSource": "opc",
      "name": "Power",
      "tagType": "AtomicTag",
      "opcServer": "KEPServerEX_UA"
    }
  ]
}

```

UDT Instances:

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/3/3/3341b94dcf3b3082fed13c8f0d768c8cfd56ea4d.png)

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [November 20, 2023, 11:37pm UTC](https://forum.inductiveautomation.com/t/udt-quality-for-its-children/82162/4 "2023-11-20T23:37:23Z")

</div>

It seems to me that you need to recurse to get qualified values for the members of your instances.

{ And for performance sake, _ **cache** _ your recursive member lists--tag browsing is not something your code should be repeating all the time. }

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [November 20, 2023, 11:39pm UTC](https://forum.inductiveautomation.com/t/udt-quality-for-its-children/82162/5 "2023-11-20T23:39:49Z")

</div>

"Reading" the base of a UDT or folder is actually an automatic read of the special computed `jsonValues` subproperty node. If you care about the inner qualities, you'll have to do a more specific read; the `jsonValues` node isn't designed to care about or return quality information.

---

<div class="post-metadata">

**Author:** ![gdube](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/gdube/32/41701_2.png) [@gdube](https://forum.inductiveautomation.com/u/gdube)\
**Post date:** [November 21, 2023, 3:42pm UTC](https://forum.inductiveautomation.com/t/udt-quality-for-its-children/82162/6 "2023-11-21T15:42:42Z")

</div>

Is jsonValues intended/designed for easily reading memory tags, where quality is not a factor?

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [November 21, 2023, 4:59pm UTC](https://forum.inductiveautomation.com/t/udt-quality-for-its-children/82162/8 "2023-11-21T16:59:10Z")

</div>

As I understand things, it's used for some internal purpose to display the 'structure' of a tag quickly, while assuming everything within it is good quality. I think its original purpose had something to do with tag dropping in Perspective, but don't quote me on that 🙂
