Writing a new script in the script library and I want to change a session property inside of it. There’s no drop down selector to pick a property. How can I reference the session property from a script library? Do I need to pass a reference to self?
You must pass what you need as function arguments. This is true in Perspective, in Vision, and in any gateway events.
Ok I thought session props were analogous to tags, and in Vision I didn’t have to pass anything as long as I knew the tag path I could just do a system.tag.read() on the path.
So there is nothing to replace Client tags in 8.0? I have almost 100 functions defined in a script library and want to change the database they point to based on the plant selected. I have a session property that does this for everything else but I can’t use it at the beginning of the script library? I would have to pass it into each function separately.
In theory, the
ThreadLocal would be populated if you’re running a project script from a Perspective thread; so something like this might work:
from com.inductiveautomation.perspective.gateway.session import InternalSession session = InternalSession.SESSION.get() if session is not None: system.perspective.print(session.custom.something)
Hah! And I thought I was bad about exposing unsupported and undocumented implementation details… (:
Definitely true. Phil’s suggestion to pass explicit parameters is the only non-magic way to do this. And I don’t want any PMs about this thread in three years when we end up breaking someone’s code
Ok so the way to do it would be something like
def myFunc(self): self.session.custom.myCustomProp = 1
or to use your undocumented method and then DM you in a few years when it breaks right?
I get how this would work with hardcoded custom session properties I know exists, but say I want to read/write to a dynamic one like
def myFunc2(self, propertyName): #How would I read the session prop #How would I write to it?
getattr builtin; the following examples will both achieve the same result:
x = self.session.custom.myCustomProp
x = getattr(self.session.custom, "myCustomProp")
The corresponding reverse function would be
setattr(self.session.custom, "myCustomProp", 1)
You really should reconsider passing self or session.self to your script libraries, except maybe to helpers to extract specific blocks of Perspective data or to re-encode (json) results for Perspective’s use.
For any script module function, ask yourself if the core logic would be applicable outside Perspective, other than the mechanics of obtaining the arguments and returning a useful result. If so, make it generic, just in case you need to use in in Vision or maybe in WebDev for some future project. Separate the Perspective-specific code from the rest.
I was planning on making getter/setter functions with using undocumented way to try to do that. But, if I want to do it in a fully documented way, and I need to pass the necessary info, and I shouldn’t pass self, how would you recommend doing it? Won’t we at some point necessarily need a self so that we can get self.session etc?
Yes, pass self.session to your Perspective-specific helpers. Pass that result to your generic business/process logic. In simple cases, just do everything needed with self in the event.
Right - invert your assumptions. If you need to do something with session properties, then only assume you have a session object in your project script:
def doSomething(session): session.custom.something = 123
And then call it with the shortcut to the session object you get from all perspective components:
if self.custom.doSomething: project.library.doSomething(self.session)
Sticking to the
self nomenclature in project scripts is just making things more confusing than they need to be.