# Gateway timer script to log folder of tags to SQL

**URL:** <https://forum.inductiveautomation.com/t/gateway-timer-script-to-log-folder-of-tags-to-sql/61180>\
**Category:** Ignition\
**Tags:** ignition80, scripting\
**Created:** [June 24, 2022, 6:47pm UTC](https://forum.inductiveautomation.com/t/gateway-timer-script-to-log-folder-of-tags-to-sql/61180 "2022-06-24T18:47:23Z")\
**Posts on this page:** 3\
**Page:** 2

<div class="post-metadata">

**Author:** ![ctodd](https://avatars.discourse-cdn.com/v4/letter/c/ed655f/32.png) [@ctodd](https://forum.inductiveautomation.com/u/ctodd)\
**Post date:** [June 27, 2022, 7:16pm UTC](https://forum.inductiveautomation.com/t/gateway-timer-script-to-log-folder-of-tags-to-sql/61180/23 "2022-06-27T19:16:12Z")

</div>

Version 8.0.16  
Your script worked using script console to run for a folder of tags.

output

```auto
[default]Hydraulic_Pressure/base1_acc_pressure 1438.41418457 Mon Jun 27 21:14:45 CEST 2022 Good
[default]Hydraulic_Pressure/base1_cb_pressure 1390.67675781 Mon Jun 27 21:14:57 CEST 2022 Good
[default]Hydraulic_Pressure/base2_acc_pressure 1452.05358887 Mon Jun 27 21:14:57 CEST 2022 Good
[default]Hydraulic_Pressure/base2_cb_pressure 1392.25048828 Mon Jun 27 21:14:57 CEST 2022 Good
[default]Hydraulic_Pressure/base3_acc_pressure 1448.38146973 Mon Jun 27 21:14:56 CEST 2022 Good
[default]Hydraulic_Pressure/base3_cb_pressure 1418.4798584 Mon Jun 27 21:14:56 CEST 2022 Good

```

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [June 27, 2022, 7:46pm UTC](https://forum.inductiveautomation.com/t/gateway-timer-script-to-log-folder-of-tags-to-sql/61180/24 "2022-06-27T19:46:21Z")

</div>

Does the browse operation need to be recursive? In other words if the search finds a folder, do those tags also need to be included?

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [June 28, 2022, 5:55pm UTC](https://forum.inductiveautomation.com/t/gateway-timer-script-to-log-folder-of-tags-to-sql/61180/25 "2022-06-28T17:55:15Z")

</div>

Taking some inspiration from @JordanCClark I did my best to refactor your code to accomplish what you’re attempting to do.

First here’s a little helper function which comes in handy for things like this. Technically you don’t need a function, but I find that `grouper(2,zip(list1,list2))` is much more readable than  
`zip(*[iter(zip(list1,list2))] * 2)`. Some may disagree.

```auto
def grouper(n, iterable):
    return zip(*[iter(iterable)] * n)

```

This will group elements of an iterable in into groups of ‘n’ size. So  
`grouper(2,'ABCDEF') --> [('A','B'),('C','D'),('E','F')]`

Here is what I came up with:

```auto
import numbers

def logDB_new(tags):
	tagReadList = []
	
	# Add fullpath of each tag, and each tag's Tooltip from the browse to the list.
	for tag in tags:
		tagReadList.append(str(tag['fullPath']))
		tagReadList.append(str(tag['fullPath']) + '.Tooltip')
	
	#Now that we have all of the paths we want, read all of the values in one go.
	qValues = system.tag.readBlocking(tagReadList)
	
	#create lists to hold the paths and values that we want to write after processing.
	writeList = []
	writeValues = []
	
	#create the base part of the query string. This part will not change.
	query = "INSERT INTO 'ride_activeity_trends' ('Name','TagValue','t_stamp') VALUES "
	#create a list to hold the values to be inserted into the table.
	queryVals = []
	
	#Loop through the current and previous values.
	#The ZIP function puts the paths with the values, and the grouper function puts the currentPath and Value
	#together with the prevPath and value. So you get something like (((currentPath,currentValue),(prevPath,prevValue)),...)
	for currentValues, prevValues in grouper(2,zip(tagReadList, qValues)):
		name, curQValue = currentValues #break apart the currentValues into the path(name) and current qualified value
		prevName, prevQValue = prevValues#break apart the prevValues into the path(prevName) and previous qualified value
		
		#this insures that the value is a type of number. This prevents an error from trying to round a string or some other non-numeric type.		
		if isinstance(prevQValue.value,numbers.Number):
			
			prevValue = round(prevQValue.value,3)
			curValue = curQValue.value
			
			#if the absolute value of prevValue is less then 0.1 or the current value is None then move on to the next itteration
			if abs(prevValue) <= 0.1 or not curValue:
				continue
			
			val_diff = abs((curQValue.value - prevValue)/prevValue)
			
			if val_diff > 0.1:
				#note that this is concatenating two lists resulting in a single list
				queryVals += [name,curValue,system.date.now()]
				#add the prevValue name and value to the lists to be written.
				writeList.append(prevName)
				writeValues.append(curQValue.value)
				
	#now that we have processed all of the tags we can construct the query.
	#the str.join() function returns a string by joining all elements of an iterable
	#the ['(?,?,?)'] * (len(queryVals) / 3 will dynamically create a list of ['(?,?,?)','(?,?,?)',...]
	#the number of elements in that list will be the length of queryVals divided by 3.
	#This will result in the syntax needed to insert the rows for all tags in one call.		
	query += ','.join(['(?,?,?)'] * (len(queryVals) / 3))
	
	#only run the query if queryVals is not empty.
	if queryVals:
		system.db.runSFPrepUpdate(query,queryVals,datasources=['MySQL'])
	
	#write all of the tags in one go.
	system.tag.writeBlocking(writeList,writeValues)

tagPath = '[default]Hydraulic_Pressure'

tags = system.tag.browse(tagPath,{'tagType' : 'AtomicTag'}).getResults()

logDB_new(tags)
```

[Previous page](https://forum.inductiveautomation.com/t/gateway-timer-script-to-log-folder-of-tags-to-sql/61180.md?page=1)
