System-wide on-screen messages

In response to another user’s request, we are publishing our solution for sending messages to system users. This is running on Ignition 7.5.2, but was ported from a 7.2 system so should work on earlier versions also. You will need to be using database-based user authentication - it looks at the user table for its list of users. I have tried to make this standalone - if anyone has problems running it, please let me know.

Our solution has the following features:

  • Pops up a ‘modal’ dialog displaying the message in front of whatever the user is currently doing
  • Copes with multiple simultaneous messages
  • Allows the user to review any current messages
  • Allows setting of the date when the message is to be displayed
  • Allows setting of the date when the message expires
  • Allows sending of a message to all system users or to a selected subset of users
  • Records when a user has seen the message so they won’t have to view it twice

This system is useful for sending messages to all system users like “The system is going down for maintenance on Friday at 4pm” or for sending a message to a subset of users like “There is a meeting for all members of shift team 1 on Monday at 10am”. It is currently used in a system dealing with manual data entry and display i.e. no real-time control or alarming. As the dialog is modal it may not be as useful in a system where the user is monitoring a live process where it could get in the way. In this case you might want to display the messages in a box at the top or bottom of other screens.

The system consists of 3 windows (included in the attached .proj file): an overview window to allow an administrator to monitor the messages, a window to allow messages to be added or edited and the message window itself. The messages are checked using a Client Timer Script, which runs the following code:app.messages.check.main('Date') This runs the following script which is stored in the Script Module:[code]def main(mode):
Used to display system messages to all users, either at login, at
periodic intervals or when a menu option is selected.

If started with a parameter of 'All', all current system messages
will be displayed.

If started with any other parameter, only the system messages the
user has not already seen will be displayed

import system

username = system.tag.getTagValue("[System]Client/User/Username")
if mode == "All":
	lastMessageDate = "1970-01-01 00:00"
	query = "SELECT lastMessageDate FROM users" \
		" WHERE username='%s'" % username
	lastMessageDate = system.db.runScalarQuery(query)
	lastMessageDate = system.db.dateFormat(lastMessageDate, "yyyy-MM-dd HH:mm")

#Check if there are any new messages since the user last viewed them.
query = "SELECT messages.message, messages.display_date" \
	" FROM messages" \
	" JOIN message_recipients ON messages.id_messages=message_recipients.id_messages"\
	" WHERE '%s' < messages.display_date" \
	" AND messages.display_date <= NOW()" \
	" AND messages.expiry_date > NOW()"\
	" AND (message_recipients.recipient='%s'"\
	" OR message_recipients.recipient='All')"\
	" GROUP BY messages.id_messages"\
	" ORDER BY display_date" % (lastMessageDate, username)
messages = system.db.runQuery(query, system.tag.getTagValue("[Client]database"))
#If any messages exist...
if len(messages)>0:
	#Open the window to view the messages, passing the messages in as a dataset.
	messages = system.dataset.toDataSet(messages)
	system.nav.openWindow("Admin/Messages/View message", {'messages': messages})
#If trying to display all messages but none exist...
elif len(messages)==0 and mode == "All":
	system.gui.messageBox("No current system messages", "")

[/code]This code can also be run from a menu option, which launches it with the following script:app.messages.check.main('All')This displays all the current system messages, whether or not the user has already seen them.

The final piece of the system if the setting up of the database tables. The system expects 2 tables which are created using the following statements (these are for MySQL, but should be straightforward to change for other databases):[code]delimiter $$

CREATE TABLE messages (
id_messages int(11) NOT NULL AUTO_INCREMENT,
display_date datetime DEFAULT NULL,
expiry_date datetime DEFAULT NULL,
message text,
PRIMARY KEY (id_messages)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1 COMMENT=‘Used to hold messages to be displayed to all users’$$[/code]and [code]delimiter $$

CREATE TABLE message_recipients (
id_message_recipients int(11) NOT NULL AUTO_INCREMENT,
id_messages int(11) NOT NULL,
recipient varchar(45) NOT NULL,
PRIMARY KEY (id_message_recipients),
KEY idx_id_messages (id_messages)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1 COMMENT=‘Used to hold who is to receive each system message’$$[/code]In addition to these 2 tables you will also have to add a datetime field to the users table with a name of lastMessageDate.

I’d be interested to know if anyone finds this useful :slight_smile:
System_messages.proj (38.6 KB)

In the light of this post, I’ve updated system messages to highlight selected users when editing using a binding on the list, rather than an invokeLater call when the window opens.

I’ve left the code run on window open in internalFrameActivated rather than putting it into visionWindowOpened so that it still works in Ignition v7.2 - feel free to move this code as required.
System_messages_2.proj (38.6 KB)

Thanks for posting this, VERY useful! :prayer: