UDT to power table

Hi All

I have around 20 UDT tags, all the same UDT. I would like to display several variables from each UDT in a table row.

The desired result would be as below (but with more rows). I have accomplished this by configuring the power table by “cell update” and manually addressing each cell. This is laborous and difficult to maintain.

Is there a way to populate each row by indirect addressing or some other method?

Thanks

I would read all the tags at once, then use a script to massage your values into a dataset for the table.

Without knowing your UDT structure or folder layout, that’s all I can recommend.

Thanks.

I did consder this option but I was concerned about the peformance impact of a script running every few seconds. The user interface will require “live” data.

The UDTs are very simple and contain only 2 integers and 1 or 2 strings as shown in the table.

image

Looks like it’ll be pretty straightforward. Except I’m not quite up to writing an example on my phone. :smile:

I’m off to bed, but I’ll try to pop something up in the morning.

1 Like

I look forward to your reply.

The following works. I have triggered it from a button click on the screen. The script populates a custom property (dataset) which is sent to the table. It’s pretty rough. I’m sure there is a nicer way to do the data selection and the table needs to be updated in real time, not on a button press.

#Create an empty dataset
data = []

#Create the dataset for the headers
headers = ["Description", "Battery remaining (weeks)", "Signal strength (dB)"]

#Return only DeltaOhmED tags in the specified directory.
results = system.tag.browse(path = '[HamJet_Tags]Fabrication/Devices', filter = {'typeId':'DeltaOhmED'})

for result in results.getResults():
    
    # If the item has children, call the function to repeat the process but starting at the child.
    if result['hasChildren'] == True:
		result2=system.tag.browse(result['fullPath'], {})

		for result in result2.getResults():
        		
        		#Store the description
          		if result['name']=='Description':
          			desc = result['value'].value
          		
          		#Store the battery		
          		if result['name']=='BatteryRemaining':
          			batt = result['value'].value
          		
          		#Store the signal	
          		if result['name']=='SignalStrength':
          			signal = result['value'].value 
	
		# Add a row of data to the dataset
		data.append([desc,batt,signal])
		
# Add the data to the headers.
event.source.parent.data = system.dataset.toDataSet(headers,data)

https://docs.inductiveautomation.com/display/DOC80/system.tag.browse

https://docs.inductiveautomation.com/display/DOC79/Datasets

You could pass the tag path to the page or table and then use indirect bindings to display the values from the individual tags in the UDT.

1 Like

Sorry for the late reply…

I’m finding that the tag browse filter doesn’t always filter when there’s stuff I want to filter. :confused: I was not able to filter on the typeId, but was able to filter on tagType.

My method reads the tags within the UDT. the keys list are the relative paths within the UDT.

It will create the tag, then group the values according the number of keys you have. So, if you need to add a column, you only need to adjust the key and headers lists.

One browse operation, one tag read operation.

Note this script, as written, will only hit tags on the root level of the UDT.


tagPath = '[HamJet_Tags]Fabrication/Devices'
udtID = 'DeltaOhmED'

keys = ["Description", "BatteryRemaining", "SignalStrength"]
headers = ["Description", "Battery remaining (weeks)", "Signal strength (dB)"]

# Browse the tags. Filters on tagType to look only for UDT instances,
# which seems to work.
browse = system.tag.browse(path = tagPath, filter = {'tagType':'UdtInstance'})

# Create tag names from browse results and keys. Filtering on typeID here seems to be more robust. 
tagsIn = [str(r['fullPath']) + '/' + key for r in browse.getResults() for key in keys if r['typeId'] == udtID]

# Get tag values
values = [t.value for t in system.tag.readBlocking(tagsIn)]

# Group the values by the number of keys
data =  [values[i:i+len(keys)] for i in range(0, len(values)-(len(keys)-1), len(keys))]

# Add the data to the headers.
event.source.parent.data = system.dataset.toDataSet(headers,data)
1 Like

Thanks very much for the reply! I’ll try to get my head around this later today.

Hi again.

Although this works, I’d like to further refine the functionality.

Using Jordan’s code from above I now have a dataset of tag paths.

  1. How can I use these tag paths to populate a power table so I don’t need to keep running the script to refresh my data?
  2. How do I trigger the script to run when a template is loaded? I’ve looked at several forum posts such as Template load event? but when I add this to PropertyChange, ignition throws an error upon saving.

I recommend using a gateway timer event script and write the results to a dataset tag. Then point the table to the dataset tag. The results will always be up to date.

I kind of want to accomplish the same thing but use a single column dataset tag for a drop down list of folders, representing each opc ua server device on the gateway using system.tag.browse. Also, create a single and multiple column dataset tags referencing multiple sub folders which each sub folder having multiple duties types list the name in a dataset as reference to a template repeater. I was looking at gateway script and/or derived tag?