Send email notification using pipeline blocks

hello, I'am trying so use pepiline blocks
And I want to know what type of pipeline blocks or functions would you recommend me if I want send an email notification to a specific user depending on the type of alarm activated ?

You have the "perspective" tag on your question but I don't think your question is related to Perspective.

1 Like

hello , yes . thanks for the remark. it was a mistake on my part

Well... If you want to send a notification, use the notification block.
Your question is way to broad to get a specific answer:

  • what do you call "alarm type" ?
  • how is the user chosen ?

But I suggest you read the doc and watch the university videos first, it should answer most of your questions. Then, if you still have some, ask them with details.

1 Like

@pascal.fragnoud merci pascal.

I have just watch the university videos.

I used Notiifcation block. I can sent email notification , I tested it usingpapercut app


the problem is: when alarm is activeted, message is send for all users. it is not what I want.

I have 6 tags (TempTurbine1,TempTurbine2,...). on each tag, I configured an AlarmHVAC alarm.

users are in the database. each user has a status (status = 1,2,3,4,5 or 6)

What I would like is:
for exemple SetPoint of alarm AlarmHVAC configured in tag TempTurbine1 = 60.

If value of TempTurbine1 is above of 60
then send email notification to users whose status = 6

If value of TempTurbine1 is above of 20
then send email notification to users whose status = 2

I watch the university videos but I can't see fonction or pipeline block I can use to solve it. maybe script block but I have no idea about it.

If you provide a roster, the roster will be used as-is (all members). Sounds like you need a calculated roster, not a static roster.

1 Like

thank you for this idea. @pturmel .

I will use calculated roster.

I will get alarm name and setPoint value.

and I will do SQL qery to get all column mail adresse and status of user
And will loop all user to know what status = setPoint value of active alarm . And I will sent notification using mail adresse.

Do the filtering in the query instead, not in the script.

1 Like

This what I did.

def calculateRoster(event, builder):
	#user1 = {"username":"bob", "phone":["5551234567"]}
	#user2 = {"username":"joe", "email":["joe@mycompany.com"]}
	#roster = [user1, user2]
	#return roster

	
	# get the alarm name property
	alarmName = event["name"]
	 
	if alarmName =="AlarmHVAC20": # status 2
		username = system.db.runNamedQuery("getUserStatus") # exemple : #SELECT username FROM wind_users WHERE status = 2 
		pyData = system.dataset.toPyDataSet(username)
		list_user = []

		for row in pyData:
			list_user.append(row["username"]) #put all username on a list
		userSource = 'WindUser'		        		
		for i in range (len(list_user)):
			userName = list_user[i]
			#print username
			data = system.user.getUser(userSource,userName)
			conInfo = data.getContactInfo()
			i = str(conInfo)
			if 'email' in i:
				email = i.split(' ')
				email = email[1] # get email adress
				#print email
				builder.username(userName).email(email).add()
				
	roster = builder.build()	
		    		
	return roster

log :

NotificationBlock	04Dec2023 19:00:39	Unable to parse calculated roster.
NotificationBlock	04Dec2023 19:00:39	Roster '<calculated>' has no users, notification for 1 alarms will go undelivered.
NotificationBlock	04Dec2023 19:00:24	Unable to parse calculated roster.
NotificationBlock	04Dec2023 19:00:24	Roster '<calculated>' has no users, notification for 1 alarms will go undelivered.
NotificationBlock	04Dec2023 18:59:58	Unable to parse calculated roster.

What is worning on my syntaxe ?

On console, I try execute script, I get email adress using script below:

username = system.db.runNamedQuery("getUserStatus") # exemple : #SELECT username FROM wind_users WHERE status = 2 
pyData = system.dataset.toPyDataSet(username)
list_user = []

for row in pyData:
    list_user.append(row["username"])
	           
userSource = 'WindUser'		        		
for i in range (len(list_user)):
	userName = list_user[i]
	#print username
	data = system.user.getUser(userSource,userName)
	conInfo = data.getContactInfo()
	i = str(conInfo)
	if 'email' in i:
		email = i.split(' ')
		email = email[1]
		
		#builder.username(userName).email(email).add()
		print email
		
#userList = builder.build()

Out :

>>> 
andrade@teste.com]
josephine@teste.com]
>>> 

what ? What do your addresses look like ? That shouldn't be necessary... there's something weird here.

pyData = system.dataset.toPyDataSet(username)
	list_user = []

	for row in pyData:
		list_user.append(row["username"]) #put all username on a list

You can replace that with

list_user = username.getColumnAsList(username.getColumnIndex('username'))

and this:

for i in range (len(list_user)):
	userName = list_user[i]

with

for username in list_user:
    ...

I'm not super familiar with the roster builder, I usually just output a list of dicts, so I really don't know what's wrong here.
Make sure the first if statement is actually entered, otherwise there's nothing to fill the roster with...

Try this:

def calculateRoster(event, builder):
	alarmName = event["name"]
	 
	if alarmName =="AlarmHVAC20": # status 2
		users = system.db.runNamedQuery("getUserStatus") # exemple : #SELECT username FROM wind_users WHERE status = 2 
		usernames = users.getColumnAsList(users.getColumnIndex('username'))
		userSource = 'WindUser'

		roster = []
		for username in usernames:
			user = system.user.getUser(userSource, username)
			conInfo = user.getContactInfo()
			info = str(conInfo)
			if 'email' in info:
				roster.append({'username': username, 'email': [info.split(' ')[1]]})
		return roster

Though that weird thing with the email split should really be addressed...
Also, are you handling other alarms in other if statements ?

Non, je ne gere pas d'autres alarms. Pour l'instant je ne gere que l'alarme AlarmHVAC20

Ah merci, c'était un broullon de ma part. merci pour l'optimisation.

Sur la console, j'obtiens les utilisateurs mais sur le block notification, ça m'affiche une erreur sur le log:

NotificationBlock	04Dec2023 19:40:13	Roster '<calculated>' has no users, notification for 1 alarms will go undelivered.

sur la console , j'ai :

\nusername = system.db.runNamedQuery("getUserStatus") # exemple : #SELECT username FROM wind_users WHERE status = 2 \npyData = system.dataset.toPyDataSet(username)\nlist_user = []\n\nfor row in pyData:\n    list_user.append(row["username"])\ndicti = {}           \nuserSource = \'WindUser\'\t\t        \t\t\nfor i in range (len(list_user)):\n\tuserName = list_user[i]\n\t#print username\n\tdata = system.user.getUser(userSource,userName)\n\tconInfo = data.getContactInfo()\n\ti = str(conInfo)\n\tif \'email\' in i:\n\t\temail = i.split(\' \')\n\t\temail = email[1]\n\t\t{"username":"bob", "phone":["5551234567"]}\n\t\t#builder.username(userName).email(email).add()\n\t\tprint email\n\t\t\n#userList = builder.build()\n'
[{'email': ['andrade@teste.com]'], 'username': u'andrade'}, {'email': ['josephine@teste.com]'], 'username': u'josephine'}]

I'am sorry because I'am writting in french.

Regarde bien tes adresses...
J'insiste: il faut revoir la méthode pour obtenir les adresses.

Dans ta console, juste après l'assignation de conInfo, ajoute

print type(conInfo)
print conInfo

Et montre moi ce que ca sort.

users = system.db.runNamedQuery("getUserStatus") # exemple : #SELECT username FROM wind_users WHERE status = 2 
usernames = users.getColumnAsList(users.getColumnIndex('username'))
userSource = 'WindUser'

roster = []
for username in usernames:
	user = system.user.getUser(userSource, username)
	conInfo = user.getContactInfo()
	info = str(conInfo)
	if 'email' in info:
		roster.append({'username': username, 'email': [info.split(' ')[1]]})
		
print type(conInfo)
print conInfo

out:

<type 'java.util.ArrayList'>
[email: josephine@teste.com]

...
if conInfo.contactType == 'email':
    ...

donc pour ton roster:

users = system.db.runNamedQuery("getUserStatus")
usernames = users.getColumnAsList(users.getColumnIndex('username'))
userSource = 'WindUser'

roster = []
for username in usernames:
	user = system.user.getUser(usersource, username)
	if user.contactInfo.contactType == 'email':
		roster.append({'username': username, 'email': [user.contactInfo.value]})

ou

selected_users = system.db.runNamedQuery("getUserStatus")
usernames = selected_users.getColumnAsList(selected_users.getColumnIndex('username'))
users = [system.user.getUser(usersource, username) for username in usernames]

return [
	{
		'username': user.get('username'),
		'email': [info.value for info in user.contactInfo if info.contactType == 'email']
	} for user in users
]

T'as vu le problème ?

no, I haven't found the problem.

I put logger on script et j'ai remarqué que le script ne s'arrete que sur la ligne
logger.info("Hello, world.") le reste ne le compile pas. parce que le logger qui est sur la boucle for n'est pas affiché sur la page web de logs.

def calculateRoster(event, builder):
	alarmName = event["name"]
	logger = system.util.getLogger("myLogger")
 	logger.info("Hello, world.") 
 	
	if alarmName =="AlarmHVAC20": # status 2
		users = system.db.runNamedQuery("getUserStatus")
		usernames = users.getColumnAsList(users.getColumnIndex('username'))
		usersource = 'WindUser'
		
		roster = []
		for username in usernames:
			user = system.user.getUser(usersource, username)
			if user.contactInfo.contactType == 'email':
			
				logger.info(str(user.contactInfo.contactType)) 
				
				roster.append({'username': username, 'email': [user.contactInfo.value]})
				
		return roster

on log have


Logger	Time	Message
NotificationBlock	05Dec2023 13:29:08	Unable to parse calculated roster.
NotificationBlock	05Dec2023 13:29:08	Roster '<calculated>' has no users, notification for 1 alarms will go undelivered.
myLogger	05Dec2023 13:29:08	Hello, world.

regarde bien !

andrade@teste.com]
josephine@teste.com]

Si avec ce script dans la console tu obtiens bien les adresses, le premier truc Ă  faire c'est d'ajouter des logs dans le calculated roster.

Essaye ca:

def calculateRoster(event, builder):
	alarmName = event["name"]
	logger = system.util.getLogger("calculatedRoster")
	logger.info(alarmName)
	if alarmName =="AlarmHVAC20": # status 2
		logger.info("dans la condition")
		users = system.db.runNamedQuery("getUserStatus")
		usernames = users.getColumnAsList(users.getColumnIndex('username'))
		userSource = 'WindUser'

		roster = []
		for username in usernames:
			user = system.user.getUser(userSource, username)
			conInfo = user.getContactInfo()
			info = str(conInfo)
			if 'email' in info:
				roster.append({'username': username, 'email': [info.split(' ')[1]]})
		return roster

et vérifie dans les logs que tu entres bien dans la condition.

NotificationBlock	05Dec2023 14:23:02	Unable to parse calculated roster.
NotificationBlock	05Dec2023 14:23:02	Roster '<calculated>' has no users, notification for 1 alarms will go undelivered.
calculatedRoster	05Dec2023 14:23:02	dans la condition
calculatedRoster	05Dec2023 14:23:02	AlarmHVAC20
Pipeline	05Dec2023 14:22:53	[name=pepilineWind,version=1701782573070] Alarm pipeline started.

T'as plus qu'à logger le reste, étape par étape, pour voir où tu as pas ce que tu devrais avoir.

Ceci dit je viens de m'apercevoir d'une erreur dans le script:

if user.contactInfo.contactType == 'email':

contactInfo est une liste, on peut pas check son type directement, il faut vérifier le type de chacun de ses élements:

roster = []
for username in usernames:
	user = system.user.getUser(usersource, username)
	addr = [ci.value for ci in user.contactInfo if ci.contactType == 'email']
	if addr:
		roster.append({'username': username, 'email': addr})
1 Like