# Import bit alarm tags from .csv to Ignition byte tags

**URL:** <https://forum.inductiveautomation.com/t/import-bit-alarm-tags-from-csv-to-ignition-byte-tags/29870>\
**Category:** Ignition\
**Tags:** ignition79\
**Created:** [November 12, 2019, 12:12pm UTC](https://forum.inductiveautomation.com/t/import-bit-alarm-tags-from-csv-to-ignition-byte-tags/29870 "2019-11-12T12:12:59Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![zxcslo](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/zxcslo/32/61610_2.png) [@zxcslo](https://forum.inductiveautomation.com/u/zxcslo)\
**Post date:** [November 12, 2019, 12:12pm UTC](https://forum.inductiveautomation.com/t/import-bit-alarm-tags-from-csv-to-ignition-byte-tags/29870/1 "2019-11-12T12:12:59Z")

</div>

To all scripting gurus out there…😉

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

```auto
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.

```auto
#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:

 ![alarm_bit_tags](https://us1.discourse-cdn.com/inductiveautomation/original/2X/a/a979d89bc0fca19071f48f3324178a867e26f013.png)  
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):  
 ![alarms_byte_tag1](https://us1.discourse-cdn.com/inductiveautomation/original/2X/0/0abece3bad00fc5795de0cd10a055d2aa4aefadc.png)  
 ![alarms_byte_tag](https://us1.discourse-cdn.com/inductiveautomation/original/2X/b/b8946e80e6b7fb830331301fc538d9153ad8cdb4.png)  
I have written a ‘few’ scripts in my Ignition days, but this one is killing me…😰

---

<div class="post-metadata">

**Author:** ![JordanCClark](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jordancclark/32/83362_2.png) [@JordanCClark](https://forum.inductiveautomation.com/u/JordanCClark)\
**Post date:** [November 12, 2019, 3:01pm UTC](https://forum.inductiveautomation.com/t/import-bit-alarm-tags-from-csv-to-ignition-byte-tags/29870/2 "2019-11-12T15:01:18Z")

</div>

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.

```python
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
						)

```

---

<div class="post-metadata">

**Author:** ![zxcslo](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/zxcslo/32/61610_2.png) [@zxcslo](https://forum.inductiveautomation.com/u/zxcslo)\
**Post date:** [November 12, 2019, 6:18pm UTC](https://forum.inductiveautomation.com/t/import-bit-alarm-tags-from-csv-to-ignition-byte-tags/29870/3 "2019-11-12T18:18:17Z")

</div>

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

```auto
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, 👍🙇‍♂️

---

<div class="post-metadata">

**Author:** ![JordanCClark](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jordancclark/32/83362_2.png) [@JordanCClark](https://forum.inductiveautomation.com/u/JordanCClark)\
**Post date:** [November 12, 2019, 6:46pm UTC](https://forum.inductiveautomation.com/t/import-bit-alarm-tags-from-csv-to-ignition-byte-tags/29870/4 "2019-11-12T18:46:09Z")

</div>

Glad it (mostly) worked! 🙂
