# OPC tag script using UDT parameters

**URL:** <https://forum.inductiveautomation.com/t/opc-tag-script-using-udt-parameters/84195>\
**Category:** Ignition\
**Tags:** scripting, vision\
**Created:** [January 12, 2024, 3:14pm UTC](https://forum.inductiveautomation.com/t/opc-tag-script-using-udt-parameters/84195 "2024-01-12T15:14:58Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Brendan\_Munroe](https://avatars.discourse-cdn.com/v4/letter/b/3ec8ea/32.png) [@Brendan\_Munroe](https://forum.inductiveautomation.com/u/Brendan_Munroe)\
**Post date:** [January 12, 2024, 3:14pm UTC](https://forum.inductiveautomation.com/t/opc-tag-script-using-udt-parameters/84195/1 "2024-01-12T15:14:58Z")

</div>

I'm trying to create a UDT for an OPC tag that uses a script. I've found some documentation and topics similar, but I'm struggling to have the script update the desired tags using the parameters from the UDT definition. Any help or guidance on the topic would be great.

script below:

```auto
def valueChanged(tag, tagPath, previousValue, currentValue, initialChange, missedEvents):
# Retrieve UDT parameters
	station_id = system.tag.readBlocking(["[Tillsonburg]ShotClockMemory/015_FAST_Trigger_udt_test/StationId"])[0].value
	station_number = system.tag.readBlocking(["[Tillsonburg]ShotClockMemory/015_FAST_Trigger_udt_test/StationNumber"])[0].value
	asset_number = system.tag.readBlocking(["[Tillsonburg]ShotClockMemory/015_FAST_Trigger_udt_test/AssetNumber"])[0].value

	if currentValue.value == True: # if trigger is activated
	    last_fault_description_tag = "[Tillsonburg]ShotClockMemory/{}_Last_Fault_description".format(station_id)
	    last_fault_description = system.tag.readBlocking([last_fault_description_tag])[0].value
	    values = 0
	    unknown = bool(system.tag.readBlocking(["[Tillsonburg]ShotClockMemory/Unkown_Fault"])[0].value)
	
	    if unknown == False:
	        for x in range(20):
	            fault_val_tag = "[Tillsonburg]ShotClockMemory/Sta{}/Fault{}".format(station_number, x + 1)
	            valuer_tag = "[Tillsonburg]ShotClockMemory/Sta{}/Value{}".format(station_number, x + 1)
	            fault_val = system.tag.readBlocking([fault_val_tag])[0].value.strip()
	            valuer = system.tag.readBlocking([valuer_tag])[0].value
	
	            if last_fault_description == fault_val:
	                if valuer <= 2:
	                    values = 0
	                elif valuer < 5:
	                    values = 2
	                elif valuer < 10:
	                    values = 5
	                elif valuer < 15:
	                    values = 10
	                elif valuer < 20:
	                    values = 15
	                elif valuer < 25:
	                    values = 20
	                elif valuer < 30:
	                    values = 25
	                elif valuer < 35:
	                    values = 30
	                elif valuer <= 40:
	                    values = 35
	                break # Exit the loop as we found the matching fault
	
	        write_tag = "[Tillsonburg]ShotClockMemory/Sta{}_Number_of_Minutes_Down_predicted".format(asset_number)
	        system.tag.writeAsync([write_tag], [values])
	    else:
	        # Reset unknown fault tag to false if not in the table
	        system.tag.writeBlocking(["[Tillsonburg]ShotClockMemory/Unkown_Fault"], [False])
	else:
	    # Reset values if the current value is not true
	    values = 0
	    write_tag = "[Tillsonburg]ShotClockMemory/Sta{}_Number_of_Minutes_Down_predicted".format(asset_number)
	    system.tag.writeAsync([write_tag], [values])

```

Desired Flow: Set UDT parameters, update OPC tag from parameters, when OPC tag is triggered the specified tags should update.

The script works with everything hard coded in a standard OPC tag, struggling to use UDT parameters.

---

<div class="post-metadata">

**Author:** ![ryan.white](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ryan.white/32/73193_2.png) [@ryan.white](https://forum.inductiveautomation.com/u/ryan.white)\
**Post date:** [January 13, 2024, 1:02am UTC](https://forum.inductiveautomation.com/t/opc-tag-script-using-udt-parameters/84195/2 "2024-01-13T01:02:31Z")

</div>

Please post code, not pictures of code. Tip: use the `</>` code formatting button to preserve code indentation and apply syntax highlighting. There’s an edit button (pencil icon) below your post so you can fix it.

> [@Wiki - how to post code on this forum](https://forum.inductiveautomation.com/t/wiki-how-to-post-code-on-this-forum/77831):
>
> This thread is intended as a short help file for all those struggling to post formatted code on the forum. Code block formatting Posting formatted code on the forum (and most others) is as simple as selecting the code and pressing the \</\> button. It works the same as applying Bold or Italic styles to your document. It preserves indentation and applies syntax highlighting. [How to post code] Note that all the \</\> button does is add three backticks ``` on the line before the code block and anot…

That aside, please explain the expected flow with more detail, ie: When tag `foo` has value `bar`, tag `knick` should have value `knack` written to it. We can't see enough of the code to figure out exactly what you are trying to accomplish.

---

<div class="post-metadata">

**Author:** ![Andy\_Guias](https://avatars.discourse-cdn.com/v4/letter/a/b3f665/32.png) [@Andy\_Guias](https://forum.inductiveautomation.com/u/Andy_Guias)\
**Post date:** [January 15, 2024, 2:11pm UTC](https://forum.inductiveautomation.com/t/opc-tag-script-using-udt-parameters/84195/3 "2024-01-15T14:11:30Z")

</div>

When I want to use UDT Parameters in the event scripting, I do this:

```auto
station_id = tag["parameters"]["StationId"]
station_number = tag["parameters"]["StationNumber"]
asset_number = tag["parameters"]["AssetNumber"]

```

---

<div class="post-metadata">

**Author:** ![Brendan\_Munroe](https://avatars.discourse-cdn.com/v4/letter/b/3ec8ea/32.png) [@Brendan\_Munroe](https://forum.inductiveautomation.com/u/Brendan_Munroe)\
**Post date:** [January 15, 2024, 4:17pm UTC](https://forum.inductiveautomation.com/t/opc-tag-script-using-udt-parameters/84195/4 "2024-01-15T16:17:46Z")

</div>

Thanks for the pro tip!

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [January 15, 2024, 4:48pm UTC](https://forum.inductiveautomation.com/t/opc-tag-script-using-udt-parameters/84195/5 "2024-01-15T16:48:58Z")

</div>

Another pro-tip. This script is not appropriate for a Tag ValueChange script. At best you are performing 7 blocking reads, at worse you are doing 45.

Tag ValueChange scripts, operate in a shared Thread Pool, and should execute in ~~10's of ms~~ single digit ms. I highly doubt this script performs that well. The limit on that pool is three concurrent threads, once that limit is reached, you will start to miss events which will result in things not working the way they should.

You should always try to reduce the number of calls to `system.tag.read*()` to as few as possible. From what I can tell you're trying to do in the script, the best you can do is 3 separate reads. Which, IMO is still too many.

A Gateway Tag Change event, is more appropriate, but might not be the best solution. What is the actual goal of this tag data structure?

EDIT: Thanks @pturmel, that's what I was meaning, but was too lazy to go look it up. That's what I get.

---

<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:** [January 15, 2024, 4:53pm UTC](https://forum.inductiveautomation.com/t/opc-tag-script-using-udt-parameters/84195/6 "2024-01-15T16:53:45Z")

</div>

> [@lrose](#):
>
> should execute in 10's of ms.

This is marginal advice, applicable to small system. A few thousand tags, perhaps, of which only a modest percentage have scripts.

Get much bigger and you will definitely want your tag events consistently running in low single-digit milliseconds, or perhaps even less than a millisecond. Tag events don't scale.

It is very common for Ignition systems to start small and then grow wildly. Don't get caught with crappy code.

---

<div class="post-metadata">

**Author:** ![Brendan\_Munroe](https://avatars.discourse-cdn.com/v4/letter/b/3ec8ea/32.png) [@Brendan\_Munroe](https://forum.inductiveautomation.com/u/Brendan_Munroe)\
**Post date:** [February 2, 2024, 3:03pm UTC](https://forum.inductiveautomation.com/t/opc-tag-script-using-udt-parameters/84195/7 "2024-02-02T15:03:11Z")

</div>

Thanks for the help folks. My project will be a small scale project for a very specific part of the plant. My brain was off for a few days and I forgot simple programming. The method I used to get the parameters in the script is below.

```auto
	station_id = system.tag.readBlocking(["[.]Parameters.StationId"])[0].value
	station_number = system.tag.readBlocking(["[.]Parameters.StationNumber"])[0].value
	asset_number = system.tag.readBlocking(["[.]Parameters.AssetNumber"])[0].value

```

There are probably more efficient ways to get the job done than readBlocking, but for an MVP it demonstrates what I want to accomplish with my project.

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [February 2, 2024, 3:09pm UTC](https://forum.inductiveautomation.com/t/opc-tag-script-using-udt-parameters/84195/8 "2024-02-02T15:09:46Z")

</div>

> [@Brendan\_Munroe](#):
>
> There are probably more efficient ways to get the job done than readBlocking

There's a more efficient way to get the job done _with_ readBlocking.

```python
station_id,station_number,asset_number = [qv.value for qv in system.tag.readBlocking(["[.]Parameters." + tag for tag in ["StationId","StationNumber","AssetNumber"]])]

```

Would still probably avoid doing it in a Tag Value Change script.

---

<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:** [February 2, 2024, 3:31pm UTC](https://forum.inductiveautomation.com/t/opc-tag-script-using-udt-parameters/84195/9 "2024-02-02T15:31:11Z")

</div>

> [@lrose](#):
>
> avoid doing it in a Tag Value Change script.

`system.tag.readBlocking()` doesn't create any external traffic when called in gateway scope, so is fine in tag value change events. The one to fear is **writeBlocking**.

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [February 2, 2024, 3:33pm UTC](https://forum.inductiveautomation.com/t/opc-tag-script-using-udt-parameters/84195/10 "2024-02-02T15:33:10Z")

</div>

Good to know, more concerned with "blocking" and execution time. Hadn't really considered external traffic.
