Project-scoped "global" variables for steering tag bindings

Basically, I want to be able to fork a project and change a single global variable like project.project_name and have all of the components in the project that are bound to tags now be bound to equivalent tags in a slightly different structure. For instance I have a tag provider [HMI] and inside of it are folders for each of the projects "project1", "project2", "myOtherProject773". I'd like to be able to duplicate a project, change a single variable somewhere from "project1" to "project2" and have all of the tag bindings play nice.

Also, does this mean I have to use only implicit tag bindings everywhere? Is anything like this possbile? Is there a best practices way to do this?

I'm a bit confused. Tag providers do not belong to projects. :man_shrugging:

If you really are using Vision, then you could create a client tag with a constant expression, and use that client tag in all relevant indirect tag bindings.

Similarly, you could define a Perspective session custom property initialized with a constant binding expression, and reference that session prop in all relevant indirect tag bindings.

There's no way to avoid the indirect tag bindings everywhere.

Or, perhaps, just use different tag providers? Then set the project default tag provider?

Tag providers do not belong to projects.

I am aware -- I want to access subdirectories of the tag providers with project awareness.

If you really are using Vision

I really am using vision. Is it better to have one tag provider per project? Currently I have it organized as one tag provider per data layer; I have [MBUS] for my predefined modbus memory block link to my PLC, I have [PROJ] that is script generated by reading my PLC documentation and mapping the [MBUS] layer variables to meaningful names (+fixing their units + some other programmatic mutations), and then a [HMI] layer filled with things like UDTs and local tags relevant for any given project. All of them are structured like
[PROVIDER]{project}/{everything else} and I want to steer by adjusting that project. Is there a way to fetch the actual project name and hold it in a tag? I found system.project.getProjectName(), but runScript("system.project.getProjectName") in an expression tag doesn't do what I want it to do, presumably because of the scoping.

I think I found at least one place I can get it: system.tag.readBlocking(["[System]Client/System/ProjectName"])[0].value which returns what I want, but when I try to do a Reference tag to [System]Client/System/ProjectName it throws Bad_NotFound

Nope. Tags are globally scoped, and running outside the context of any project, which is why you can't use system.project.getProjectName() in an expression tag.

The [System]Client/ folder meanwhile, only works...on an actual client.

I can definitely see that [System]Client/System/ProjectName in my tag browser in my designer, but I suppose it's the reference that is causing it to break as it can't access that scope from the gateway running the reference?

Oooo! Very not good. Do not "map" tags just for naming. Use reference or derived tags only for knotty data retrieval issue. Create tags, including OPC tags, in a hierarchy of folders and/or UDT instances to yield repeating patterns of named leaf tags that are meaningful to your UI. That usually means plant/area/process/machine/subunit/whatever. So you can efficiently use tag paths to drive dynamic windows and templates.

OPC tags accept arbitrary OPC Item Paths so that the folder location doesn't need to have any specific relationship to the item path (though it often does).

Where you need different folder architectures for different processes in different projects, that is a good case for a different tag provider per project.

(If you have lots of modbus devices, and they have some repeating patterns, you should consider using my spreadsheet import tool to automate tag and UDT instance creation.)

1 Like

Oooo! Very not good. Do not "map" tags just for naming. Use reference or derived tags only for knotty data retrieval issue. Create tags, including OPC tags, in a hierarchy of folders and/or UDT instances to yield repeating patterns of named leaf tags that are meaningful to your UI. So you can efficiently use tag paths to drive dynamic windows and templates.

It is a lot more complicated than that, the name is just one of the things mapped and they follow a specific schema. This layer isn't going anywhere anytime soon, but it can be modified as I evolve our system.

Where you need different folder architectures for different processes in different projects, that is a good case for a different tag provider per project.

The architecture is the same, the references are just different because they point to another project. The entire stack is design to be switched on the project name at the top folder level of each tag provider.

So I might ask, how can I get this variable that I want? The name of the project should not be different gateway to client, so I feel like there should be a manner with which I can make a project at least know what its own name is.


this returns 'null' on the tag, but doesn't claim anything is wrong.


this returns Bad_NotFound

Is that an expression tag (in a tag provider)? If so, it can never know what project is applicable.

Tags are executing independent of any project. The only relationship between the two is that projects can have a default tag provider, which will be used to implicitly find tag references if no other information is specified, but there is no link in the other direction; a tag provider is not associated with a particular project.

Ok. I think that what I want the way I want it is not possible in the architecture of Ignition. Likely a consequence of the 25 year old design choice to operate more like a mainframe with clients instead of an edge-native IIoT swarm. I will try to figure out a workaround so that my projects can't step on each other. I think I'd have to redo everything aggressively using indirect tags and put a central switch memory tag in each main project directory.

To sum it up, basically it sucks to try to clone a project and point it at another PLC because the cloned project keeps all of the original references and there is not a good built in switch to have it point at identical references in a different top level folder. I probably should have handled this when I was first designing it but I underestimated the relevants of the gateway/project scoping paradim.

What references?

Every tag that is bound to an element is exactly the same as before the clone. Which is of course, to be expected when cloning. However, if I want to change the 4th letter of every tag path from a 1 to a 2, that is not something I can do easily.

But tags are not part of projects, and are therefore not cloned. They do not and cannot have dynamic references by project. That can only happen in your user interfaces.

You are really, really deep into an XY problem, and seem to be in complete denial about it. :man_shrugging:

Carry on as you wish. Or share explicit, real details of your application so our advice can be more specific.

More politely:
What Phil said in his first post is accurate. You are going to have to bite the bullet and redo all your referencing if this is truly what you need.

You are really, really deep into an XY problem, and seem to be in complete denial about it. :man_shrugging:

I don't know what this means, but I am not sure what I am denying. I understand the gateway project schism, hence my acceptance:

Ok. I think that what I want the way I want it is not possible in the architecture of Ignition.

and

But tags are not part of projects, and are therefore not cloned . They do not and cannot have dynamic references by project. That can only happen in your user interfaces .

The references are cloned. You know, in the brand new user interface that I have made a copy of.

Yeah, I think I got that at this point. I am looking to see if I can make some scripted adjustments or if I am going to have to redo two years of development one element at a time. The answer is probably both.

Perhaps this helps clarify, because I think you're both talking past each other a bit.

In Ignition, whether you're working in Vision, Perspective, or anything else, the only unique identifier for a tag that has any meaning is its path.

That is, when you duplicate a project, nothing in the tag system even knows about that. It's a totally independent operation. Any kind of tag reference in Ignition is ultimately assembling a string-like tag path. There are various means of "indirection" within that path, particularly around the aforementioned project default tag provider, and of course you can use indirect tag bindings. But all they're doing is changing the way that tag path string is assembled. The "under the hood" machinery is constantly reading, writing, subscribing, etc to the actual tags, but nothing in the user interface or anywhere is literally pointing to the same memory segment that the tag "owns".