Import bit alarm tags from .csv to Ignition byte tags

To all scripting gurus out there…:wink:

I have a simple .csv file with some alarm texts for some bits in PLC (this is only a test file):

M610.0;COMMUNICATION ERROR OF SINAMICS FOR LIFT 3266
M610.1;ERROR OF SINAMICS FOR LIFT 3266
M610.2;ALARM OF SINAMICS FOR LIFT 3266
M610.3;WRONG MODE OF SINAMICS FOR LIFT 3266
M610.4;SINAMICS FOR LIFT 3266 NOT READY FOR OPERATION
M610.5;WRONG POSITION OF LIFT 3266 (ABSOLUTE MEASURING SYSTEM)
M610.6;LIMIT SWITCH OF LIFT 3266 BELOW ACTIVE
M610.7;LIMIT SWITCH OF LIFT 3266 ABOVE ACTIVE
M611.0;LIFT 3266 NOT ON GROUND FLOOR
M611.1;LIFT 3266 NOT ON SECOND FLOOR
M611.2;LIFT 3266 NOT IN POSITION
M612.0;COMMUNICATION ERROR OF SINAMICS FOR LIFT 3272
M612.1;ERROR OF SINAMICS FOR LIFT 3272
M612.2;ALARM OF SINAMICS FOR LIFT 3272
M612.3;WRONG MODE OF SINAMICS FOR LIFT 3272
M612.4;SINAMICS FOR LIFT 3272 NOT READY FOR OPERATION
M612.5;WRONG POSITION OF LIFT 3272 (ABSOLUTE MEASURING SYSTEM)
M612.6;LIMIT SWITCH OF LIFT 3272 BELOW ACTIVE
M612.7;LIMIT SWITCH OF LIFT 3272 ABOVE ACTIVE
M613.0;LIFT 3272 NOT ON GROUND FLOOR
M613.1;LIFT 3272 NOT ON SECOND FLOOR
M613.2;LIFT 3272 NOT IN POSITION
M614.0;FORKLIFT AT CONVEYOR 3205
M614.1;FORKLIFT AT CONVEYOR 3214
M614.2;FORKLIFT AT CONVEYOR 3215
M614.3;FORKLIFT AT CONVEYOR 3224
M614.4;FORKLIFT AT CONVEYOR 3225
M614.5;FORKLIFT AT CONVEYOR 3234
M614.6;FORKLIFT AT CONVEYOR 3235
M614.7;FORKLIFT AT CONVEYOR 3275
M615.0;FORKLIFT AT CONVEYOR 3284
M616.0;FIFO STORAGE FULL
M616.1;FIRE-ALARM IN WAREHOUSE
M616.2;COMMUNICATION WITH MFCS AND SRM SWITCHED OFF
M616.3;COMMUNICATION ERROR OF SAFETY CONTROLLER FLEXI SOFT
M617.0;WRONG DESTINATION PLACE NUMBER - PALLET ON TRANSFER CAR 3000
M617.1;WRONG DESTINATION PLACE NUMBER - PALLET ON TRANSFER CAR 3100
M618.0;FUSES OF TRANSFER CAR 3000 SWITCHED OFF
M618.1;FUSES OF TRANSFER CAR 3100 SWITCHED OFF
M618.2;FUSES OF LIFT 3266 SWITCHED OFF
M618.3;FUSES OF LIFT 3272 SWITCHED OFF
M620.0;EMERGENCY STOP BUTTON ON MAIN CABINET ACTIVE
M620.5;EMERGENCY STOP BUTTON AT CONVEYOR 3275 ACTIVE
M620.7;EMERGENCY STOP BUTTON AT CONVEYOR 3284 ACTIVE

I have a script which I run in script console to import this .csv file and create alarm tags.

#in Execel save as .csv (ANSI)
#in Notepad++ convert to UTF-8

import xml.etree.ElementTree as ET
import locale

decimalPoint=locale.localeconv()['decimal_point']
thousandsSep=locale.localeconv()['thousands_sep']

#print decimalPoint
#print thousandsSep

OPCServer='Ignition OPC-UA Server'
deviceName='[testrampe]'	#what name you have in Ignition/Config/Devices website
alarmFolderName=u"testrampe/Alarms"	#In which folder in Tag Browser in the designer you want to put your alarms
scanClass='Default'	#which scanclass should your alarms tags run under
pathIn=system.file.openFile('csv')	#choose your .csv file
priority=2	#priority of the alarm:0-Diagnostic, 1-Low, 2-Medium, 3-High, 4-Critical

if pathIn != None:
    txt = system.gui.inputBox("OPC Server:", OPCServer)	#show/input OPCServer
    if txt != None:
        OPCServer=txt   
    txt = system.gui.inputBox("Device Name:", deviceName)	#show/input deviceName
    if txt != None:
        deviceName=txt   
    txt = system.gui.inputBox("Alarm Folder Name:", alarmFolderName)	#show/input alarmFolderName
    if txt != None:
        alarmFolderName=txt   
    fileIn=open(pathIn)	#open .csv file
    xx = 0
    
    for line in fileIn:	#read line by line
    	xx += 1 #for numbering the alarms, so that they are sequenced
    	bitname=line[line.find(';')-line.find(';'):line.find(';')].strip().replace(' ','') #for adding at the end of alarm text
    	#print "bitname= ", bitname
        bit=line[line.find(';')-line.find(';'):line.find(';')].strip().replace('M','MX') #in Ignition M is MX; for adding in OPCItemPath
        #print "bit: ", bit
        tagname=line[line.find(';')-line.find(';'):line.find(';')].strip().replace('.','_')	#name of the tag visible in Tag Browser in the Designer
        #print "tagname=",tagname
        alarmtext = unicode(line[line.find(';')+1:].strip())	#alarm text
        if alarmtext == '':
        	alarmtext = 'Rezerva'
        #alarmtext = str(xx) + ". " + alarmtext + " (" + bitname + ")"	#alarm nr. + alarm text + bitname
        alarmtext = alarmtext + " (" + bitname + ")"	#alarm text + bitname
        #print "alarmtext=",alarmtext
        #displaypath = u'KA ML1'	#displayPath of the Tag; for grouping tags in groups, if you need it
        #print "displaypath= ", displaypath
        #print "xx= ", xx
        system.tag.addTag(parentPath=alarmFolderName, 
        			name=tagname, 
        			tagType="OPC", 
        			dataType="Boolean", 
        			attributes={"OPCServer":OPCServer, 
        				"OPCItemPath":deviceName+bit, 
        				"ScanClass":scanClass}, 
        			alarmConfig={alarmtext:[["name", "Value", alarmtext],
        			 				["priority","Value", priority], 
        							["label", "Value", alarmtext],
        							["setpointA","Value", 1.0], 
        							["ackMode", "Value", 1]]
        					}
        		)

    fileIn.close()

That script is working OK. I get all alarm tags inside the Ignition as bit tags:


What I would like to do is to create BYTE tags from this .csv file with 8 alarms for each byte tag, like this (with bit state as Alarm Mode):


I have written a ‘few’ scripts in my Ignition days, but this one is killing me…:cold_sweat:

1 Like

Hi Anton,

This is what I came up with. I processed the file into a set of nested dictionaries to group all of the alarms under one byte, then iterate through the dictionary to make the dictionary used for alarm parameters in each tag.

import csv

OPCServer='Ignition OPC-UA Server'
deviceName='[testrampe]'	#what name you have in Ignition/Config/Devices website
alarmFolderName=u"testrampe/Alarms"	#In which folder in Tag Browser in the designer you want to put your alarms
scanClass='Default'	#which scanclass should your alarms tags run under
priority=2	#priority of the alarm:0-Diagnostic, 1-Low, 2-Medium, 3-High, 4-Critical

#pathIn=system.file.openFile('csv')
pathIn = 'c:/test/testFileIn.txt'
fileIn = open(pathIn, 'rb')

reader=csv.reader(fileIn, delimiter = ';')

dictIn = {}

# Read File into dictionary
for row in reader:
	# Split address into byte/bit
	address = row[0].split('.') 
	if address[0] not in dictIn.keys():
		dictIn[address[0]] = {}
	dictIn[address[0]][address[1]] = row[1]


# Create tags		
for byte in (dictIn.keys()):
	alarmDict = {}
	# Create alarm dictionary for each tag
	for bit in sorted(dictIn[byte].keys()):
		alarmtext = dictIn[byte][bit]]
		alarmDict[alarmtext] = [["name", "Value", alarmtext],
        			 			["priority","Value", priority], 
        						["label", "Value", alarmtext],
        						["bitPosition","Value", int(bit)], 
        						["ackMode", "Value", 1]]
	system.tag.addTag(parentPath=alarmFolderName, 
						name=byte, 
						tagType = "OPC", 
						dataType = "Byte", 
						attributes={"OPCServer" : OPCServer, 
						"OPCItemPath" : deviceName+byte, 
        				"ScanClass" : scanClass}, 
						alarmConfig = alarmDict
						)

2 Likes

Kudos @JordanCClark :+1:
Thank you.
Just a little correction (for mode and DataType):

import csv

OPCServer='Ignition OPC-UA Server'
deviceName='[testrampe]'	#what name you have in Ignition/Config/Devices website
alarmFolderName=u"testrampe/Alarms"	#In which folder in Tag Browser in the designer you want to put your alarms
scanClass='Default'	#which scanclass should your alarms tags run under
priority=2	#priority of the alarm:0-Diagnostic, 1-Low, 2-Medium, 3-High, 4-Critical

pathIn=system.file.openFile('csv')
#pathIn = 'c:/test/testFileIn.txt'
fileIn = open(pathIn, 'rb')

reader=csv.reader(fileIn, delimiter = ';')

dictIn = {}

# Read File into dictionary
for row in reader:
	# Split address into byte/bit
	address = row[0].split('.') 
	address[0] = address[0].replace("M","MB")
	if address[0] not in dictIn.keys():
		dictIn[address[0]] = {}
	dictIn[address[0]][address[1]] = row[1]

# Create tags		
for byte in (dictIn.keys()):
	alarmDict = {}
	# Create alarm dictionary for each tag
	for bit in sorted(dictIn[byte].keys()):
		alarmtext = dictIn[byte][bit]
		alarmDict[alarmtext] = [["name", "Value", alarmtext],
        			 			["priority","Value", priority], 
        						["label", "Value", alarmtext],
        						["mode","Value", 9], 
        						["bitPosition","Value", int(bit)], 
        						["ackMode", "Value", 1]]
	system.tag.addTag(parentPath=alarmFolderName, 
						name=byte, 
						tagType = "OPC",  
						attributes={"OPCServer" : OPCServer, 
						"DataType" : 0,
						"OPCItemPath" : deviceName+byte, 
        				"ScanClass" : scanClass}, 
						alarmConfig = alarmDict
						)

and it’s working perfectly.
Again, :+1::bowing_man:

3 Likes

Glad it (mostly) worked! :slight_smile: