No perspective session attached to this thread" error for system.perspective functions

Hi!

I’ve been trying to use system.perspective.sendMessage in a gateway timer script but I keep getting the “No perspective session attached to this thread.” error. For a test, I made a tag change script with only:

sessionInfo = system.perspective.getSessionInfo()
system.perspective.print(sessionInfo)

in the script and received the same error.

However, this works:

sessionInfo = system.perspective.getSessionInfo()
print sessionInfo

Am I not allowed to use certain system.perspective functions in gateway scripts? What am I missing?

Thank you!

To which console are you trying to print session information?

system.perspective.print will try to print the given message to the browser console (if the target page belongs to a client session) or the designer console (if the target page belongs to a designer session), but in order to do this, it needs to know which page’s console to target. If you do not provide the target session and page, Perspective will default to the session and page in the context of the script which calls system.perspective.print, but since Gateway timer scripts do not run in the context of a Perspective Session, it does not know where to print the message, and will throw an error.

If you want to print session information to the Gateway’s output console, then using the print command will work. You could also target a Gateway logger using system.util.getLogger

2 Likes

I was calling perspective.print with a tag change script to test any system.perspective function within a gateway script.

What I really need is to run the system.perspective.sendMessage function from a gateway timer script. This is the full code which does work when run from a button press but not from the gateway timer script:

# state of alarms we care about
state = ["ActiveUnacked", "ActiveAcked", "ClearUnacked"]

numAlarmsShelved = 0
sources = []

# get alarms objects
alarms = system.alarm.queryStatus(state = state)
alarmsShelved = system.alarm.queryStatus(includeShelved=True)
 
# get number of active alarms
numAlarms = len(alarms)

# extract from the alarm object the number of
#    shelved alarms with *unique* sources
for i in alarmsShelved:
	if not (i.getSource() in sources):
		if i.isShelved():
			sources.append(i.getSource())
			numAlarmsShelved += 1

# cast to string
numAlarms = str(numAlarms)
numShelved = str(numAlarmsShelved)

# construct message to be sent to alarms label in the upper navigation dock
messageType = 'alarmAlert'
payload = {'alarms': numAlarms, 'shelved': numShelved}
scope = 'session'

# send message
system.perspective.sendMessage(messageType, payload, scope)

This always throws the “no perspective session attached to this thread” error. Should we be able to use sendMessage() from a timer script?

As Joel alluded to, calling (most) system.perspective scripting functions requires contextual information about which session the action should be applied to - because unlike Vision, where clients are each an independent Java Virtual Machine, Perspective sessions all execute on the gateway, and share script execution threads. When calling scripts directly from Perspective, we do some automatic bookkeeping for you, so that the functions ‘know’ the context of where they’re being called.

But when you’re in the context of a gateway timer script, or tag change script, or anything else that’s running on the gateway, you’re totally separate from Perspective. When you call system.perspective.sendMessage from a timer script - how would it “know” what session to send the message to? So you have to specify a session ID, which is what the error message is indicating. You can do that, now, using system.perspective.getSessionInfo(). If you want to send a message to all sessions, then you would iterate through the object you get from getSessionInfo(), and call system.perspective.sendMessage, specifying a sessionId in each call:
system.perspective.sendMessage(messageType, payload, scope, sessionId=session)

7 Likes

Thanks for the clarification! I added:

sessionInfo = system.perspective.getSessionInfo()

for session in sessionInfo:
	thisSessionID = session["id"]
	# send message
	system.perspective.sendMessage(messageType, payload, scope, sessionId = thisSessionID)

Unfortunately now I’m getting and error that reads: “Invalid UUID string:” and then the session id. I also tried using parentSessionId instead which gives me “Perspective session “1c62b5a0-acb0-45a…” not found”.

Am I iterating through the getSessionInfo object incorrectly?

Cancel that, I came back from lunch and now it works. I’ll go with it. Thank you so much for your help!

1 Like

I had the same problem as OP. Got that fixed up with sessionid as suggested. I am getting the UUID too large.

system.perspective.sendMessage(“pumpUnlock”, payload = {}, scope = “session”, sessionID = sessionInfo)

Perhaps I need to pass the pageId parameter as well as mentioned in the system.perspective.sendMessage documentation? I tried that, but not sure if I am getting it right, I assume it;'s the name of the page as lasted in the Perspective Page Configuration?

I’m going to bed, I’m hoping it just starts working tomorrow like OP.

Thanks

It's not going to.

You need to look at what you're passing as sessionInfo. If you're using the code supplied in a previous thread, then you're passing a list of current sessions and all their available information. You need to supply the id of a singular session from that list. How you make that determination is up to you.

Indeed it did not lol. Thanks for the tip. I realized there was not any Perspective context within it anyway, so moved it into the project library. Thanks!

In the project script you trigger a project wide message:
system.util.sendMessage("myProject", "GWMSG",{'stuff':'things'},'S')

Then in the session events create a handler for this message.
The name needs to match the message above ie GWMSG.
In this message handler you send a new message at the session level. Make sure to add the scope argument = session.
system.perspective.sendMessage("SMSG",payload,'session')

Then on the page you can add a message handler script with the message type matching the session message name ie SMSG

You do not necessarily need to iterate over the sessions manually as long as you set the scope to session.

The error with the UUID is because the session iterator also includes designer sessions, if you manually iterate you would need to add a line to check the if(session['userAgent']!='designer')

Hope this help clear it up for anyone still struggling.