GetTagHistory

(Historian Manager Library)

Description: Launched module that retrieves historical data for a tag. Replaces GetLog.
Returns: Nothing. (Data returned using the first two parameters.)
Usage: Script Only.
Function Groups: Log
Related to: GetLog | EditData | WriteHistory
Format: \HistorianManager.GetTagHistory(PtrReturnCode, PtrResult, TagObj, FieldNames, StartTime, EndTime, TPP, NumEntries[, Modes, StaleTime, EnableDownTimeOverride, UseRecordOverrides])
Parameters:  
PtrReturnCode

Required. A pointer to a return code. If launching GetTagHistory multiple times for a set of tags this should be an array with an index incrementing for each launch.

PtrReturnCode will be invalid until this launched function finishes. Watch for this value to become valid before attempting to process the results. In the case of an array, use AValid to watch for every instance to finish.

Defined error codes are provided in the reference chapter. See: Historian Error Codes

PtrResult
A pointer to the historical data that will be returned in this parameter. Always returns an array with at least two dimensions according to the parameter, Fields.
TagObj
Object value of the tag for which the history is to be retrieved.
FieldNames

Either the name or an array of names of the fields to retrieve.
Typically, the field in which you are interested is "Value" for most tag values, or "Value!" for tag attribute data (Value! was introduced with VTScada version 12 and is not available in legacy data. It cannot be retrieved by SQL queries.)

Note that TagData will still be a two-dimensional array even if FieldsNames is simply text. In most cases, it is better to specify this parameter as a one-dimensional array containing two elements: "Timestamp" and "Value". Both dimensions of TagData will then have data.

StartTime
UTC time stamp indicating the beginning of the data range to retrieve.
A local time value should be converted to UTC as follows. (LocalTimeZone should be 0 in almost all cases.)
UTCStartTime = ConvertTimestamp(Start, LocalTimeZone, FALSE, Invalid);
EndTime
UTC time stamp indicating the end of the data range to retrieve. (Selection is inclusive of this time.)
Ignored if TPP is non-zero.
TPP

Required. Any numeric expression giving the time span in seconds for each array entry. Each array element will contain the data which correspond exactly to this time period which corresponds to 0 or more data points.
If TPP is equal to 0, the data is read and placed in the array on a one to one basis.
If TPP is less than 0, an error will be returned.

If reading string values with TPP > 0 and Modes = 4 then valid text values are returned. Attempting to do the same with any Modes value other than 4 will return only Invalid.

NumEntries
The number of log entries to be returned in the array.
Use a negative value to retrieve values in reverse chronological order.
Modes

Optional numeric expression giving the method of handling the data. If TPP is greater than 0, the values that fall in each time span will be represented as follows:

Mode

Data Collection

0

Time-weighted average

1

Minimum in range

2

Maximum in range

3

Change in value over the range

4

Value at start of range

5

TimeOfMinInRange

6

TimeOfMaxInRange

7

SumOfZtoNZTransitions

8

SumOfNonZeroTime

9

Totalizer. (Invalid is counted as zero)

10

Deprecated. Equivalent to mode 4.

11

Difference between the start and end

values of a range (see following note)

12 Bitwise OR (see following note)
13 Bitwise AND (see following note)

Mode 11:

This is for hardware that can count to a limited number, then rolls over to start a fresh count. For example, a tag that counts equipment starts, but which can only count from 0 to 15 before wrapping around to start again. This gives a value of sixteen per roll-over since there must be one more start after fifteen to have the roll-over occur. A graph of a very simple case where there is a start every second would look like the following:

(Each rollover must be followed by a fresh start, not a gradually declining value. If there are a series of declining values then, because each is less than the previous, each counts as another rollover.)

The formula used is (RolloverCount * RolloverValue) + (LastValidValue - FirstValidValue).

Where, for any given time interval:

  • Rollovers are counted when a new value is smaller than the last valid value.
  • The RolloverValue is passed to the function in the parameter StaleTime.
  • LastValidValue starts with the last valid value in the previous time interval (if any), and is updated with each new valid value within the time interval.
  • FirstValidValue starts with the last valid value in the previous time interval (if any), and is updated with only the first valid value found in the current time span.

Given this example, suppose that you want a count of starts in each thirty-second interval. In the first interval there is no previous valid value, one wrap-around and a last valid value of 12. (1*16) + (12 - 0) = 28.

This is an idealized case. Consider a more realistic case where not all values are logged. (This may be due to factors such as polling intervals, deadbands, hardware, etc.) The following graph shows the same data where the orange dots represent values obtained and logged and the gray line represents what really happened:

In the first 30 seconds there is one roll-over when the value drops from 13 to 2. The first value is 0 and the last is 11. The Historian will return 27: (1*16) + (11-0) = 27.

The Historian will return 30 for the period from 30 to 60. The first valid value (carried from the previous period) is 11. The last valid value is 9 and there are two roll-overs. (2*16) + (9-11) = 30.

Modes 12 and 13:

These are intended to provide a summary of the bit-wise Historian value attributes within a query. (Value attributes were added in VTScada version 11.5 / 12.0)

With mode 12, the first value is OR'd with zero, and each successive value in the time period is OR'd with result of the last comparison. From the result you will know whether any particular attribute bit was set on any values within the period.

With mode 13, the first value is AND'd with a value having all bits set to 1 and each successive value is AND'd with the result of the last comparison. From the result you will know whether any particular attribute bit was set on all values within the period.

In the case of modes 5 and 6, FieldName should still be set to indicate the field on which the mode is to act. The return values will be times indicating the maximum or minimum in that field for each time span.

If TPP is less than or equal to 0, Mode is ignored. If the data is text, the first entry in a given time range is used for the array entry and Mode is ignored.

It is possible to retrieve more than one mode in a single GetTagHistory statement. To do this, pass an array of values in as the Mode parameter.

StaleTime
The meaning of StaleTime depends on the selected Mode.
For all Modes but 11, this optional parameter sets a maximum validity duration for data elements that are being TPP processed.
For Mode 11, this is the maximum value of a range. (See comments in the Mode parameter.)
Normally, every data point is treated as remaining valid until the next data point. If a valid StaleTime parameter is given, then any data point will be treated as invalid, StaleTime seconds after the recorded time. If TPP is less than or equal to 0, StaleTime is ignored. If StaleTime is not required but EnableDowntimeOverride is, then StaleTime should be given as an Invalid value.
It is possible to specify more than one stale time in a single GetTagHistory statement. To do this, pass an array of values in as the StaleTime parameter.
EnableDownTimeOverride
An optional Boolean. Set TRUE to return INVALID for downtime. Defaults to the value from the Historian tag's "Represent system downtime as missing data" parameter.
UseRecordOverrides
An optional Boolean. Flag indicating if record overrides are in effect. Setting the UseRecordOverrides parameter to FALSE will cause all records in storage to be returned even if there are duplicate timestamps.
Typically, a new record with a timestamp matching an existing record would be considered to override the existing record. The parameter defaults to TRUE, returning only the most recently added record for each timestamp.
Comments:

This function is a replacement for GetLog. It has the following advantages over GetLog:

1) Works purely in UTC. Any conversion to local timestamps should be done by the caller only when absolutely necessary (only when they are about to display or be presented to an end-user).

2) Ambiguity removed from the StartTime, EndTime, TPP and NumEntries parameters:   If TPP is non-zero, then EndTime is ignored and NumEntries explicitly specifies the number of periods to return.

3) Ambiguity removed from return values. There is an explicit return code set when the function is complete, rather than just returning a single-element array when an error occurs, which is ambiguous to whether it indicates an error or returned data. Moreover, the array returned is always a two-dimensional array.

Note: if multiple modes are being returned from the same field, the array size of fields needs to match that of mode.

This function forwards to GetLog if there is legacy history data involved in the query.

No downtime invalids are inserted when reading in the reverse order.

Querying Value Attributes

Version 12 of VTScada introduced value attributes. These can be queried using "Value!" rather than "Value" for the field name or array of field names. Value! stores bitwise values according the following table.

Attributes flagged with a star (*) apply only if the I/O tag is attached to a DNP3 driver or a custom driver supporting this feature.

Refer to the constant, #NUM_DATA_ATTR_BITS, to discover the number of bits in data attributes for your version of VTScada.

Bit Number Defined Constant Name Meaning
0 #DATA_ATTR_MANUAL_DATA The value was from the tag's ManualData parameter
1 #DATA_ATTR_MANUAL_ENTRY The value was manually entered
2 #DATA_ATTR_EDITED_DATA The historical value was manually edited
3 #DATA_ATTR_QUESTIONABLE The tag was marked as questionable
4 #DATA_ATTR_STALE_DATA (*) The value was reported as stale by VTSDriver
5 #DATA_ATTR_IMPORTED (*) The value was imported from a CSV file
6 #DATA_ATTR_COMMFAIL (*) The driver experienced a comm failure
7 #DATA_ATTR_QUALITY (*) The tag has marked the value as unreliable
8 #DATA_ATTR_DRIVER_COMMFAIL (*) The PLC reported a downstream comm failure
9 #DATA_ATTR_DRIVER_QUALITY (*) The PLC reported the value may be unreliable
10 #DATA_ATTR_DRIVER_OVERRIDDEN (*) The PLC reported the value was overridden
11 #DATA_ATTR_DRIVER_NODATA (*) The PLC reported there is no data available

See Also: 

WriteHistory, ConvertTimeStamp

Examples 

There are two distinct ways to retrieve historical data: (1) Raw history and  (2) Statistically processed data ("TPP").

A raw history retrieval retrieves the actual records that were logged by the tag

    FieldNames = New(2); 
    FieldNames[0] = "Timestamp"; 
    FieldNames[1] = "Value"; 
    \HistorianManager.GetTagHistory(&RetCode, &Results, AnalogStatus1, 
                                  FieldNames, UTCStartTime, UTCEndTime, 
                                  0 {TPP=0 indicates raw records requested}, 
                                  100 { Maximum number of records to return}); 

TPP-type query (average daily values for a 10-day period):

    Modes = New(2); 
    Modes[0] = 4; { Timestamp at start of period }
    Modes[1] = 0; { Time-weighted average of Value over the period }
    \HistorianManager.GetTagHistory(&RetCode, &Results, AnalogStatus1, 
                                    FieldNames, UTCStartTime, 0 {EndTime ignored},
                                    86400 { 1-day time periods },
                                    10    { 10 days requested  }, Modes);

Retrieve an average and a minimum:

    Modes = New(2);
    Modes[0] = 0 { Average };
    Modes[1] = 1 { Minimum };

    Fields = New(2);
    Fields[0] = "Value";
    Fields[1] = "Value";

    \HistorianManager.GetTagHistory(&ReturnCode, &Result, TagObj, Fields,
                                    StartTime, EndTime, EndTime - StartTime, 1, Modes);