dataPARC.Store SDK
  • 17 Jan 2025
  • PDF

dataPARC.Store SDK

  • PDF

Article summary

HeaderImage5

Overview

The dataPARC Historian SDK provides developers of third-party applications the ability to make connections to the dataPARC Historian and read/write/manipulate data.

Specific data source connections (i.e. OPC server, flat file, etc.) are represented by Interfaces. Interface Sets can combine multiple interfaces for use within a single dataPARC Source. A group of sources, typically representing a physical plant location, is called an Interface Group. Connections can be made to individual Interfaces, Interface Sets, and Interface Groups.

Tags within each Interface expose all attributes of each configured historian tag. The dataPARC Historian SDK allows subscriptions to tags for reading data as it is acquired.

Datapoints represent individual data records for each tag. In addition to the value, the timestamp and quality are available within Datapoints. These can be read individually, over a time range or streamed.

The documents below describe the use of the dataPARC Historian SDK and provide code examples.

Getting Started

Prerequisites

The 3rd Party application will need the dataPARC Historian SDK Nuget package (dataPARC.Store.Public.SDK) added in Visual Studio. Once added, this Nuget source will stay up to date if on a public feed.  Alternatively, it can be hosted locally on the development system.

The Historian SDK is designed for .NET 4.8, .NET Standard 2.0 and .NET 8.0 compatibility.

Nothing additional is needed on the dataPARC Historian side.

Further Information:

dataPARC Historian GitHub Code Reference

Capabilities

Clients

Create clients that have methods for calling historian functions. There are 4 client classes: ReadClient, WriteClient, ConfigurationClient, and PublishingClient.

Each client can be created separately, or by using the ClientFactory. Using the ClientFactory to create multiple clients allows any of the available clients can be accessed as properties that lazily create the clients. There's no need for using contexts when referencing these clients since the client factory owns them and is itself being used in a using context. Subsequent references to the ClientFactory's client properties will return the same instance.

Failover

Reading calls support failover to backup servers if the primary server becomes unavailable. Simply create an array of servers referencing their hostname and port, then use this as the "Server" argument when creating the ReadClient.  The primary server is the first server specified in the array of servers. Reading calls include reading configurations, data, and publishing. Read calls will automatically try again on a backup server. Upon switching to a backup server, the client will wait about 3 minutes before trying to reconnect to the primary server. As many backup servers as needed can be added.

Authentication

When creating clients, you are required to pass in an ICertificateValidation that is used to validate the server's certificate. This can be a custom validator as long as it implements ICertificateValidation.

The other authentication related parameter the clients have is an optional IAuthProvider that is used to get access tokens from a token provider. This can also be a custom provider as long as it implements IAuthProvider. This is optional since a historian might have security turned off, but is required to talk to secured historians.

Connections

The reading, writing, and configuration clients have a CheckConnectionAsync method that acts like a ping by trying to connect to a historian server.

The publishing client instead has a Publishing property that indicates if tag publishing has been started. For long running operations such as tag publishing, connections might become transient in changing network conditions, but the publishing client will recover and continue working.

Historian Paths

Historian paths are a path to a location for the historian to store data, i.e. directory path, network path. etc. These are saved as HistorianPathConfig objects. These can then be applied to individual ConfigurationClients. 

When saving configs, the saved configs are returned wrapped in a SaveResult<T>. This provides a status for the save operation, the saved values, and more. When reading configs, the configs are returned wrapped in a GetResult<T>. This provides a status for the read operation, the values read if successful, and more.

Interface Groups

Interface groups are the top level entity in the historian. All interfaces, interface sets, and tags must belong to an interface group.

Multiple interface groups can be saved, and they support reading a single group or all groups.

Interfaces

Interfaces are a grouping of tags, often associated with a specific data source. Every tag must belong to one interface. Each interface must belong to an interface group.

Multiple interfaces can be saved, and they support reading a single interface, all interfaces within a group, or all interfaces within all groups.

Interface Sets

Interface sets are a grouping of interfaces within the same interface group. Each interface set must belong to an interface group.

Interfaces within the same interface group can be added to the interface set. One interface group can have multiple interface sets but each interface can only belong to one interface set.

Multiple interface sets can be saved, and they support reading a single interface set, all interface sets within a group, or all interface sets within all groups.

Tags

Tags are anything that has a data stream such as a sensor, calculation, etc. The Client object includes a method for saving tags.

Multiple tags can be saved, and they support reading a single tag, all tags within an interface, or all tags within an interface set.  Tags can be queried by fully qualified tagname or GUID.

Writing Data

The Client object supports writing data to one more more tags using the WriteDataPointAsync or WriteDataPointsAsync methods.

Multiple data points of different types can be combined into a TagDataPointSet object to facilitate writing data of multiple types in one method (WriteDataPointSetAsync).

Reading Current Values

The ReadClient object's ReadCurrentValueAsync method allows a single tag's current value to be retrieved.  It requires a ReadCurrentValueParameters object to specify the tagname or GUID.

Multiple tag values can be read by passing an array of ReadCurrentValueParameters objects to the ReadCurrentValuesAsync method.

Reading Specific Timestamps

The ReadClient object's ReadAtTimeAsync method allows a single tag's value from a specific point in history to be retrieved.  It requires a ReadAtTimeParameters object to specify the tagname or GUID and timestamp.

This method supports reading multiple timestamps for a single tag; an array is returned containing the data points.

Reading Raw Data

The ReadClient object's ReadRawAsync method allows a single tag's value from a span of time to be retrieved. It requires a ReadRawParameters object to specify the tagname or GUID, starting timestamp, and ending timestamp. An array of datapoints is returned.

This ReadRawBulkAsync method supports reading multiple tag values over a span of time.

The count of data points over a period of time can be read using the ReadRawCountAsync method.

The DirectionalReadRawAsync method can be used to read a specified number of datapoints either forwards or backwards from a starting timestamp for a single tag. It requires a DirectionalReadRawParameters object to specify the tagname or GUID, starting timestamp, direction, and number of data points. An array of datapoints is returned.

Raw data can be streamed using the StreamRawAsync method. It requires a StreamRawParameters object to specify the tagname or GUID, starting timestamp, and ending timestamp. Streaming is equivalent to reading in the data it can return, but it starts returning data faster since the server sends data into the stream as soon as it starts reading it. It also provides more flexibility around client memory constraints.

The DirectionalStreamRawAsync method can be used to read a specified number of datapoints either forwards or backwards from a starting timestamp for a single tag. It requires a DirectionalStreamRawParameters object to specify the tagname or GUID, starting timestamp, direction, and number of data points. An array of datapoints is returned.

Reading Processed Data

The ReadClient object also includes methods for reading processed data such as aggregates.

The ReadProcessedAsync method allows a single tag's processed value from a span of time to be retrieved. It requires a ReadProcessParameters object to specify the tagname or GUID, starting timestamp, ending timestamp and aggregate configuration.  The aggregate configuration is specified using an AggregateConfig object, which contains the type and processing interval. An array of datapoints is returned.

This ReadProcessedBulkAsync method supports reading multiple processed tag values.

The count of processed data points over a period of time can be read using the ReadProcessedCountAsync method.

Methods are also available for directional reads of processed data and streaming processed data, similarly to raw data (described above).

Reading Processed Data By Config

Aggregate configurations can be saved with names as strings and passed into the ReadClient's ReadProcessedByConfigAsync method.  All the same capabilities as "Reading Processed Data" above are available, but the methods include "ByConfig" before "Async" in their names.

Reading Array Data

All read calls support two additional parameters for slicing array tags: arrayStartIndex and arrayLength. The datapoints returned will be slices of the shape [arrayStartIndex..arrayLength] from the array datapoints.

Using DataPoints From Read Responses

All read calls return datapoints in 1 of 2 types: DataPoints or IDataPoint

DataPoints: an array of 1 of multiple types of datapoints, i.e. one of DataPointSingle[], DataPointByte[], etc.

IDataPoint: 1 of datapoint types, i.e. one of DataPointSingle, DataPointByte, etc.

When you know the type of datapoints returned, you can grab them by property. This is best case in terms of performance.

When you don't know the type, such as in a function that operates over any type of datapoints, you can pass in a function for every type. This is how the Count property is implemented on DataPoints. You can also pass in an action for every type.

Finally, since each datapoint type implements IDataPoint, you can get an array of IDataPoint from all datapoints contained in a DataPoints instance. This is least ideal when working with DataPoints since every datapoint contained is boxed upon being referenced as an IDataPoint.

Tag Publishing

The PublishingClient object facilitates subscribing to tags for receiving the latest data points.  The StartPublishingAsync method subscribes to a single tag, and requires a StartTagPublishingParameters object to specify the tagname or GUID, and time interval.

Methods are also available to change the publishing interval and stop publishing.

The OnReconnected event can be utilized to take action based on a client-server connection status change, and the OnPublish event can be utilized to take action when the client receives a newly published data point from the server.


Was this article helpful?