All posts

Where your Ignition script actually runs

A script that works in one place and fails in another, with an error saying the function does not exist, is rarely a syntax problem. It is a scope problem, and scope is worth understanding once rather than rediscovering per script.

There are three scopes, not two

Ignition declares three: gateway, Vision client, and Perspective session. Every function page in the appendix lists which of them a function belongs to, and the values you see there are exactly those three.

Perspective session scope is the one that catches people, and it is worth quoting the platform on it: scripts in Perspective execute on the gateway, not in the browser, but that scope is still distinct from gateway scope. Both halves matter. The code runs on the gateway, and it is not gateway-scoped code.

That distinction has teeth. system.perspective.navigate works from a component event with no arguments beyond the destination, because the session and page are implied. The same function is available in gateway scope but needs a session id and a page id supplied, because from there nothing is implied. A two-scope mental model has nowhere to put that difference, which is why it produces surprises.

The clearest case is a Perspective session event script. It is Perspective code in a Perspective project, and Inductive Automation puts session event scripts in gateway scope — so navigate needs the ids there, just as it would from a tag event script, and unlike the component event above.

Scope decides which functions exist

Some functions work in one scope, some in two, some anywhere. A function outside its scope usually is not there at all — the name does not resolve, rather than the call failing partway through. The exceptions are functions that exist in more than one scope and need extra arguments in the wider one.

The Designer will tell you, with one caveat. The autocomplete popup shows the system functions scoped to the script you are editing, so a function that does not appear is not available in that scope. The caveat is Project Library scripts, which carry a Script Hint Scope setting — None, Designer, Gateway or All — deciding what the popup draws from. Set to None it shows nothing regardless of scope, so check that before trusting the hints in shared code.

The scope nobody counts: the Designer

The Designer is a scope too — Inductive Automation’s own troubleshooting table lists it alongside the other three — but no function is tagged for it, which is why it does not appear in the taxonomy above. It matters for a different reason: the Script Console is where most people test the script they are trying to place.

The Script Console cannot interact with components on a window. More importantly, gateway-scoped output does not appear there — it goes to the wrapper log instead. So testing gateway logic in the Script Console can mislead you twice over, about what is available and about whether anything happened. Some events, such as client startup scripts, will not fire in the Designer at all, which is why launching a real client is the habit worth having when testing non-component events.

Gateway scope: always running, no handle on a screen

Gateway event scripts run on the gateway and always run, regardless of whether any session or client is open. That is what you want for anything that has to happen whether or not somebody is watching.

What a gateway script does not have is a direct handle on a screen. There is no component to reach for, no event source, no window. It can still reach a session or a client indirectly, and the mechanisms are documented: system.util.sendMessage delivers to client and session message handlers, and system.perspective.sendMessage, openPopup and navigate all work from gateway scope provided you supply the session id and page id.

So the honest answer to “can I pop a message box from a gateway script” is yes, but you have to name the session you mean. Having to name it is usually the sign that the logic wants splitting rather than reaching. The reverse direction — what a script on a screen can reach on the gateway — we covered separately in session permissions are not gateway permissions.

What Perspective load actually scales with

Because Perspective scripting runs on the gateway, script work on a screen is gateway work. It does not scale per session, though — it scales with the number of things doing it.

A session can have any number of pages open, a page any number of views, and a view can be instantiated more than once on the same page. So the multiplier is sessions times open pages times view instances, times however often the event fires. Eight copies of an embedded view with a component event script on each is eight executions per trigger from a single session.

Bindings are the exception worth knowing. A query binding with Cache and Share enabled runs once through a polling engine shared across every running session, caches the value and delivers it to all registered consumers — so identical polled bindings consolidate rather than multiply. Scripts get no such treatment, which is why the arithmetic above is about script work specifically.

Vision keeps its client scope

Vision clients are real clients: a process on somebody’s machine with its own scope and its own access to the window it belongs to. Client event scripts and gateway event scripts both exist, and some system functions belong to one or the other.

So code moved from a Vision project into a Perspective one may be perfectly valid and still wrong — not because the syntax changed, but because the ground under it did. system.file functions are the sharp example: available in Perspective session scope, where they read the gateway’s filesystem rather than the machine in front of the user.

The question worth asking first

Does this need to happen when nobody is looking? If yes, it belongs in gateway scope, and having no screen to touch is a feature. If it exists to respond to a person, it belongs with the visualisation — and in Perspective that still executes on the gateway, with the load arithmetic above.

Scripts that are hard to place are often doing both jobs, and splitting them is usually the cheaper option. One thing to know before you do: shared code lives in the Project Library, and a gateway-scoped resource such as a tag event script can only reach it if that project is named as the Gateway Scripting Project. Otherwise you get “global name is not defined” in the gateway log, which is a confusing error for a problem that is really about where code lives.

Common questions

How many scripting scopes does Ignition have?
Three: gateway, Vision client, and Perspective session. Every function page in the appendix lists which scopes a function belongs to. The Designer is a further context to be aware of when testing, since the Script Console runs there.
Does Perspective have a client scope?
No. Perspective does not have clients in the way Vision does, and all Perspective scripting runs on the gateway. Perspective session scope is still a distinct scope from gateway scope, which is why some functions need a session id and page id when called from the gateway but not from a component event.
Can a gateway script show something on a screen?
Not directly, since it has no component or window to reach for. It can reach a session or client indirectly: system.util.sendMessage delivers to message handlers, and system.perspective.sendMessage, openPopup and navigate work from gateway scope provided a session id and page id are supplied.
Why does my script work in the Designer but not on the gateway?
The Script Console runs in the Designer rather than in gateway scope. It cannot interact with components on a window, and gateway-scoped output goes to the wrapper log rather than the console, so a gateway script tested there can appear to do nothing.
How does Perspective script load scale?
With the number of things executing, not with sessions alone. A session can have several pages open, a page several views, and a view can be instantiated more than once, so script work multiplies by sessions times pages times view instances times event frequency. Bindings behave differently: a query binding with Cache and Share enabled runs once through a polling engine shared across sessions and delivers the cached result to all of them.

References

Scripts behaving differently than you expect? We work on Ignition systems across California’s Central Valley, and scope confusion is one of the more common things we untangle in a project somebody else started.

Contact us