Create UDT OK, when I create an Instance, structure is invalid

Hi Everyone,

I have created several UDT's and they are working great. Today I created a new one but things went bad.

Here is my UDT:

Here is my instance:

If I export my UDT structure, it is populated like so:

If I export my newly created Instance, It is essentially Un-populated:

The only time it populates, is when I override the UDT and apply/save.
I now have to override all the parameters in the UDT with the SAME OPC Item Path, and it will populate/work, but everything is "over-ridden". Why must I do this?

Is this a bug?

Thanks!

Please post formatted code, not pictures of code. Please see Wiki - how to post code on this forum.

I was merely showing examples of what is going on, for brevity.

However, if you want to see all, the code is as follows:

Original UDT:

{
  "typeColor": -16711936,
  "name": "Motor Starter",
  "parameters": {
    "TagNum": {
      "dataType": "Integer",
      "value": 0
    }
  },
  "tagType": "UdtType",
  "tags": [
    {
      "valueSource": "opc",
      "historyTimeDeadband": 10,
      "historyMaxAge": 1,
      "opcItemPath": "ns\u003d1;s\u003d[MCP]EQ_P{TagNum}.Sts_Running",
      "dataType": "Boolean",
      "historyProvider": "Tag_History",
      "historicalDeadbandStyle": "Discrete",
      "name": "Sts_Running",
      "historyEnabled": true,
      "tagType": "AtomicTag",
      "opcServer": "Ignition OPC UA Server"
    },
    {
      "valueSource": "opc",
      "opcItemPath": "ns\u003d1;s\u003d[MCP]EQ_P{TagNum}.Alm_FailToStart",
      "dataType": "Boolean",
      "alarms": [
        {
          "setpointA": 1.0,
          "activePipeline": "ShawHMI/Alarms",
          "CustomEmailMessage": "{[.]Cfg_Label}+\" Fail to Start Alarm\"",
          "name": "Alarm",
          "priority": "High",
          "label": {
            "bindType": "Expression",
            "value": "{[.]Cfg_Label}+\" Fail to Start Alarm\""
          }
        }
      ],
      "name": "Alm_FailToStart",
      "tagType": "AtomicTag",
      "opcServer": "Ignition OPC UA Server"
    },
    {
      "valueSource": "opc",
      "historyMaxAge": 10,
      "opcItemPath": "ns\u003d1;s\u003d[MCP]EQ_P{TagNum}_Runtime.Val_Starts",
      "historicalDeadband": 0.1,
      "historySampleRateUnits": "HOUR",
      "tagType": "AtomicTag",
      "dataType": "Int4",
      "historyProvider": "Tag_History",
      "historyMaxAgeUnits": "MIN",
      "name": "Val_Starts",
      "historyEnabled": true,
      "sampleMode": "Periodic",
      "historySampleRate": 1,
      "opcServer": "Ignition OPC UA Server"
    },
    {
      "valueSource": "opc",
      "opcItemPath": "ns\u003d1;s\u003d[MCP]EQ_P{TagNum}.Alm_FailToStop",
      "dataType": "Boolean",
      "alarms": [
        {
          "setpointA": 1.0,
          "activePipeline": "ShawHMI/Alarms",
          "CustomEmailMessage": "{[.]Cfg_Label}+\" Fail to Stop Alarm\"",
          "name": "Alarm",
          "label": "{[.]Cfg_Label}+\" Fail to Stop Alarm\"",
          "priority": "High"
        }
      ],
      "name": "Alm_FailToStop",
      "tagType": "AtomicTag",
      "opcServer": "Ignition OPC UA Server"
    },
    {
      "valueSource": "opc",
      "historyMaxAge": 10,
      "opcItemPath": "ns\u003d1;s\u003d[MCP]EQ_P{TagNum}_Runtime.Val_DayStarts",
      "historicalDeadband": 0.1,
      "historySampleRateUnits": "HOUR",
      "tagType": "AtomicTag",
      "dataType": "Int4",
      "historyProvider": "Tag_History",
      "historyMaxAgeUnits": "MIN",
      "name": "Val_DayStarts",
      "historyEnabled": true,
      "sampleMode": "Periodic",
      "historySampleRate": 1,
      "opcServer": "Ignition OPC UA Server"
    },
    {
      "valueSource": "opc",
      "historyMaxAge": 10,
      "opcItemPath": "ns\u003d1;s\u003d[MCP]EQ_P{TagNum}_Runtime.Val_MaxRunHrs",
      "historicalDeadband": 0.1,
      "historySampleRateUnits": "HOUR",
      "tagType": "AtomicTag",
      "dataType": "Float4",
      "historyProvider": "Tag_History",
      "historyMaxAgeUnits": "MIN",
      "name": "Val_MaxRunHrs",
      "historyEnabled": true,
      "sampleMode": "Periodic",
      "historySampleRate": 1,
      "opcServer": "Ignition OPC UA Server"
    },
    {
      "valueSource": "opc",
      "historyMaxAge": 10,
      "opcItemPath": "ns\u003d1;s\u003d[MCP]EQ_P{TagNum}_Runtime.Val_PrevStarts",
      "historicalDeadband": 0.1,
      "historySampleRateUnits": "HOUR",
      "tagType": "AtomicTag",
      "dataType": "Int4",
      "historyProvider": "Tag_History",
      "historyMaxAgeUnits": "MIN",
      "name": "Val_PrevStarts",
      "historyEnabled": true,
      "sampleMode": "Periodic",
      "historySampleRate": 1,
      "opcServer": "Ignition OPC UA Server"
    },
    {
      "valueSource": "opc",
      "historyTimeDeadband": 10,
      "historyMaxAge": 1,
      "opcItemPath": "ns\u003d1;s\u003d[MCP]EQ_P{TagNum}.Sts_Stopped",
      "dataType": "Boolean",
      "historyProvider": "Tag_History",
      "historicalDeadbandStyle": "Discrete",
      "name": "Sts_Stopped",
      "historyEnabled": true,
      "tagType": "AtomicTag",
      "opcServer": "Ignition OPC UA Server"
    },
    {
      "valueSource": "opc",
      "opcItemPath": "ns\u003d1;s\u003d[MCP]EQ_P{TagNum}.Cfg_Label",
      "dataType": "String",
      "name": "Cfg_Label",
      "tagType": "AtomicTag",
      "opcServer": "Ignition OPC UA Server"
    },
    {
      "valueSource": "opc",
      "historyMaxAge": 10,
      "opcItemPath": "ns\u003d1;s\u003d[MCP]EQ_P{TagNum}_Runtime.Val_PrevRunHrs",
      "historicalDeadband": 0.1,
      "historySampleRateUnits": "HOUR",
      "tagType": "AtomicTag",
      "dataType": "Float4",
      "historyProvider": "Tag_History",
      "historyMaxAgeUnits": "MIN",
      "name": "Val_PrevRunHrs",
      "historyEnabled": true,
      "sampleMode": "Periodic",
      "historySampleRate": 1,
      "opcServer": "Ignition OPC UA Server"
    },
    {
      "valueSource": "opc",
      "historyMaxAge": 10,
      "opcItemPath": "ns\u003d1;s\u003d[MCP]EQ_P{TagNum}_Runtime.Val_CurRunHrs",
      "historicalDeadband": 0.1,
      "historySampleRateUnits": "HOUR",
      "tagType": "AtomicTag",
      "dataType": "Float4",
      "historyProvider": "Tag_History",
      "historyMaxAgeUnits": "MIN",
      "name": "Val_CurRunHrs",
      "historyEnabled": true,
      "sampleMode": "Periodic",
      "historySampleRate": 1,
      "opcServer": "Ignition OPC UA Server"
    },
    {
      "valueSource": "opc",
      "historyMaxAge": 10,
      "opcItemPath": "ns\u003d1;s\u003d[MCP]EQ_P{TagNum}_Runtime.Val_DayRunHrs",
      "historicalDeadband": 0.1,
      "historySampleRateUnits": "HOUR",
      "tagType": "AtomicTag",
      "dataType": "Float4",
      "historyProvider": "Tag_History",
      "historyMaxAgeUnits": "MIN",
      "name": "Val_DayRunHrs",
      "historyEnabled": true,
      "sampleMode": "Periodic",
      "historySampleRate": 1,
      "opcServer": "Ignition OPC UA Server"
    },
    {
      "valueSource": "opc",
      "opcItemPath": "ns\u003d1;s\u003d[MCP]EQ_P{TagNum}.Cfg_HasFailToStopAlm",
      "dataType": "Boolean",
      "name": "Cfg_HasFailToStopAlm",
      "tagType": "AtomicTag",
      "opcServer": "Ignition OPC UA Server"
    },
    {
      "valueSource": "opc",
      "opcItemPath": "ns\u003d1;s\u003d[MCP]EQ_P{TagNum}.Cfg_HasFailToStartAlm",
      "dataType": "Boolean",
      "name": "Cfg_HasFailToStartAlm",
      "tagType": "AtomicTag",
      "opcServer": "Ignition OPC UA Server"
    },
    {
      "valueSource": "opc",
      "historyMaxAge": 10,
      "opcItemPath": "ns\u003d1;s\u003d[MCP]EQ_P{TagNum}_Runtime.Val_TotRunHrs",
      "historicalDeadband": 0.1,
      "historySampleRateUnits": "HOUR",
      "tagType": "AtomicTag",
      "dataType": "Float4",
      "historyProvider": "Tag_History",
      "historyMaxAgeUnits": "MIN",
      "name": "Val_TotRunHrs",
      "historyEnabled": true,
      "sampleMode": "Periodic",
      "historySampleRate": 1,
      "opcServer": "Ignition OPC UA Server"
    }
  ]
}

Inherited from UDT:

{
  "name": "EQ_P101",
  "typeId": "Motor Starter",
  "parameters": {
    "TagNum": {
      "dataType": "String",
      "value": "101"
    }
  },
  "tagType": "UdtInstance",
  "tags": [
    {
      "name": "Val_DayStarts",
      "tagType": "AtomicTag"
    },
    {
      "name": "Cfg_HasFailToStartAlm",
      "tagType": "AtomicTag"
    },
    {
      "name": "Val_PrevStarts",
      "tagType": "AtomicTag"
    },
    {
      "name": "Val_DayRunHrs",
      "tagType": "AtomicTag"
    },
    {
      "name": "Sts_Running",
      "tagType": "AtomicTag"
    },
    {
      "name": "Sts_Stopped",
      "tagType": "AtomicTag"
    },
    {
      "opcItemPath": {
        "bindType": "parameter",
        "binding": "ns\u003d1;s\u003d[MCP]EQ_P{TagNum}.Alm_FailToStart"
      },
      "name": "Alm_FailToStart",
      "tagType": "AtomicTag"
    },
    {
      "name": "Cfg_Label",
      "tagType": "AtomicTag"
    },
    {
      "name": "Cfg_HasFailToStopAlm",
      "tagType": "AtomicTag"
    },
    {
      "name": "Val_TotRunHrs",
      "tagType": "AtomicTag"
    },
    {
      "name": "Val_PrevRunHrs",
      "tagType": "AtomicTag"
    },
    {
      "name": "Val_Starts",
      "tagType": "AtomicTag"
    },
    {
      "name": "Val_CurRunHrs",
      "tagType": "AtomicTag"
    },
    {
      "name": "Val_MaxRunHrs",
      "tagType": "AtomicTag"
    },
    {
      "name": "Alm_FailToStop",
      "tagType": "AtomicTag"
    }
  ]
}

From the files, in the Def your "TagNum" parameter is an INT, but in the Instance you changed the Data Type to string, perhaps unintentionally?

Go to the instance > Param > Click the Green dot , to remove the overrides, then set the value to a valid value. This likely resolves it.

I changed that only because another UDT that worked had that structure.

I tried making this one easier to follow by allowing the entire tag name "P_101" in lieu of "TagName" variable of "101" with hard-coded "P_" in the UDT.

Anyway, neither method is working at the moment.

Drill down in your tag browser and see how the opc tags are being generated. That should give you a hint as to what might be wrong.

Nothing seems out of the ordinary. It involves tag substitution in the OPC path. If I direct link the tag, it works fine. Once I put my tag substitution back in, it fails.

Can you screenshot the opcitempath of one of the tags?

Nevermind, this is the issue:

"opcItemPath": "ns\u003d1;s\u003d[MCP]EQ_P{TagNum}.Sts_Running",

In the UDT instance this resolved to literally that string - it's not a binding/expression with dynamic parts; the {TagNum} is static, not a binding. It looks like you did a simple find/replace from notepad to add in those parameterisations.

Bindings need to be like this instead:

"opcItemPath": {
   "bindType": "parameter",
   "binding": "ns\u003d1;s\u003d[MCP]EQ_P{TagNum}.Sts_Running"
}

In my opinion, the tag import tool / paste json should automatically convert this for you, as this trips up a lot of people! and really, I'm 99% sure that you can't use these braces statically within these paths anyway, so there's no reason they shouldn't be auto-converted.

However the easy way to spot this is, if your UDT Instance tag's opcitempath has { } in them, then that's the likely cause. These should be resolved paths, not still have "dynamic" parts in them.

I added a feature request: [FEATURE] Auto-convert relevant UDT Type tag prop values with {..} in them to bindings

While IA doesn't use them for their own drivers, they are not forbidden in OPC Node IDs. So, some random OPC server could expect them.

OK, I'm understanding this a lot better.

What works for now is I bring the OPC item(s) I need into my UDT. I create my "TagName" parameter. I then find the tag identifier from the element import(s), highlight it manually with the mouse (I can double-click and it highlights just the tag!), and click the chain-link to BIND to my parameter called "TagName", hit ENTER.

Do this for the remainder of UDT and it works perfectly..

I believe a proper export to .json for find/replace, would be ever so handy. I think Ignition doesn't bind the initial elements by default.

Or just run a script over your tag json copied to your clipboard and convert them from strings to the bindings structure, then you can reuse it again an snot potentially miss any