Dynamic UDT Assignment to Template

I have a few hundred devices in several areas. I am trying to create one window that will show about 20 at a time and filter based on the parameters passed to the windows.

I setup a bound dataset on the window that holds a list of UDT tag paths that I would like to pass to the templates on the screen. The template has a UDT defined as its parameter, and for its binding I am trying to perform a lookup in the data set for the tag path, however, I get an error.

For my expression I am using:

lookup({Root Container.Resources},1,"","id","tagPath")

How can I pass the path of the UDT to the template without throwing a type error?

And the error…

[code]java.lang.ClassCastException: Cannot coerce value ‘Camstar/CFG/ETS-123_300E’ into type: class com.inductiveautomation.factorypmi.application.binding.UDTProperty
at com.inductiveautomation.ignition.common.TypeUtilities.coerce(TypeUtilities.java:1141)
at com.inductiveautomation.factorypmi.application.binding.AbstractPropertyAdapter.setQValue(AbstractPropertyAdapter.java:216)
at com.inductiveautomation.factorypmi.application.binding.AbstractPropertyAdapter.updateValue(AbstractPropertyAdapter.java:256)
at com.inductiveautomation.factorypmi.application.binding.ExpressionPropertyAdapter.runExpression(ExpressionPropertyAdapter.java:79)
at com.inductiveautomation.factorypmi.application.binding.ExpressionPropertyAdapter.startup(ExpressionPropertyAdapter.java:103)
at com.inductiveautomation.factorypmi.application.binding.DefaultInteractionController.setPropertyAdapter(DefaultInteractionController.java:203)
at com.inductiveautomation.factorypmi.designer.property.configurators.ExpressionConfigurator.bind(ExpressionConfigurator.java:269)
at com.inductiveautomation.factorypmi.designer.property.configurators.ExpressionConfigurator.tryCommit(ExpressionConfigurator.java:216)
at com.inductiveautomation.factorypmi.designer.property.configurators.ConfiguratorMultiplexor$EditorParent.tryCommit(ConfiguratorMultiplexor.java:213)
at com.inductiveautomation.factorypmi.designer.property.configurators.ConfiguratorMultiplexor.tryCommit(ConfiguratorMultiplexor.java:358)
at com.inductiveautomation.factorypmi.designer.property.configurators.DynamicOptsDialog.doOK(DynamicOptsDialog.java:117)
at com.inductiveautomation.factorypmi.designer.property.configurators.DynamicOptsDialog.access$000(DynamicOptsDialog.java:43)
at com.inductiveautomation.factorypmi.designer.property.configurators.DynamicOptsDialog$1.actionPerformed(DynamicOptsDialog.java:83)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.WaitDispatchSupport$2.run(Unknown Source)
at java.awt.WaitDispatchSupport$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.awt.WaitDispatchSupport.enter(Unknown Source)
at java.awt.Dialog.show(Unknown Source)
at java.awt.Component.show(Unknown Source)
at java.awt.Component.setVisible(Unknown Source)
at java.awt.Window.setVisible(Unknown Source)
at java.awt.Dialog.setVisible(Unknown Source)
at com.inductiveautomation.factorypmi.designer.property.configurators.DynamicOptsDialog.showDialog(DynamicOptsDialog.java:185)
at com.inductiveautomation.factorypmi.designer.model.VisionDesignerImpl.openBindingDialog(VisionDesignerImpl.java:756)
at com.inductiveautomation.factorypmi.designer.property.editors.bb.DynamicOptionsButton.actionPerformed(DynamicOptionsButton.java:36)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at com.jidesoft.plaf.basic.BasicJideButtonListener.mouseReleased(Unknown Source)
at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

Ignition v7.6.4 (b2013112117)
Java: Oracle Corporation 1.7.0_45
[/code]

This sounds like you are trying to pass a string argument (the path) into a UTD type parameter.
If your dataset holds UDT paths (strings), your parameter needs to be a string too.

Hi Ryan,

Instead of trying to bind your template instance to your UDT tag with a string directly, do this indirectly. Make an indirect binding that references your string path.

Here are the steps:

  1. Create another Template Property that is a string type on your template. For example this could be called “path”.

  2. Then bind your lookup expression to the path property.

  3. Then make an indirect tag binding on your UDT property and use your path property.

Does this make sense?
Nick

1 Like

[quote=“nmudge”]Hi Ryan,

Instead of trying to bind your template instance to your UDT tag with a string directly, do this indirectly. Make an indirect binding that references your string path.

Here are the steps:

  1. Create another Template Property that is a string type on your template. For example this could be called “path”.

  2. Then bind your lookup expression to the path property.

  3. Then make an indirect tag binding on your UDT property and use your path property.

Does this make sense?
Nick[/quote]

This is the way we do it, so I can vouch for it’s effectiveness. However, usually binding to a UDT property for most circumstances will negatively affect performance. As an example, if you have a UDT with 50 properties, and you loaded 20 templates backed by those UDTs, it would have to subscribe to 1000 tags. If you are using most of there values on your template, then that is fine. However, if you are only using a small set of the UDT, then it becomes a problem, and you should switch do doing indirect tag bindings. This way, only the values that are required are subscribed to.

Kyle has brought up a great point about the use of UDT property bindings. I have seen this numerous times where a customer has a rather large UDT and is only using a few tags on their templates and the performance isn't as expected. As Kyle said, this is a where you should switch to indirect tag bindings.

I’ve already told him to use an indirect tag binding to bind to the entire UDT tag, so he is already using an indirect tag binding.

I am telling him to use an indirect binding to bind to the entire UDT tag because he has a dataset full of string paths to UDTs and the only way I know of to convert a string path to a tag binding is to use an indirect tag binding.

It is the job of the tag expression function to convert strings to tag bindings but I noticed that the tag expression function doesn’t work for UDTs so I have submitted a request to the developers that the tag expression function be improved to support UDTs.

I think what Kyle and Greg mean is to use indirect tag bindings to bind to the parts of the UDT tag instead of binding to the entire UDT tag.

That is correct Nick