Well I eventually figured out how to make this work.
I had to use separate GetLog instructions to get both the lowest value and the time that the lowest value occurred. I just could not get it to work with using a single GetLog instruction and using arrays for the Mode and Name fields. Followed a few examples but could not get it to work. I could get it to poll for a single date, but would not work for a group of dates like an entire month.
This is the working code. You can select multiple tags and it will create additional columns showing the lowest value and the date-time the lowest value occurred.
{======================= Daily Minimum Snapshot ==========================}
{ This generates a snapshort report given the time interval }
{=========================================================================}
(
Reporter { Object value for call-backs };
Start { Starting time (local, not UTC!) };
End { Ending time };
Tags { List of tag names to report on };
)
[
Titles { Array of ODBC database field names };
Types { Array of ODBC column type names };
Data { Actual data for the body of the report };
Format { Array of format strings which will be used
in successive SWrites to write Data };
TitleStrm { Stream to build title line in };
i { Loop counter };
j { Loop counter };
NTags { Number of tags };
NRows { Number of periods (rows) in the report };
TagData { Array of tag data };
TagData2 { Array of tag data };
LocalTime { Result timestamp converted to local };
TZBias { Only Valid if Called from Report Page };
Constant NUMFMT = "%13.2f";
Constant COLFMT = "%13s";
{ Set up this module to become a plug-in for the reports }
[(POINTS)
Shared Report;
]
Constant TypeFilter = "Loggers" { type of tags to use in the report };
Constant ReportName = "Daily Minimum Snapshot" { title for the report };
Constant TPP = 86400 { 900 sec = 15 minutes };
Constant Mode = 1;
Constant Mode2 = 5;
]
Init [
If 1 Loop;
[
{ Initialize the arrays for the tags }
TZBias = \IsTimeZoneAware ? TimeZone(0) : Invalid;
NTags = ArraySize(Tags, 0);
TagData = New(NTags);
TagData2 = New(NTags);
{ Remaining arrays include Date and Time as well as NTags }
Titles = New((NTags * 2) + 2);
Types = New((NTags * 2) + 2);
Data = New((NTags * 2) + 2);
Format = New((NTags * 2) + 2);
{ Build the title lines }
TitleStrm = BuffStream(0);
SWrite(TitleStrm, "%s from %s %s to %s %s\r\n\r\n",
ReportName { Title for the report },
Date(Start / 86400, "MMM d, yyyy"),
Time(Start, "HH:mm:ss"),
Date(End / 86400, "MMM d, yyyy"),
Time(End , "HH:mm:ss"));
{ Set the value, type and format of the first two title columns }
Titles[0] = "Date";
Titles[1] = "Time";
Types [0] = "TEXT";
Types [1] = "TEXT";
Format[0] = "%-13s";
Format[1] = "%-9s";
{ write the first 2 columns of the title line }
SWrite(TitleStrm, Format[0], Titles[0]);
SWrite(TitleStrm, Format[1], Titles[1]);
{ Reset the loop counter }
i = 0;
{ For each selected tag... }
WhileLoop(i < NTags;
{ Add the tag name to the title line }
Titles[(i * 2) + 2] = PickValid(Scope(\Code, Tags[i])\Name, "Unknown");
Types [(i * 2) + 2] = "TEXT";
Format[(i * 2) + 2] = COLFMT;
SWrite(TitleStrm, COLFMT, Titles[(i * 2) + 2]);
Titles[(i * 2) + 3] = "Date - Time";
Types [(i * 2) + 3] = "TEXT";
Format[(i * 2) + 3] = COLFMT;
SWrite(TitleStrm, COLFMT, Titles[(i * 2) + 2]);
{ and, query data for the tag }
\GetLog(&TagData[i],
Scope(\Code, Tags[i]) { Point object value },
"Value" { Read data },
Start { Start time },
End { End time },
TPP { Time per point },
Invalid { No max number of points },
Mode { Calculation mode },
Invalid { N/A },
Invalid { Stale time },
TZBias { Time Zone Bias });
\GetLog(&TagData2[i],
Scope(\Code, Tags[i]) { Point object value },
"Value" { Read data },
Start { Start time },
End { End time },
TPP { Time per point },
Invalid { No max number of points },
Mode2 { Calculation mode },
Invalid { N/A },
Invalid { Stale time },
TZBias { Time Zone Bias });
i++;
);
{ Add CR, LF to title line and reset the stream }
SWrite(TitleStrm, "\r\n");
Seek(TitleStrm, 0, 0);
{ Let the VTScada Reporter module set up the ODBC columns }
Reporter\ODBCColumns(Titles, Types);
{ And, the title line }
Reporter\TitleLine(TitleStrm);
]
]
Loop [
{ ensure that GetLog has finished }
If AValid(TagData[0], NTags) == NTags;
[
{ Calculate the correct number of rows to avoid off-by-one errors }
NRows = Ceil((End - Start) / TPP);
{ Reset the row counter }
j = 0;
{ Loop through retrieved data, creating each report row }
WhileLoop(j < NRows;
{ First two columns of the row will be date and time }
Data[0] = Date((Start + j * TPP) / 86400, 7); { Date at start of TPP }
Data[1] = Time((Start + j * TPP) % 86400, 2); { Time at start of TPP }
{ Loop through TagData array to get the data }
i = 0;
WhileLoop(i < NTags;
{ Fill in data array }
Data[(i * 2) + 2] = Valid(Cast(TagData[i][j], 3)) ?
TagData[i][j] : Invalid;
{ Fill in format array }
Format[(i * 2) + 2] = NUMFMT;
{ Convert the UTC timestamp to local time }
LocalTime = ConvertTimestamp(TagData2[i][j],Invalid,Invalid,0);
{ Format for human consumption }
Data[(i * 2) + 3] = concat(Date(LocalTime / 86400, 4), " - ", Time(LocalTime % 86400, 2));
{ Increment loop counter }
i++;
); { End WhileLoop }
{ Pass the report line to the VTScada Reporter module }
Reporter\DataLine(Format, Data);
{ Increment the data time index }
j++;
); { End WhileLoop }
Slay(Self, 0);
]
]
Well I eventually figured out how to make this work.
I had to use separate GetLog instructions to get both the lowest value and the time that the lowest value occurred. I just could not get it to work with using a single GetLog instruction and using arrays for the Mode and Name fields. Followed a few examples but could not get it to work. I could get it to poll for a single date, but would not work for a group of dates like an entire month.
This is the working code. You can select multiple tags and it will create additional columns showing the lowest value and the date-time the lowest value occurred.
````
{======================= Daily Minimum Snapshot ==========================}
{ This generates a snapshort report given the time interval }
{=========================================================================}
(
Reporter { Object value for call-backs };
Start { Starting time (local, not UTC!) };
End { Ending time };
Tags { List of tag names to report on };
)
[
Titles { Array of ODBC database field names };
Types { Array of ODBC column type names };
Data { Actual data for the body of the report };
Format { Array of format strings which will be used
in successive SWrites to write Data };
TitleStrm { Stream to build title line in };
i { Loop counter };
j { Loop counter };
NTags { Number of tags };
NRows { Number of periods (rows) in the report };
TagData { Array of tag data };
TagData2 { Array of tag data };
LocalTime { Result timestamp converted to local };
TZBias { Only Valid if Called from Report Page };
Constant NUMFMT = "%13.2f";
Constant COLFMT = "%13s";
{ Set up this module to become a plug-in for the reports }
[(POINTS)
Shared Report;
]
Constant TypeFilter = "Loggers" { type of tags to use in the report };
Constant ReportName = "Daily Minimum Snapshot" { title for the report };
Constant TPP = 86400 { 900 sec = 15 minutes };
Constant Mode = 1;
Constant Mode2 = 5;
]
Init [
If 1 Loop;
[
{ Initialize the arrays for the tags }
TZBias = \IsTimeZoneAware ? TimeZone(0) : Invalid;
NTags = ArraySize(Tags, 0);
TagData = New(NTags);
TagData2 = New(NTags);
{ Remaining arrays include Date and Time as well as NTags }
Titles = New((NTags * 2) + 2);
Types = New((NTags * 2) + 2);
Data = New((NTags * 2) + 2);
Format = New((NTags * 2) + 2);
{ Build the title lines }
TitleStrm = BuffStream(0);
SWrite(TitleStrm, "%s from %s %s to %s %s\r\n\r\n",
ReportName { Title for the report },
Date(Start / 86400, "MMM d, yyyy"),
Time(Start, "HH:mm:ss"),
Date(End / 86400, "MMM d, yyyy"),
Time(End , "HH:mm:ss"));
{ Set the value, type and format of the first two title columns }
Titles[0] = "Date";
Titles[1] = "Time";
Types [0] = "TEXT";
Types [1] = "TEXT";
Format[0] = "%-13s";
Format[1] = "%-9s";
{ write the first 2 columns of the title line }
SWrite(TitleStrm, Format[0], Titles[0]);
SWrite(TitleStrm, Format[1], Titles[1]);
{ Reset the loop counter }
i = 0;
{ For each selected tag... }
WhileLoop(i < NTags;
{ Add the tag name to the title line }
Titles[(i * 2) + 2] = PickValid(Scope(\Code, Tags[i])\Name, "Unknown");
Types [(i * 2) + 2] = "TEXT";
Format[(i * 2) + 2] = COLFMT;
SWrite(TitleStrm, COLFMT, Titles[(i * 2) + 2]);
Titles[(i * 2) + 3] = "Date - Time";
Types [(i * 2) + 3] = "TEXT";
Format[(i * 2) + 3] = COLFMT;
SWrite(TitleStrm, COLFMT, Titles[(i * 2) + 2]);
{ and, query data for the tag }
\GetLog(&TagData[i],
Scope(\Code, Tags[i]) { Point object value },
"Value" { Read data },
Start { Start time },
End { End time },
TPP { Time per point },
Invalid { No max number of points },
Mode { Calculation mode },
Invalid { N/A },
Invalid { Stale time },
TZBias { Time Zone Bias });
\GetLog(&TagData2[i],
Scope(\Code, Tags[i]) { Point object value },
"Value" { Read data },
Start { Start time },
End { End time },
TPP { Time per point },
Invalid { No max number of points },
Mode2 { Calculation mode },
Invalid { N/A },
Invalid { Stale time },
TZBias { Time Zone Bias });
i++;
);
{ Add CR, LF to title line and reset the stream }
SWrite(TitleStrm, "\r\n");
Seek(TitleStrm, 0, 0);
{ Let the VTScada Reporter module set up the ODBC columns }
Reporter\ODBCColumns(Titles, Types);
{ And, the title line }
Reporter\TitleLine(TitleStrm);
]
]
Loop [
{ ensure that GetLog has finished }
If AValid(TagData[0], NTags) == NTags;
[
{ Calculate the correct number of rows to avoid off-by-one errors }
NRows = Ceil((End - Start) / TPP);
{ Reset the row counter }
j = 0;
{ Loop through retrieved data, creating each report row }
WhileLoop(j < NRows;
{ First two columns of the row will be date and time }
Data[0] = Date((Start + j * TPP) / 86400, 7); { Date at start of TPP }
Data[1] = Time((Start + j * TPP) % 86400, 2); { Time at start of TPP }
{ Loop through TagData array to get the data }
i = 0;
WhileLoop(i < NTags;
{ Fill in data array }
Data[(i * 2) + 2] = Valid(Cast(TagData[i][j], 3)) ?
TagData[i][j] : Invalid;
{ Fill in format array }
Format[(i * 2) + 2] = NUMFMT;
{ Convert the UTC timestamp to local time }
LocalTime = ConvertTimestamp(TagData2[i][j],Invalid,Invalid,0);
{ Format for human consumption }
Data[(i * 2) + 3] = concat(Date(LocalTime / 86400, 4), " - ", Time(LocalTime % 86400, 2));
{ Increment loop counter }
i++;
); { End WhileLoop }
{ Pass the report line to the VTScada Reporter module }
Reporter\DataLine(Format, Data);
{ Increment the data time index }
j++;
); { End WhileLoop }
Slay(Self, 0);
]
]
````