Using system.tag.browse with relative path

Hi,
I’m trying to browse a folder to find the tags configured in that folder. The script is executed in the Value Changed Event of a tag that is in an adjacent level from the path I wish to browse.

BaseFolder
-CtrlFolder
–ParseTag
-MachineFolder
–MachineTag1
–MachineTag2

The Event Script is in “ParseTag” from “CtrlFolder” and I want to browse for tags in “MachineFolder”… My code looks like this:

path = "[.]../MachineFolder"
tagsData = system.tag.browse(path)

Normally, I should get a dictionnary containing data for “MachineTag1” and “MachineTag2” but there is an error in the Gateway Logs : Error browsing tags through scripting

Can anyone help?

Thanks

java.util.concurrent.ExecutionException: java.lang.Exception: provider not found: .

at java.base/java.util.concurrent.CompletableFuture.reportGet(Unknown Source)

at java.base/java.util.concurrent.CompletableFuture.get(Unknown Source)

at com.inductiveautomation.ignition.gateway.script.GatewayTagUtilities.browseImpl(GatewayTagUtilities.java:119)

at com.inductiveautomation.ignition.common.script.builtin.AbstractTagUtilities.browse(AbstractTagUtilities.java:344)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

at java.base/java.lang.reflect.Method.invoke(Unknown Source)

at org.python.core.PyReflectedFunction.call(PyReflectedFunction.java:188)

at com.inductiveautomation.ignition.common.script.ScriptManager$ReflectedInstanceFunction.call(ScriptManager.java:538)

at org.python.core.PyObject.call(PyObject.java:480)

at org.python.core.PyObject.call(PyObject.java:484)

at org.python.pycode._pyx21291.valueChanged$1(:49)

at org.python.pycode._pyx21291.call_function()

at org.python.core.PyTableCode.call(PyTableCode.java:171)

at org.python.core.PyBaseCode.call(PyBaseCode.java:308)

at org.python.core.PyFunction.function___call__(PyFunction.java:471)

at org.python.core.PyFunction.call(PyFunction.java:466)

at org.python.core.PyFunction.call(PyFunction.java:461)

at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:836)

at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:820)

at com.inductiveautomation.ignition.gateway.tags.scripting.TagScriptManagerImpl$FunctionInvokerImpl.run(TagScriptManagerImpl.java:530)

at com.inductiveautomation.ignition.gateway.tags.scripting.events.AbstractTagScript.invoke(AbstractTagScript.java:34)

at com.inductiveautomation.ignition.gateway.tags.scripting.TagScriptManagerImpl$Task.invoke(TagScriptManagerImpl.java:479)

at com.inductiveautomation.ignition.gateway.tags.scripting.TagScriptManagerImpl$TagScriptDispatcher.run(TagScriptManagerImpl.java:442)

at com.inductiveautomation.ignition.common.execution.impl.BasicExecutionEngine$ThrowableCatchingRunnable.run(BasicExecutionEngine.java:538)

at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)

at java.base/java.util.concurrent.FutureTask.run(Unknown Source)

at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)

at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at java.base/java.lang.Thread.run(Unknown Source)

Caused by: java.lang.Exception: provider not found: .

at com.inductiveautomation.ignition.gateway.tags.model.impl.GatewayTagManagerImpl.browseAsync(GatewayTagManagerImpl.java:603)

… 30 common frames omitted

FWIW, I would strongly recommend against browsing tags in a tag event script.

looks like the browse function doesn't know the provider. I would say you probably need to provide the fully qualified tag path.

Thanks @lrose
Yes! That was the problem. If I change the [.] part for [MyProvider], it works.
Is it possible to retrieve the provider using the Event parameters in some way?
I use a tag event on a tag that I know will not change very often. It’s a trigger of some sort.
The script in this event parses the structure and generates a json string with the key being the tag name. That json is passed to a database stored procedure. So if the structure is changed in the PLC, the json adapts automatically.
What do you suggest to replace the Event Script with something more secure?
Thanks for your help!

Generally, since you are storing this in a DB, I would tend to recommend a Gateway Timer Event. The event would then check the PLC's copy of the structure against the DB copy and then choose to record a change or not.

You could also achieve this with a Gateway Tag Change Event on a Trigger Tag, then the device could be responsible for triggering the database operation.

It's less about security and more about execution time. Tag event scripts run in a limited thread pool, so best practice is to not execute potentially long running tasks there. Doing so can lead to missed events.

Here is a discussion on the topic.

1 Like

Thanks @lrose! This will help! Case closed!