I am running Ignition Edge 8.1.21.
I am trying to figure out the most efficient way to read in tag values and then use these values as my data for a script running the csv library.
For each digital input I have two tags within a data type I created that I want to read in, the first being name and the second being StateOnOff. I want my csv file to look like this as an example using the screenshot of my tag structure:
LSHH-100 OFF
LSH-200 ON
I know there is a way to read in these tags using code where you aren't reading in each individual tag within the script. And is it better to put the values into a dataset and then transfer this data set into a csv? Better to do it with a dictionary?
system.tag.readBlocking
takes a list of tags paths. Use this.
Build the tags paths:
from itertools import chain
base_name = "[provider]DigitalO/InputSlot3In"
paths = list(chain(*(["{}/Name".format(base_name, i), "{}/StateOnOff".format(base_name, i)] for i in xrange(1, 5))))
values = [qval.value for qval in system.tags.readBlocking(paths)]
Then format and export to csv.
If you need help with that part too, I'll try and do my best.
interesting. I do want to get values from the following tag data types though:
InputSlot3In0, InputSlot3In2, InputSlot3In3, InputSlot3In4, InputSlot3In5, InputSlot4In0
As you can see they aren't in order
system.tag.readBlocking returns a list of qualified values in the order of the list of tag paths passed in. Note, it returns qualified values; not values. You have to handle those accordingly.
https://docs.inductiveautomation.com/display/DOC81/system.tag.readBlocking
that's easily fixable:
folders = [
"InputSlot3In0",
"InputSlot3In2",
... etc
]
paths = list(chain(*(["DigitalO/{}/Name".format(f), "DigitalO/{}/StateOnOff".format(f)] for f in folders)))
edit: note that if you have a lot of instances of this UDT, you can use system.tag.browse
to build the list programmatically instead.
This is what I have for the script using your example above
def create_DI_file ():
"""Create CSV file showing digital input status.
Params: N/A
Returns: N/A
"""
import csv
from itertools import chain
header = ['Digital Input', 'State']
folders = ["InputSlot3In0", "InputSlot3In2", "InputSlot3In3", "InputSlot3In4", "InputSlot3In5", "InputSlot4In0"]
paths = list(chain(*("[PLC]DigitalO/{}/Name".format(f), "[PLC]DigitalO/{}/StateOnOff".format(f)] for f in folders)))
values = [qval.value for qval in system.tags.readBlocking(paths)]
with open('C:\DailyCSVFiles\DIStatus.csv', 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(header)
writer.writerow(values)
... I get this error when trying to run the script
you're missing a [
:
paths = list(chain(*(["[PLC]DigitalO/{}/Name".format(f), "[PLC]DigitalO/{}/StateOnOff".format(f)] for f in folders)))
By the way, there are system functions to convert to csv and download a file. You should use those.
And you'll need to re-structure the data, as it is it's a simple list. You'll need a list of lists, with each inner list containing the name and state of that particular machine/whatever they are.
data_table = list(zip(values[::2], values[1::2]))
1 Like
Thanks. I did get it to work but like you said it just gave me a list as seen here:
Where would this other line of code go and what would it be replacing?
I tried putting this into the code as follows and got this:
def create_DI_file ():
"""Create CSV file showing digital input status.
Params: N/A
Returns: N/A
"""
import csv
from itertools import chain
header = ['Digital Input', 'State']
folders = ["InputSlot3In0", "InputSlot3In2", "InputSlot3In3", "InputSlot3In4", "InputSlot3In5", "InputSlot4In0"]
paths = list(chain(*(["[PLC]DigitalO/{}/Name".format(f), "[PLC]DigitalO/{}/StateOnOff".format(f)] for f in folders)))
values = [qval.value for qval in system.tag.readBlocking(paths)]
data_table = list(zip(values[::2], values[1::2]))
with open('C:\DailyCSVFiles\DIStatus.csv', 'w') as f:
writer = csv.writer(f)
writer.writerow(header)
writer.writerow(data_table)
Because that's not how you use writerow
.
But I'd repeat my suggestion: use the system functions.
dataset = system.dataset.toDataSet(header, data_table)
csv = system.dataset.toCSV(dataset, True, False, False)
system.perspective.download("filename", csv)
edit: wait, is this vision or perspective ?
Then if you piece together the little snippets in the posts above, it should do the trick.
If don't want to use a standard download, (maybe you're doing this in a gateway script) you'll need to dig in the csv writer doc to find how to write a table.
Or loop through it:
for row in data_table:
writer.writerow(row) #might need formatting, I don't know how this function works
I am doing it through a button right now but eventually I want to create this csv file once a day through gateway scripting. I tried the method above using system.perspective.download but did not have luck. The file isn't changing at all. If I am doing it through gateway scripting would this perspective download function not work?
Did you not get a download prompt ? What do your logs say ?
Nope.
Read up on ignition's scopes, this will help you tremendously in using ignition.
Is the file supposed to go on the same machine as the gateway is running ?
Yes. Same machine. I want to create the file locally on same machine running Gateway and then send this file out in an email shortly after.
I am getting nothing in the logs, no errors or other indications when I press the button.
so seems like I would have to go the route of using the csv write instead is what you are saying if I intend to do this through a scheduled gateway event
There might be system functions for that but I never used them.
One of those should do:
https://docs.inductiveautomation.com/display/DOC81/system.file
Ok. Will check it out. Thanks for the help!