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.
A quick reference for this interface is provided below. A more detailed discussion can be found in the OPC Overview Document.
[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
);
This interface must be provided, and all functions implemented
as specified.
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
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 enumerations) 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
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.
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.
HRESULT GetErrorString(
[in] HRESULT dwError,
[in] LCID dwLocale,
[out, string] LPWSTR *ppString
);
Description
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 servers 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
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.
HRESULT GetGroupByName(
[in, string] LPCWSTR szName,
[in] REFIID riid,
[out, iid_is(riid)] LPUNKNOWN * ppUnk
);
Description
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
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.
HRESULT GetStatus(
[out] OPCSERVERSTATUS ** ppServerStatus
);
Description
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
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.
HRESULT RemoveGroup(
[in] OPCHANDLE hServerGroup,
[in] BOOL bForce
);
Description
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
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.
HRESULT CreateGroupEnumerator(
[in] OPCENUMSCOPE dwScope,
[in] REFIID riid,
[out, iid_is(riid)] LPUNKNOWN* ppUnk
);
Description
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
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.
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.
IEnumConnectionPoints **ppEnum
);
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
REFIID riid,
IConnectionPoint **ppCP
);
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
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 |
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. |
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. |
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.
[in] LPWSTR szItemID,
[out] DWORD * pdwCount,
[out, size_is(,*pdwCount)] DWORD **ppPropertyIDs,
[out, size_is(,*pdwCount)] LPWSTR *ppDescriptions,
[out, size_is(,*pdwCount)] VARTYPE **ppvtDataTypes
);
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
[in] LPWSTR szItemID,
[in] DWORD dwCount,
[in, size_is(dwCount)] DWORD * pdwPropertyIDs,
[out, size_is(,dwCount)] VARIANT ** ppvData,
[out, size_is(,dwCount)] HRESULT **ppErrors
);
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
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.
[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
);
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
The caller must Free the returned NewItemIDs and Errors array.
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.
HRESULT GetPublicGroupByName(
[in, string] LPCWSTR szName,
[in] REFIID riid,
[out, iid_is(riid)] LPUNKNOWN * ppUnk
);
Description
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
Note that when the clients 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 clients connection to the public group. It is not
necessary for the client to call RemoveGroup or RemovePublicGroup to free
these client specific resources.
HRESULT RemovePublicGroup(
[in] OPCHANDLE hServerGroup ,
[in] BOOL bForce
);
Description
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
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.
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
);
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
IOPCBrowseServerAddressSpace::
ChangeBrowsePosition
[in] OPCBROWSEDIRECTION dwBrowseDirection,
[in, string] LPCWSTR szString
);
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
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.
[in] OPCBROWSETYPE dwBrowseFilterType,
[in, string] LPCWSTR szFilterCriteria,
[in] VARTYPE vtDataTypeFilter,
[in] DWORD dwAccessRightsFilter,
[out] LPENUMSTRING * ppIEnumString
);
Parameters | Description |
dwBrowseFilterType | OPC_BRANCH - returns only items
that have children
OPC_LEAF - returns only items that dont 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
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.
[in] LPCWSTR szItemDataID,
[out, string] LPWSTR * szItemID
);
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
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.
[in, string] LPCWSTR szItemID,
[out] LPENUMSTRING * ppIEnumString
);
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
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.
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 its 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 servers 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.
HRESULT IsDirty(
void
);
Description
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
HRESULT Load(
[in] LPCOLESTR pszFileName,
[in] DWORD dwMode
);
Description
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 programmers 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
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.
HRESULT Save(
[in, unique] LPCOLESTR pszFileName,
[in] BOOL fRemember
);
Description
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
HRESULT SaveCompleted(
[in, unique] LPCOLESTR pszFileName
);
Description
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
HRESULT GetCurFile(
[out] LPOLESTR *ppszFileName
);
Description
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
The client must free the returned string.