How to change opcItemPath's using scripting on UDT's that have a 'binding' that uses parameters

Here is my tag:

Here is the UDT:

Notice the OPC Item Path uses a binding that involves parameters in the tag.

{
  "parameters": {
    "SensorLocation": {
      "dataType": "String",
      "value": "A01.2 Reach-In Frozen"
    }
  },
  "name": "CleanModeSts",
  "tagType": "UdtInstance",
  "tags": [
    {
      "name": "Value",
      "tagType": "AtomicTag"
    },
    {
      "name": "ValueOverrideTimerSP",
      "tagType": "AtomicTag"
    },
    {
      "name": "HighestAlarmPri",
      "tagType": "AtomicTag"
    },
    {
      "name": "ValueOverrideMode",
      "tagType": "AtomicTag"
    }
  ]
}

Here is the json, it makes sense since there are no overrides, the opcItemPath doesn't exist. However when I try and script an opcItemPath change like this:

path = '[014Edge]Beaverton/Refrigeration/Rack1/A01/Case02/CleanModeSts'
system.tag.writeBlocking(path+'.opcItemPath','Test')
print(system.tag.readBlocking(path+'.opcItemPath')[0].value)

The console read's back

[Good]
Test

and when I copy the tag JSON I get:

{
  "opcItemPath": "Test",
  "parameters": {
    "SensorLocation": {
      "dataType": "String",
      "value": "A01.1 Reach-In Frozen"
    }
  },
  "name": "CleanModeSts",
  "tagType": "UdtInstance",
  "tags": [
    {
      "name": "HighestAlarmPri",
      "tagType": "AtomicTag"
    },
    {
      "name": "ValueOverrideTimerSP",
      "tagType": "AtomicTag"
    },
    {
      "name": "Value",
      "tagType": "AtomicTag"
    },
    {
      "name": "ValueOverrideMode",
      "tagType": "AtomicTag"
    }
  ]
}

Which looks great. HOWEVER... when I open the tag editor it looks like this:
And it appears to take priority over the binding rather than the overwritten opcItemPath 'Test' (Which should give an error configuration)


image

The tag server is on 8.1.21, so to me it would seem like a bug. Not sure if this is fixed on newer versions.
But any clarity onto why this might be the case and the overwrite isn't actually setting would be greatly appreciated.

If the OPC item path is a value determined by an internal binding on the UDT definition then update the parameters that drive that binding do not try to override the actual value. This sounds expected.

You can create a new param that represents the whole item path and do what you are describing by writing to the parameter.

Why are you trying to overwrite the opc item path if it is already determined by the outcome of the binding. Doesn't the binding already exists to represent dynamic paths for this UDT?

You're trying to write to the UDT instance's opcitempath, not its Value tag

Ie the path should be:

path = '[014Edge]Beaverton/Refrigeration/Rack1/A01/Case02/CleanModeSts/Value'
system.tag.writeBlocking(path+'.opcItemPath','Test')

The former just added a custom prop to the UDT instance which just holds a value, nothing functional

Well we have a many stores that use these UDT’s and on occasion the program will have a minor difference needing a manual override for the Opc Item Path. But typically we do this through scripting as it’s far more efficient.
I mean that is the whole point of being able to override a default right? And if I can do it manually through the tag editor why shouldn’t I be able to do it automatically through scripting

I’m not sure why this would be the intended way for this to function, it should work the same way everything else works in ignition, where it takes the default UDT properties unless an override is made which then it should accept that override.

And I could make the whole path a parameter but that also defeats the purpose because at the parent level tag I want to specify a device and a system number. Not every opcItemPath that’s under that parent tag it just doesn’t make sense to do it like that, at that point I might as well manually fill in every opcItemPath as the parameter would serve no actual purpose

I don't think you can use system.tag.writeBlocking to change a binding, use system.tag.configure instead. system.tag.configure | Ignition User Manual
Something like this

basePath = "[014Edge]Beaverton/Refrigeration/Rack1/A01/Case02/CleanModeSts/"
tags = [{
  "name": "Value", 
  "opcItemPath": {
    "bindType": "parameter",
    "binding": "<your new binding>"
  }
}]
collisionPolicy	= "m" #MergeOverwrite to update only the opcItemPath
system.tag.configure(basePath, tags, collisionPolicy)

Because, you're not creating an override, you're writing a new value to a property, which already has a defined value provided by a binding. This is similar to trying to write a new value to an OPC Tag Value which is being written from the PLC. The write is successful but then is immediately overwritten by the PLC.

To create an override in scripting you would need to use system.tag.configure() on the UDT instance to configure the appropriate property.

1 Like

I refer you back to my post further up.

It IS possible to override the opcItemPath of a tag inside a UDT Instance that has a binding

This below will apply an override to the value of the opcItemPath property on the tag in the udt instance:

system.tag.writeBlocking(
	'Testing/New Instance/New Tag.OPCItemPath',
	'ns=1;s=[WyS]WyS_Sch.RFV01.Event[0].EndDateTimeEpoch'
)

This is the UDT definition for "New Instance"

{
  "name": "New Type",
  "tagType": "UdtType",
  "tags": [
    {
      "opcItemPath": {
        "bindType": "parameter",
        "binding": "ns\u003d1;s\u003d[{PLCName}]WyA_Net.WyA_AVR.Healthy"
      },
      "valueSource": "opc",
      "name": "New Tag",
      "tagType": "AtomicTag",
      "opcServer": "Ignition OPC-UA Server"
    }
  ]
}

When you did this, you added a custom property to the UDT Instance called "opcItemPath" and set its value to "Test". A UDT Instance does not have functionality that uses a property called "opcItemPath", only an atomic 'opc' tag has functionality for this property. You need to write this to an actual atomic tag, not to the UDT instance

1 Like