How To Implement Dynamically Changing Custom Notification Roster In Ignition

Hi Everyone,

Just wanted to share how we have implemented a fully dynamic custom Roster for alarming in Ignition. We notice this question came up few times on how to implement.

Before we get started on the tutorial/our implementation, I’ll give a little background on what we use our Ignition for. I work for business that manages a large watershed with about 130 remote gauge stations and about 8 dams spread out over 6,800 square kilometer area. As you can imagine we have a lot of tags that have alarms defined, our need was to find a way to route the alarm notifications to specific individuals/groups. This routing is based on the type of alarm, their severity, as well as considering who is on call or onsite at specific times through the week. The individuals that need to receive these alarms are constantly changing and moving around to new areas according to their work schedule and is not feasible to keep manually updating the notification rosters through the gateway web console. Our solution takes this into account and below is our tutorial.

Step 1 – Setting up Static On-Call Rosters (Used to Contain Group Of People or only Single Specific User)
The first thing that needs to be done on the Ignition gateway web-port are rosters setup for each users (we look through all of the rosters in step 3 to find the proper individual contact info). Basically, at our business we use the employees first & last name as the static roster name, and under these rosters the specific user account is added that contains the contact information such as Phone, SMS, Email. This same method also works for groups/departments with multiple users assigned.

Step 2 – Ignition String Memory Tags For Combining Specific Individuals/Group Rosters (Comma Separated String)
In this step we create the variables/tag that contains the roster(s) name that need to be contacted for a specific alarm. This info will be passed in with the defined alarm to the alarming pipeline to figure the peoples contact info. This variable/tag has values that are comma separated roster names we defined in step 1. This variable can also be an expression as long as it creates a string that’s comma separated and contains the roster names from step 1. We have a process at our business for example where the Dam Operators submit a report that contains the info of who is on call during the week at that specific location where the report is being submitted from, we use that info to drive these tags in Step 2. This allows our employees to move around the watershed without requiring IT or Ignition administrators to change the rosters manually (or relying on employees to manage their own rosters).
E.g. Ignition Memory Tag Name: “RiverWatch_Section_A” contains value= Person_A,Person_B,Engineering

Step 3 – Looking Up Contact Info To Build The Custom Roster Inside The Notification Block (Alarming Pipeline Code Snippets)
In this step assuming you have the rosters properly defined, and your mechanism is in place that will update employee names/Roster names that you want to notify for specific alarms automatically. Then all that is left is setting up the notification blocks to lookup the contact info and execute the messages. There are 3 code snippets at the end/below, the Only difference between them is the contact info that it extracted from the rosters in step 1 to build the unique dynamic roster (we generate separate notifications for Phone, SMS, Email at our business and priority controls what type of notification is triggered/sent out).
When the notification block is added to the pipeline, the roster type located under “Contacts” tab needs to be changed to “Calculated”. Then one of the following snippets needs to be pasted into the Scripts window of the notification block based on the method of notification (SMS, Email, Phone). One thing that needs to be changed though based on your specific implementation/ignition setup is the “user source name” that contains your employees/users. The “source name” that you need to specify is located on the gateway web console under Config->Security->Users, Roles (This can be local user source, AD, or AD/Internal Hybrid), usually the same source as what the ignition client also uses.
Note: When defining the actual alarm that enters the pipeline, the custom passed in variable that the notification block is looking for/expecting is called “CustomRoster” which is then linked to the proper string variable in Step 2.

Summary: If you have all 3 steps setup you are pretty much all done and the system will automatically look up the contact info based on your dynamically changing string variable in “Step 2” and notify the proper individual(s) without having to go back and manually keep changing the Rosters or the Alarming Pipeline.

Note: Our method/Implementation of a dynamically changing custom roster has worked in version 7.9 and still continued working in update 8.1.19-rc1.

Thanks,
Erik R.

Code Snippet 1 – Used For SMS

#Receive Roster List From Custom Variable & Split
    CustomAlarmVar = event.get('CustomRoster')
    CustomAlarmVar = CustomAlarmVar.replace("null","--------")
    SplitRosterIn=CustomAlarmVar.split(",")
    
    #Loop Through Roster Split List
    for SpecificRoster in SplitRosterIn:
        rosterUser = system.alarm.getRosters()[SpecificRoster]
        userDirectory={}
        emailEntry={}
        email=[]
        
        if rosterUser<>"--------":
            #Lookup User From Hybridy-AD Ignition User & Get Contact Info
            for name in rosterUser:
                user= system.user.getUser((# “User Source Name” #),name)
                userDirectory[user]=user.getContactInfo()
                
            #Process Contact Info From Each User & Build The Roster List For the Alarm
            for user in userDirectory:
                for contact in userDirectory[user]:
                    daName= user.get(user.Username)
                    if contact.contactType== 'sms': (# Use To Filter Contact TO SMS #)
                        #Add User Info To Roster List
                        builder.username(daName).sms(contact.value).add()
    
    
    #Assemble Roster List        
    roster=builder.build()
    
    #Return Built Dynamic Roster To The Notification Block
    return roster

Code Snippet 2 – Used For Email

 #Receive Roster List From Custom Variable & Split
    CustomAlarmVar = event.get('CustomRoster')
    CustomAlarmVar = CustomAlarmVar.replace("null","--------")
    SplitRosterIn=CustomAlarmVar.split(",")
    
    
    #Loop Through Roster Split List
    for SpecificRoster in SplitRosterIn:
        rosterUser = system.alarm.getRosters()[SpecificRoster]
        userDirectory={}
        emailEntry={}
        email=[]
        
        if rosterUser<>"--------":
            #Lookup User From Hybrid Ignition User & Get Contact Info
            for name in rosterUser:
                user= system.user.getUser((# “User Source Name” #),name)
                userDirectory[user]=user.getContactInfo()
            
            #Process Contact Info From Each User & Build The Roster List For the Alarm
            for user in userDirectory:
                for contact in userDirectory[user]:
                    daName= user.get(user.Username)
                    if contact.contactType== 'email': (# Use To Filter Contact TO Email #)
                        
                        builder.username(daName).email(contact.value).add()
        
    #Assemble Roster List        
    roster=builder.build()
    return roster
**Code Snippet 3 – Used For Phone/Voice Calls**
 #Receive Roster List From Custom Variable & Split
    CustomAlarmVar = event.get('CustomRoster')
    CustomAlarmVar = CustomAlarmVar.replace("null","--------")
    SplitRosterIn=CustomAlarmVar.split(",")
    
    #Loop Through Roster Split List
    for SpecificRoster in SplitRosterIn:
        rosterUser = system.alarm.getRosters()[SpecificRoster]
        userDirectory={}
        emailEntry={}
        email=[]
        
        if rosterUser<>"--------":
            #Lookup User From Hybridy Ignition User & Get Contact Info
            for name in rosterUser:
                user= system.user.getUser((# “User Source Name” #),name)
                userDirectory[user]=user.getContactInfo()
                
            #Process Contact Info From Each User & Build The Roster List For the Alarm
            for user in userDirectory:
                for contact in userDirectory[user]:
                    daName= user.get(user.Username)
                    if contact.contactType== 'phone': (# Use To Filter Contact TO Phone #)
                        builder.username(daName).phone(contact.value).add()
    
    
    #Assemble Roster List        
    roster=builder.build()
    
    #Return To The Block
    return roster
1 Like

Nice of you to share that valuable information.

In my case, I enabled User and Schedule management using these resources:
Perspective Schedule Management
Perspective User Management