Description of Data Types, Parameters and Structures

Some structures contain ‘reserved’ words. These are generally inserted to pad structures to be 32 bit aligned. Item Definition The ItemID is the fully qualified definition of a data item in the server, commonly referred to as the WHAT. No other information is required to identify the data item for the client to be able to read/write values.

The Item definition (ItemID) used in the OPCITEMDEF and elsewhere is a nul-terminated string that uniquely identifies an OPC data item. The syntax of the identifier is server dependent (although it should include only printable UNICODE characters) and it provides a reference or ‘key’ to an ‘item’ in the data source. The item is anything that can be represented by a VARIANT although it is typically a single value such as an analog, digital or string value.

For example, an item such as FIC101 might represent an entire record such as a Fieldbus, Hart Foundation or ProfiBus data structure. Such behavior is specifically allowed but not required by OPC - the return of such structures is considered to be vendor specific behavior. Alternately FIC101.PV might represent one attribute of a record such as the process value. This would probably take the form of a double which could be used by any client.

As an extreme example, since the syntax of the item ID is server specific, additional information such as Counts, Engineering Units Scaling and Signal conditioning information could be embedded in the definition string (although this is not recommended).

Examples:

A server which supports access to an existing DCS might support a simple syntax such as

"TIC101.PV"

A server that supports low level access to a PLC might support a syntax such as

"COM1.STATION:42.REG:40001;0,4095,-100.0,+1234.0"

AccessPath

The AccessPath is intended as a way for the client to provide to the server a suggested data path (e.g. a particular modem or network interface). It indicates HOW to get the data.

The ITEM ID provides all of the information needed to locate and process a data item. The Access Path is an optional piece of information that can be provided by the client. Its use is highly server specific but it is intended to allow the client to provide a ‘recommendation’ to the server regarding how to get to the data. As an analogy, if the ItemID represented a phone number, the access path might represent a request to route the call via satellite (or transatlantic cable or microwave link). The call will go through regardless of whether you specify an access path and also whether or not the server is able to use that suggested path.

For example, suppose you wanted to access a value in an RTU and had a high speed modem on COM1 and a low speed modem on COM2. You might specify COM1 as the preferred access path. Either one will work, but you would prefer to use COM1 if it is available for better performance.

In any case, the use of access path by both the server and the client is optional. Servers need not provide the function and clients need not use it even if it is provided.

Servers which do not support access paths will completely ignore any passed access path (and will not treat this as an error by the client). Also, when queried, such servers will always return a null access path for all items (i.e. a NUL string).
 
 

Blob We will discuss why the Blob exists and how it behaves.

The Blob is basically a scratch area for the server to associate with items in order to speed up access to or processing of those items. The exact way in which it is used is server specific.

The idea is that clients refer to items via ASCII strings while internally, to speed up access, the server will probably need to resolve this string into some internal server specific address; a network address, a pointer into a table, a set of indices or files or register numbers, etc. This address resolution could take considerable time and the resulting internal address could take an arbitrary amount of space. This Blob allows the server to return this internal address and allows the client to save it and to provide the Blob back to the server for future references to this item. The server could use the ‘Blob’ as a ‘hint’ to help find the item more quickly the next time; "The Blob says that last time I looked for this tag I found it ‘here’ - so lets see if its still in that location". However, in all cases, the ITEM ID is still the ‘key’ to the data. Regardless of the contents of the Blob, the server needs to insure that it is in fact referencing the item referred to by the ITEM ID.

The behavior of the Blob is as follows.

Its use by both client and server is optional. Servers which can perform ‘AddItems’ quickly based just on the item definition should generally not return a Blob. In cases where servers do return a Blob, clients are free to ignore these Blobs (although this will probably affect the performance of that server).

The Blob is passed to AddItems and ValidateItems and is also returned by the server any time an AddItems or ValidateItems or EnumItemAttributes is done. The returned Blob may differ in size and content from the one passed.

Note that the server can update the Blob for an item at any time entirely at the server’s discretion (including, for example, whenever the client changes an attribute of an Item).

Proper behavior of a client that wishes to support the Blob is to Enumerate the item attributes to get a fresh copy of the Blobs for each item prior to deleting an item or group and to save that updated copy along with the other application data related to the items.

Comment:

The difference between the server handle and the Blob is that the server handle is fixed in size (DWORD), should not be stored between sessions by the client and that it’s implementation is required since it is the only way to identify items after they have been added. The Blob is variable in length, is optional and may be stored by the client between sessions.

Time Stamps Time stamps are in the form of a FILETIME as this is more compact than other available standard time structures. There are numerous WIN32 functions for converting between various time formats and time zones. Time stamps are always in UTC, this form is beneficial because it is always increasing and is unambiguous. As discussed earlier in this document, time stamps should reflect the best estimate of the most recent time at which the corresponding value was known to be accurate. If this is not provided by the device itself then it should be provided by the server.
 
Variant Data Types for OPC Data Items Under NT 4.0 and Windows 95 with DCOM support, all VARIANT data types can be marshaled through standard marshalling. Under Automation, types will be coerced to known Automation data types. NOTE Real values in the variant (VT_R4, VT_R8) will contain IEEE floating point numbers. Note that the IEEE standard allows certain non numeric values (called NANs) to be stored in this format. While use of such values is rare, they are specifically allowed. If such a value is returned (in the OPCITEMSTATE or in the DATA STREAM to the IAdviseSink) it is required that the QUALITY flag be set to OPC_QUALITY_BAD.
 

Constants

OPCHANDLE

OPCHANDLEs are used in conjunction with both groups and items within groups. The purpose of handles in OPC is to allow faster access to various objects by both the client and the server.

The exact internal implementation of the server handles is entirely vendor specific. The client should never make any assumptions about the server handles and the server should never make any assumptions about the client handles.

Group Handles OPC groups have both a client and a server handle associated with them.

The server group handle is unique across the server and must be returned when the group is created. The handle is then passed by the client to various methods. The server group handle can be assumed to remain valid until the client Removes the group and free’s all of the interfaces.

It should not be persistently stored by the client as it may be different the next time the OPC group is created.

The client group handle is provided by the client to the server. It can be any value and does not need to be unique. It is included in the data stream sent to IAdviseSink in order to help the client identify the source of the data.

In practice it is expected that a client will assign a unique value to it’s handle if it intends to use any of the asynchronous functions of the OPC interfaces( including IOPCAsyncIO and IDataObject/IAdviseSink interfaces), since this is the only key to the information that the server gives back to the client via the IAdviseSink interface.
 
 

Item Handles OPC items have both a client and a server handle associated with them.

The server item handle is unique within the group and will be returned when the item is created. It is then passed by the client to various methods. The server item handle can be assumed to remain valid until the client Removes the items or Removes the Group containing the items.

It should not be persistently stored by the client as it may be different the next time the OPC Item is created.

The client item handle is provided by the client to the server. It can be any value and does not need to be unique. It is included in the data stream sent to IAdviseSink in order to help the client quickly identify which object in the client application is affected by the changed data.

In practice however it is expected that a client will assign unique values it’s handles if it intends to use any of the asynchronous functions of the OPC interfaces (including IOPCAsyncIO and IDataObject/IAdviseSink interfaces), since this is the only key to the information that the server gives back to the client via the IAdviseSink interface.
 
 

Structures and Masks

OPCITEMSTATE

This structure is used by IOPCSyncIO::Read typedef struct {

OPCHANDLE hClient;

FILETIME ftTimeStamp;

WORD wQuality;

WORD wReserved;

VARIANT vDataValue;

} OPCITEMSTATE;
 
 

Member Description
hClient the client provided handle for this item
ftTimeStamp UTC TimeStamp for this item's value. If the device cannot provide a timestamp then the server should provide one.
wQuality The quality of this item. 
vDataValue The value itself as a variant.

 

Comments

The Client should call VariantClear() to free any memory associated with the Variant.

Real values in the variant (VT_R4, VT_R8) will contain IEEE floating point numbers. Note that the IEEE standard allows certain non numeric values (called NANs) to be stored in this format. While use of such values is rare, they are specifically allowed. If such a value is returned it is required that the QUALITY flag be set to OPC_QUALITY_BAD.
 
 

OPCITEMDEF

typedef struct {

[string] LPWSTR szAccessPath;

[string] LPWSTR szItemID;

BOOL bActive ;

OPCHANDLE hClient;

DWORD dwBlobSize;

[size_is(dwBlobSize)] BYTE * pBlob;

VARTYPE vtRequestedDataType;

WORD wReserved;

} OPCITEMDEF;

This structure is used by IOPCItemMgt::AddItems and ValidateItems. The ‘used by’ column below indicates which of these two functions use each member.

Member Used by Description
szAccessPath both The access path the server should associate with this item. By convention a pointer to a NUL string specifies that the server should select the access path. Support for accesspath is optional

NOTE: version 1 indicated that a NULL pointer would allow the server to pick the path however passing a NULL pointer will cause a fault in the proxy/stub code and thus is not allowed.

szItemID both A null-terminated string that uniquely identifies the OPC data item. See the Item ID discussion and the AddItems function for specific information about the contents of this field.
bActive add This Boolean value affects the behavior various methods as described elsewhere in this specification. 
hClient add The handle the client wishes to associate with the item. See the OPCHANDLE for more specific information about the contents of this field.
dwBlobSize both The size of the pBlob for this item. 
pBlob both pBlob is a pointer to the Blob. 
vtRequestedDataType both The data type requested by the client. An error is returned (See Additems or ValidateItems) if the server cannot provide the item in this format. Passing VT_EMPTY means the client will accept the servers canonical datatype.

Comments

Regarding the datatype; often the same value can be returned in more than one format. For example, a numeric value might be returned as text (VT_BSTR) or real (VT_R8). Such conversions are typically handled in the server by VariantChangeType(). Similarly a status (SCAN status, AUTO/MAN, Alarm, etc.) might be returned as an integer (VT_I4) to be used in animation or color selection or as a string ( VT_BSTR) to be shown directly to the user. This second case is also known as an enumeration and would be vendor specific. Client vendors should note that this specification does not specify what enumeration’s exist or how a server maps the values into strings. Server vendors are strongly encouraged to follow a standard such as FIELDBUS in this area. See IEnumOPCItemAttributes for more information on this topic.
 
OPCITEMRESULT

typedef struct {

OPCHANDLE hServer;

VARTYPE vtCanonicalDataType;

WORD wReserved;

DWORD dwAccessRights;

DWORD dwBlobSize;

[size_is(dwBlobSize)] BYTE * pBlob;

} OPCITEMRESULT;

This structure is used by IOPCItemMgt::AddItems() and ValidateItems().
Member Used by Description
hServer add The server handle used to refer to this item.
vtCanonicalDataType both The native data type. The type of data maintained within the server for this item.
dwAccessRights both Indicates if this item is read only, write only or read/write. This is NOT related to security but rather to the nature of the underlying hardware. See the Access Rights section below.
dwBlobSize both The size of the Blob for this item. Note that this size may be 0 for servers that do not support or require this feature.
pBlob both Pointer to the Blob.

 

Comments

For AddItems pBlob will always be returned by servers which support this feature. For ValidateItems it will only be returned if the dwBlobUpdate parameter to ValidateItems is TRUE.

The client software must free the memory for the Blob before freeing the OPCITEMRESULT structure.

OPCITEMATTRIBUTES

typedef struct {

[string] LPWSTR szAccessPath;

[string] LPWSTR szItemID;

BOOL bActive;

OPCHANDLE hClient;

OPCHANDLE hServer;

DWORD dwAccessRights;

DWORD dwBlobSize;

[size_is(dwBlobSize)] BYTE * pBlob;

VARTYPE vtRequestedDataType;

VARTYPE vtCanonicalDataType;

OPCEUTYPE dwEUType;

VARIANT vEUInfo;

} OPCITEMATTRIBUTES;
 
 

Member Description
szAccessPath The access path specified by the client. A pointer to a NUL string is returned if the server does not support access paths.
szItemID The unique identifier for this item.
bActive FALSE if the item is not currently active, TRUE if the item is currently active
hClient The handle the client has associated with this item.
hServer The handle the server uses to reference this item.
dwAccessRights Indicates if this item is read only, write only or read/write. This is NOT related to security but rather to the nature of the underlying hardware. See the Access Rights section below.
dwBlobSize The size of the pBlob for this item. Note that this size may be 0 for servers that do not support or require this feature.
pBlob Pointer to the Blob.
vtRequestedDataType The data type in which the item's value will be returned. Note that if the requested data type was rejected then this field will return the canonical data type.
vtCanonicalDataType The data type in which the item's value is maintained within the server.
dwEUType Indicate the type of Engineering Units (EU) information (if any) contained in vEUInfo.

0 - No EU information available (vEUInfo will be VT_EMPTY)

1 - Analog - vEUInfo will contain a SAFEARRAY of exactly two doubles (VT_ARRAY | VT_R8) corresponding to the LOW and HI EU range.

2 - Enumerated - vEUInfo will contain a SAFEARRAY of strings (VT_ARRAY | VT_BSTR) which contains a list of strings (Example: "OPEN", "CLOSE", "IN TRANSIT", etc.) corresponding to sequential numeric values (0, 1, 2, etc.)

vEUInfo The VARIANT containing the EU information. See Comments below.

 

Comment:

The EU support is optional. Servers which do not support this will always return EUType as 0 and EUInfo as VT_EMPTY. EU information (analog or enumerated) can be returned for any value where the canonical type is any of: VT_I2, I4, R4, R8, BOOL, UI1 although in practice some combinations are clearly more likely than others. Where the item contains an array of values (VT_ARRAY) the EU information will apply to all items in the array (just as the Requested and Canonical Data types apply to all items in the array).

EU information is provided by the server to the client and is essentially Read Only. OPC Does not provide the client with any control over the EU settings.

For analog EU the information returned represents the ‘usual’ range of the item value. Sensor or instrument failure or deactivation can result in a returned item value which is actually outside this range. Client software must be prepared to deal with this. Similarly a client may attempt to write a value which is outside this range back to the server. The exact behavior (accept, reject, clamp, etc.) in this case is server dependent however in general servers must be prepared to handle this.

For enumerated EU the information returned represents ‘string lookup table’ corresponding to sequential integer values starting with 0. The number of values represented is determined by the size of the SAFEARRAY. Again, robust clients should be prepared to handle item values outside the range of the list and robust servers should be prepared to handle writes of illegal values.

Servers may optionally support Localization of the enumeration. In this case the server should use the current locale ID of the group. See IOPCServer::AddGroup and IOPCGroupStateMgt::GetState and SetState.

The client is responsible for freeing the VARIANTs in the OPCITEMATTRIBUTES structure including all elements of any SAFEARRAYs.

Client writers may wish to create and use a common function such as FreeOPCITEMATTRIBUTES(ptr) in order to minimize the chance of memory leaks.
 
 

OPCSERVERSTATUS

typedef struct {

FILETIME ftStartTime;

FILETIME ftCurrentTime;

FILETIME ftLastUpdateTime;

OPCSERVERSTATE dwServerState;

DWORD dwGroupCount;

DWORD dwBandWidth;

WORD wMajorVersion;

WORD wMinorVersion;

WORD wBuildNumber;

WORD wReserved;

[string] LPWSTR szVendorInfo;

} OPCSERVERSTATUS;

This structure used to communicate the status of the server to the client. This information is provided by the server in the IOPCServer::GetStatus() call.
 
 

Member Description
ftStartTime Time (UTC) the server was started. This is constant for the server instance and is not reset when the server changes states. Each instance of a server should keep the time when the process started.
ftCurrentTime The current time (UTC) as known by the server.
ftLastUpdateTime The time (UTC) the server sent the last data value update to this client. This value is maintained on an instance basis.
dwServerState The current status of the server. Refer to OPC Server State values below.
dwGroupCount The total number of groups (all public and private) being managed by the server. This is mainly for diagnostic purposes.
dwBandWidth The behavior of this field is server specific. A suggested use is that it return the approximate Percent of Bandwidth currently in use by server. If multiple links are in use it could return the ‘worst case’ link. Note that any value over 100% indicates that the aggregate combination of items and UpdateRate is too high. The server may also return 0xFFFFFFFF if this value is unknown.
wMajorVersion The major version of the server software
wMinorVersion The minor version of the server software
wBuildNumber The ‘build number’ of the server software
szVendorInfo Vendor specific string providing additional information about the server. It is recommended that this mention the name of the company and the type of device(s) supported.

 
OPCSERVERSTATE Values Description
OPC_STATUS_RUNNING The server is running normally. This is the usual state for a server
OPC_STATUS_FAILED A vendor specific fatal error has occurred within the server. The server is no longer functioning. The recovery procedure from this situation is vendor specific. An error code of E_FAIL should generally be returned from any other server method. 
OPC_STATUS_NOCONFIG The server is running but has no configuration information loaded and thus cannot function normally. Note this state implies that the server needs configuration information in order to function. Servers which do not require configuration information should not return this state.
OPC_STATUS_SUSPENDED The server has been temporarily suspended via some vendor specific method and is not getting or sending data. Note that Quality will be returned as OPC_QUALITY_OUT_OF_SERVICE.
OPC_STATUS_TEST The server is in Test Mode. The outputs are disconnected from the real hardware but the server will otherwise behave normally. Inputs may be real or may be simulated depending on the vendor implementation. Quality will generally be returned normally. 

 

Access Rights

This represents the server's ability to access a single OPC data item. Note the low 16 bits of the DWORD are reserved for OPC use and currently include the OPC Access Rights defined in the IDL and described below. The high 16 bits of the DWORD are available for vendor specific use.
AccessRights Values Description
OPC_READABLE The client can read the data item's value.
OPC_WRITEABLE The client can change the data item's value.

 
 
 

OPC Quality flags

These flags represent the quality state for a item's data value. This is intended to be similar to but slightly simpler than the Fieldbus Data Quality Specification (section 4.4.1 in the H1 Final Specifications). This design makes it fairly easy for both servers and client applications to determine how much functionality they want to implement.

The low 8 bits of the Quality flags are currently defined in the form of three bit fields; Quality, Substatus and Limit status. The 8 Quality bits are arranged as follows:

QQSSSSLL

The high 8 bits of the Quality Word are available for vendor specific use. If these bits are used, the standard OPC Quality bits must still be set as accurately as possible to indicate what assumptions the client can make about the returned data. In addition it is the responsibility of any client interpreting vendor specific quality information to insure that the server providing it uses the same ‘rules’ as the client. The details of such a negotiation are not specified in this standard although a QueryInterface call to the server for a vendor specific interface such as IMyQualityDefinitions is a possible approach.

Details of the OPC standard quality bits follow:
 
 

The Quality BitField
QQ BIT VALUE DEFINE DESCRIPTION
0 00SSSSLL Bad Value is not useful for reasons indicated by the Substatus.
1 01SSSSLL Uncertain The quality of the value is uncertain for reasons indicated by the Substatus.
2 10SSSSLL N/A Not used by OPC
3 11SSSSLL Good The Quality of the value is Good.

 

Comment:

A server which supports no quality information must return 3 (Good). It is also acceptable for a server to simply return Bad or Good (0x00 or 0xC0) and to always return 0 for Substatus and limit.

It is recommended that clients minimally check the Quality Bit field of all results (even if they do not check the substatus or limit fields).

Even when a ‘BAD’ value is indicated, the contents of the value field must still be a well defined VARIANT even though it does not contain an accurate value. This is to simplify error handling in client applications. For example, clients are always expected to call VariantClear() on the results of a Sychronous Read. Similarly the IAdviseSink needs to be able to interpret and ‘unpack’ the Value and Data included in the Stream even if that data is BAD.

If the server has no known value to return then some reasonable default should be returned such as a NUL string or a 0 numeric value.
 
 

The Substatus BitField

The layout of this field depends on the value of the Quality Field.

Substatus for BAD Quality:

SSSS BIT VALUE DEFINE DESCRIPTION
0 000000LL Non-specific The value is bad but no specific reason is known
1 000001LL Configuration Error There is some server specific problem with the configuration. For example the item is question has been deleted from the configuration.
2 000010LL Not Connected The input is required to be logically connected to something but is not. This quality may reflect that no value is available at this time, for reasons like the value may have not been provided by the data source.
3 000011LL Device Failure A device failure has been detected
4 000100LL Sensor Failure A sensor failure had been detected (the ’Limits’ field can provide additional diagnostic information in some situations.)
5 000101LL Last Known Value Communications have failed. However, the last known value is available. Note that the ‘age’ of the value may be determined from the TIMESTAMP in the OPCITEMSTATE.
6 000110LL Comm Failure Communications have failed. There is no last known value is available.
7 000111LL Out of Service The block is off scan or otherwise locked This quality is also used when the active state of the item or the group containing the item is InActive.
8-15   N/A Not used by OPC

 

Comment

Servers which do not support Substatus should return 0. Note that an ‘old’ value may be returned with the Quality set to BAD (0) and the Substatus set to 5. This is for consistency with the Fieldbus Specification. This is the only case in which a client may assume that a ‘BAD’ value is still usable by the application.
 
 

Substatus for UNCERTAIN Quality:

SSSS BIT VALUE DEFINE DESCRIPTION
0 010000LL Non-specific There is no specific reason why the value is uncertain.
1 010001LL Last Usable Value Whatever was writing this value has stopped doing so. The returned value should be regarded as ‘stale’. Note that this differs from a BAD value with Substatus 5 (Last Known Value). That status is associated specifically with a detectable communications error on a ‘fetched’ value. This error is associated with the failure of some external source to ‘put’ something into the value within an acceptable period of time. Note that the ‘age’ of the value can be determined from the TIMESTAMP in OPCITEMSTATE.
2-3   N/A Not used by OPC
4 010100LL Sensor Not Accurate Either the value has ‘pegged’ at one of the sensor limits (in which case the limit field should be set to 1 or 2) or the sensor is otherwise known to be out of calibration via some form of internal diagnostics (in which case the limit field should be 0).
5 010101LL Engineering Units Exceeded The returned value is outside the limits defined for this parameter. Note that in this case (per the Fieldbus Specification) the ‘Limits’ field indicates which limit has been exceeded but does NOT necessarily imply that the value cannot move farther out of range.
6 010110LL Sub-Normal The value is derived from multiple sources and has less than the required number of Good sources.
7-15   N/A Not used by OPC

 

Comment

Servers which do not support Substatus should return 0.
 
 

Substatus for GOOD Quality:

SSSS BIT VALUE DEFINE DESCRIPTION
0 110000LL Non-specific The value is good. There are no special conditions
1-5   N/A Not used by OPC
6 110110LL Local Override The value has been Overridden. Typically this is means the input has been disconnected and a manually entered value has been ‘forced’. 
7-15   N/A Not used by OPC

 

Comment

Servers which do not support Substatus should return 0.
 
 

The Limit BitField

The Limit Field is valid regardless of the Quality and Substatus. In some cases such as Sensor Failure it can provide useful diagnostic information.

LL BIT VALUE DEFINE DESCRIPTION
0 QQSSSS00 Not Limited The value is free to move up or down
1 QQSSSS01 Low Limited The value has ‘pegged’ at some lower limit
2 QQSSSS10 High Limited The value has ‘pegged’ at some high limit.
3 QQSSSS11 Constant The value is a constant and cannot move.

 

Comment

Servers which do not support Limit should return 0.

Symbolic Equates are defined for values and masks for these BitFields in the "QUALITY" section of the OPC header files.