Custom Collector Toolkit Interface Technical Reference

The Collector Toolkit interfaces help in writing collectors with basic functionality such as initializing collectors, adding data and tags, the others help in writing advanced features such as store and forward functions, heartbeat, buffering, queuing. The following are the various interfaces in detail:

ihCollectorToolkitASyncAddTag

The shell will call this function at start up and on change to indicate a tag that should be collected. The collector specific code should keep all information about the tags and use it later to deliver the collected data.

Prototype
int ihInterfaceTKASyncAddTag(ihInterfaceTKASyncTagInfo *ASyncTag, 
int IsCollectorStarting)
Returns
TRUE on success. FALSE if the tag could not be added. For example, if the tag has an invalid address you can return an error here or report bad data later after ihCollectorToolkitAsyncStartReading is called.
Parameters
NameData TypeDescription
ASyncTagihInterfaceTKASyncTagInfoRefer to the structure description.
IsCollectorStartingintTRUE if this function is being called as part of collector start-up. FALSE if this is being called because a tag was added or modified while the collector was running.

ihCollectorToolkitASyncDeleteTag

Use this tag to update information to the Collector when a tag is deleted so that it will stop collecting data from the source. For example, if you delete a tag or stop collection in the administrator then the shell will call this function.

Prototype
int ihCollectorToolkitASyncDeleteTag(int tagId)
Returns
TRUE on success; your collector specific code should always return TRUE.
Parameters
NameData TypeDescription
tagIdIntTag identifier; the tag name is not passed into this function. You would have to match the tag identifier with a magnate passed in ihCollectorToolkitASyncAddTag.

ihCollectorToolkitASyncInit

The collector shell will call this to indicate the start of a list of tags to be collected asynchronously. The tags will be delivered via the ihCollectorToolkitASyncAddTag function and the collector specific code should keep track of all tag information.

Prototype
int ihInterfaceTKASyncInit(void);
Returns

TRUE on success; your collector specific code should always return TRUE.

ihCollectorToolkitASyncInitCompleted

The collector shell will call this method to indicate the end of a list of tags to be collected asynchronously.

Prototype
int ihInterfaceTKASyncInitCompleted(void)
Returns
TRUE on success; your collector specific code should always return TRUE.

ihCollectorToolkitASyncReload

This function is used to perform a recalculation on all unsolicited tags in the custom collector. Custom collector must implement the necessary changes to read data from the source and send values via the ihCollectorToolkitDataCallback. The time frame for recalculation is given in the input parameters StartTime and EndTime.

For more information on the methods of unsolicited tags, refer the methods listed for unsolicited tags in About Interfaces.

Prototype
int ihCollectorToolkitASyncReload(ihTKTimeStruct TimeStruct *StartTime, ihTKTimeStruct TimeStruct *EndTime)
Returns
Always, TRUE.
Parameters
NameData TypeDescription
StartTimeihTKTimeStructReserved
EndTimeihTKTimeStructReserved

ihCollectorToolkitASyncStartReading

The collector shell will call this method to indicate that the collector should start reading data for asynchronous tags from the source and report any data changes to the shell.

Prototype
int CustomCollector:: ihCollectorToolkitASyncStartReading(void)
Returns
TRUE on success; your collector specific code should return TRUE.

ihCollectorToolkitDataCallback

This callback is used when unsolicited tags get the data and asynchronously writes them into the Historian. Custom collector receives the data from unsolicited tags and sends it to the ihCollectorToolkitDataCallback. This call back function internally writes the data into the Historian.

Prototype
voidihCollectorToolkitDataCallback(void *Param)
Returns
Void.
Parameters
NameData TypeDescription
ASyncTagihInterfaceTKASyncDataRefer to the structure description.
Example
You can use this function as shown in the following example to create a thread using which the unsolicited tags
data is written into the Historian.
/// Summary;
/// Unsolicited dedicated thread corresponding method. 
Here all unsolicited tags get data from source(usually, way should be source 
notification to historian) and sends to historian
/// </summary>
/// <param name="param">;Collector instance&lt;/param>
UINT RandomValueSimulator::TKAsyncReadFunc(void* param)
{
POSITION pos = NULL;
RandomValueSimulator* pColl = (RandomValueSimulator*) param;
while (TRUE)
{
?if (g_DoAsyncRead)
?{
CSingleLock lock(&;g_Sync, TRUE);
if (!g_AsyncTags.IsEmpty())
{
?// gets each unsolicited tag into ihInterfaceTKAsyncTagInfo object
if (!pos) 
?pos = g_AsyncTags.GetHeadPosition();
?ihInterfaceTKASyncTagInfo* tag = g_AsyncTags.GetNext(pos);
?int numTags = 1;
?ihInterfaceTKDataInfo data;
?memset(&;data, 0, sizeof(ihInterfaceTKDataInfo));
?data.Tag = pColl->;TKStrdup(tag->;Tag);
?data.DataProp.ValueDataType = tag->;DataType; 
?data.DataProp.TimeStamp = pColl->;TKGetSystemTime();
?// gets data for selected tag
?pColl->;ihCollectorToolkitGetData(0, 0, 0, numTags, NULL, &;data);
?unsigned long collectionTime = (unsigned long)time(0);
?int tagId = tag->;TagId;
?ihInterfaceTKASyncData asyncData;
?memset(&;asyncData, 0, sizeof(ihInterfaceTKASyncData));
?asyncData.NumValues = numTags;
?asyncData.TagIds = &;tagId;
?asyncData.Values = &;data.DataProp;
?asyncData.CollectionTimes = &;collectionTime;
?// sends to historian
?pColl->;ihCollectorToolkitDataCallback(&;asyncData);
?}
?else
?{
pos = NULL;
?}
?}
?else
?{
pos = NULL;
?}
?long sleepTimeInMs = 500 + (rand() % 46) * 100; 
              // sleep from 0.5 to 5 seconds
?Sleep(sleepTimeInMs);
}
return 0;
}

ihCollectorToolkitDefinitionInitialize

Use this interface to specify what labels you want to appear on the collector configuration page of the administrator. The administrator will show 5 edit boxes for General 1 to General 5 but with this function you can control what text is show next to each edit box.

All custom collectors share the same set of labels.

Prototype
void ihCollectorToolkitDefinitionInitialize(ihCollectorToolkitDefProperties* CustomPropertyDesc)
Returns
Void.
Parameters
NameData TypeDescription
CustomPropertyDescihCollectorToolkitDefPropertiesPointer to a Custom Collectors specific properties General 1-5 definitions.

ihCollectorToolkitDestroyGroupData

Reserved for future use. Your collector specific code should call the CCollectorDelegator function.

Prototype
void ihCollectorToolkitDestroyGroupData(int NumTags, void *Data, void *Misc)
Returns
Void.
Parameters
NameData TypeDescription
NumTagsintReserved
DatavoidReserved
MiscvoidReserved

ihCollectorToolkitDebugModeChange

The collector calls this method when a change is detected. 0 indicates only errors and important information should be written to log. 255 is the highest setting for all debug information to display.

Prototype
void ihCollectorToolkitDebugModeChange(int DoDebug)
Returns
Void.
Parameters
NameData TypeDescription
DoDebugintZero or non zero debug level.

ihCollectorToolkitGetData

This is the function called by the collector shell each time the collector should poll data from the data source. The shell will pass a list of tags by tag id to be read. The tagids were provided to the collector specific code in the PolledAddTag call. The string tagnames, if needed, are available in the ihInterfaceTKDataInfo structure. The collector should gather the data and fill in the remaining fields of the ihInterfaceTKDataInfo.

Prototype
void ihCollectorToolkitGetData(int MinInterval, int AnySourceTimes, int CreatePermGroup, int NumTags, 
int *TagIds, ihInterfaceTKDataInfo *Data)
Returns
Void.
Parameters
NameData TypeDescription
MinIntervalintThe minimum configured collection interval of the tags being passed in for polling.
AnySourceTimesIntTRUE if any of the tags to be collected are configured for Time assigned by source. This would mean the collector specific code has to do additional work to provide a timestamp with the data. If this is FALSE, then the collector shell will provide the timestamp.
CreatePermGroupIntFALSE if this is a one time read such at start up or collector redundancy fail over. In this case, you can choose to not make a permanent collection group inside your code. If this is TRUE, then this is a normal scheduled polled read and you should consider making a permanent group in your code for greater efficiency.
NumTagsIntNumber of tags to be read.
TagIdsIntList of tags to be read, identified by tag ID. The tag names are in the data parameter, if required.
DataihInterfaceTKDataInfoPointer to the Proficy Historian Collector Data Properties. This contains some information from the shell and then the collector specific code needs to fill in the collected values.
Example
Populating data for a single tag.
ihInterfaceTKDataInfodata;
memset(&data,0, sizeof(ihInterfaceTKDataInfo));
data.Tag= Lcomputername.OperatorName
data.DataProp.ValueDataType= ihTKFloat;       // correct data type- same as tag type
data.DataProp.TimeStamp= pColl->TKGetSystemTime(); //10/01/2014 07:05:00
data.DataProp.Value = 10;   // value that matches the data type.
data.DataProp.Quality = ihTKOPCGood;

ihCollectorToolkitGetTagsHierarchical

Use this interface to retrieve and represent the data in a hierarchical manner.

Prototype
void ihCollectorToolkitGetTagsHierarchical(wchar_t* BrowsePosition, wchar_t* NodeFilter, 
ihInterfaceTKHierarchicalBrowseResponse* Response) 
Returns
Void.
Parameters
NameData TypeDescription
BrowsePositionwchar_t*Position of browsing for specific Tag.
NodeFilterwchar_t*

Node filtering required for tag to get hierarchical information.

ResponseihTKHierarchicalBrowseResponseHierarchical Groups of tags browse response.

ihCollectorGetTags

Use this interface to browse tags from source. The shell will give some criteria and the collector specific code should fill in the result.

Tags can be skipped when they exist in the data source but should not be collected into Proficy Historian. For example, if a tag has a data type that is not compatible with Proficy Historian, you would not return it and you can increment the number skipped.

Prototype
void ihCollectorToolkitGetTags(ihInterfaceTKTagRecordset *Tags, ihInterfaceTKCfgInfo *Cfg, wchar_t *BrowsePosition, 
ihTKBoolean Recursive, wchar_t *DescriptionMask, wchar_t *SourceAddressMask, int CanReadASync, 
int DoMsgPump, int *NumSkipped
Returns
Void.
Parameters
NameData TypeDescription
TagsihInterfaceTKRecordsetPointer to a Proficy Historian Tags Record set containing browse criteria and where you can return the tags.
CfgihInterfaceTKCfgInfoPointer to Proficy Historian Collector Configuration Information. Use this if necessary to help determine the browse results.
BrowsePositionwchar_tPointer to a position of browsing for specific Tag.
RecursiveihTKBooleanTRUE if the browse should be recursive in collector specific code. Applies only if your data source has a tree of available tags.
DescriptionMaskwchar_t* or a description mask that you should use when determining tags to return.
SourceAddressMaskwchar_t* or a source address mask that you should use when determining tags to return.
CanReadASyncintNon-zero if your collector is capable of asynchronous reads. Typically, this parameter does not affect browse results.
DoMsgPumpint0 should be ignored.
NumSkippedintUse this to return any tags that were skipped because they did not match the description or source address mask or had an invalid data type.

ihCollectorToolkitInitializeCompleted

When this method is called by the collector shell, it indicates that the initialization is complete.

Prototype
ihCollectorToolkitInitializeCompleted(void)
Returns
FALSE on success; collector should return FALSE.

ihCollectorToolkitInitialize

Use this interface to initialize the collector by using information in the ihInterfaceTKCfgInfo and ihInterfaceTKPreCfgInfo structures. Your code also needs to save away the callback pointers passed into this function for use later with unsolicited reads and browses.

Prototype
int ihCollectorToolkitInitialize(ihInterfaceTKCfgInfo *Cfg, ihInterfaceTKPreCfgInfo *PreCfg, wchar_t *ErrorMsg, 
int ErrorMsgSize,wchar_t *RegKeyName, ihCollectorToolkitCollectorCallbacks *Callbacks, int DoDebug)
Returns

TRUE if initialization was successful. Otherwise, FALSE. If initialization failed, you can return a text string error message in the ErrorMsg parameter and that message will be entered into the collector log.

Parameters
NameData TypeDescription
CfgihInterfaceTKCfgInfoPointer to the Proficy Historian Collector Configuration Information.
PreCfgihInterfaceTKPreCfgInfoPointer to the Collector pre-Configuration Information.
ErrorMsgwchar_tPointer to an Initialization Error Message, if any. Any error would be reported to collector log.
ErrorMsgSizeintError Message Size. This is the maximum length that your error message size can be.
RegKeyNamewchar_tPointer to a Registry Key Name. Will be filled in with the location of your collectors registry information.
CallbacksihTKCollectorCallbacksPointer to callbacks to functions inside the collector shell. Save these function pointers and call them at the appropriate time, such as to deliver unsolicited data into the shell.
DoDebugintThis value will be zero if the collector is not in debug mode and non-zero if debug mode is enabled. Save this value and use it to log more or less information to your collector log.

ihCollectorToolkitMiscReload

Reserved for future use. Your collector specific code should simply call the function in the CCollectorDelegator.

Prototype
int ihCollectorToolkitMiscReload(ihTKTimeStruct *StartTime, ihTKTimeStruct *EndTime)
Returns

TRUE; your collector specific code should return TRUE.

Parameters
NameData TypeDescription
*StartTimeihInterfaceTKTimeStructReserved
*EndTimeihTKTimeStructReserved

ihCollectorToolkitPolledAddTag

The collector shell calls this to indicate the tag will be used later in polled collection. The collector specific code should keep all information given as it will be used in the ihInterfaceGetData call.

The polled tag add notification is done via ihCollectorToolkitPolledAddTag and data is sent to Historian via ihCollectorToolkitGetData. The frequency of asking for data for polled tag is based on the tag collection interval.

Prototype
int ihCollectorToolkitPolledAddTag(ihInterfaceTKPolledTagInfo *PolledTag, int IsCollectorStarting)
Returns
TRUE on success; your collector specific code should return TRUE.
Parameters
NameData TypeDescription
PolledTagihInterfaceTKPolledTagInfoPointer to a Historian Collector Polled Tag Information.
IsCollectorStartingintParameter to provide information about collector state.

ihCollectorToolkitPreInitialize

Use this interface to provide the toolkit with some of the capabilities of the collector. Here, you can specify if you support multiple instances, if you support unsolicited reads, and if your collector supports browsing.

Information filled into the ihInterfaceTKCfgInfo structure will later be passed into the ihCollectorToolkitInitialize function.

Prototype
void ihCollectorToolkitPreInitialize(ihInterfaceTKPreCfgInfo *PreCfg, ihInterfaceTKCfgInfo *Cfg)
Returns
Void.
Parameters
NameData TypeDescription
PreCfgihInterfaceTKPreCfgInfoPointer to Collector Configuration Information.
CfgihInterfaceTKCfgInfoPointer to additional Collector Configuration Information.

ihCollectorToolkitPropertyUpdate

This function is called when the user changes any collector property in the Historian Administrator such as the General1 -5 properties. Your collector specific code can decide what changes are meaningful.

Prototype
void ihCollectorToolkitPropertyUpdate(ihInterfaceTKCfgInfo *Cfg)
Returns
Void.
Parameters
NameData TypeDescription
CfgihInterfaceTKCfgInfoCurrent values of Collector configuration information.

ihCollectorToolkitPolledInit

The collector shell calls this method at start up and on change to indicate the start of a list of tags to be polled, as the collector runs. The actual polling takes place in the ihInterfaceGetData call.

Prototype
int ihCollectorToolkitPolledInit(void);
Returns
FALSE on success; your collector specific code should return FALSE.

ihCollectorToolkitPolledInitCompleted

The collector shell will call this to indicate the end of the polled tag list. This informs the source to begin its initialization.

Prototype
int ihCollectorToolkitPolledInitCompleted(void);
Returns
FALSE on success; your collector specific code should return FALSE.

ihCollectorToolkitPropertyUpdate

This function is called when the user changes any collector property in the Historian Administrator such as the General1 -5 properties. Your collector specific code can decide what changes are meaningful.

Prototype
void ihCollectorToolkitPropertyUpdate(ihInterfaceTKCfgInfo *Cfg)
Returns
Void.
Parameters
NameData TypeDescription
CfgihInterfaceTKCfgInfoCurrent values of Collector configuration information.

ihCollectorToolkitPolledDeleteTag

The shell calls this function to notify the collector specific code that a tag will no longer be polled.

Prototype
int ihCollectorToolkitPolledDeleteTag(int tagId);
Returns
TRUE on success; your collector specific code should return TRUE.
Parameters
NameData TypeDescription
TagIdintTagId that is being deleted. The tag name is not passed into this function. Match the TagId with the information passed in the ihCollectorToolkitPolledAddTag.

ihCollectorToolkitPolledInitCompleted

The collector shell will call this to indicate the end of the polled tag list. This informs the source to begin its initialization.

Prototype
int ihCollectorToolkitPolledInitCompleted(void);
Returns
FALSE on success; your collector specific code should return FALSE.

ihCollectorToolkitReset

The toolkit will call this function when the collector is being paused or shutdown. Proficy Historian stores collector information before the Collector is shut down.

Prototype
void ihCollectorToolkitReset(int Shutdown)
Returns
Void.
Parameters
NameData TypeDescription
Shutdownint0 if the collector pauses and non-zero if the collector is shutting down.

ihCollectorToolkitStartReading

When the shell calls this method, it indicates the collector specific code to start polled and unsolicited reading from the source.

Prototype
int ihCollectorToolkitStartReading(void)
Returns
TRUE on success; your collector specific code should return TRUE.

ihCollectorToolkitShutdown

The collector shell will call this function when the collector executable (.exe) is shutting down.

Prototype
void ihInterfaceTKShutdown(void);
Returns
Void.

ihCollectorToolkitTagChange

The toolkit will call this function when the properties of a tag are changed in client tools, Proficy Historian Administrator, or other external tools. The tag and what properties have changed are indicated in the tag props and changed fields.

This function is called on tag property change and is not involved with data changes.

Your collector should decide how to react to tag property changes or should ignore the changes.

Prototype
int ihCollectorToolkitTagChange(int TagId, iHTKTagProperties *TagProps, iHTKTagFields *ChangedFields
Returns
int (TRUE/FALSE).
Parameters
NameData TypeDescription
TagIdintTagID that has changed.
TagPropsihTKTagPropertiesPointer to a Proficy Historian Tag Property structure that indicates the new tag property values.
ChangedFieldsihTKTagFieldsPointer to information about which tag properties have changed.

ihCollectorToolkitGetEnumeratedSets

The toolkit calls this function based on the value configured under the SynchInterval registry key value. This function is called every x minutes, where x is the value configured for the registry key.

Collectors implemented using the Collector Toolkit have to implement this method to fetch the EnumeratedSet from their source.

Prototype
int ihCollectorToolkitGetEnumeratedSets(ihTKEnumeratedSetRecordSet *EnumeratedSetRecordSet)
Returns
int (TRUE/FALSE).
Parameters
NameData TypeDescription
EnumeratedSetRecordSetihTKEnumeratedSetRecordSetPointer to an EnumeratedSetRecordSet structure which should be added to Historian Server.

ihCollectorToolkitWriteValue

The toolkit will call this function once per minute if the user has configured heartbeat/status/rate tags. If your collector does not support this feature you can hard code a return value and not do the write.

Prototype
void ihCollectorToolkitWriteValue(wchar_t *Tag, wchar_t *SValue, double DValue
Returns
Void.
Parameters
NameData TypeDescription
Tagwchar_ tPointer to a source address in the data source to write to.
doubled ValueDValueNumeric value to be written, if the Tag is a numeric tag. For example, a report rate would be written to a rate tag or a 1 would be written to a heartbeat tag.
SValueSValueThe string value to be written if tag source address is a string tag. For example, the string Running would be written to a status tag.

What is a Helper Method?

Helper Methods are used to allocate memory for variables while developing Collectors. Using these helper methods will prevent cross boundary issues. The following are the Helper Methods:

NameDescription
wchar_t*TKStrdup(const wchar_t* string)Use this method to allocate memory on the heap, assign values and returns.
voidTKFree(void* pointer)Use this method to free up pointer memory.
void*TKMalloc(_In_ size_t _Size)Use this method to allocate memory.