Automation Professionals' Integration Toolkit Module

dibs

3 Likes

@Samuel_Sueur, you definitely may trust @pturmel... and best of all, he is speaking french :wink:
see you at icc @pturmel

2 Likes

Bien sûr! :grin:

1 Like

Automation Professionals is pleased to announce a new version of the Integration Toolkit:

For Ignition v8.1+, as usual: v2.0.19.242411414

Fixes a couple bugs, including the NPE found by @lrose, and adds some new scripting functions:

system.dataset.orderBy()

This new orderBy() function is very similar to the same-named expression function, but doesn't require you to supply expressions that extract cell values. String arguments are interpreted as column names and turned into the necessary lambda for you (entirely with java code), similar to how IA's system.dataset.sort() works, but not limited to a single column key.

system.dataset.descending()

system.dataset.naturalOrder()

system.dataset.naturalCasedOrder()

Note that the latter three are function-returning functions, intended to be used with system.dataset.orderBy(). These function-returning functions similarly accept strings as column names, and can be nested. The following will order a dataset by ascending natural order on one column, then descending natural order on a second column:

newDS = system.dataset.orderBy(
	sourceDS,
	system.dataset.naturalOrder('col1'),
	system.dataset.descending(system.dataset.naturalOrder('col2')))
4 Likes

I feel as though my post about sorting using arbitrary key functions may have inspired system.dataset.orderBy... :slight_smile:

Not really. I've had the expression function which sorts by arbitrary key expressions since last year. But I needed a scripted version that can efficiently handle some potentially very large datasets. So an actual jython lambda is suboptimal. (Though you can pass those to my new function if you must.)

Phil,

Perhaps I am missing something, but I don't see any where in the documentation where you show what values can be used to specify each type when providing columninfo to unionAll(). Specifically, I am trying to provide a column with type Date.

I have tried "Date","date", and "java.util.Date". Non-of which work. I get an Unsupported inner columnInfo element error.

I use the same class as IA uses in their CSV tools to handle those strings. Documented here: system.dataset.fromCSV().

So, "date" should work.

Show your expression?

This test expression:

unionAll(
	asMap('someDate', 'date'),
	asList()
)

Produces this empty dataset:

"#NAMES"
"someDate"
"#TYPES"
"date"
"#ROWS","0"

Here is the Expression:

unionAll(
	asList(
		"BestByDate","date",
		"CaseCode", "str",
		"FGItem", "str",
		"ShopOrder","I",
		"RecordID", "str",
		"ShopOrderQty","F",
		"CaseUpcCode","str",
		"SerialKey","I",
		"TemplateName","str",
		"GtinCode","str",
		"CaseProductDesc","str",
		"LogoCode","str",
		"CaseCountUnitSize","str",
		"BestBuyFormatCode","str",
		"BB_YEAR4","I",
		"BB_YEAR2","I",
		"BB_MONTHNAME","str",
		"BB_MONTHNUMBER","I",
		"BB_DAY","I",
		"MISC1","str",
		"MISC2","str",
		"MISC3","str",
		"StockNumber","str",
		"DATE_FMT","str"
	),
	forEach(
		objectScript("system.util.sendRequest('<project name>','retrievePalletInfo',{'line':'1A'},'<remoteServer>')"),
		it()[1]
	)
)

The objectScript() returns the following map:

{u'BB_MONTHNAME': u'December', u'ShopOrderQty': 19208.0, u'DATE_FMT': u'                                                  ', u'BestBuyFormatCode': u'XX', u'CaseCode': u'SFY59P1E424208                ', u'FGItem': u'HOUY59PNEL                         ', u'CaseProductDesc': u'Tomato Ketchup                          ', u'BB_YEAR4': u'2025', u'BB_DAY': 28, u'BB_MONTHNUMBER': 12, u'MISC3': u'                                                  ', u'MISC2': u'                                                  ', u'TemplateName': u'M00C2', u'MISC1': u'                                                  ', u'BestByDate': 2025-12-28 00:00:00.0, u'BB_YEAR2': 25, u'GtinCode': u'10734730058341', u'CaseUpcCode': u'34730-05834*/*          ', u'SerialKey': 395740, u'ShopOrder': 1146113.0, u'LogoCode': u'HOU  ', u'StockNumber': u'                                   ', u'RecordID': u'PH', u'CaseCountUnitSize': u'6/114 OZ            '}
Error

java.lang.Exception: Error executing expression binding on
AutoCasePrint.Root Container.Text Area.palletInfo
at com.inductiveautomation.factorypmi.application.binding.ExpressionPropertyAdapter.runExpression(ExpressionPropertyAdapter.java:92)
at com.inductiveautomation.factorypmi.application.binding.ExpressionPropertyAdapter.startup(ExpressionPropertyAdapter.java:113)
at com.inductiveautomation.factorypmi.application.binding.DefaultInteractionController.setPropertyAdapter(DefaultInteractionController.java:248)
at com.inductiveautomation.factorypmi.designer.property.configurators.ExpressionConfigurator.bind(ExpressionConfigurator.java:246)
at com.inductiveautomation.factorypmi.designer.property.configurators.ExpressionConfigurator.tryCommit(ExpressionConfigurator.java:192)
at com.inductiveautomation.factorypmi.designer.property.configurators.ConfiguratorMultiplexor$EditorParent.tryCommit(ConfiguratorMultiplexor.java:398)
at com.inductiveautomation.factorypmi.designer.property.configurators.ConfiguratorMultiplexor.tryCommit(ConfiguratorMultiplexor.java:546)
at com.inductiveautomation.factorypmi.designer.property.configurators.DynamicOptsDialog.doOK(DynamicOptsDialog.java:95)
at com.inductiveautomation.factorypmi.designer.property.configurators.DynamicOptsDialog$1.actionPerformed(DynamicOptsDialog.java:64)
at java.desktop/javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at java.desktop/javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.desktop/java.awt.Component.processMouseEvent(Unknown Source)
at java.desktop/javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.desktop/java.awt.Component.processEvent(Unknown Source)
at java.desktop/java.awt.Container.processEvent(Unknown Source)
at java.desktop/java.awt.Component.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Window.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.desktop/java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.desktop/java.awt.WaitDispatchSupport$2.run(Unknown Source)
at java.desktop/java.awt.WaitDispatchSupport$4.run(Unknown Source)
at java.desktop/java.awt.WaitDispatchSupport$4.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
at java.desktop/java.awt.WaitDispatchSupport.enter(Unknown Source)
at java.desktop/java.awt.Dialog.show(Unknown Source)
at java.desktop/java.awt.Component.show(Unknown Source)
at java.desktop/java.awt.Component.setVisible(Unknown Source)
at java.desktop/java.awt.Window.setVisible(Unknown Source)
at java.desktop/java.awt.Dialog.setVisible(Unknown Source)
at com.inductiveautomation.factorypmi.designer.property.configurators.DynamicOptsDialog.showDialog(DynamicOptsDialog.java:163)
at com.inductiveautomation.factorypmi.designer.model.VisionDesignerImpl.openBindingDialog(VisionDesignerImpl.java:1236)
at com.inductiveautomation.factorypmi.designer.property.editors.bb.DynamicOptionsButton.actionPerformed(DynamicOptionsButton.java:37)
at java.desktop/javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at java.desktop/javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at com.jidesoft.plaf.basic.BasicJideButtonListener.mouseReleased(Unknown Source)
at java.desktop/java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.desktop/java.awt.Component.processMouseEvent(Unknown Source)
at java.desktop/javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.desktop/java.awt.Component.processEvent(Unknown Source)
at java.desktop/java.awt.Container.processEvent(Unknown Source)
at java.desktop/java.awt.Component.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
at java.desktop/javax.swing.plaf.basic.BasicTableUI$Handler.repostEvent(Unknown Source)
at java.desktop/javax.swing.plaf.basic.BasicTableUI$Handler.mouseReleased(Unknown Source)
at com.jidesoft.swing.DelegateMouseInputListener.mouseReleased(Unknown Source)
at java.desktop/java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.desktop/java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.desktop/java.awt.Component.processMouseEvent(Unknown Source)
at java.desktop/javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.desktop/java.awt.Component.processEvent(Unknown Source)
at java.desktop/java.awt.Container.processEvent(Unknown Source)
at java.desktop/java.awt.Component.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Window.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.desktop/java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.run(Unknown Source)
Caused by: com.inductiveautomation.ignition.common.expressions.ExpressionException: Unsupported inner columnInfo element BestByDate
at com.automation_pros.simaids.expressions.UnionAll.builderFromColumnInfo(UnionAll.java:71)
at com.automation_pros.simaids.expressions.UnionAll.execute(UnionAll.java:112)
at com.inductiveautomation.ignition.client.expressions.ClientDynamicDispatchFunction.execute(ClientDynamicDispatchFunction.java:43)
at com.inductiveautomation.ignition.common.expressions.FunctionExpression.execute(FunctionExpression.java:69)
at com.inductiveautomation.factorypmi.application.binding.ExpressionPropertyAdapter.runExpression(ExpressionPropertyAdapter.java:83)
... 102 more

Ignition v8.1.35 (b2023120517)
Java: Azul Systems, Inc. 17.0.8

For context, I am using this in Vision. The reason I am turning a perfectly acceptable map back into a Dataset here is that I would like to store the result of this expression in a custom property. This way it can be accessed multiple times without the need to query across the GAN every time (The function is located on a remote server for other reasons). However, I do not know of any way to store a map in a custom property in Vision without also having all column values converted to strings.

Replace your first asList() with an asMap(). When using lists to supply column info, each pair must be a nested list.

FWIW, using objectScript() completely breaks the justification for my expression functions. Consider just processing the return value locally in your script.

1 Like

Is there any reason why

vvm = system.perspective.viewVarMap()
vvm.tagQueryResult = retv

returns "AttributeError: 'com.automation_pros.simaids.persist.BindableVarMap' object has no attribute 'tagQueryResult' " for Ignition 8.1.43, but works fine in 8.1.42 ?

Are you sure you are using the latest version of my module in both versions of Ignition? And rebooted, actually. That bug was in a persistent jar that can only be replaced by restarting the service.

I tried to restart the ignition service, but same result. Same version of the modules, different versions of igntion 8.1.42 (running in docker) <--Working and 8.1.43 (running on windows) <---Not working

Solved, My bad, restarted the module, and now its working

1 Like

Hey Phil, apologies if you've already answered this, but can I do the equivalent of ','.join(map(str, [10,20,30])) with your toolkit expression functions? And just in case, what about "','".join(map(str, [10,20,30]))?

As of v8.1.8:

groupConcat(
	forEach(
		asList(10, 20, 30),
		stringFormat("%s", it())
	),
	","
)

Adjust to suit.

4 Likes

For posterity, I'm pretty sure bare groupConcat should just work:

groupConcat(
	asList(10, 20, 30),
	","
)

Assuming asList spits out a regular java.util.List.

asList() produces an ArrayList, so yes. groupConcat() stringifies the elements of the list? (I did not test.)

Yes, using Objects.toString, using empty string for null inputs.

1 Like

Automation Professionals is pleased to announce a BETA release of its Integration Toolkit, with many new functions.

For Ignition v8.1+: v2.0.20.242841644

New/Updated Expression functions:

New/Updated Scripting functions:

Only lightly tested.

Edit: Survived some weeks with a client under heavy use. I consider this production grade, now.

10 Likes