Get Perspective Session Page Info from PageIds

Hello,

I'd like to drill down into the page details, in a gateway script scope, for the perspective sessions returned from system.perspective.getSessionInfo similar to the "Details" returned when you click on the following button in the Status -> Connections -> Perspective Sessions gateway web-page
image
Specifically, I need to be able to parse the list of View Instances that are shown in the details page when you click on the above pictured button to tell if a certain view is open in each session.

I've looked at this thread under module development, but I need to get at the same info in a gateway script without building a module, and the com.inductiveautomation.perspective.gateway.session module fails to import for me in a gateway scope (8.1.22) with

com.inductiveautomation.ignition.common.GenericTransferrableException: ImportError: No module named perspective

What am I missing, or is there an easier way to drill down to this info in a python script?

Looks like I am essentially asking the same question as this thread. @nminchin did you ever find a solution on this? I haven't figured out how to get the PerspectiveSessionMonitor object in a gateway script, either in a timer script or gateway message handler...

You won't be able to do this easily, because the gateway has per-module classloaders and scripts aren't loaded in those classloaders. You could potentially do it from a GatewayContext -> ModuleManager -> findClass -> hope there's a static accessor on the class.

Do you mean this as a possible path for accessing the com.inductiveautomation.perspective namespace?

I looked at the SDK for getModuleManager and the gateway context and don't see any methods like "findClass"...

Basically, you use the gateway context's module manager to "get" the module, which will give you the module's hook class instance. You then use that instance's class to get its classloader, then ask that classloader to lookup the class you are after (by canonical string name). Assign that to a variable in your script as if it was an import and carry on.

2 Likes

resolveClass, not findClass. But yeah, what Phil said:
https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.15/com/inductiveautomation/ignition/gateway/model/ModuleManager.html#resolveClass(java.lang.String)

1 Like

Yep, was just about to reply that context.getModuleManager().resolveClass('com.inductiveautomation.perspective.gateway.session.PerspectiveSessionMonitor') appears to do what I need, or at least gets me closer to what the gateway status page is doing...

EDIT: See reply below, this method of resolving the class results in an unusable (null) instance of PerspectiveSessionMonitor

Haven't gotten all the way down to the info I need, but I did manage to drill down to the actual PerspectiveSessionMonitor instance that matches what is running on the gateway by using the module manager resolveClass method to get the PerspectiveContext class interface, and then instantiate that with the gateway context to get the actual perspective context. From here it is a simple matter of calling the getSessionMonitor method to get the "live" session data.

from com.inductiveautomation.ignition.gateway import IgnitionGateway

context = IgnitionGateway.get()
mod_mgr = context.getModuleManager()
# the below uses the gateway context module manager to function essentially as an import statement
persp_ctx_class = mod_mgr.resolveClass('com.inductiveautomation.perspective.gateway.api.PerspectiveContext')
# instantiate the PerspectiveContext using the gateway context
persp_ctx = persp_ctx_class.get(context)
# get the PerspectiveSessionMonitor object running in gateway context
psm = persp_ctx.getSessionMonitor()
all_sessions_info = psm.getSessionInfos()

I was close with the resolveClass('com.inductiveautomation.perspective.gateway.session.PerspectiveSessionMonitor') but ultimately that route gives you an empty session monitor that is out of the gateway context.

3 Likes

Just for completeness/posterity, here is a sample of full code that does what I set out to do, ie browse active sessions for a given project, determine if a given view is open on those sessions, and then grab the session id and a couple of session custom props from those sessions and build it out into a map to write to a JSON tag.

Session Monitor Browse Code
from com.inductiveautomation.ignition.gateway import IgnitionGateway
import json

project_name = sytem.util.getProjectName()
target_view_path = 'path/to/desired/view'

context = IgnitionGateway.get()
mod_mgr = context.getModuleManager()
# need to get "com.inductiveautomation.perspective.common.api.PropertyType" from module manager to
# get the "props" and "custom" enums for fetching the session props and the custom props
prop_type_class = mod_mgr.resolveClass('com.inductiveautomation.perspective.common.api.PropertyType')
props_enum = prop_type_class.valueOf('props')
custom_enum = prop_type_class.valueOf('custom')
# the below uses the gateway context module manager to function essentially as an import statement
persp_ctx_class = mod_mgr.resolveClass('com.inductiveautomation.perspective.gateway.api.PerspectiveContext')
# instantiate the PerspectiveContext using the gateway context
persp_ctx = persp_ctx_class.get(context)
# get the PerspectiveSessionMonitor object running in gateway context
psm = persp_ctx.getSessionMonitor()
# grab <InternalSession> object list for the target project
int_sessions = psm.getClientSessionsForProject(project_name)
active_sessions = {}
# loop over internal sessions to build a map of active sessions with the target view open
for i, sess in enumerate(int_sessions):
	# loop over the open pages for each session and get the id for each
	for page in sess.getPages():
		# this returns the page id that matches the gateway Status -> Connections -> Perspective Sessions -> Session detail page
		page_id = page.getId()
		views = page.getViews()
		# iterate over the views to see if any of the ids match the target view path
		view_id, view = next(((str(view.getId()), view) for view in views if target_view_path in str(view.getId())), (None, None))
		if view_id and view:
			# if view_id is found, that means this session has the target view open
			# grab the session object from the view, we will use this to grab the session id, and custom props
			session = view.getSession()
			# grab session props and custom props using "getPropertyTreeOf" method of SessionScriptWrapper.SafetyWrapper
			session_props = session.getPropertyTreeOf(props_enum)
			session_custom = session.getPropertyTreeOf(custom_enum)
			session_id = session_props.get('id')
			prop1 = session_custom.get('custom_prop_1_name', None)
			prop2 = session_custom.get('custom_prop_2_name', None)
			# build object to store for the active session
			active_sessions[session_id] = {
				'custom_prop_1_name': prop1, 
				'custom_prop_2_name': prop2
			}
# convert the active sessions object to json and write to string memory tag
active_sessions = json.dumps(active_sessions)
system.tag.writeBlocking(['[default]path/to/active_sessions_tag'], [active_sessions])

Thanks to @pturmel and @PGriffith for getting me off the ground/out of the ditch on this. You guys rock!

4 Likes

Hello guys! This post is really interesting to me but I cannot execute it. My question is where you execute this code? I try to execut it in the Gateway events and script conssole but always I have and error when I try to import the IgnitionGateway.

Thanks for your answer!