Sending Messages Between Pages in Perspective

Is there anyway to send a message to a message handler on another page in ignition perspective? I currently have a button that runs this:

messageType = “assetParameterHandler”
system.perspective.sendMessage(messageType)
system.perspective.navigates("/Utilities/Test_Asset")

On the page “/Utilities/Test_Asset”, I have a message handler called “assetParameterHandler” on a label. All it does is set the label text to “Hello World”. I have tried changing setting the listener scope to “Session” and have also enabled all three scopes in case something else is happening without any results. No error messages in the log.

Can the message handlers even send payloads between pages?
Thanks,
G

1 Like

So a couple things here.

When you want to send a message across a different scope, you have to set the listener to the scope and then you also need to specify the scope in the script: https://docs.inductiveautomation.com/display/DOC81/system.perspective.sendMessage. See specifically the part about the scope.

Although you can change the scope, if the page isn’t open I’m not sure that the listener is active.

Your best bet will be to put the params on the the view that you are calling and use system.perspective.navigate to pass those params down to the view rather than using a message.

Hint: it's not.
If you call someone and they haven't been born yet, then they won't receive your call.

As @bschroeder said, there are a couple of things going on here that don't mesh. You are sending a message:

messageType = “assetParameterHandler”
system.perspective.sendMessage(messageType)

but then you are navigating to a page:

# 'navigate', not 'navigates'
system.perspective.navigate("/Utilities/Test_Asset")  

If you don't expect the page to be open yet, then you should modify the navigation call to supply parameters, as bschroeder suggested. This requires that you supply params at the view level:

it also requires that you supply a parameterized url as part of the Page Configuration:

And it requires that you then pass those params as part of the Page "path"

system.perspective.navigate("/parameterizedView/2/SomethingElse")  

If you expect this other page to be open in a different tab, then you can send a message at the "session" scope, which means that any Page/View open in this session will "hear" the message. Assuming an appropriate listener is set up, your other page should hear the message in the configured listener. If you don't want to broadcast at the session level for some reason, you could also specify a "page" scope, but then you would need to obtain the pageId of the page you want to send the message to by using system.perspective.getSessionInfo() and filtering through the available sessions to find the session invoking the call, and then locating the appropriate page from all of the pages listed for that session.

4 Likes

@cmallonee

Much better with the words and such.

Thanks for the writeup @cmallonee. I’m still trying to get my sea legs with regards to perspective.

I was just looking for a way to send a parameter to a page without having to enter it into the URL. I’ve used page parameters before but they’ve been one or two word text strings. I would then use the parameters to build a tag paths inside my template view and map data accordingly. What I was hoping to do now was send a whole data structure that contained configuration data for a set of views on a carousel on a template view without garbling up the URL.

I know that views can be navigated to with parameters and they won’t appear in the URL but I don’t want to trip up the user if they press the back button.

I’ll try to find another way to get where I need to go.
Thanks again,
G

Thanks @bschroeder. I’m probably going to have to go the page parameter route. I was mostly looking for a way to send a parameter to a page without it having to appear in the URL. I’ll keep chipping away at it and see where I end up.

Thanks again,
G

You could put the data into a session parameter and go that route as well.

1 Like

Based on the criteria @gjack1978 is trying to meet, this sounds like the best option in this scenario. Considerations will need to be made, however, for the instances where a user navigates to that page without having previously set those values. I would avoid using params if this route is taken (you can't bind input params to other values), and just bind to the session properties.

here you are sending a hard coded as a param. Is it possible to send as a variable that contains some data?

Yes

system.perspective.navigate("/parameterizedView/{}/{}".format(var1, var2)) 
2 Likes

In 8.1.13 you can also pass URL-encoded query parameters:
https://docs.inductiveautomation.com/display/DOC81/Pages+in+Perspective#PagesinPerspective-PassingParameters(URLParameters)

1 Like
1 Like

And how does one filter through active sessions? Say there are 3 sessions active, how to catch the session which is invoking the message handler call + how to catch the pageName? Is there any example of this?

There is no way to glean that information unless it is supplied as part of the payload from the originating source.

payload = {}
payload["sessionId"] = self.session.props.id
payload["pagePath"] = self.page.props.path
# add any other content to the payload here
system.perspective.sendMessage("MESSAGEHANDLERNAME", payload=payload, scope="session")
3 Likes

I was trying to do the same. So, now I'm looking for a way to get the pageID of the unborn page.

I think that I can locate the new page by using this code:

Then if page_id == self.page.props.pageId: should do the trick. But, If that's true, why not use self.page.props.pageId directly?

Edit #1:
I tested using a delay but now I know that it's using the old pageID.

from threading import Timer
	
	page = "/newtestpage"
	system.perspective.navigate(page)
	
	
	def runThisLater(param):
		payload = {"test": True}
		scope = "page"
		message = "newStatus"
		system.perspective.sendMessage(message, payload , scope)
	 
	# Call invokeLater with a 3000ms delay. Note that our function will not run immediately
	# because invokeLater always executes once the rest of this script is complete.
	Timer(1.0, runThisLater, ["Stop Waiting, I'm done"]).start()

If it's "unborn" then you won't be able to locate it. Let's assume it has been created/born, and so you have two pages, A and B. I'm also going to assume your script is on page A, and that B is the new page.

Invoking the mentioned code on Page A and comparing the iterated pageId to self.page.props.pageId will close page A - not B. You need the negation (!=) to target other pages - in this case page B.

Why don't you explain exactly what it is you're trying to do and maybe I can make things more clear.

For a project that is already in place, send a message to a new page B that opens in the same tab as page A. The purpose was to just add that send.message without changing anything else. But I see is not as easy as we thought it would be. Not even with the new thread and delay.

It depends on how you're opening the new page. If the page supports params, just send params. If you must wait, then maybe you should look at session properties.

1 Like