OPCServer Object


Overview

The OPCServer object is the primary object that an OPC server exposes. The interfaces that this object provides include: The functionality provided by each of the above interfaces is defined in this section.

NOTE: Version 1.0 of this specification listed IEnumUnkown as an interface on the OPC Server. This was an error and has been removed. The semantics of QueryInterface do not allow such an implementation. The proper way to obtain a group enumerator is through IOPCServer::CreateGroupEnumerator.

IUnknown The server must provide a standard IUnknown Interface. Since this is a well defined interface it is not discussed in detail. See the OLE Programmer’s reference for additional information. This interface must be provided, and all functions implemented as required by Microsoft.. IOPCCommon Other OPC Servers such as alarms and events share this interface design. It provides the ability to set and query a LocaleID which would be in effect for the particular client/server session. That is, as with a Group definition, the actions of one client do not affect any other clients.

A quick reference for this interface is provided below. A more detailed discussion can be found in the OPC Overview Document.

HRESULT SetLocaleID (

[in] LCID dwLcid

);

HRESULT GetLocaleID (

[out] LCID *pdwLcid

);

HRESULT QueryAvailableLocaleIDs (

[out] DWORD *pdwCount,

[out, sizeis(, *pdwCount)] LCID **ppdwLcid

);

HRESULT GetErrorString(

[in] HRESULT dwError,

[out, string] LPWSTR *ppString

);

HRESULT SetClientName (

[in, string] LPCWSTR szName

);
 
 
 

IOPCServer

This is the main interface to an OPC server. The OPC server is registered with the operating system as specified in the Installation and Registration Chapter of this specification.

This interface must be provided, and all functions implemented as specified.
 
 

IOPCServer::AddGroup

HRESULT AddGroup(

[in, string] LPCWSTR szName,

[in] BOOL bActive,

[in] DWORD dwRequestedUpdateRate,

[in] OPCHANDLE hClientGroup,

[unique, in] LONG *pTimeBias,

[in] FLOAT * pPercentDeadband,

[in] DWORD dwLCID,

[out] OPCHANDLE * phServerGroup,

[out] DWORD *pRevisedUpdateRate,

[in] REFIID riid,

[out, iid_is(riid)] LPUNKNOWN * ppUnk

);
 
 

Description

Add a Group to a Server.
 
Parameters Description
szName Name of the group. The name must be unique among the other groups created by this client. If no name is provided (szName is pointer to a NUL string) the server will generate a unique name. The server generated name will also be unique relative to any existing public groups.
bActive FALSE if the Group is to be created as inactive.

TRUE if the Group is to be created as active. 

dwRequestedUpdateRate Client Specifies the fastest rate at which data changes may be sent to OnDataChange for items in this group. This also indicates the desired accuracy of Cached Data. This is intended only to control the behavior of the interface. How the server deals with the update rate and how often it actually polls the hardware internally is an implementation detail. Passing 0 indicates the server should use the fastest practical rate. The rate is specified in milliseconds.
hClientGroup Client provided handle for this group. [refer to description of data types, parameters, and structures for more information about this parameter]
pTimeBias Pointer to Long containing the initial TimeBias (in minutes) for the Group. Pass a NULL Pointer if you wish the group to use the default system TimeBias. This bias behaves like the Bias field in the Win32 TIME_ZONE_INFORMATION structure.
pPercentDeadband The percent change in an item value that will cause a subscription callback for that value to a client. This parameter only applies to items in the group that have dwEUType of Analog. [See discussion of Percent Deadband in Section 0]. A NULL pointer is equivalent to 0.0.
dwLCID The language to be used by the server when returning values (including EU enumeration’s) as text for operations on this group. This could also include such things as alarm or status conditions or digital contact states.
phServerGroup Place to store the unique server generated handle to the newly created group. The client will use the server provided handle for many of the subsequent functions that the client requests the server to perform on the group.
pRevisedUpdateRate The server returns the value it will actually use for the UpdateRate which may differ from the RequestedUpdateRate. 

Note that this may also be slower than the rate at which the server is internally obtaining the data and updating the cache.

In general the server should ‘round up’ the requested rate to the next available supported rate. The rate is specified in milliseconds. Server returns HRESULT of OPC_S_UNSUPPORTEDRATE when it returns a value in revisedUpdateRate that is different than RequestedUpdateRate.

riid The type of interface desired (e.g. IID_IOPCItemMgt)
ppUnk Where to store the returned interface pointer. NULL is returned for any FAILED HRESULT.

 

Return Codes
Return Code Description
S_OK The operation succeeded.
E_FAIL The operation failed.
E_OUTOFMEMORY Not enough memory
E_INVALIDARG An argument to the function was invalid.
OPC_E_DUPLICATENAME Duplicate name not allowed.
OPC_S_UNSUPPORTEDRATE Server does not support specified rate, server returns the rate that it can support in the revised update rate.
E_NOINTERFACE The interface(riid) asked for is not supported by the server.

Behavior

A Group is a logical container for a client to organize and manipulate data items.

The server will create a group object, and return a pointer to the interface requested by the client. If the client requests an optional interface that the server does not support, the server is expected to return an error indicating the interface is not supported.

The requested update rate / revised update rate behavior should be deterministic between client / server sessions. The client expects that for the same server configuration or workspace; adding a group with a requested update rate will always result in the same RevisedRate independent of the number of clients or items that have been added.
 
 

Comments The expected object lifetime behavior is as follows. Even if all the interfaces are released, the group will not be deleted until RemoveGroup is called. One way for the server to implement this is to assign the group an initial reference count of 2; one for the ‘Add’ and one for the Interface that was created. However, clients should not make assumptions about the Group’s reference count.

The client should not call RemoveGroup without releasing all interfaces for the group. The client should also not release the server without removing all private groups.

Since the server is the ‘container’ for the groups it is permissible for the server to forcibly remove any remaining groups at the time all of the server interfaces are released. (This should not be necessary for a well behaved client).

See also the CreateGroupEnumerator function.

The level of localization supported (dwLCID) is entirely server specific. Servers which do not support dynamic localization can ignore this parameter.

See the MoveToPublic function for additional requirements related to public groups.

The default TimeBias for the group will be that of the system in which the group is created.
 
 
 
 
 
 

IOPCServer::GetErrorString

HRESULT GetErrorString(

[in] HRESULT dwError,

[in] LCID dwLocale,

[out, string] LPWSTR *ppString

);
 
 

Description

Returns the error string for a server specific error code.
Parameters Description
dwError A server specific error code that the client application had returned from an interface function from the server, and for which the client application is requesting the server’s textual representation. 
dwLocale The locale for the returned string .
ppString Pointer to pointer where server supplied result will be saved

Return Codes
Return Code Description
E_FAIL The operation failed.
E_OUTOFMEMORY Not enough memory
E_INVALIDARG An argument to the function was invalid. (For example, the error code specified is not valid.)
S_OK The operation succeeded.

 

Comments

This is essentially the same function as is found in the newer IOPCCommon.

Note that if this method is called on a remote server, an RPC error may result. For this reason it is probably good practice for the client to attempt to call a local Win32 function if this function fails.

The expected behavior is that this will include handling of Win32 errors as well (such as RPC errors).

The Client must free the returned string.

It is recommended that the server put any OPC specific strings into an external resource to simplify translation.

To get the default value for the system, the dwLocale should be LOCALE_SYSTEM_DEFAULT.
 
 
 
 

IOPCServer::GetGroupByName

HRESULT GetGroupByName(

[in, string] LPCWSTR szName,

[in] REFIID riid,

[out, iid_is(riid)] LPUNKNOWN * ppUnk

);

Description

Given the name of a private group (created earlier by the same client), return an additional interface pointer. Use GetPublicGroupByName to attach to public groups.
Parameters Description
szName The name of the group. That is the group must have been created by the caller. 
riid The type of interface desired for the group (e.g. IOPCItemMgt)
ppUnk Pointer to where the group interface pointer should be returned. NULL is returned for any HRESULT other than S_OK.

Return Codes
Return Code Description
E_FAIL The operation failed.
E_OUTOFMEMORY Not enough memory
E_INVALIDARG An argument to the function was invalid.
S_OK The operation succeeded.
E_NOINTERFACE The interface(riid) asked for is not supported by the server.

Comments

This function can be used to reconnect to a private group for which all interface pointers have been released.

The client must release the returned interface when it is done with it.

If needed, the client can obtain the hServerGroup Handle via IOPCGroupStateMgt::GetState.
 
 

IOPCServer::GetStatus

HRESULT GetStatus(

[out] OPCSERVERSTATUS ** ppServerStatus

);

Description

Returns current status information for the server.
Parameters Description
ppServerStatus Pointer to where the OPCSERVERSTATUS structure pointer should be returned. The structure is allocated by the server.

Return Codes
Return Code Description
E_FAIL The operation failed.
E_OUTOFMEMORY Not enough memory
E_INVALIDARG An argument to the function was invalid.
S_OK The operation succeeded.

Comments

The OPCSERVERSTATUS is described later in this specification.

Client must free the structure as well as the VendorInfo string within the structure.

Periodic calls to GetStatus would be a good way for the client to determine that the server is still connected and available.
 
 

IOPCServer::RemoveGroup

HRESULT RemoveGroup(

[in] OPCHANDLE hServerGroup,

[in] BOOL bForce

);

Description

Deletes the Group
Parameters Description
hServerGroup Handle for the group to be removed
bForce Forces deletion of the group even if references are outstanding

Return Codes
Return Code Description
E_FAIL The operation failed.
E_OUTOFMEMORY Not enough memory
E_INVALIDARG An argument to the function was invalid.
S_OK The operation succeeded.
OPC_S_INUSE Was not be removed because references exist. Group will be marked as deleted, and will be removed automatically by the server when all references to this object are released.

Comments

A group is not deleted when all the client interfaces are released, since the server itself maintains a reference to the group. The client may still call GetGroupByName after all the interfaces have been released. RemoveGroup() causes the server to release it's `last' reference to the group, which results in the group being truly deleted.

In general, a well behaved client will call this function only after releasing all interfaces.

If interfaces still exist, Remove group will mark the group as ‘deleted’. Any further calls to this group via these interfaces will return E_FAIL. When all the interfaces are released, the group will actually be deleted. If bForce is TRUE then the group is deleted unconditionally even if references (interfaces) still exist. Subsequent use of such interfaces will result in an access violation.

This function should not be called for Public Groups.
IOPCServer::CreateGroupEnumerator

HRESULT CreateGroupEnumerator(

[in] OPCENUMSCOPE dwScope,

[in] REFIID riid,

[out, iid_is(riid)] LPUNKNOWN* ppUnk

);
 
 

Description

Create various enumerators for the groups provided by the Server.
Parameters Description
dwScope Indicates the class of groups to be enumerated

OPC_ENUM_PRIVATE_CONNECTIONS or

OPC_ENUM_PRIVATE enumerates all of the private groups created by the client 

OPC_ENUM_PUBLIC_CONNECTIONS or

OPC_ENUM_PUBLIC enumerates all of the public groups available in the server 

OPC_ENUM_ALL_CONNECTIONS or

OPC_ENUM_ALL enumerates all private groups and all public groups 

riid The interface requested. This must be IID_IEnumUnknown or IID_IEnumString.
ppUnk Where to return the interface. NULL is returned for any HRESULT other than S_OK.

NOTE: Version 1.0 of this specification described slightly different behavior for enumerating connected vs non-connected groups. However this behavior has been found to be difficult or impossible to implement in practice. The description here represents a simplification of this behavior. It is recommended that use of OPC_ENUM_PRIVATE_CONNECTIONS, OPC_ENUM_PUBLIC_CONNECTIONS, OPC_ENUM_ALL_CONNECTIONS be avoided by clients.

HRESULT Return Codes
Return Code Description
E_FAIL The operation failed.
E_OUTOFMEMORY Not enough memory
E_INVALIDARG An argument to the function was invalid.
S_OK The operation succeeded.
S_FALSE There is nothing to enumerate (There are no groups that satisfy the request)..
E_NOINTERFACE The interface(riid) asked for is not supported by the server.

Comments

Connected means an interface pointer exists.

Servers which do not support public groups will simply behave as if they had no public groups. That is they will NOT return E_INVALIDARG if the scope includes public groups.

IEnumUnknown creates an additional interface pointer to each group in the enumeration (even if the client already has a connection to the group). If the server has a large number of public groups available then this may involve considerable overhead as well as requiring additional cleanup by the client. In general, enumerating groups by name will be much faster.

In the case of IEnumUnknown (per the COM specification) the client must also release all of the returned IUnknown pointers when he is done with them.
 
 
 
 

IConnectionPointContainer (on OPCServer) This interface provides access to the connection point for IOPCShutdown.

The general principles of ConnectionPoints are not discussed here as they are covered very clearly in the Microsoft Documentation. The reader is assumed to be familiar with this technology. OPC 2.0 Compliant Servers are REQUIRED to support this interface.

Likewise the details of the IEnumConnectionPoints, IConnectionPoint and IEnumConnections interfaces are well defined by Microsoft and are not discussed here.

Note: OPC Compliant servers are not required to support more than one connection between each Server and the Client. Given that servers are client specific entities it is expected that a single connection will be sufficient for virtually all applications. For this reason (as per the COM Specification) the EnumConnections method for IConnectionPoint interface for the IOPCShutdown is allowed to return E_NOTIMPL.
 
 

IConnectionPointContainer::EnumConnectionPoints HRESULT EnumConnectionPoints(

IEnumConnectionPoints **ppEnum

);
 
 

Description Create an enumerator for the Connection Points supported between the OPC Group and the Client.
Parameters Description
ppEnum Where to save the pointer to the connection point enumerator. See the Microsoft documentation for a discussion of IEnumConnectionPoints.
   

HRESULT Return Codes
Return Code Description
S_OK The function was successful.
For other codes see the OLE programmers reference  

Comments

OPCServers must return an enumerator that includes IOPCShutdown. Additional vendor specific callbacks are also allowed. IConnectionPointContainer:: FindConnectionPoint HRESULT FindConnectionPoint(

REFIID riid,

IConnectionPoint **ppCP

);
 
 

Description Find a particular connection point between the OPC Server and the Client.
Parameters Description
ppCP Where to store the Connection Point. See the Microsoft documentation for a discussion of IConnectionPoint.
riid The IID of the Connection Point. (e.g. IID_IOPCShutdown)

HRESULT Return Codes
Return Code Description
S_OK The function was successful.
For other codes see the OLE programmers reference  

Comments

OPCServers must support IID_IOPCShutdown. Additional vendor specific callbacks are also allowed.


IOPCItemProperties

Overview

This interface can be used by clients to browse the available properties (also refered to as attributes or parameters) associated with an ITEMID and to read the current values of these properties. In some respects the functionality is similar to that provided by BrowseServerAddressSpace, by EnumItemAttributes and by the SyncIO Read function. It differs from these interfaces in two important respects; (a) it is intended be much easier to use and (b) it is not optimized for efficient access to large amounts of data. Rather it is intended to allow an application to easily browse and read small amounts of additional information specific to a particular ITEMID.

The design of this interface is based upon the assumption is that most ITEMIDs are associated with more complex objects within the underlying system which have additional information (properties) beyond their value, quality and timestamp. This interface allows a flexible and convenient way to browse and read this information without imposing any particular design structure on the underlying system.

It also allows such information to be read without the need to create and manage OPCGroups.

Typical Use

Typical Client use of this interface would be to obtain an ITEMID either by obtaining a 'LEAF' via BrowseServerAddress or via direct input to an edit box by the user. That ITEMID would be passed to QueryAvailableProperties(). The resulting list would be presented to the user. He would select the properties he wanted to see from the list. The client would pass this set to GetItemProperties () to get a 'snapshot' of the data. Optionally the client could pass the set to LookupItemIDs and use the resulting set of ITEMIDs to create an OPCGroup to be used to repeatedly obtain the data.

Examples

This is just an example. It is not intended to impose any particular structure on any server implementation.

A typical OPC ITEMID might be FIC101.CV. This could represent the current value of a tag or function block called FIC101. This function block commonly has other properties associated with it such as Engineering Units, a loop description, etc. This function block could also have alarm limits and status, a setpoint, tuning parameters as well as documentation cross references, maintenance information, help screens, default operator displays and a limitless set of other properties. All of these properties are associated with each other by virtue of their common association with FIC101. This interface provides a convenient shortcut to accessing those related properties.

An MMI package for example might use this interface to allow the user to indicate that the Hi and Lo Engineering Units values should be used to scale a bargraph representation of the value.

Note that because these associations can be 'many to many' and can also be circular, a client application would not want to automatically investigate them all.

It is NOT intended that property browsing be hierarchical.

Another similar example could be a function block such as a TIMER or COUNTER in a high end PLC where various Properties are associated with each object.

How ‘Properties’ relate to ItemIDs.

In most cases it is expected (but not required) that such properties can also be accessed via ItemIDs such as FIC101.HI_EU, FIC101.DESC, FIC101.ALMSTAT, etc. These related ITEMIDs could be used in an OPCGroup. This interface provides a way to easily determine if such an alternate method of access can be used for the properties if large amounts of information need to be obtained more efficiently.

Property IDs

The server will need to assign DWORD ID codes to the properties. This allows the client to more easily manage the list of properties it wants to access. These properties are divided (somewhat arbitrarily) into 3 ‘sets’. The OPC ‘Fixed’ set contains properties that are identical to some of those returned by OPCITEMATTRIBUTES, the ‘recommended’ set is expected to be common to many servers, the ‘vendor specific’ set contains additional properties as appropriate. The assigned IDs for the first two sets are fixed. The vendor specific properties should use ID codes above 5000.

The OPC Property Sets

This is a set of property IDs that are common to many servers. Servers which provide the coresponding properties must do so using the ID codes from this list. Symbolic equates for these properties are provided in the OPCProps.H file. (See Appendix to this document).

ID Set 1 - OPC Specific Properties - This includes information directly related to the OPC Server for the system.

ID DATATYPE of returned VARIANT STANDARD DESCIPTION
1 VT_I2 "Item Canonical DataType"

(VARTYPE stored in an I2)

2 <varies> "Item Value"

(VARIANT)

Note the type of value returned is as indicated by the "Item Canonical DataType" above and depends on the item. This will behave like a read from DEVICE.

3 VT_I2 "Item Quality"

(OPCQUALITY stored in an I2). This will behave like a read from DEVICE.

4 VT_DATE  "Item Timestamp"

(will be converted from FILETIME). This will behave like a read from DEVICE.

5 VT_I4  "Item Access Rights"

(OPCACCESSRIGHTS stored in an I4)

6 VT_R4 "Server Scan Rate" 

In Milliseconds. This represents the fastest rate at which the server could obtain data from the underlying data source. The nature of this source is not defined but is typically a DCS system, a SCADA system, a PLC via a COMM port or network, a Device Network, etc. This value generally represents the ‘best case’ fastest RequestedUpdateRate which could be used if this item were added to an OPCGroup.

The accuracy of this value (the ability of the server to attain ‘best case’ performance) can be greatly affected by system load and other factors.

7-99   Reserved for future OPC use
ID Set 2 - Recommended Properties - This is additional information which is commonly associated with ITEMs. This includes additional ranges of values that are reserved for use by other future OPC specifications. For information about the newest field ID assignments, consult the other OPC Foundation specifications.

The position of the OPC Foundation is that if you have properties associated with an item which seem to fit the descriptions below then it is recommended that you use these specific descriptions and ID codes to expose those properties via this interface.

A server can provide any subset of these values (or none of them).

ID DATATYPE of returned VARIANT STANDARD DESCIPTION
    Properties related to the Item Value.
100 VT_BSTR "EU Units"

e.g. "DEGC" or "GALLONS"

101 VT_BSTR "Item Description"

e.g. "Evaporator 6 Coolant Temp"

102 VT_R8 "High EU"

Present only for ‘analog’ data. This represents the highest value likely to be obtained in normal operation and is intended for such use as automatically scaling a bargraph display.

e.g. 1400.0

103 VT_R8 "Low EU"

Present only for ‘analog’ data. This represents the lowest value likely to be obtained in normal operation and is intended for such use as automatically scaling a bargraph display.

e.g. -200.0

104 VT_R8 "High Instrument Range"

Present only for ‘analog’ data. This represents the highest value that can be returned by the instrument.

e.g. 9999.9

105 VT_R8 "Low Instrument Range"

Present only for ‘analog’ data. This represents the lowest value that can be returned by the instrument.

e.g. -9999.9

106 VT_BSTR "Contact Close Label"

Present only for ‘discrete' data. This represents a string to be associated with this contact when it is in the closed (non-zero) state

e.g. "RUN", "CLOSE", "ENABLE", "SAFE" ,etc.

107 VT_BSTR "Contact Open Label"

Present only for ‘discrete' data. This represents a string to be associated with this contact when it is in the open (zero) state

e.g. "STOP", "OPEN", "DISABLE", "UNSAFE" ,etc.

108 VT_I4 "Item Timezone" The difference in minutes between the items UTC Timestamp and the local time in which the item value was obtained. See the OPCGroup TimeBias property. Also see the WIN32 TIME_ZONE_INFORMATION structure.
109-199   Reserved for future OPC use. Additional IDs may be added without revising the interface ID.
     
    Properties related operator displays
200 VT_BSTR "Default Display"

The name of an operator display associated with this ItemID

201 VT_I4 "Current Foreground Color"

The COLORREF in which the item should be displayed

202 VT_I4 "Current Background Color"

The COLORREF in which the item should be displayed

203 VT_BOOL "Current Blink"

Should a display of this item blink?

204 VT_BSTR "BMP File"

e.g. C:\MEDIA\FIC101.BMP

205 VT_BSTR "Sound File"

e.g. C:\MEDIA\FIC101.WAV, or .MID

206 VT_BSTR "HTML File"

e.g. http:\\mypage.com/FIC101.HML

207 VT_BSTR "AVI File"

e.g. C:\MEDIA\FIC101.AVI

207-299   Reserved for future OPC use. Additional IDs may be added without revising the interface ID.
     
    Properties Related to Alarm and Condition Values (preliminary)…

IDs 300 to 399 are reserved for use by OPC Alarms and Events.

See the OPC Alarm and Events specification for additional information.

300 VT_BSTR "Condition Status"

The current alarm or condition status associated with the Item

e.g. "NORMAL", "ACTIVE", "HI ALARM", etc

301 VT_BSTR "Alarm Quick Help"

A short text string providing a brief set of instructions for the operator to follow when this alarm occurs.

302 VT_BSTR

|VT_ARRAY

"Alarm Area List"

An array of stings indicating the plant or alarm areas which include this ItemID.

303 VT_BSTR "Primary Alarm Area"

A string indicating the primary plant or alarm area including this ItemID

304 VT_BSTR "Condition Logic"

An arbitrary string describing the test being performed.

e.g. "High Limit Exceeded" or "TAG.PV >= TAG.HILIM"

305 VT_BSTR "Limit Exceeded"

For multistate alarms, the condition exceeded

e.g. HIHI, HI, LO, LOLO

306 VT_R8 "Deadband"
307 VT_R8 "HiHi Limit"
308 VT_R8 "Hi Limit"
309 VT_R8 "Lo Limit"
310 VT_R8 "LoLo Limit"
311 VT_R8 "Rate of Change Limit"
312 VT_R8 "Deviation Limit"
313-399   Reserved for future OPC Alarms and Events use. Additional IDs may be added without revising the interface ID.
     
400-4999   Reserved for future OPC use. Additional IDs may be added without revising the interface ID.
NOTE the OPC Foundation reserves the right to expand this list from time to time. Clients should be prepared to deal with this.

ID Set 3 - Vendor specific Properties

5000… VT_xxx Vendor Specific Properties. ID codes for these properties must have values of 5000 or greater. They do not need to be sequential. The datatypes must be compatable with the VARIANT.
     
The client should take care dealing with these vendor specific IDs - i.e. not make assumptions about them. Different vendors may not provide the same information for IDs of 5000 and above.

Note again that this interface is NOT intended to allow efficient access to large amounts of data.

The LocaleID of the server (as set by IOPCCommon::SetLocaleID) will be used by the server to localize any data items returned as strings. The item descriptions are not localized.
 
 
 
 

IOPCItemProperties::QueryAvailableProperties HRESULT QueryAvailableProperties(

[in] LPWSTR szItemID,

[out] DWORD * pdwCount,

[out, size_is(,*pdwCount)] DWORD **ppPropertyIDs,

[out, size_is(,*pdwCount)] LPWSTR *ppDescriptions,

[out, size_is(,*pdwCount)] VARTYPE **ppvtDataTypes

);
 
 

Description Return a list of ID codes and descriptions for the available properties for this ITEMID. This list may differ for different ItemIDs. This list is expected to be relatively stable for a particular ItemID. That is, it could be affected from time to time by changes to the underlying system’s configuration.
Parameters Description
szItemID The ItemID for which the caller wants to know the available properties
pdwCount The number of properties returned
ppPropertyIDs DWORD IDs for the returned properties. These IDs can be passed to GetItemProperties or LookupItemIDs
ppDescriptions A brief vendor supplied text description of each property. NOTE LocalID does not apply to Descriptions. They are from the tables above.
ppvtDataTypes The datatype which will be returned for this property by GetItemProperties.

 

HRESULT Return Codes
Return Code Description
S_OK The function was successful.
OPC_E_UNKNOWNITEMID The ItemID is not in the server address space
OPC_E_INVALIDITEMID The ItemID is not syntactically valid
E_OUTOFMEMORY Not enough Memory.
E_INVALIDARG An invalid argument was passed
E_FAIL The function failed.

 

Comments

The ItemID is passed to this function because servers are allowed to return different sets of properties for different ItemIDs. IOPCItemProperties::GetItemProperties HRESULT GetItemProperties(

[in] LPWSTR szItemID,

[in] DWORD dwCount,

[in, size_is(dwCount)] DWORD * pdwPropertyIDs,

[out, size_is(,dwCount)] VARIANT ** ppvData,

[out, size_is(,dwCount)] HRESULT **ppErrors

);
 
 

Description Return a list of the current data values for the passed ID codes.
Parameters Description
szItemID The ItemID for which the caller wants to read the list of properties.
dwCount The number of properties passed
ppPropertyIDs DWORD IDs for the requested properties. These IDs were returned by QueryAvailableProperties or obtained from the fixed list described earlier.
ppvData An array of count VARIANTS returned by the server which contain the current values of the requested properties.
ppErrors Error array indicating wether each property was returned.

 

HRESULT Return Codes
Return Code Description
S_OK The function was successful.
OPC_E_UNKNOWNITEMID The ItemID is not in the server address space
OPC_E_INVALIDITEMID The ItemID is not syntactically valid
E_OUTOFMEMORY Not enough Memory.
E_INVALIDARG An invalid argument was passed
E_FAIL The function failed.

 

‘Errors’ Return Codes
Return Code Description
S_OK The corresponding PropertyID was read.
OPC_E_INVALID_PID The passed Property ID is not defined for this item.
E_xxx The passed Property ID could not be read. The server can return a server specific error code to provide a detailed explanation as to why this property could not be read. This error code can be passed to GetErrorMessage. In general this will be the same set of errors as is returned by the OPC Read function.

 

Comments

The caller must Free the returned Variants and Errors array. The client must first do a VariantClear() on each of the returned Variants.

Clients should not use this interface to obtain large amounts of data. Clearly each server vendor will provide the best performace possible however as a practical matter it is expected that the design of this interface will make it difficult for the server to optimize performace. See LookupItemIDs.
 
 

IOPCItemProperties::LookupItemIDs HRESULT LookupItemIDs(

[in] LPWSTR szItemID,

[in] DWORD dwCount,

[in, size_is(dwCount)] DWORD *pdwPropertyIDs,

[out, string, size_is(,dwCount)] LPWSTR ** ppszNewItemIDs,

[out, size_is(,dwCount)] HRESULT **ppErrors

);
 
 

Description Return a list of ITEMIDs (if available) for each of the passed ID codes. These indicate the ITEMID which could be added to an OPCGroup and used for more efficient access to the data corresponding to the Item Properties.
Parameters Description
szItemID The ItemID for which the caller wants to lookup the list of properties
dwCount The number of properties passed
pdwPropertyIDs DWORDIDs for the requested properties. These IDs were returned by QueryAvailableProperties
ppszNewItemIDs The returned list of ItemIDs.
ppErrors Error array indicating wether each New ItemID was returned.

 

HRESULT Return Codes
Return Code Description
S_OK The function was successful.
OPC_E_UNKNOWNITEMID The ItemID is not in the server address space
OPC_E_INVALIDITEMID The ItemID is not syntactically valid
E_OUTOFMEMORY Not enough Memory.
E_INVALIDARG An invalid argument was passed
E_FAIL The function was not successful

 

‘Errors’ Return Codes
Return Code Description
S_OK The corresponding Property ID was translated into an ItemID.
OPC_E_INVALID_PID The passed Property ID is not defined for this item.
E_FAIL The passed Property ID could not be translated into an ItemID.

 

Comments

It is expected and recommended that servers will allow most or all item properties to be translated into specific ItemIDs.

The caller must Free the returned NewItemIDs and Errors array.
 
 

IOPCServerPublicGroups (optional) This optional interface allows management of public groups. Public Groups An application may be designed so that the same groups of data items are used by many clients. In those cases the optional Public Group capability of the server provides a convenient mechanism for both clients and servers to share these groups.

Public groups may be created by the server or they may be created by a client. When created by the client, they are first created as private groups and then converted to public groups by MoveToPublic.

A client can enumerate the available public groups by name using IOPCServer::CreateGroupEnumerator. He can ‘connect’ to a public group by calling GetPublicGroupByName. He can examine the contents of the group via IEnumOPCItemAttributes. He can assign client handles and datatypes that are meaningful for the particular client using various IOPCItemMgt functions.

Once a client connects to a Public group, it behaves very much like a private group. He can activate and deactivate the group or items in the group. He can set client handles for the group and items within the group. He can set requested data type for the items in the group. All of these operations affect only that particular client. They do not affect the behavior of other clients connected to that group. The exception to this behavior is that he cannot add or remove items.
 
 
 
 

IOPCServerPublicGroups:: GetPublicGroupByName

HRESULT GetPublicGroupByName(

[in, string] LPCWSTR szName,

[in] REFIID riid,

[out, iid_is(riid)] LPUNKNOWN * ppUnk

);
 
 

Description

‘Connects’ the client to a public group. This returns an interface pointer to the group.
Parameters Description
szName Name of group to be connected
riid requested interface
ppUnk pointer to place to store interface. NULL is returned for any HRESULT other than S_OK

Return Codes
Return Code Description
E_FAIL The operation failed.
E_OUTOFMEMORY Not enough memory
E_INVALIDARG An argument to the function was invalid.
S_OK The operation succeeded.
E_NOINTERFACE The interface(riid) asked for is not supported by the server.
OPC_E_NOTFOUND Requested Public Group was not found.

Comments

If needed, the client can obtain the hServerGroup Handle via IOPCGroupStateMgt::GetState.

Note that when the client’s last interface for the public group is released, the client is effectively disconnected from the group. At this point the server should release any resources or instance data associated with this particular client’s connection to the public group. It is not necessary for the client to call RemoveGroup or RemovePublicGroup to free these client specific resources.
 
 

IOPCServerPublicGroups:: RemovePublicGroup

HRESULT RemovePublicGroup(

[in] OPCHANDLE hServerGroup ,

[in] BOOL bForce

);
 
 

Description

Delete a public group.
Parameters Description
hServerGroup Handle of group to be removed.
bForce Forces deletion of the group even if references are outstanding

Return Codes
Return Code Description
E_FAIL The operation failed.
E_OUTOFMEMORY Not enough memory
E_INVALIDARG An argument to the function was invalid.
S_OK The operation succeeded.
OPC_S_INUSE Was not be removed because references exist. Group will be marked as deleted, and will be removed by the server when all references to this object are released.

Comments

A public group is not deleted when all the client interfaces are released, since the server itself maintains a reference to the group. The client may still call GetPublicGroupByName after all the interfaces have been released. RemovePublicGroup() causes the server to release it's `last' reference to the group, which results in the group being truly deleted.

It is permissible for a server to publish ‘hard coded’ groups which cannot be deleted. The server should return E_FAIL in this case.

In general, a well behaved client will call this function only after releasing all interfaces.

If interfaces still exist, RemovePublicGroup will mark the group as ‘deleted’. Any further calls to this group via these interfaces will return E_FAIL. When all the interfaces are released, the group will actually be deleted. If bForce is TRUE then the group is deleted unconditionally even if references (interfaces) still exist. Subsequent use of such interfaces will result in an access violation.

Note that any client can delete a public group. You can get the server handle of the group by calling IOPCGroupStateMgt::GetState.
 
 

IOPCBrowseServerAddressSpace (optional) This interface provides a way for clients to browse the available data items in the server, giving the user a list of the valid definitions for an ITEM ID. It allows for either flat or hierarchical address spaces and is designed to work well over a network. It also insulates the client from the syntax of a server vendor specific ITEM ID.

NOTE: Version 1.0A of the specification stated that each instance of this interface was a separate object (like an enumerator), which would have allowed multiple independent browse sessions by the same client on the server address space. This turns out to be in violation of the rules of COM and as a result it does not work in combination with DCOM. In practice, this interface MUST be implemented (like any other interface) as a separate interface on the single underlying Data Access Object. The text of this section has been modified to reflect this. Note that the 'footprint' of the interface is unchanged for 2.0.

Note that the Data Access Server object maintains state information related to browsing (i.e. the current position in the address hierarchy) on behalf of the client using this interface. Since there is just one underlying Server object, there is just a single copy of this state information. Therefore the client CANNOT create a separate and independent browser object by doing a second QueryInterface for IOPCBrowseServerAddressSpace. (Doing this would simply give him a second copy of the original interface). If a second, independent browser object is required by a client, the client would need to create a second OPC Data Access Object and perform a QueryInterface for IOPCBrowseServerAddressSpace on that object.

It is assumed that the underlying server address space is either flat or hierarchical. A flat space will always be presented to the client as Flat. A hierarchical space can be presented to the client as either flat or hierarchical.

A hierarchical presentation of the server address space would behave much like a file system, where the directories are the branches or paths, and the files represent the leaves or items. For example, a server could present a control system by showing all the control networks, then all of the devices on a selected network, and then all of the classes of data within a device, then all of the data items of that class. A further breakdown into vendor specific ‘Units’ and ‘Lines’ might be appropriate for a BATCH system.

The browse position is initially set to the ‘root’ of the address space. The client can optionally choose a starting point within a hierarchical space by calling ChangeBrowsePosition using OPC_BROWSE_TO. For a FLAT space this is ignored. For a HIERARCHICAL space you may pass any partial path (or a pointer to a NUL string to indicate the root). This sets an initial position from which you can browse up or down.

The Client can browse the items below (contained in) the current position via BrowseOPCItemIDs. For a hierarchical space you can specify BRANCH (which returns things on that level with children) or LEAF (things on that level without children)- or FLAT (everything including children of children). This gives you back a String enumerator.

This browse can also be filtered by a vendor specific filter string, by datatype, or by Access Rights.

In a hierarchy, the enumerator will return ‘short’ strings; the name of the ‘child’. These short strings will generally not be sufficient for AddItem. The client should always convert this short string to a ’fully qualified’ string via GetItemID. For example the short string might be TIC101; the fully qualified string might be AREA1.REACTOR5.TIC101. Note that the Server fills in any needed delimiters.

This ItemID can optionally be passed to BrowseAccessPaths to get a list of valid access paths to this item. (this returns another string enumerator).

If the client browsed for BRANCHs (things with children) then he can pass the result (short string) to ChangeBrowsePosition to move ‘down’. This method can also move ‘up’ in which case the short string is not used.

Examples of a Hierarchical Space:

Example 1

<ROOT>

AREA1 (branch)

REACTOR10 (branch)

TIC1001 (branch)

CURRENT_VALUE (leaf)

SETPOINT

ALARM_STATUS

LOOP_DESCIPTION

TIC1002

CURRENT_VALUE

etc…

REACTOR11

etc…

AREA2

etc…

Example 2

<ROOT>

PLC_STATION_1 (branch)

ANALOG_VALUES (branch)

40001 (leaf)

40002

etc…

IOPCBrowseServerAddressSpace:: QueryOrganization HRESULT QueryOrganization( [out] OPCNAMESPACETYPE * pNameSpaceType

);
 
 

Description Provides a way to determine if the underlying system is inherently flat or hierarchical and how the server may represent the information of the address space to the client.
Parameters Description
pNameSpaceType Place to put OPCNAMESPACE result which will be OPC_NS_HIERARCHIAL or OPC_NS_FLAT

Return Codes
Return Code Description
E_FAIL The operation failed.
E_OUTOFMEMORY Not enough memory
E_INVALIDARG An argument to the function was invalid.
S_OK The operation succeeded.

Comments

FLAT and HIERARCHICAL spaces behave somewhat different. If the result is ‘FLAT’ then the client knows that there is no need to pass the BRANCH or LEAF flags to BrowseOPCItemIDs or to call ChangeBrowsePosition


IOPCBrowseServerAddressSpace:: ChangeBrowsePosition

HRESULT ChangeBrowsePosition(

[in] OPCBROWSEDIRECTION dwBrowseDirection,

[in, string] LPCWSTR szString

);
 
 

Description Provides a way to move ‘up’ or ‘down’ or 'to' in a hierarchical space.
Parameters Description
dwBrowseDirection OPC_BROWSE_UP or OPC_BROWSE_DOWN or OPC_BROWSE_TO.
szString For DOWN, the name of the branch to move into. This would be one of the strings returned from BrowseOPCItemIDs. 

E.g. REACTOR10

For UP this parameter is ignored and should point to a NUL string.

For TO a fully qualified name (e.g. as returned from GetItemID) or a pointer to a NUL string to go to the 'root'.

E.g. AREA1.REACTOR10.TIC1001

Return Codes
Return Code Description
E_FAIL The operation failed.
E_OUTOFMEMORY Not enough memory
E_INVALIDARG An argument to the function was invalid.
S_OK The operation succeeded.

Comments

The function will return E_FAIL if called for a FLAT space.

An error is returned if the passed string does not represent a ‘branch’.

Moving UP from the ‘root’ will return E_FAIL.

Note OPC_BROWSE_TO is new for version 2.0. Clients should be prepared to handle E_INVALIDARG if they pass this to a 1.0 server.
 
 
 
 

IOPCBrowseServerAddressSpace:: BrowseOPCItemIDs HRESULT BrowseOPCItemIDs(

[in] OPCBROWSETYPE dwBrowseFilterType,

[in, string] LPCWSTR szFilterCriteria,

[in] VARTYPE vtDataTypeFilter,

[in] DWORD dwAccessRightsFilter,

[out] LPENUMSTRING * ppIEnumString

);
 
 

Description Returns an IENUMString for a list of ItemIDs as determined by the passed parameters. The position from the which the browse is done can be set via ChangeBrowsePosition.
Parameters Description
dwBrowseFilterType OPC_BRANCH - returns only items that have children
OPC_LEAF - returns only items that don’t have children
OPC_FLAT - returns everything at and below this level including all children of children - basically ‘pretends’ that the address space in actually FLAT 
This parameter is ignored for FLAT address space.
szFilterCriteria A server specific filter string. This is entirely free format and may be entered by the user via an EDIT field. Although the valid criteria are vendor specific, source code for a recommended filter function is included in an Apppendix at the end of this document. This particular filter function is commonly used by OPC interfaces and is very similar in functionality to the LIKE function in visual basic. A pointer to a NUL string indicates no filtering.
vtDataTypeFilter Filter the returned list based in the available datatypes (those that would succeed if passed to AddItem). VT_EMPTY indicates no filtering. 
dwAccessRightsFilter Filter based on the AccessRights bit mask (OPC_READABLE or OPC_WRITEABLE). 0 indicates no filtering. 
ppIEnumString Where to save the returned interface pointer. NULL if the HRESULT is other than S_OK or S_FALSE

Return Codes

Return Code Description
S_OK The operation succeeded.
S_FALSE There is nothing to enumerate. (However an Enumerator is still returned and must be released).
E_FAIL The operation failed.
E_OUTOFMEMORY Not enough memory
E_INVALIDARG An argument to the function was invalid.
OPC_E_INVALIDFILTER The filter string was not valid

 

Comments

The returned enumerator may have nothing to enumerate if no ItemIDs satisfied the filter constraints. The strings returned by the enumerator represent the BRANCHs and LEAFS contained in the current level. They do NOT include any delimiters or ‘parent’ names. (See GetItemID).

Whenever possible the server should return strings which can be passed directly to AddItems. However, it is allowed for the Server to return a ‘hint’ string rather than an actual legal Item ID. For example a PLC with 32000 registers could return a single string of "0 to 31999" rather than return 32,000 individual strings from the enumerator. For this reason (as well as the fact that browser support is optional) clients should always be prepared to allow manual entry of ITEM ID strings. In the case of ‘hint’ strings, there is no indication given as to whether the returned string will be acceptable by AddItem or ValidateItem

Clients are allowed to get and hold Enumerators for more than one ‘browse position’ at a time.

Changing the browse position will not affect any String Enumerator the client already has.

The client must Release each Enumerator when he is done with it.
 
 

IOPCBrowseServerAddressSpace:: GetItemID HRESULT GetItemID(

[in] LPCWSTR szItemDataID,

[out, string] LPWSTR * szItemID

);
 
 

Description Provides a way to assemble a ‘fully qualified’ ITEM ID in a hierarchical space. This is required since the browsing functions return only the components or tokens which make up an ITEMID and do NOT return the delimiters used to separate those tokens. Also, at each point one is browsing just the names ‘below’ the current node (e.g. the ‘units’ in a ‘cell’).
Parameters Description
szItemDataID The name of a BRANCH or LEAF at the current level. or a pointer to a NUL string. Passing in a NUL string results in a return string which represents the current position in the hierarchy. 
szItemID Where to return the resulting ItemID.

Return Codes
Return Code Description
E_FAIL The function failed 
E_INVALIDARG An argument to the function was invalid.
E_OUTOFMEMORY Not enough memory
S_OK The function was successful

Comments

A client would browse down from AREA1 to REACTOR10 to TIC1001 to CURRENT_VALUE. As noted earlier the client sees only the components, not the delimiters which are likely to be very server specific. The function rebuilds the fully qualified name including the vendor specific delimiters for use by ADDITEMs. An extreme example might be a server that returns:
\\AREA1:REACTOR10.TIC1001[CURRENT_VALUE]

It is also possible that a server could support hierarchical browsing of an address space that contains globally unique tags. For example in the case above, the tag TIC1001.CURRENT_VALUE might still be globally unique and might therefore be acceptable to AddItem. However the expected behavior is that (a) GetItemID will always return the fully qualified name (AREA1.REACTOR10.TIC1001.CURRENT_VALUE) and that (b) that the server will always accept the fully qualified name in AddItems (even if it does not require it).

This function does not need to be called for a FLAT space. If it is called, then it will simply return the same string that was passed in.

It is valid to form an ItemID that represents a BRANCH (e.g. AREA1.REACTOR10). This could happen if you pass a BRANCH (AREA1) rather than a LEAF (CURRENT_VALUE). The resulting string might fail if passed to AddItem but could be passed to ChangeBrowsePosition using OPC_BROWSE_TO.

The client must free the returned string.

ItemID is the unique ‘key’ to the data, it is considered the ‘what’ or ‘where’ that allows the server to connect to the data source.
 
 

IOPCBrowseServerAddressSpace:: BrowseAccessPaths HRESULT BrowseAccessPaths(

[in, string] LPCWSTR szItemID,

[out] LPENUMSTRING * ppIEnumString

);
 
 

Description Provides a way to browse the available AccessPaths for an ITEM ID.
Parameters Description
szItemID Fully Qualified ItemID
ppIEnumString Where to save the returned string enumerator. NULL if the HRESULT is other that S_OK.

Return Codes
Return Code Description
E_FAIL The function failed 
E_INVALIDARG An argument to the function was invalid.
S_FALSE There is nothing to enumerate
E_OUTOFMEMORY Not enough memory
E_NOTIMPL The server does not require or support access paths.
S_OK The function was successful

Comments

Clients are allowed to get Access Path Enumerators for more than one item at a time.

Changing the browse position will not affect any enumerator the client already has.

The client must Release each Enumerator when he is done with it.

AccessPath is the "how" for the server to get the data specified by the itemID (the what). The client uses this function to identify the possible access paths for the specified itemID.

IPersistFile (optional)

This is a standard implementation of the IPersistFile Interface. The descriptions below are brief and describe behavior specific to OPC. Refer to the OLE programmers reference for additional information.

This optional interface allows Clients to load or save a server ‘configuration’. The reason for providing this interface is to allow a client application to have access to any ‘hooks’ it might need to get the system started or to change the system configuration without requiring the user to start a separate program.

The filename discussed below tells the server where it’s configuration information is located. Filename syntax and semantics is server specific, and may include the fully qualified path and file name, or may refer to a proprietary database where the server’s configuration is stored. The format and content of the file or database is server specific.

Note that this interface does NOT save any client specific information such as group and item definitions. Rather, it is a ‘hook’ intended to load or save the server configuration such as a SCADA or DCS database, communications baud rates, PLC station addresses, etc.

IPersistFile::IsDirty

HRESULT IsDirty(

void

);
 
 

Description

Returns whether or not there have been any configuration changes (by any client) since the last save operation. Parameters

Return Codes
Return Code Description
S_OK The server has configuration information that has been modified since the last save operation.
S_FALSE The server does not have configuration information that has been modified since the last save operation.

Comments

The client cannot change any of the configuration of the server address space through a standard OPC interface. The client uses this function to determine if the configuration has been modified by a server specific configuration tool or by a client using a server specific configuration interface. This function could be used by the client before shutting the server down to determine if the server’s configuration needs to be saved.
 
 
IPersistFile::Load

HRESULT Load(

[in] LPCOLESTR pszFileName,

[in] DWORD dwMode

);
 
 

Description

Instructs the server to load the server’s configuration data from the file (pszFileName). The previous configuration (if any) is replaced by the new configuration. OPC servers are assumed to support a single (global) active configuration. That is, a load will affect all other OPC clients which are accessing this server.

The exact effect of doing a load while groups and subscriptions are active is server specific. In general, it is assumed that this will cause some or all of the items in the active groups to disappear from the server address space. Such items would subsequently return a BAD Quality.

Parameters Description
pszFileName The filename from which the server configuration information is to be loaded.
dwMode Access mode to be used on the file. See ‘Storage Access Mode Flags" in the OLE programmer’s reference for more information.

Return Codes
Return Code Description
S_OK The server successfully loaded configuration information from the file specified.
E_FAIL The server was unsuccessful in loading the configuration information from the file specified.
E_OUTOFMEMORY Not enough memory to load configuration.
OPC_E_INVALIDCONFIGFILE The server's configuration file is an invalid format.

Comments

In most cases, an error during load will leave the server without a valid configuration.

A load will cause other clients connected to this server to be effectively disconnected, or the results of the other clients subsequent interactions with the server to be unknown.

IPersistFile::Save

HRESULT Save(

[in, unique] LPCOLESTR pszFileName,

[in] BOOL fRemember

);
 
 

Description

Save current configuration. Parameters
Parameters Description
pszFileName The filename to which the server configuration information is to be saved.
fRemember Determines of the logically associated filename for this configuration should be changed (if TRUE) or not (if FALSE).

 

Return Codes
Return Code Description
S_OK The server successfully saved configuration information
E_FAIL The server was unsuccessful in saving the configuration
OPC_E_INVALIDCONFIGFILE The server's configuration file is an invalid format.

Comments

Save should clear the server’s configuration dirty flag (as returned from IsDirty interface). IPersistFile::SaveCompleted

HRESULT SaveCompleted(

[in, unique] LPCOLESTR pszFileName

);
 
 

Description

This function may be implemented as a ‘stub’.
Parameters Description
pszFileName The filename to which the configuration was previously saved using IPersistFile::Save

Return Codes
Return Code Description
S_OK S_OK is always returned
OPC_E_INVALIDCONFIGFILE The server's configuration file is an invalid format.

Comments

IPersistFile::GetCurFile

HRESULT GetCurFile(

[out] LPOLESTR *ppszFileName

);
 
 

Description

Instructs the server to return the name associated with the currently loaded configuration.
Parameters Description
ppszFileName The full filename (if any).

Return Codes
Return Code Description
S_OK The operation succeeded
S_FALSE There is not filename currently associated with the configuration
E_OUTOFMEMORY Not enough memory
E_FAIL operation failed

Comments

This may or may not match the last name passed to Load or Save since there can be other vendor specific tasks that control the server configuration.

The client must free the returned string.