This section also identifies the interfaces required to be implemented to support the OLE mechanism for delivering a COM interface.
A private Group and a public group may have the same name as long as the client is not connected to the public group with the same name.
Group names are Case Sensitive. Group1 would be different from group1.
For the most part the Active flag is treated as abstract within this specification. The state of these flags affects the described behavior of various interfaces in a well defined way. The implementation details of these capabilities is not dictated by this specification.
In practice it is expected that most servers will make use of this flag to optimize their use of communications and CPU resources. Items and Groups which are not active do not need to be maintained in the CACHE.
It is also expected that clients will simply set and clear active flags of groups and items as a more efficient alternative to adding and removing entire groups and items. For example if an operator display is minimized, its items might be set to inactive.
Refer to the Data Acquisition and Active State Behavior summary earlier in this document for a quick overview of the behavior of a client and server with respect to the active state of a group and items.
OnDataChange within the client's address space can be called whenever any active item data in a active group changes, where "change" is defined as a change in value (from the last value sent to this client), or a change in the Quality of the value. The server can return values and quality flags for those items within the group that changed.(this will be discussed more in later sections)
IMPORTANT:
Note that this is NOT necessarily related to the server's underlying processing rate. For example if a device is performing PID control at 0.05 second rate the an MMI requests updates at a 5 second rate via OPC, the device would of course continue to control at a 0.05 second rate.
In addition, the server implementation would also be allowed to update the cached data available to sync or async read at a higher rate than 5 seconds if it wished to do so. All the update rate indicates is that (a) callbacks should happen no faster than this and (b) the cache should be updated at at least this rate.
The update rate is a request from the client. The server should respond with an update rate that is as close as possible to that requested.
This time zone information may rarely be used and the device providing the data may not know its local time zone, therefore it was not prudent to add this overhead to all data transactions. Instead, the OPCGroup provides a place to store a time zone which can be set and read by the client. The default value for this is the time zone of the host computer. The OPCServer will not make use of this value. It is there only for the convenience of the client.
Exception if (absolute value of (last cached value - current value) > pPercentDeadband * (EU High - EU Low) )
If the exception limit is exceeded, then the last cached value is updated with the new value and a notification will be sent to the IAdviseSink (if any). The pPercentDeadband is an optional behavior for the server. If the client does not specify this value on a server that does support the behavior, the default value of 0 (zero) will be assumed, and all value changes will update the CACHE. Note that the timestamp will be updated regardless of wether the cached value is updated.
The UpdateRate for a group determines time between when a value is checked to see if the exception limit has been exceeded. The PercentDeadband is used to keep noisy signals from updating the client unnecessarily.
It is expected that a client will assign unique value to the client handle if it intends to use any of the asynchronous functions of the OPC interfaces, including IOPCAsyncIO, IOPCAsyncIOs, and IDataObject/IAdviseSink or IConnectionPoint/IOPCDataCallback interfaces.
There are two ways to write data out:
HRESULT AddItems(
[in] DWORD dwCount,
[in, size_is(dwCount)] OPCITEMDEF * pItemArray,
[out, size_is(,dwCount)] OPCITEMRESULT ** ppAddResults,
[out, size_is(,dwCount)] HRESULT ** ppErrors
);
Description
Parameters | Description |
dwCount | The number if items to be added |
pItemArray | Array of OPCITEMDEFs. These tell the server everything it needs to know about the item including the access path, definition and requested datatype |
ppAddResults | Array of OPCITEMRESULTs. This tells the client additional information about the item including the server assigned item handle and the canonical datatype. |
ppErrors | Array of HRESULTs. This tells the client which of the items was successfully added. For any item which failed it provides a reason. |
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 | The operation completed with partial success. Refer to individual error returns for failure analysis. |
OPC_E_PUBLIC | Cannot add items to a public group |
ppErrors Return Codes
Return Code | Description |
S_OK | The function was successful for this item. |
OPC_E_INVALIDITEMID | The ItemID is not syntactically valid |
OPC_E_UNKNOWNITEMID | The ItemID is not in the server address space |
OPC_E_BADTYPE | The requested data type cannot be returned for this item (See comment) |
E_FAIL | The function was unsuccessful. |
OPC_E_UNKNOWNPATH | The item's access path is not known to the server. |
Comments
Any FAILED code in ppErrors indicates that the corresponding item was NOT added to the group and that the corresponding OPCITEMRESULT will not contain useful information.
As an alternative to OPC_E_BADTPYE it is acceptable for the server to return any FAILED error returned by VariantChangeType or VariantChangeTypeEx.
The server provided item handle will be unique within the group, but may not be unique across groups. The server is allowed to reuse the handles of deleted items.
Items cannot be added to public groups.
The client needs to free all of the memory associated with the OPCITEMRESULTs including the BLOB.
If the server supports the BLOB it will return an updated BLOB in the OPCITEMRESULTs. This BLOB may differ in both content and size from the one passed by the client in OPCITEMDEF.
Note that if an Advise is active, the client will begin receiving
callbacks for active items. This can occur very quickly, perhaps even before
the client has time to process the returned results. The client must be
designed to deal with this. One simple solution is for the client to clear
the Active state of the group while doing AddItems and to restore it after
the AddItems is completed and the results are processed.
HRESULT ValidateItems(
[in] DWORD dwCount,
[in, size_is(dwCount)] OPCITEMDEF * pItemArray,
[in] BOOL bBlobUpdate,
[out, size_is(,dwCount)] OPCITEMRESULT ** ppValidationResults,
[out, size_is(,dwCount)] HRESULT ** ppErrors
);
Description
Parameters | Description |
dwCount | The number if items to be validated |
pItemArray | Array of OPCITEMDEFs. These tell the server everything it needs to know about the item including the access path, definition and requested datatype |
bBlobUpdate | If non-zero (and the server supports Blobs) the server should return updated Blobs in OPCITEMRESULTs. If zero (False) the server will not return Blobs in OPCITEMRESULTs. |
ppValidationResults | Array of OPCITEMRESULTs. This tells the client additional information about the item including the canonical datatype. |
ppErrors | Array of HRESULTs. This tells the client which of the items was successfully validated. For any item which failed it provides a reason. |
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 | The operation completed with partial success. Refer to individual error returns for failure analysis. |
ppErrors Codes
Return Code | Description |
S_OK | The function was successful for this item. |
OPC_E_INVALIDITEMID | The ItemID is not syntactically valid |
OPC_E_UNKNOWNITEMID | The ItemID is not in the server address space |
OPC_E_BADTYPE | The requested data type cannot be returned for this item (See comment) |
E_FAIL | The function was unsuccessful for this item. |
OPC_E_UNKNOWNPATH | The item's access path is not known to the server. |
Comments
As an alternative to OPC_E_BADTPYE it is acceptable for the server
to return any FAILED error returned by VariantChangeType or VariantChangeTypeEx.
HRESULT RemoveItems(
[in] DWORD dwCount,
[in, size_is(dwCount)] OPCHANDLE * phServer,
[out, size_is(,dwCount)] HRESULT ** ppErrors
);
Description
Parameters | Description |
dwCount | Number of items to be removed |
phServer | Array of server items handles. These were returned from AddItem. |
ppErrors | Array of HRESULTs. Indicates which items were successfully removed. |
HRESULT Return Codes
Return Code | Description |
S_OK | The function was successful. |
S_FALSE | The function was partially successful. See the ppErrors to determine what happened |
E_FAIL | The function was unsuccessful. |
OPC_E_PUBLIC | Cannot remove items from a public group |
ppError Codes
Return Code | Description |
S_OK | The corresponding item was removed. |
OPC_E_INVALIDHANDLE | The corresponding Item handle was invalid. |
Comments
Items are not really objects in the custom interface (do not have interfaces), and there is no concept of a reference count for items. The client should insure that no further references are made to deleted items.
Items cannot be removed from a public group.
HRESULT SetActiveState(
[in] DWORD dwCount,
[in, size_is(dwCount)] OPCHANDLE * phServer,
[in] BOOL bActive,
[out, size_is(,dwCount)] HRESULT ** ppErrors
);
Description
Parameters | Description |
dwCount | The number of items to be affected |
phServer | Array of Server items handles. |
bActive | TRUE if items are to be activated. FALSE if items are to be deactivated. |
ppErrors | Array of HRESULTs. Indicates which items were successfully affected. |
HRESULT Return Codes
Return Code | Description |
S_OK | The function was successful. |
S_FALSE | The function was partially successful. See the ppErrors to determine what happened |
E_FAIL | The function was unsuccessful. |
ppError Codes
Return Code | Description |
S_OK | The function was successful. |
OPC_E_INVALIDHANDLE | The corresponding Item handle was invalid. |
Comments
HRESULT SetClientHandles(
[in] DWORD dwCount,
[in, size_is(dwCount)] OPCHANDLE * phServer,
[in, size_is(dwCount)] OPCHANDLE * phClient,
[out, size_is(,dwCount)] HRESULT ** ppErrors
);
Description
Parameters | Description |
dwCount | The number of items to be affected |
phServer | Array of Server items handles. |
phClient | Array of new Client item handles to be stored. The Client handles do not need to be unique. |
ppErrors | Array of HRESULTs. Indicates which items were successfully affected. |
HRESULT Return Codes
Return Code | Description |
S_OK | The function was successful. |
S_FALSE | The function was partially successful. See the itemResults to determine what happened |
E_FAIL | The function was unsuccessful. |
itemResults Codes
Return CodeDescription | |
S_OK | The function was successful. |
OPC_E_INVALIDHANDLE | The corresponding Item handle was invalid. |
Comments
HRESULT SetDatatypes(
[in] DWORD dwCount,
[in, size_is(dwCount)] OPCHANDLE * phServer,
[in, size_is(dwCount)] VARTYPE * pRequestedDatatypes,
[out, size_is(,dwCount)] HRESULT ** ppErrors
);
Description
Parameters | Description |
dwCount | The number of items to be affected |
phServer | Array of Server items handles. |
pRequestedDatatypes | Array of new Requested Datatypes to be stored. |
ppErrors | Array of HRESULTs. Indicates which items were successfully affected. |
HRESULT Return Codes
Return Code | Description |
S_OK | The function was successful. |
S_FALSE | The function was partially successful. See the itemResults to determine what happened |
E_FAIL | The function was unsuccessful. |
itemResults Codes
Return Code | Description |
S_OK | The function was successful. |
OPC_E_INVALIDHANDLE | The corresponding Item handle was invalid. |
OPC_E_BADTYPE | The requested datatype cannot be supported for this item. (See comment). The previous requested type is left unchanged. |
Comments
As an alternative to OPC_E_BADTPYE it is acceptable for the server
to return any FAILED error returned by VariantChangeType or VariantChangeTypeEx.
HRESULT CreateEnumerator(
[in] REFIID riid,
[out, iid_is(riid)] LPUNKNOWN* ppUnk
);
Description
Parameters | Description |
riid | The interface requested. Normally this is IID_IEnumOPCItemAttributes. |
ppUnk | Where to return the interface. NULL is returned for any HRESULT other than S_OK |
HRESULT Return Codes
Return Code | Description |
S_OK | The function was successful. |
S_FALSE | There is nothing to enumerate (There are no items in the group). |
E_OUTOFMEMORY | Not enough memory |
E_INVALIDARG | An argument to the function was invalid (e.g. a bad riid parameter was passed.) |
E_FAIL | The function was unsuccessful. |
Comments
The client must release the returned interface pointer when it is
done with it.
[out] DWORD * pUpdateRate,
[out] BOOL * pActive,
[out, string] LPWSTR * ppName,
[out] LONG * pTimeBias,
[out] FLOAT * pPercentDeadband,
[out] DWORD * pLCID,
[out] OPCHANDLE * phClientGroup,
[out] OPCHANDLE * phServerGroup
);
Parameters | Description |
pUpdateRate | The current update rate. The Update Rate is in milliseconds |
pActive | The current active state of the group. |
ppName | The current name of the group |
pTimeBias | The TimeZone Bias of the group (in minutes) |
pPercentDeadband | The percent change in an item value that will cause an exception report of 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] |
pLCID | The current LCID for the group. |
phClientGroup | The client supplied group handle |
phServerGroup | The server generated group handle |
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. |
Comments
All out arguments must be valid pointers. The marshaling mechanism requires valid pointers for proper behavior. NULL pointers will throw an RPC exception.
The client must free the returned ppName string.
HRESULT SetState(
[unique, in] DWORD * pRequestedUpdateRate,
[out] DWORD * pRevisedUpdateRate,
[unique, in] BOOL *pActive,
[unique, in] LONG * pTimeBias,
[unique, in] FLOAT * pPercentDeadband
[unique, in] DWORD * pLCID,
[unique, in] OPCHANDLE *phClientGroup
);
Description
The pRevisedUpdateRate argument must contain a valid pointer.
Parameters | Description |
pRequestedUpdateRate | New update rate requested for the group by the client |
pRevisedUpdateRate | Closest update rate the server is able to provide for this group. |
pActive | TRUE (non-zero) to active the group. FALSE (0) to deactivate the group. |
pTimeBias | TimeZone Bias if Group (in minutes) |
pPercentDeadband | The percent change in an item value that will cause an exception report of 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] |
pLCID | The Localization ID to be used by the group. |
phClientGroup | New client supplied handle for the group. This handle is returned in the data stream provided to the clients IAdvise by the Groups IDataObject. |
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. |
OPC_S_UNSUPPORTEDRATE | The server does not support the requested data rate but will use the closest available rate. |
Comments
Refer to Data Acquistion Section for details on the behavior
of an OPC server with respect to the Synchronous and Asynchronous interfaces
and Active state of groups.
HRESULT SetName(
[in, string] LPCWSTR szName,
);
Description
Parameters | Description |
szName | New name for group. |
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. |
OPC_E_DUPLICATENAME | Duplicate name not allowed. |
Comments
HRESULT CloneGroup(
[in, string] LPCWSTR szName,
[in] REFIID riid,
[out, iid_is(riid)] LPUNKNOWN * ppUnk
);
Description
Properties NOT copied to the new group are
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 a 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. |
riid | requested interface type |
ppUnk | place to return interface pointer. NULL is returned for any HRESULT other than S_OK |
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. |
E_NOINTERFACE | The interface(riid) asked for is not supported by the server. |
Comments
The client must also release the returned interface when it is no longer needed.
The primary use or intent of this function is to create a private
duplicate of a public group which can then be modified by the client.
[out] BOOL * pPublic
);
Parameters | Description |
pPublic | TRUE if the group is public, FALSE if it is private |
HRESULT Return Codes
Return Code | Description |
E_FAIL | The operation failed. |
E_INVALIDARG | An argument to the function was invalid. |
S_OK | The operation succeeded. |
Comments
void
);
Parameters | Description |
void |
HRESULT Return Codes
Return Code | Description |
S_OK | The function was successful. |
E_OUTOFMEMORY | Not enough memory |
E_FAIL | The function was unsuccessful. |
OPC_E_DUPLICATENAME | Duplicate Name not allowed |
Comments
For public groups, the update rate, client group handle and active status are maintained as instance data for each client.
The client is required to set the client groupHandle before any asynchronous functions are performed on a public group. After the group is made public other clients can connect to the group. Generally, they must set their client instance information (e.g. group and item handles) prior to using the other standard group interfaces associated with a group.
Once a group is made public, items cannot be added or deleted.
For the items in the group, the client handle, active status and
requested data type are maintained as instance data for each client.
Refer to the Data Acquisition and Active State Behavior table for an overview of the server data acquisition behavior and its affect on functionality within this interface.
Also refer to the Serialization and Syncronization issues section earlier in this document.
HRESULT Read(
[in] OPCDATASOURCE dwSource,
[in] DWORD dwCount,
[in, size_is(dwCount)] OPCHANDLE * phServer,
[out, size_is(,dwCount)] OPCITEMSTATE ** ppItemValues,
[out, size_is(,dwCount)] HRESULT ** ppErrors
);
Description
When reading from CACHE, the data is only valid if both the group and the item are active. If either the group or the item is inactive, then the Quality will indicate out of service (OPC_QUALITY_OUT_OF_SERVICE). Refer to the discussion of the quality bits later in this document for further information.
DEVICE reads are not affected by the ACTIVE state of the group or item.
Refer to the Data Acquisition and Active State Behavior table earlier in this document for an overview of the server data acquisition behavior and its affect on functionality within this interface.
Parameters | Description |
dwSource | The data source; OPC_DS_CACHE or OPC_DS_DEVICE |
dwCount | The number of items to be read. |
phServer | The list of server item handles for the items to be read |
ppItemValues | Array of structures in which the item values are returned. |
ppErrors | Array of HRESULTs indicating the success of the individual item reads. The errors correspond to the handles passed in phServer. This indicates whether the read succeeded in obtaining a defined value, quality and timestamp. NOTE any FAILED error code indicates that the corresponding Value, Quality and Time stamp are UNDEFINED. |
HRESULT Return Codes
Return Code | Description |
S_OK | The operation succeeded. |
S_FALSE | The operation succeeded but there are one or more errors in ppErrors. Refer to individual error returns for more infomation. |
E_FAIL | The operation failed. |
E_OUTOFMEMORY | Not enough memory |
E_INVALIDARG | An argument to the function was invalid. |
ppError Codes
Return Code | Description |
S_OK | Successful Read. |
E_FAIL | The Read failed for this item |
OPC_E_BADRIGHTS | The item is not readable |
OPC_E_INVALIDHANDLE | The passed item handle was invalid. |
OPC_E_UNKNOWNITEMID | The item is no longer available in the server address space. |
S_xxx
E_xxx |
S_xxx - Vendor specific information
can be provided if this item quality is other than GOOD.
E_xxx - Vendor specific error if this item cannot be accessed. These vendor specific codes can be passed to GetErrorString(). |
Comments
If the HRESULT is S_FALSE, then ppError will indicate which the status of each individual Item Read.
If the HRESULT is any FAILED code then (as noted earlier) the server should return NULL pointers for all OUT parameters including ppErrors.
For any S_xxx ppError code the client should assume the curresponding ITEMSTATE is well defined although the Quality may be UNCERTAIN or BAD. It is recommended (but not required) that server vendors provide additional information here regarding UNCERTAIN or BAD items.
For any FAILED ppError code the client should assume the curresponding ITEMSTATE is undefined. In fact the Server must set the corresponding ITEMSTATE VARIANT to VT_EMPTY so that it can be marshalled properly and so that the client can execute VariantClear on it.
Note that here (as in the OPCItemMgt methods) OPC_E_INVALIDHANDLE on one item will not affect the processing of other items and will cause the main HRESULT to return as S_FALSE
Expected behavior is that a CACHE read should be completed very quickly (within milliseconds). A DEVICE read may take a very long time (many seconds or more). Depending on the details of the implementation (e.g. which threading model is used) the DEVICE read may also prevent any other operations from being performed on the server by any other clients.
For this reason Clients are expected to use CACHE reads in most cases. DEVICE reads are intended for special circumstances such as diagnostics.
The ppItemValues and ppErrors arrays are allocated by the server
and must be freed by the client. Be sure to call VariantClear() on the
variant in the ITEMRESULT.
HRESULT Write(
[in] DWORD dwCount,
[in, size_is(dwCount)] OPCHANDLE * phServer,
[in, size_is(dwCount)] VARIANT * pItemValues,
[out, size_is(,dwCount)] HRESULT ** ppErrors
);
Description
Writes are not affected by the ACTIVE state of the group
or item.
Parameters | Description |
dwCount | Number of items to be written |
phServer | The list of server item handles for the items to be read |
pItemValues | List of values to be written to the items. The datatypes of the values do not need to match the datatypes of the target items. However an error will be returned if a conversion cannot be done. |
ppErrors | Array of HRESULTs indicating the success of the individual item Writes. The errors correspond to the handles passed in phServer. This indicates whether the target device or system accepted the value. NOTE any FAILED error code indicates that the value was rejected by the device. |
HRESULT Return Codes
Return Code | Description |
S_OK | The operation succeeded. |
S_FALSE | The operation succeeded but there are one or more errors in ppErrors. Refer to individual error returns for more infomation. |
E_FAIL | The operation failed. |
E_OUTOFMEMORY | Not enough memory |
E_INVALIDARG | An argument to the function was invalid. |
ppError Codes
Return Code | Description |
S_OK | The function was successful. |
E_FAIL | The function was unsuccessful. |
OPC_S_CLAMP | The value was accepted but was clamped. |
OPC_E_RANGE | The value was out of range. |
OPC_E_BADTYPE | The passed data type cannot be accepted for this item (See comment) |
OPC_E_BADRIGHTS | The item is not writeable |
OPC_E_INVALIDHANDLE | The passed item handle was invalid. |
OPC_E_UNKNOWNITEMID | The item is no longer available in the server address space |
E_xxx
S_xxx |
Vendor specific errors may also be returned. Descriptive information for such errors can be obtained from GetErrorString. |
Comments
If the HRESULT is any FAILED code then (as noted earlier) the server should return NULL pointers for all OUT parameters.
Note that here (as in the OPCItemMgt methods) OPC_E_INVALIDHANDLE on one item will not affect the processing of other items and will cause the main HRESULT to return as S_FALSE
As an alternative to OPC_E_BADTPYE it is acceptable for the server to return any FAILED error returned by VariantChangeType or VariantChangeTypeEx.
A DEVICE write may take a very long time (many seconds or more). Depending on the details of the implementation (e.g. which threading model is used) the DEVICE write may also prevent any other operations from being performed on the server by any other clients.
For this reason Clients are expected to use ASYNC write rather than SYNC write in most cases.
The ppErrors array is allocated by the server and must be freed by
the client.
It differs from AsyncIO as follows;
Also the expected behavior is that for any one transaction to Async Read, Write and Refresh, ALL of the results of that transaction will be returned in a single call to appropriate function in IOPCDataCallback.
A server must be able to queue at least one transaction of each type (read, write, refresh) for each group. It is acceptable for a server to return an error (CONNECT_E_ADVISELIMIT) if more than one transaction of the same type is performed on the same group by the same client. Server vendors may of course support queueing of additional transactions if they wish.
All operations that are successfully started are expected to complete even if they complete with an error. The concept of time-out is not explicitly addressed in this specification however it is expected that where appropriate the server will internally implement any needed time-out logic and return a server specific error to the caller if this occurs.
Client Implementation Note:
The Unique Transaction ID passed to Read, Write and Refresh is generated by the Client and is returned to the client in the callback. This ID must be non-zero and unique to this particular client/server conversation. It does not need to be unique relative to other conversations by this or other clients. Note that the Group's Clienthandle is also returned in the callback and is generally sufficient to identify the returned data.
IMPORTANT NOTE: depending on the mix of client and server threading models used, it has been found in practice that the IOPCDataCallback can occur within the same thread as the Refresh, Read or Write and in fact can occur before the Read, Write or Refresh method returns to the caller.
Thus, if the client wants to save a record of the transaction in some list of outstanding transactions in order to verify completion of a transaction it will need to generate the Transaction ID and save it BEFORE making the method call.
In practice most clients will probably not need to maintain
such a list and so do not actually need to record the transaction ID.
HRESULT Read(
[in] DWORD dwCount,
[in, size_is(dwCount)] OPCHANDLE * phServer,
[in] DWORD dwTransactionID,
[out] DWORD *pdwCancelID,
[out, size_is(,dwCount)] HRESULT ** ppErrors
);
Description
Reads are from DEVICE and are not affected by the ACTIVE state of the group or item.
Parameters | Description |
dwCount | Number of items to be read. |
phServer | Array of server item handles of the items to be read |
dwTransactionID | The Client generated transaction ID. This is included in the completion information provided to the OnReadComplete. |
pdwCancelID | Place to return a Server generated ID to be used in case the operation needs to be canceled. |
ppErrors | Array of errors for each item - returned by the server. See below. |
HRESULT Return Codes
Return Code | Description |
S_OK | The operation succeeded. The read was successfully initiated |
E_FAIL | The operation failed. |
E_OUTOFMEMORY | Not enough memory |
E_INVALIDARG | An argument to the function was invalid. |
S_FALSE | One or more of the passed items could not be read The ppError array indicates which items in phServer could not be read. Any items which do not return errors (E) here will be read and results will be returned to OnReadComplete. Items which do return errors here will not be returned in the callback. |
CONNECT_E_NOCONNECTION | The client has not registered a callback through IConnectionPoint::Advise. |
ppError Codes
Return Code | Description |
S_OK | The corresponding Item handle was valid and the item information will be returned on OnReadComplete. |
E_FAIL | The Read failed for this item |
OPC_E_BADRIGHTS | The item is not readable |
OPC_E_INVALIDHANDLE | The passed item handle was invalid. |
OPC_E_UNKNOWNITEMID | The item is no longer available in the server address space. |
E_xxx
S_xxx |
Vendor specific errors may also be returned. Descriptive information for such errors can be obtained from GetErrorString. |
Comments
If the HRESULT is S_OK, then ppError can be ignored (all results in it are guaranteed to be S_OK).
If the HRESULT is any FAILED code then (as noted earlier) the server should return NULL pointers for all OUT parameters. Note that in this case no Callback will occur.
If ALL errors in ppError are Failure codes then No callback will take place.
Items for which ppError returns any success code (including S_xxx) will be returned in the OnReadComplete callback. Note that the error result for an item returned in the callback may differ from that returned from Read.
NOTE: the server must return all of the results in a single callback. Thus, if the items in the group require multiple physical transactions to one or more physical devices then the server must wait until all of them are complete before invoking OnReadComplete.
The Client must free the returned ppError array.
HRESULT Write(
[in] DWORD dwCount,
[in, size_is(dwCount)] OPCHANDLE * phServer,
[in, size_is(dwCount)] VARIANT * pItemValues,
[in] DWORD dwTransactionID,
[out] DWORD *pdwCancelID,
[out, size_is(,dwCount)] HRESULT ** ppErrors
);
Description
Parameters | Description |
dwCount | Number of items to be written |
phServer | List of server items handles for the items to be written |
pItemValues | List of values to be written. The value data types do not match the requested or canonical item datatype but must be convertible to the canonical type. |
dwTransactionID | The Client generated transaction ID. This is included in the completion information provided to the OnWriteComplete. |
pdwCancelID | Place to return a Server generated ID to be used in case the operation needs to be canceled. |
ppErrors | Array of errors for each item - returned by the server. See below. |
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. |
S_FALSE | One or more of the passed items could not be written The ppError array indicates which items in phServer could not be write. Any items which do not return errors (E) here will be written and results will be returned to OnWriteComplete. Items which do return errors here will not be returned in the callback. |
CONNECT_E_NOCONNECTION | The client has not registered a callback through IConnectionPoint::Advise. |
ppError Codes
Return Code | Description |
S_OK | The corresponding Item handle was valid. The write will be attempted and the results will be returned on OnWriteComplete |
E_FAIL | The function was unsuccessful. |
OPC_E_BADRIGHTS | The item is not writeable |
OPC_E_INVALIDHANDLE | The passed item handle was invalid. |
OPC_E_UNKNOWNITEMID | The item is no longer available in the server address space |
E_xxx
S_xxx |
Vendor specific errors may also be returned. Descriptive information for such errors can be obtained from GetErrorString. |
Comments
If the HRESULT is S_OK, then ppError can be ignored (all results in it are guaranteed to be S_OK).
If the HRESULT is any FAILED code then (as noted earlier) the server should return NULL pointers for all OUT parameters. Note that in this case no Callback will occur.
If ALL errors in ppError are Failure codes then No callback will take place.
Items for which ppError returns any success code (including S_xxx) will also have a result returned in the OnWriteComplete callback. Note that the error result for an item returned in the callback may differ from that returned from Write.
NOTE: all of the results must be returned by the server in a single callback. Thus if the items in the group require multiple physical transactions to one or more physical devices then the server must wait until all of them are complete before invoking the callback.
Client must free the returned ppError array.
HRESULT Refresh2(
[in] OPCDATASOURCE dwSource,
[in] DWORD dwTransactionID,
[out] DWORD *pdwCancelID
);
Description
Parameters | Description |
dwSource | Data source CACHE or DEVICE. If the DEVICE, then all active items in the CACHE are refreshed from the device BEFORE the callback. |
dwTransactionID | The Client generated transaction ID. This is included in the completion information provided to the OnDataChange. |
pdwCancelID | Place to return a Server generated ID to be used in case the operation needs to be canceled. |
HRESULT Return Codes
Return Code | Description |
S_OK | The operation succeeded. |
E_FAIL | The operation failed. (See notes below) |
E_OUTOFMEMORY | Not enough memory |
E_INVALIDARG | An argument to the function was invalid. |
CONNECT_E_NOCONNECTION | The client has not registered a callback through IConnectionPoint::Advise. |
Comments
Calling Refresh for an InActive Group will return E_FAIL. Calling refresh for an Active Group, where all the items in the group are InActive also returns E_FAIL.
The behavior of this function is identical to what happens when Advise is called initially except that the Callback will include a non-zero transaction ID.
Functionally it is also similar to what could be achieved by doing a READ of all of the active items in a group.
NOTE: all of the results must be returned in a single callback. Thus if the items in the group require multiple physical transactions to one or more physical devices then the server must wait until all of them are complete before invoking OnDataChange.
The expected behavior is that this Refresh will not affect the timing
of normal OnDataChange callbacks which are based on the UpdateRate. For
example, if the update rate is 1 hour and this method is called after 45
minutes then the server should still do its internal checking at the
end of the hour (15 minutes after the Refresh call). Calling this method
may affect the contents of that next callback (15 minutes later) since
only items where the value or status changed during that 15 minutes would
be included. Items which had changed during the 45 minutes preceding the
Refresh will be sent (along with all other values) as part of the Refresh
Transaction. They would not be sent a second time at the end of the hour.
The value sent in response to the Refresh becomes the last value sent
to the client when performing the normal subscription logic.
HRESULT Cancel2(
[in] DWORD dwCancelID
);
Description
Parameters | Description |
dwCancelID | The Server generated Cancel ID which was associated with the operation when it was initiated. |
HRESULT Return Codes
Return Code | Description |
S_OK | The operation succeeded. |
E_FAIL | The operation failed. Either the Cancel ID was invalid or it was too late to cancel the transaction. |
Comments
In general, if this operation succeeds then a OnCancelComplete callback
will occur. If this operation fails then a read, write or datachange callback
may occur (or may already have occurred).
HRESULT SetEnable(
[in] BOOL bEnable
);
Description
Parameters | Description |
bEnable | TRUE enables OnDataChange callbacks, FALSE disables OnDataChange callbacks. |
HRESULT Return Codes
Return Code | Description |
S_OK | The operation succeeded. |
CONNECT_E_NOCONNECTION | The client has not registered a callback through IConnectionPoint::Advise. |
E_FAIL | The operation failed. |
Comments
The purpose of this function is to allow a Connection to be established to an active group without necessarily enabling the OnDataChange notifications. An example might be a client doing an occasional Refresh from cache.
Even if a client does not intend to use the OnDataChange, it should still be prepared to deal with one or more OnDataChange callbacks which might occur before the client has time to disable them (i.e. at least free the memory associated with the 'out' parameters).
If the client really needs to prevent these initial unwanted callbacks then the following procedure can be used. Client creates and populates the group. Client sets the group Active state to FALSE. Client creates connection to group. Client uses this function to disable OnDataChange. sets the group Active state back to TRUE.
This does NOT affect operation of Refresh2(). I.e. calling Refresh2
will still result in an OnDataChange callback (with a non-zero transaction
ID). Note that this allows Refresh to be used as essentially an Async read
from Cache.
HRESULT GetEnable(
[out] BOOL *pbEnable
);
Description
Parameters | Description |
pbEnable | Where to save the returned result. |
HRESULT Return Codes
Return Code | Description |
S_OK | The operation succeeded. |
CONNECT_E_NOCONNECTION | The client has not registered a callback through IConnectionPoint::Advise. |
E_FAIL | The operation failed. |
Comments
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 that IConnectionPointContainer is implemented on the OPCGROUP rather than on the individual items. This is to allow the creation of a Callback connection between the client and the group using the IOPCDataCallback Interface for the most efficient possible transfer of data (many items per tranaction).
One callback object implemented by the client application can be used to service multiple groups. Therefore, information about the group and the particular transaction must be provided to the client application for it to be able to successfully interpret the items that are contained in the callback. Each callback will contain only items defined within the specified group.
Note: OPC Compliant servers are not required to support
more than one connection between each Group and the Client. Given that
groups are client specific entities it is expected that a single connection
(to each group) will be sufficient for virtually all applications. For
this reason (as per the COM Specification) the EnumConnections method for
IConnectionPoint interface for the IOPCDataCallback 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_IOPCDataCallBack) |
HRESULT Return Codes
Return Code | Description |
S_OK | The function was successful. |
For other codes see the OLE programmers reference |
Comments
NOTE: most of the returned information was either supplied by or returned to the client at the time it called AddItem.
The optional EU information (see the OPCITEMATTRIBUTES discussion) may be very useful to some clients. This interface is also useful for debugging or for enumerating the contents of a public group.
This interface is returned only by IOPCItemMgt::CreateEnumerator. It is not available through query interface.
Since enumeration is a standard interface this is described only briefly.
See the OLE Programmers reference for Enumerators for a list and discussion of error codes.
HRESULT Next(
[in] ULONG celt,
[out, size_is(,*pceltFetched)] OPCITEMATTRIBUTES ** ppItemArray,
[out] ULONG * pceltFetched
);
Description
Parameters | Description |
celt | number of items to be fetched. |
ppItemArray | Array of OPCITEMATTRIBUTES. Returned by the server. |
pceltFetched | Number of items actually returned. |
Comments
HRESULT Skip(
[in] ULONG celt
);
Description
Parameters | Description |
celt | Number of items to skip |
Comments
HRESULT Reset(
void
);
Description
Parametersvoid |
Comments
HRESULT Clone(
[out] IEnumOPCItemAttributes** ppEnumItemAttributes
);
Description
Parameters | Description |
ppEnumItemAttributes | Place to return the new interface |
Comments
Also the expected behavior is that for any one transaction to Async Read, Write and Refresh, ALL of the results of that transaction will be returned in a single call to OnDataChange.
A server must be able to queue at least one transaction of each type (read, write, refresh) for each group. It is acceptable for a server to return an error (CONNECT_E_ADVISELIMIT) if more than one transaction of the same type is performed on the same group by the same client. Server vendors may of course support queueing of additional transactions if they wish.
All operations are expected to complete even if they complete with an error. The concept of time-out is not explicitly addressed in this specification however it is expected that where appropriate the server will internally implement any needed time-out logic.
Client Implementation Note:
The Transaction ID is generated by the Server and returned to the client in the callback. Some clients may want to save the ID returned by the server in some list of outstanding transactions in order to verify completion of a transaction. This could be complicated if the OnDataChange callback occurs before the client has saved the returned ID.
Note: Version 1.0 of this specification suggested an approach involving critical sections. However, depending on the mix of client and server threading models used, it has been found in practice that the OnDataChange callback can occur within the same thread as the Read or Write and in fact can occur before the Read or Write returns to the caller. Clearly, critical sections cannot resolve this case.
Although it has also been found in practice that many clients do not actually need to record the transaction ID (the Groups ClientHandle is generally sufficient to identify the returned data), the following possible approach is suggested for those cases where this is needed.
Mainline Code
START CRITICAL SECTION
RECORD ALL NEEDED INFO ABOUT TRANSACTION EXCEPT TID.
CLEAR TID COMPLETED
SET A SPECIAL FLAG: TID PENDING
IOPCAsyncIO::Read or Write or Refresh
CHECK TID COMPLETED
IF SET AND EQUAL TO RETURNED TID THEN TRANSACTION IS COMPLETE
ELSE SAVE TRANSACTION ID IN LIST OF PENDING TRANSACTIONS
CLEAR TID PENDING
END CRITICAL SECTION
OnDataChange Code
START CRITICAL SECTION
READ DATA STREAM AND LOCATE TRANSACTION ID
LOCATE TRANSACTION ID IN LIST OF PENDING TRANSACTIONS
IF NOT FOUND, CHECK TID PENDING
IF TID PENDING SET THEN RECORD THIS TID IN TID COMPLETED
END CRITICAL SECTION
HRESULT Read(
[in] DWORD dwConnection,
[in] OPCDATASOURCE dwSource,
[in] DWORD dwCount,
[in, size_is(dwCount)] OPCHANDLE * phServer,
[out] DWORD *pTransactionID,
[out, size_is(,dwCount)] HRESULT ** ppErrors
);
Description
For CACHE reads the data is only valid if both the group and the item are active.
DEVICE reads are not affected by the ACTIVE state of the group or item.
Parameters | Description |
dwConnection | The OLE Connection number returned from IDataObject::DAdvise. This is passed to help the server determine which advise sink to call when the request completes. |
dwSource | The data source; OPC_DS_CACHE or OPC_DS_DEVICE |
dwCount | Number of items to be read. |
phServer | Array of server item handles of the items to be read |
pTransactionID | Place to return a Server generated transaction ID. This is included in the completion information provided to the IAdvise. |
ppErrors | Array of errors for each item - returned by the server. Indicates only if the corresponding server handle was valid. Any other errors (communications time-out, access rights, etc.) will be returned in the callback. Note that at this time the only item level status information available in the callback is the QUALITY field. |
HRESULT Return Codes
Return Code | Description |
S_OK | The operation succeeded. The read was successfully initiated |
E_FAIL | The operation failed. |
E_OUTOFMEMORY | Not enough memory |
E_INVALIDARG | An argument to the function was invalid. |
S_FALSE | One or more of the passed handles was invalid. The ppError array indicates which handles in phServer were invalid. NOTE if any handle is invalid this error is returned and the entire ASYNC Read operation is rejected. No callback will occur. |
CONNECT_E_NOCONNECTION | The client has not registered a callback of type OPCSTMFORMATDATA or OPCSTMFORMATDATATIME through IDataObject:DAdvise. |
ppError Codes
Return Code | Description |
S_OK | The corresponding Item handle was valid. |
OPC_E_INVALIDHANDLE | The corresponding Item handle was invalid |
Comments
If the HRESULT is any FAILED code then (as noted earlier) the server should return NULL pointers for all OUT parameters. Note that in this case no Callback will occur.
Note that there is a difference in the handling of OPE_E_INVALIDHANDLE between SYNC read and ASYNC read. In this case (ASYNC read) an INVALIDHANDLE on one item will cause the entire request to be rejected and will cause the main HRESULT to return as S_FALSE. In this case the ppErrors will contain one or more OPC_E_INVALIDHANDLE errors and no callback will occur.
The only item specific error checking done by this call is to validate the passed handles. Thus ppErrors always contains values of either S_OK or OPC_E_INVALIDHANDLE. If all of the passed handles are valid and the operation is performed then all item level error returns will be via OnDataChange. Note that at this time the only item level status information available in the Callback is the QUALITY field.
NOTE: all of the results must be returned by the server in a single callback.
If the items in the group require multiple physical transactions to one or more physical devices then the server must wait until all of them are complete before invoking OnDataChange.
The Client must free the returned ppError array.
The transaction ID generated by the server should be globally unique and non-zero.
The transaction ID is used to identify the results that are returned
in the OnDataChange. The client may also use the transactionID when attempting
to cancel an in progress asynchronous function
HRESULT Write(
[in] DWORD dwConnection,
[in] DWORD dwCount,
[in, size_is(dwCount)] OPCHANDLE * phServer,
[in, size_is(dwCount)] VARIANT * pItemValues,
[out] DWORD *pTransactionID,
[out, size_is(,dwCount)] HRESULT ** ppErrors
);
Description
Parameters | Description |
dwConnection | The OLE Connection number returned from IDataObject::DAdvise. This is passed to help the server determine which advise sink to call when the request completes. |
dwCount | Number of items to be written |
phServer | List of server items handles for the items to be written |
pItemValues | List of values to be written. The value data types do not match the requested or canonical item datatype but must be convertible to the canonical type. |
pTransactionID | Place to return a Server generated transaction ID. This is included in the completion information provided to the IAdvise. |
ppErrors | Array of errors for each item - returned by the server. Indicates only if the corresponding server handle was valid. Any other errors (communications time-out, access rights, etc.) will be returned in the callback. |
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. |
S_FALSE | One or more of the passed handles was invalid. The ppError array indicates which handles in phServer were invalid. NOTE that if any handle is invalid this error is returned and the entire operation is rejected. No callback will occur. |
CONNECT_E_NOCONNECTION | The client has not registered a callback of type OPCSTMFORMATWRITECOMPLETE through IDataObject:DAdvise. |
ppError Codes
Return Code | Description |
S_OK | The corresponding Item handle was valid. |
OPC_E_INVALIDHANDLE | The corresponding Item handle was invalid |
Comments
If the HRESULT is any FAILED code then (as noted earlier) the server should return NULL pointers for all OUT parameters. Note that in this case no Callback will occur.
Note that there is a difference in the handling of OPE_E_INVALIDHANDLE between SYNC write and ASYNC write. In this case (ASYNC write) an INVALIDHANDLE on one item will cause the entire request to be rejected and will cause the main HRESULT to return as S_FALSE. In this case the ppErrors will contain one or more OPC_E_INVALIDHANDLE errors and no callback will occur.
The only item specific error checking done by this call is to validate the passed handles. . Thus ppErrors always contains values of either S_OK or OPC_E_INVALIDHANDLE. If all of the passed handles are valid and the operation is performed then all item level error returns will be via OnDataChange. These error codes have the same values as those returned by IOPCSyncIO::Write.
NOTE: all of the results must be returned by the server in a single callback.
If the items in the group require multiple physical transactions to one or more physical devices then the server must wait until all of them are complete before invoking OnDataChange.
Client must free the returned ppError array.
See the notes under Read regarding the transaction ID.
HRESULT Refresh(
[in] DWORD dwConnection,
[in] OPCDATASOURCE dwSource,
[out] DWORD *pTransactionID
);
Description
Parameters | Description |
dwConnection | The OLE Connection number returned from IDataObject::DAdvise. This is passed to help the server determine which advise sync to call when the request completes. |
dwSource | Data source CACHE or DEVICE |
pTransactionID | Place to return a Server generated transaction ID. This is included in the completion information provided to the IAdvise. |
HRESULT Return Codes
Return Code | Description |
S_OK | The operation succeeded. |
E_FAIL | The operation failed. (See notes below) |
E_OUTOFMEMORY | Not enough memory |
E_INVALIDARG | An argument to the function was invalid. |
CONNECT_E_NOCONNECTION | The client has not registered a callback of type OPCSTMFORMATDATA or OPCSTMFORMATDATATIME through IDataObject:DAdvise. |
Comments
Calling refresh for an InActive Group will return E_FAIL. Calling refresh for an Active Group, where all the items in the group are InActive also returns E_FAIL.
The behavior of this function is identical to what happens when DAdvise is called using ADVF_PRIMEFIRST except that the Callback will include a non-zero transaction ID.
Functionally it is also similar to what could be achieved by doing a READ from CACHE of all of the active items in a group.
NOTE: all of the results must be returned in a single callback.
If the items in the group require multiple physical transactions to one or more physical devices then the server must wait until all of them are complete before invoking OnDataChange.
The expected behavior is that this Refresh will not affect the timing of normal OnDataChange callbacks which are based on the UpdateRate. For example, if the update rate is 1 hour and this method is called after 45 minutes then the server should still do its internal checking at the end of the hour (15 minutes after the Refresh call). Calling this method may affect the contents of that next callback (15 minutes later) since only items where the value or status changed during that 15 minutes would be included. Items which had changed during the 45 minutes preceding the Refresh will be sent (along with all other values) as part of the Refresh Transaction. They would not be sent a second time at the end of the hour. The value sent in response to the Refresh becomes the last value sent to the client when performing the normal subscription logic.
HRESULT Cancel(
[in] DWORD dwTransactionID
);
Description
Parameters | Description |
dwTransactionID | The transaction ID which was associated with the operation to be canceled. |
HRESULT Return Codes
Return Code | Description |
S_OK | The operation succeeded. |
E_FAIL | The operation failed. Either the transaction ID was invalid or it was too late to cancel the transaction. |
Comments
In general, if this operation succeeds then no callback will occur.
If this operation fails then a callback may occur (or may already have
occured).
IDataObject is implemented on the OPCGroup rather than on the individual items. This allows the creation of an Advise connection between the client and the group using the OPC Data Stream Formats for the efficient data transfer.
It is required that the following methods be supported.
DAdvise
DUnadvise
Because the IDataObject deals with a STREAM rather than individual items, the following methods do not need to be supported (they can be implemented as stubs which return E_NOTIMPL.
GetData
GetDataHere
GetCanonicalFormatEtc
The server vendor may chose to implement additional methods on the IDataObject. It is the intent of this design that data items be transferred to applications primarily via the Advise connection or via the Synchronous or Asynchronous Read methods.
The data returned to the Advise connection is returned via a IAdviseSink which receives data in a Global Memory Section also referred to here as the stream. These streams can be in several formats. They are used to provide exception data as well as completion information for Async Reads and Writes. The stream formats are
"OPCSTMFORMATDATA"
"OPCSTMFORMATDATATIME"
"OPCSTMFORMATWRITECOMPLETE"
Use the function
RegisterClipboardFormat()
to obtain the format value (cfFormat) to be used for data transfers between OPC client applications and OPC server applications.
The registered callback function (OnDataChange in the clients IAdviseSink) may be specified by the client application so that it spans multiple groups. Information about the group (the Groups ClientHandle) must be provided to the client application as part of the stream so that the client can successfully interpret the items that are contained in the data stream. Each data stream will only contain the items defined within the specified group.
Because of the nature of the asynchronous calls, OLE requires that no synchronous calls are made from a method that has been called asynchronously (as all of the IAdviseSink methods are) which would cause the asynchronous function to be blocked. It is very important that the methods that are called asynchronously (the IAdviseSink methods) have limited processing, and return quickly. Lengthy processing should be done outside of the context of the asynchronous method that has been invoked.
It is the client applications responsibility to keep up with the data changes that the server (configured by the client app) sends. The client should assume that the server may send data at the update rate specified in the group, and that for each group that identical throughput may occur. Various Windows and OLE related internal errors can result if the server sends data faster than the client can receive it. The performance of the OPC servers and OPC clients is highly tied to the developers implementation of these critical interfaces.
The server should be implemented to optimize the acquisition of the data items for multiple clients wherever possible. This means that it is best for the server to read data from devices at the fastest rate possible: (a) to support the needs of multiple clients configured for the same item or (b), if a single client has configured the same item in different groups at different update rates.
Refer to the OLE programming manual for a tutorial and guide to implementing
the required functionality.
FORMATETC *pFmt,
DWORD adv,
LPADVISESINK pSnk,
DWORD * pConnection
);
Parameters | Description |
pFmt | The format in which the client is interested. This will always be one of the three supported OPC formats as described below. |
adv | Data Advise Flags specifier. Not used by OPC. |
pSnk | Pointer to the Clients IAdviseSink |
pConnection | OLE Connection key for use with IOPCAsyncIO and UnAdvise |
HRESULT Return Codes
Return Code | Description |
S_OK | The function was successful. |
CONNECT_E_ADVISELIMIT | The group cannot support additional connections of this type. |
For other codes see the OLE programmers reference |
Comments
The Advise Flags Parameter (adv) is not used by OPC. Servers should ignore this parameter and should always send a copy of all data items when a connection is made. Note that this is equivalent to the behavior associated with ADVF_PRIMEFIRST.
It is expected that a client will assign unique values to the group and item client handles if they intend to use any of the asynchronous functions of the OPC interfaces, including IOPCAsyncIO, and IDataObject/IAdviseSink interfaces, since this is the only key to the information that the server provides back to the client with the OnDataChange stream.
The formats really represent different types of events rather than different formats for the same data.
The FORMATETC must be filled in as follows;
fe.cfFormat = OPCSTMFORMATDATA or
OPCSTMFORMATWRITECOMPLETE.
(See RegisterClipboardFormat())
fe.ptd = NULL;
fe.tymed = TYMED_HGLOBAL;
fe.lindex = -1;
The storage medium will always be TYMED_HGLOBAL (for computability
with DCOM).
DWORD Connection
);
Parameters | Description |
Connection | The connection to be terminated |
HRESULT Return Codes
Return Code | Description |
S_OK | The function was successful. |
For other codes see the OLE programmers reference |
Comments