messageHandlers in Perspective

I have a general question in regards to message handlers in ignition.

I want to open a popup with a messagehandler, through either a gateway event script or a tag change script.

I know that i define the popup id through system.perspective.openPopup like so:

system.perspective.openPopup(
		id="dataReceivedPopup",
		view="Views/DataRecieved",
		params={},
		modal=True,
		showCloseIcon=True
	    )
		logger.info("Popup 'dataRecievedPopup' opened successfully.")

so if i want to call this message handler, how do i refer to its id directly?
i know there's a parameter called messageType but it doesn't seem to be what i need.

Note that this is not a message handler via a Component, but rather a message that should be invoked after a Boolean Tag is set to True, as a result of a doPost method in WebDev.

For invoking the message handler, I looked into using a Tag Change(value changed) script (for the boolean tag) :

def valueChanged(tag, tagPath, previousValue, currentValue, initialChange, missedEvents):
		
	logger = system.util.getLogger("DataArrivalTagChange")
	logger.info("DataArrival tag changed to: {}".format(currentValue))
	
	if currentValue.value and not initialChange:
	
		
		system.perspective.sendMessage(
		    messageType="openDataReceivedPopup",
		    payload={},  #  pass necessary data here if needed
		    scope="session"
		)

but it seems to only be for gateway scope and not the perspective session, which is what i need.

i could perhaps create a property change script and bind the property to the boolean tag?

Any good ideas on how to solve this?

The dataflow would be something like:
Data -> doPost -> Save data to tag and set DataArrival tag to True ->
Invoke message handler to open popup -> "data recieved view"

So you want to open the popup on every session open?

No, the idea is that the popup opens when new data from a device is recieved through http, displaying a popup "new data recieved" with buttons to view data etc.

Yes, but should the popup open on all open perspective clients (aka sessions)?

No, it should only open for certain sessions

i set up a session property "clientIdentifier" for this.

if clientIdentifier == "ClientA":
		    system.tag.writeBlocking([dataArrival], [True])
		    
		    system.tag.writeBlocking([timeStamp], [timestamp])
		else:
			system.tag.writeBlocking([dataArrival], [False])

Here's the complete doPost method:

def doPost(request, session):
	logger = system.util.getLogger("GetData_SaveToTag_Project")
	logger.info("jsonPostSimatic start")
	
	tagPath = "[default]RFID_UID"
	timeStamp = "[default]DataArrivalTimestamp"
	dataArrival = "[default]DataArrival"
	
	logger.info("BEFORE DATA: tagPath: {}, timeStamp: {}, dataArrival: {}".format(tagPath, timeStamp, dataArrival))
	
	# jsonPayload = '{"UID": "E004015062F0D272", "MAC": "78:C4:0E:A0:7E:26", "Timestamp": "2024-08-15T10:00:00.000+02:00"}'
	
	try:
		# Extract raw data from the POST request
		raw_data = request.get('postData')
		
		# Log the type and content of raw_data
		logger.info("Type of postData: {}".format(type(raw_data)))
		logger.info("Raw POST Data: {}".format(raw_data))
		
		# Check if raw_data is already a dictionary
		if isinstance(raw_data, dict):
		    data = raw_data
		else:
		    # Attempt to decode JSON if it's not a dictionary
		    if isinstance(raw_data, bytes):
		        raw_data = raw_data.decode('utf-8')
		    data = system.util.jsonDecode(raw_data)
		
		# Log the data received
		logger.info("DATA: {}".format(data))
		
		# Extract UID, client and timestamp
		uid = data.get("UID", "Ingen UID funnet..")
		clientIdentifier = data.get('clientIdentifier', 'UnknownClient')
		timestamp = data.get('Timestamp', system.date.now()) # bruker timestamp fra JSON eller now() hvis ikke angitt)
		
		logger.info("UID: {}".format(uid))
		logger.info("clientIdentifier: {}, timestamp: {}".format(clientIdentifier, timestamp))
		
		# Write UID to tag
		system.tag.writeBlocking([tagPath], [uid])
		
		# client check
		if clientIdentifier == "ClientA":
		    system.tag.writeBlocking([dataArrival], [True])
		    system.tag.writeBlocking([timeStamp], [timestamp])
		else:
			system.tag.writeBlocking([dataArrival], [False])
		
		return {'html': "<html><body>Data recieved - tags updated.</body></html>"}
	
	except Exception as e:
		system.tag.writeBlocking([dataArrival], [False])
		return {'html': "<html><body>Error trying request: {}</body></html>".format(str(e))}

This method successfully updates tags:
DataArrival (True)
DataArrivalTimestamp(Datetime)
RFID_UID(the uid from the request)

i made a custom property on the main view, bound to the boolean tag, with a change script that should open the popup:

def valueChanged(self, previousValue, currentValue, origin, missedEvents):
    if currentValue:  # When the value is True
        system.perspective.openPopup(
            id="dataReceivedPopup",
            view="Views/DataRecieved",
            params={},  # Pass any required parameters here
            modal=True,
            showCloseIcon=True,
			position={"left": 100, "top": 100},
			size={"width": 400, "height": 300}  # Adjust size as needed
        )

the tags update - the popup opens, but it displays nothing

image

1 Like

Looks to me like the view you're trying to load doesn't exist.

Double check the name of the view, it looks like there's an error:

2 Likes

DataRecieved :x:
DataReceived :white_check_mark:

2 Likes

Thanks for noticing.

Although, that typo was consistent in both my code and view name. It's been corrected now, but it seems like the problem is something else.

The request is coming through, but the error happens on the Change Script for my custom property dataArrival

image

logs seem fine

until i hit the change script:

Hi,

Just a shot in the dark, the "currentValue" parameter of a valueChanged property script is a QualifiedValue.

You might want to use
if currentValue.value

This might not solve your issue, but worth trying anyways.

1 Like