WriteCSV.g — writes data to CSV files.
![]() | The code for this and other example scripts can be found in the DataHub distribution archive, typically at one of these locations: C:\Program Files\Cogent\OPC DataHub\scripts\ C:\Program Files\Cogent\Cascade DataHub\scripts\ Please refer to Section 3.1, “How to Run a Script” for more information on using scripts. |
/*
* Write data to a number of different CSV files. Each data set is written at
* a different interval, either per second, per minute or per hour. A new CSV
* file is created every hour or every day.
*
* The points names in each data set are read from a file. The file consists of each
* point name, one per line. The output file will contain a time stamp followed
* by the value for each point in the order that the points are listed in the
* point name file.
*
* To change the format of the file name, change the method "GenerateFileName".
*
* To change the extension of the file, change the member variable "filesuffix".
*
* To change the file names and timing, change the .NewDataSet calls in the
* method WriteCSV.constructor.
*/
require ("Application");
require ("CSVSupport");
class WriteCSV Application
{
datasets;
}
class MyCSVWriter CSVWriter
{
pointfile; // The name of a file containing the point list.
sample_rate; // one of #second, #minute, #hour or list(hour,minute,second)
file_rotate_rate; // one of #minute, #hour, #day or list(hour,minute,second)
filesuffix = ".csv"; // normally .csv. Override it to create .txt files.
}
/* This will produce a file name like:
* base_20090423_PM3.csv
*/
/*
method MyCSVWriter.GenerateFileName()
{
local tm = localtime(nanoclock());
format("%s_%d%02d%02d_%s%d%s", .filebase,
tm.year+1900, tm.mon+1, tm.mday,
tm.hour >= 12 ? "PM" : "AM",
tm.hour > 12 ? tm.hour - 12 : (tm.hour == 0 ? 12 : tm.hour),
.filesuffix);
}
*/
/* This will produce a file name like:
* base-20090423-1545.csv
*/
method MyCSVWriter.GenerateFileName()
{
local tm = localtime(nanoclock());
format("%s-%d%02d%02d-%02d%02d%s", .filebase,
tm.year+1900, tm.mon+1, tm.mday,
tm.hour, tm.min,
.filesuffix);
}
/*
* Create a new writer and start the timers to write new data and to
* create a new log file.
*/
method WriteCSV.NewDataSet (output_file_base, pointfile, sample_rate, file_rotate_rate, separate_lines)
{
local writer = new MyCSVWriter();
if (writer.ReadPointsFromCSV(pointfile))
{
writer.sample_rate = sample_rate;
writer.file_rotate_rate = file_rotate_rate;
writer.SetFileBase(output_file_base);
writer.SetSeparateLines(separate_lines);
switch(writer.sample_rate)
{
case (#second):
.TimerAt(nil,nil,nil,nil,nil,nil,`(@self).WriteData(@writer));
case (#minute):
.TimerAt(nil,nil,nil,nil,nil,0,`(@self).WriteData(@writer));
case (#hour):
.TimerAt(nil,nil,nil,nil,0,0,`(@self).WriteData(@writer));
case (#day):
.TimerAt(nil,nil,nil,0,0,0,`(@self).WriteData(@writer));
default:
if (list_p(writer.sample_rate))
{
// List of hour, minute, second specification
local times = list_to_array(writer.sample_rate);
.TimerAt(nil,nil,nil,times[0],times[1],times[2],`(@self).WriteData(@writer));
}
else // Default is hourly
{
.TimerAt(nil,nil,nil,nil,0,0,`(@self).WriteData(@writer));
}
}
switch(writer.file_rotate_rate)
{
case (#minute):
.TimerAt(nil,nil,nil,nil,nil,0,`(@self).RotateFile(@writer));
case (#hour):
.TimerAt(nil,nil,nil,nil,0,0,`(@self).RotateFile(@writer));
case (#day):
.TimerAt(nil,nil,nil,0,0,0,`(@self).RotateFile(@writer));
default:
if (list_p(writer.file_rotate_rate))
{
// List of hour, minute, second specification
local times = list_to_array(writer.file_rotate_rate);
.TimerAt(nil,nil,nil,times[0],times[1],times[2],`(@self).RotateFile(@writer));
}
else // Default is hourly
{
.TimerAt(nil,nil,nil,nil,0,0,`(@self).RotateFile(@writer));
}
}
.datasets = cons(writer, .datasets);
}
}
method WriteCSV.WriteData(writer)
{
writer.WriteLine();
}
method WriteCSV.RotateFile(writer)
{
.TimerAfter(0.1, `(@writer).IncrementFileName());
}
/* Write the 'main line' of the program here. */
method WriteCSV.constructor ()
{
/* Specify the CSV files to write. Modify the .NewDataSet lines to specify how
* to write each CSV file.
* Arguments are:
* output_file_base: The first part of the file, before the date string
* pointfile: The name of a file containing the point names for this data set
* sample_rate: One of #second, #minute, #hour or list(hour,minute,second)
* telling how frequently to write a line to the CSV file
* file_rotate_rate: One of #minute, #hour, #day or list(hour,minute,second)
* telling how frequently to create a new CSV file.
* separate_lines: If this is nil, write all point values on one line. If this
* is t, write each point value on a separate line.
*
* This function will read the pointfile as a CSV file and treat the first field in each
* row as the name of a point to be recorded into the output file.
*
* When specifying timing, the input is the list of (hour,minute,second) as accepted
* by the "at" function (see documentation). A value of nil for hour, minute or second
* stands for all values for that parameter. A list of values for hour, minute or second
* specifies an event only when the hour, minute or second matches one of the values in
* the list.
* Examples:
* list(nil,nil,nil) - every second
* list(nil,list(0,15,30,45),0) - every 15 minutes
* list(nil,list(0,15,30,45),30) - every 15 minutes, 30 seconds past the minute
* list(list(0,8,16), 0, 0) - at midnight, 8AM and 4PM exactly
* list(list(0,8,16), 5, 0) - at 12:05AM, 8:05AM and 4:05PM
*
* The symbols #second, #minute, #hour, #day are conveniences for:
* second: list(nil,nil,nil) - any hour, any minute, every second
* minute: list(nil,nil,0) - any hour, every minute at 0 seconds
* hour: list(nil,0,0) - every hour, on the hour
* day: list(0,0,0) - at midnight (0 hour, 0 minute, 0 second)
*/
.NewDataSet("c:/tmp/Group1", "c:/tmp/Group1_Points.txt", #second, #hour, nil);
.NewDataSet("c:/tmp/Group2", "c:/tmp/Group2_Points.txt", #second, list(nil,list(0, 15,30,45),0), nil);
.NewDataSet("c:/tmp/Group3", "c:/tmp/Group3_Points.txt", #second, list(nil,nil,0), nil);
}
/* Any code to be run when the program gets shut down. */
method WriteCSV.destructor ()
{
with writer in .datasets do
{
destroy(writer);
}
}
/* Start the program by instantiating the class. If your
* constructor code does not create a persistent reference to
* the instance (self), then it will be destroyed by the
* garbage collector soon after creation. If you do not want
* this to happen, assign the instance to a global variable, or
* create a static data member in your class to which you assign
* 'self' during the construction process. ApplicationSingleton()
* does this for you automatically. */
ApplicationSingleton (WriteCSV);
Copyright © 1995-2010 by Cogent Real-Time Systems, Inc. All rights reserved.