Read and Write Functions

Data reading and writing is a key part of Historian functionality. There are many rules and best practices and many use cases that are not all documented here. With the following documentation you will see how to write raw values and read them back as raw values and then how to instruct the Data Archiver to perform calculations on the raw samples and return the result.

The method to pass filter parameters and query modifiers is shown but not the meaning of those parameters. Store and forward buffering is available for data writes but is an advanced topic not demonstrated here.

The Read and Write functions are:

ihDataAdd

Use this function to add data to the Data Archiver:

Prototype

ihDataAdd {
ihServerHandle hServer, // server handle returned from previous call to ihServerConnect
ihUNSIGNED long NumberOfTags, // the number of data samples being written
ihString *Tagnames, // the tagname of each sample
ihDataProperties *DataValues, // the timestamp, value, and quality of each sample 
ihAPIStatus *ErrorStatuses, // output parameter for per data sample errors
ihBoolean WaitForReply, // TRUE if the call should wait for success or failure from Data Archiver. 
FALSE means that you do not want to do any error checking
ihBoolean ErrorOnReplace // TRUE if you want an error returned instead of overwriting data
);

Remarks

Although the parameter is called NumberOfTags it is really NumberOfSamples. Even if you are writing multiple samples to the same tagname you need to pass the tagname with each data sample. Every data sample you pass needs a tagname in the Tagnames parameter and a timestamp, value, and quality in the DataValues parameter.

The application would write data timestamps that are in GMT+0 timezone. The Data Archiver does not do any conversion. If your timestamps are in local time and the data is retrieved in other clients, the timestamps will not be adjusted to your time zone. The System API uses the ihTimeLCLPartsToUTCStructEx () function to help you convert timestamps.

Part of your application design is to bundle multiple data samples into one write. You can send one sample per call to ihDataAdd or send 100,000 samples or more. In most cases you can write data periodically to make it available to clients in bundles of 1,000 to 10,000 samples per call to ihDataAdd

Part of your application design is to determine what to consider bad or uncertain quality and what sub- quality to use. Your tags may be in a Data Archiver with many other tags from many other sources, these include tags written by collectors or Excel Import. You must be consistent with those tags so that clients need not have special logic for specific tags. For example, collectors use a quality of bad and a subquality of ihOffline to indicate that collection has stopped at this time in the real world. Consider including such a data sample and using the same quality and subquality in your program. In this way reports and trends need not know where the data came from.

The data type you write in the ihDataProperties does not need to match the data type of the tag in the Data Archiver. The Data Archiver will do the conversion prior to storing the data.

You should typically write with WaitForReply=TRUE so that you can check for errors and implement error handling such as retries. If you have no error handling strategy or if you are relying on the store and for- ward functionality to deliver data you can write with wait = FALSE. This is a rare use case. Understand that store and forward functionality only make sure that the data reaches the Data Archiver, not that the data is stored in the Historian archive. There could be security errors or the Archiver may be out of disk space. The most reliable way to write data is to check for errors and even possibly to read back the data that was written.

If you do get a per data sample error that does not mean the whole write failed. Samples that return ihSTATUS_OK were written successfully.

If your program only writes data going forward in time, there is no risk of replacing data and you can pass either TRUE or FALSE for the ErrorOnReplace parameter. Otherwise, pass TRUE if you do not want accidental data overwrite or FALSE to intentionally overwrite existing data.

There are rules about writes having timestamps that are too old or too new and those are not all given here. But, you will receive an error if your write is rejected.

Returns

If you write with WaitForReply=FALSE then the return code will be ihSTATUS_OK. When using WaitForReply=FALSE the return value of the overall function will be ihSTATUS_OK on success and non ihSTATUS_OK on error which means you should investigate the per data sample error returned in the ErrorStatuses output parameter. Those errors include these values:

If you write with WaitForReply=FALSE then the return code will be ihSTATUS_OK. When using WaitForReply=FALSE the return value of the overall function will be ihSTATUS_OK on success and non ihSTATUS_OK on error which means you should investigate the per data sample error returned in the ErrorStatuses output parameter. Those errors include these values:

Returns Status Message
ihSTATUS_OK The data sample was successfully written.
ihSTATUS_API_TIMEOUT If the client program did not receive a return code before the timeout expired. This does not necessarily mean the write was not performed at the archiver, only that the client did not receive a response.
ihSTATUS_NOT_CONNECTED If you are not currently connected to the Data Archiver.
ihSTATUS_WRITE_IN_FUTURE If you specified a timestamp that was more than 15 minutes ahead of the Data Archiver PC clock. The Data Archiver will not accept writes that are too far into the future because it has no data file to hold them.
ihSTATUS_DUPLICATE_DATA If you set ErrorOnReplace to TRUE and you would have overwritten data.
ihSTATUS_WRITE_ARCH_OFFLINE If you wrote to a time period that has no archive.
ihSTATUS_ARCH_READONLY If the archive covering the timestamp written is set to read only in the Historian Administrator
ihSTATUS_ACCESS_DENIED If you are not allowed to write data to this tag and timestamp. Under most conditions, writes from user programs are allowed. But if you receive this error consider the following scenarios:
  • Your account is not a member of ihAuditedWriters or ihUnaudited Writers group.
  • The tag you are writing has tag level security enabled.
  • The entire archive is set to read only in the Historian Administrator.
The tag you are writing has tag level security enabled. The entire archive is set to read only in the Historian Administrator.
ihSTATUS_WRITE_OUTSIDE_ACTIVE The timestamp on the data sample is older than the ?data is read only"
ihSTATUS_INVALID_TAGNAME The tagname you wrote to does not exist in the Data Archiver configuration.
ihSTATUS_FAILED For any other type of error.

ihDataDelete

This function is used to delete data. By using this function you are not actually deleting the data from the Data Archiver but instead hiding it and marking it as deleted.

Prototype

ihDataDelete {
ihServerHandle hServer, // server handle returned from previous call to ihServerConnect
ihUNSIGNED long NumberOfTags, // the number of data samples included in the Tagnames and DataValues parameters
ihString *Tagnames, // the tagname of the data sample to be deleted
ihDataProperties *DataValues, // the list of data samples to be deleted
ihAPIStatus *ErrorStatuses // output parameter containing error codes for individual data samples

);

Remarks

Deleting data is not actually done and this function does not clear or reset an entire tag. The reason is that the data is only hidden and not truly deleted. If you write and delete the same time range repeatedly the Historian storage becomes very inefficient.

Use the delete function to delete individual data samples so they are not returned in raw data queries or considered in calculation modes. Delete a small range of data if you have recalculated values and want to discard the previous calculations. You do not need to delete data prior to data overwrite.

The return codes for a delete are much like the ones returned from a write. ihSTATUS_OK - the data sample was successfully deleted.

Returns

Returns Status Message
ihSTATUS_OK The data sample was successfully deleted.
ihSTATUS_API_TIMEOUT If the client program did not receive a return code before the timeout expired. This does not necessarily mean the write was not performed at the archiver, only that the client did not receive a response.
ihSTATUS_NOT_CONNECTED If you are not currently connected to the Data Archiver
ihSTATUS_WRITE_ARCH_OFFLINE If you wrote to a time period that has no archive.
ihSTATUS_ACCESS_DENIED If you are not allowed to write data to this tag and timestamp. Under most conditions, writes from user programs are allowed. But if you receive this error consider the following scenarios:
  • The tag you are writing has tag level security enabled.
  • The entire archive is set to read only in the Historian Administrator.
The tag you are writing has tag level security enabled. The entire archive is set to read only in the Historian Administrator.
ihSTATUS_WRITE_OUTSIDE_ACTIVE The timestamp on the data sample is older than the ?data is read only"
ihSTATUS_FAILED For any other type of error.

ihDataOpenRecordset

This function is used to read values for one or more tags for a single start and end time, and sampling mode.

Prototype

ihDataOpenRecordset {
ihServerHandle hServer, // server handle returned from previous call to ihServerConnect
ihDataFields *Fields, // which fields such as value and quality and comments you want returned
ihDataCriteria *Criteria, // all of the parameters for the read including the tagname and time range and 
sampling mode
ihDataRecordset *DataRecordset // output parameter containing the retutned data samples or any per tag errors
);

Remarks

This function is used to read values for a single start and end time and sampling mode. This function is typ- ically used to read a single tagname. However, a wildcard can be passed or multiple individual tagnames can be passed.

The list of sampling and calculation modes, filtering parameters and query modifiers are passed to this function to indicate if you want raw samples returned or you want the Data Archiver to perform some calculation or summarization of the data and return the results. For example you can instruct the Data Archiver to perform hourly averages and return the results instead of returning the samples themselves.

All calculated values are returned as Double Float, regardless of the data type of the tag. Sampling modes such as lab or interpolated will return data in the tag ?s current data type, even if the data type was changed over a period of time.

The start and end time that you enter are assumed to be in the GMT+0 time zone. If you need to convert local time zone timestamps to UTC use the ihTimeLCLPartsToUTCStructEx() utility function. The returned data will also be in GMT+0 timezone and you can use the ihTimeUTCStructToLCLPartsEx() function to convert to local time in preparation for trending or reporting.

The memory holding the returned data must be freed but do not free each field directly. Simply call the ihDataCloseRecordset() function.

For examples, refer to SDK Sample Programs.

Returns

Returns Status Message
ihSTATUS_OK The data sample was successfully read.
ihSTATUS_API_TIMEOUT The client program did not receive a portion of the returned values before the timeout expired. Large reads are sent back in multiple responses and the SystemAPI must receive at least a partial response before the timeout expires. For example if there is 90 second timeout configured, a read can take several minutes or more, as long as at least a part of the response is received every 90 seconds.
ihSTATUS_NOT_CONNECTED If you are not currently connected to the Data Archiver
ihSTATUS_ACCESS_DENIED If you are not allowed to read data:
  • The tag you are reading has tag level security enabled.
  • You are not a member of the ihReaders security group. .
The tag you are writing has tag level security enabled. The entire archive is set to read only in the Historian Administrator.
ihSTATUS_WRITE_OUTSIDE_ACTIVE The timestamp on the data sample is older than the ?data is read only"
ihSTATUS_FAILED For any other type of error.

ihDataCloseRecordset

This function used to free the data recordset that was allocated inside the System API in a previous read call.

Prototype

void ihDataCloseRecordset {
ihDataRecordset *DataRecordset // the recordset to be freed. This comes from a previous call to 
ihDataOpenRecordset
);

Remarks

Use this function to free the data recordset that was allocated inside the System API in a previous read calls.

Returns

Returns Status Message
VOID Void

ihDataClearAllFields

This function is used to clear the set of requested data fields.

void ihDataClearAllFields {
ihDataFields *Fields  // structure to be cleared
);

Remarks

Use this function to clear the set of requested data fields (timestamp,value,quality and so on) in preparation for doing a read. After

clearing, you should set the fields that you want returned.

Returns

Returns Status Message
VOID Void

ihDataSubscribe

This function is used to subscribe or unsubscribe the data changes for a tag or tags in the Data Archiver.

Prototype

ihDataSubscribe {
ihServerHandle hServer, // server handle returned from previous call to ihServerConnect
ihChar *Tagname, // the tagname or wildcard of tagnames to subscribe
ihUNSIGNED long MinimumElapsedTime, // the fastest rate in milliseconds that you want data returned or 0 to return every data change
ihBoolean Subscribe // TRUE to setup a subscription or FALSE to stop receiving changes from an existing subscription
);
Remarks

Use this function to subscribe or unsubscribe to data changes for a tag or tags in the Data Archiver. Subscriptions will be delivered within a few seconds of data change and are delivered to you as DataRecordset structures through the callback you previously registered with ihDataRegisterCallback() callback function. You must register a callback first if you want to receive changes. This ihDataSubscribe() function indicates the tags you want to monitor.

You can subscribe to one tag by passing a specific tagname or pass a * or other wildcard to get changes for multiple tags. If you need to monitor multiple individual tag names, then call ihDataSubscribe() function once for each tag.

Most applications will pass a 0 for minimum elapsed time indicating they want all data changes. But you can specify a minimum rate. However, you may not be notified of every change. As you are notified, you should receive the data, possibly queuing the data change, and return from the callback.

Subscriptions stay in place even after the connection lost to archiver. However, once you call ihServerDisconnect() all subscriptions are cleared. It is not necessary to unsubscribe before calling disconnect but it is suggested.

For Examples, refer Sample Programs section.
Returns Status Message
ihSTATUS_OK if the data was successfully read.
ihSTATUS_API_TIMEOUT

if the client program did not receive a portion of the returned values before the timeout expired. Large reads are sent back in multiple responses and the SystemAPI must receive at least a partial response before the timeout expires. For example, if there is 90 second timeout configured, a read can take several minutes or more, as long as at least a part of the response is received every 90 seconds.

ihSTATUS_NOT_CONNECTED

if you are not currently connected to the Data Archiver.

ihSTATUS_FAILED

For any other type of error.

ihDataGetCurrentValue

Use this function to get the current values of the one or more tags.

Prototype

ihDataGetCurrentValue {
ihServerHandle hServer, 
ihDataFields *Fields, 
unsigned long NumberOfTags,
ihChar **Tagnames,
ihDataProperties *DataValues,
ihAPIStatus *ErrorStatuses
);

Remarks

The ihDataGetCurrentValue function returns timestamp, value, quality, and comments. You can choose to return any of these values using the ihDataFields.

Values are returned based on the tag datatype. You should free the returned values using ihDataFreeCurrentValue() function. Do not free the memory in your program.

You can have per tag errors. For example, if the tag does not exist or you are not allowed to read it.

Returns

Returns Status Message
ihSTATUS_OK The data sample was successfully read.
ihSTATUS_ACCESS_DENIED If you are not allowed to add or modify tags, or you are not a member of the ihReaders security group.
ihSTATUS_FAILED If the tag does not exist.

ihDataFreeCurrentValue

Use this function to free the memory in your program for the current value of the selected tags.

Prototype

ihDataFreeCurrentValue {
ihUNSIGNED long NumberOfRecords,
ihDataProperties *DataValues
);

Remarks

Use this function to free what is returned from ihDataGetCurrentValue() function. Do not free the memory any other way.

Returns

Returns Status Message
VOID Void

ihDataSubscribe

Use this function to subscribe or unsubscribe to data changes for a tag or tags in the Data Archiver. Subscriptions will be delivered within a few seconds of data change and are delivered to you as DataRecordset structures through the callback you previously registered with ihDataRegisterCallback() callback function. You must register a callback first if you want to receive changes. This ihDataSubscribe() function indicates the tags you want to monitor.

You can subscribe to one tag by passing a specific tagname or pass a * or other wildcard to get changes for multiple tags. If you need to monitor multiple individual tag names, then call ihDataSubscribe() function once for each tag.

Most applications will pass a 0 for minimum elapsed time indicating they want all data changes. But you can specify a minimum rate. However, you may not be notified of every change. As you are notified, you should receive the data, possibly queuing the data change, and return from the callback.

Subscriptions stay in place even after the connection lost to archiver. However, once you call ihServer- Disconnect() all subscriptions are cleared. It is not necessary to unsubscribe before calling disconnect but it is suggested.

For Examples, refer to the Sample Programs section.
Returns Status Message
ihSTATUS_OK The data sample was successfully read.
ihSTATUS_API_TIMEOUT The client program did not receive a portion of the returned values before the timeout expired. Large reads are sent back in multiple responses and the SystemAPI must receive at least a partial response before the timeout expires. For example if there is 90 second timeout configured, a read can take several minutes or more, as long as at least a part of the response is received every 90 seconds.
ihSTATUS_NOT_CONNECTED If you are not currently connected to the Data Archiver
ihSTATUS_FAILED For any other type of error.

ihDataOpenMultiRecordset

This function is used if you need to do a single read but use different sampling or calculation modes or different start and end times.
ihDataOpenMultiRecordset {
ihServerHandle hServer,
ihUNSIGNED long NumberOfRequests,
ihDataFields *Fields, 
ihDataCriteria *Criteria, 
ihDataRecordset *DataRecordset
);

Remarks

This function can be used if you need to do a single read but use different sampling or calculation modes or different start and end times. You do not need to use this function simply to read multiple tags.

After checking the return value of the API call you can check the return value of each included query.

Returns

Returns Status Message
ihSTATUS_OK The data sample was successfully read.
ihSTATUS_API_TIMEOUT The client program did not receive a portion of the returned values before the timeout expired. Large reads are sent back in multiple responses and the SystemAPI must receive at least a partial response before the timeout expires. For example if there is 90 second timeout configured, a read can take several minutes or more, as long as at least a part of the response is received every 90 seconds.
ihSTATUS_NOT_CONNECTED If you are not currently connected to the Data Archiver
ihSTATUS_ACCESS_DENIED If you are not allowed to read data.
  • The tag you are reading has tag level security enabled.
  • You are not a member of the ihReaders security group
ihSTATUS_DATA_RETRIEVAL_COUNT_EXCEEDED If the read exceeded the Max Query Time or Max Query Intervals configured in Historian Administrator.
ihSTATUS_FAILED For any other type of error.

ihDataCloseMultiRecordset

This function is used to free the multiple recordsets returned from a ihDataOpenMultipleRecordset() call.

Prototype

void ihDataCloseMultiRecordset {
ihUNSIGNED long NumberOfRequests,
ihDataRecordset *DataRecordsetd
);

Remarks

Use this function to properly free the multiple recordsets that were allocated inside the System API in a previous read call.

Returns

Returns Status Message
VOID Void

ihArchiver options

ihArchiverFreeOption Function

Prototype

ihArchiveFreeOption{
ihChar *OptionValue // the string returned from ihArchiveGetOption()
);            

Remarks

Use this function to free the memory inside the structure. Do not free the fields in your code.

Returns

Returns Status Message
VOID Void

ihArchiverGetOption

This function retrieves an Archiver option from the data store.

ihArchiverGetOption {
ihServerHandle hServer,// server handle returned from previous call to ihServerConnect 
ihOptionEx *Option, // the option and data store name
ihChar **OptionValue // output parameter containing the option value
);

This function retrieves an Archiver option from a data store. You can indicate the data store in the ihOptionEx structure. You can pass NULL as the data store name to use the default data store.

You can get an option value to confirm it is set as requested by your application, or you can use this call to verify that a set option call was successful.

ihArchiverSetOption

This function sets an Archiver option from a data store.

ihArchiverGetStatistics

This function is used to get performance statistics from the Data Archiver.

ihArchiverGetStatistics(
ihServerHandle hServer, 
ihArchiveStatistics *Statistics
);
This returns the performance statistics about data writes, failed writes, and disk space usage.
Returns Status Message
ihSTATUS_OK If the option was successfully read
ihSTATUS_API_TIMEOUT If the option could not be read and you can try again later
ihSTATUS_NOT_CONNECTED If you are not currently connected to the Data Archiver
ihSTATUS_FAILED For any other type of error.