⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 idatasink20.cpp

📁 OPC Client 源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// IDataSink20.cpp: implementation of the IDataSink20 class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "IDataSink20.h"
#include "OPCData.h"


#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

class COPCItem;
class COPCGroup;
class COPCServer;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

IDataSink20::IDataSink20():m_cnRef (0)
{

}

IDataSink20::~IDataSink20()
{

}

// **************************************************************************
// AddRef ()
//
// Description:
//	This function is called to increment our reference count.  Caller should 
//	increment our reference count each time a new pointer to this interface
//	is created (except when obtained by a call to QueryInterface which will
//  bump the reference count on its behalf). 
//
//	This is one of the 3 member functions all COM interfaces must implement. 
//
// Parameters:
//	none
//
// Returns:
//	STDMETHODIMP_(ULONG) - Reference count resulting from this call.
// **************************************************************************
STDMETHODIMP_(ULONG) IDataSink20::AddRef ()
	{
	// Increment the reference count then return value:
	return (++m_cnRef);
	}

// **************************************************************************
// Release ()
//
// Description:
//	This function is called to decrement our reference count.  Caller should
//	decrement our reference count just before each pointer to this interface 
//	is destroyed (goes out of scope).  Standard COM practice requires us to
//  self-delete once the refernce count returns to zero.
//
//	This is one of the 3 member functions all COM interfaces must implement.
//
// Parameters:
//	none
//
// Returns:
//	STDMETHODIMP_(ULONG) - Reference count resulting from this call.
// **************************************************************************
STDMETHODIMP_(ULONG) IDataSink20::Release ()
	{
	// Decrement reference count and return immediately if not zero:
	if (--m_cnRef != 0)
		return (m_cnRef);

	// If we make it here, then the reference count is zero.  We are 
	// therefore obliged to delete ourselves:
	delete this;

	// Return our refence count, which is zero now:
	return (0);
	}

// **************************************************************************
// QueryInterface ()
//
// Description:
//	This function is called to obtain a pointer to one of the COM interfaces
//	objects of this class support (in this case only IAdviseSink and its base
//	class IUnknown).  As is standard COM practice, our reference count is 
//	incremented upon a successful query.  
//
//  This is one of the 3 member functions all COM interfaces must implement.	
//
// Parameters:
//	REFIID		riid			Requested interface type: IID_IUnknown,
//								  or IID_IAdviseSink.
//	LPVOID		*ppInterface	Pointer to requested interface.
//
// Returns:
//	STDMETHODIMP -
//		S_OK - Query successful, ppInterface set to requested pointer.
//		E_INVALIDARG - One of the arguments was invalid.
//		E_NOINTERFACE - Requested interface is not supported.
// **************************************************************************
STDMETHODIMP IDataSink20::QueryInterface (REFIID iid, LPVOID *ppInterface)
	{
	// Validate ppInterface.  Return with "invalid argument" error code if invalid:
	if (ppInterface == NULL)
		return (E_INVALIDARG);

	// Standard COM practice requires that we invalidate output arguments
	// if an error is encountered.  Let's assume an error for now and invalidate
	// ppInterface.  We will reset it to a valid interface pointer later if we
	// determine requested ID is valid:
	*ppInterface = NULL;	

	// Reset ppInterface if requested interface type is valid:
	if (iid == IID_IUnknown)
		*ppInterface = (IUnknown *) this;
	else if (iid == IID_IOPCDataCallback)
		*ppInterface = (IOPCDataCallback *) this;
	else
		{
		// We have been asked for an interface we don't support.  Return 
		// immediately with "no interface" error code.  ppInterface should
		// still be NULL as required by COM.
		return (E_NOINTERFACE);
		}

	// If we made it here, then the query was successful and ppInterface
	// has been set to requested interface pointer.  Standard COM practice
	// requires us to increment our reference count now.
	AddRef ();

	// Return with "success" code:
	return (S_OK);
	}

// **************************************************************************
// OnDataChange ()
//
// Description:
//	This method is provided to handle notifications from an OPC Group for
//	exception based (unsolicited) data changes and refreshes.  Data for one
//	or possibly more active items in the group will be provided.
//
// Parameters:
//	DWORD		dwTransID			Zero for normal OnDataChange events, 
//                                    non-zero for Refreshes.
//	OPCHANDLE	hGroup				Client group handle.
//	HRESULT		hrMasterQuality		S_OK if all qualities are GOOD, otherwise S_FALSE.
//	HRESULT		hrMasterError		S_OK if all errors are S_OK, otherwise S_FALSE.
//	DWORD		dwCount				Number of items in the lists that follow.
//	OPCHANDLE	*phClientItems		Item client handles.
//	VARIANT		*pvValues			Item data.
//	WORD		*pwQualities		Item qualities.
//	FILETIME	*pftTimeStamps		Item timestamps.
//	HRESULT		*pErrors			Item errors.
//
// Returns:
//	STDMETHODIMP - 
//		S_OK - Processing of advisement successful.
//		E_INVALIDARG - One of the arguments was invalid.
// **************************************************************************
// 数据更新回调函数
// **************************************************************************
STDMETHODIMP IDataSink20::OnDataChange (DWORD dwTransID,
						OPCHANDLE hGroup,
						HRESULT hrMasterQuality,
						HRESULT hrMasterError,
						DWORD dwCount,
						OPCHANDLE *phClientItems,
						VARIANT *pvValues,
						WORD *pwQualities,
						FILETIME *pftTimeStamps,
						HRESULT *pErrors)
	{
	COPCGroup *pGroup = NULL;
	COPCItem *pItem = NULL;

	// Initialize a bad item handle counter (used for debugging only):
	DWORD cdwBadItemHandles = 0;

	// Validate arguments.  Return with "invalid argument" error code 
	// if any are invalid:
	if (hGroup					== NULL	||
		dwCount					== 0	||
		phClientItems			== NULL	||
		pvValues				== NULL	||
		pwQualities				== NULL	||
		pftTimeStamps			== NULL	||
		pErrors					== NULL)
		return (E_INVALIDARG);

	// The group argument gives us a pointer to the destination COPCGroup:
	pGroup = (COPCGroup *) hGroup;

	// Post a "read complete" message for refresh transactions (which will 
	// have a non-zero transaction ID).  No need to load up event log with 
	// "read complete" messages for unsolicited data updates, which could be
	// coming in many times per second.
	if (dwTransID != 0)
		{
//		LogMsg (IDS_ASYNC20_READXACT_COMPLETE, dwTransID, dwCount,
//				pGroup->GetName (), hrMasterError);
		}

	// Loop over items:
	// 读取项数据
	for (DWORD dwItem = 0; dwItem < dwCount; dwItem++)
		{
		// The client item handles give us pointers to the destination
		// COPCItem objects:
		pItem = (COPCItem *) phClientItems [dwItem];

		// Wrap use of pItem in exception handler in case pointer is bad:
		try
			{
			// Update the item's value, quality, and timestamp:
			pItem->UpdateData (pvValues [dwItem], pwQualities [dwItem], pftTimeStamps [dwItem]);
			}
		catch (...)
			{
			// Must have tried to use a bad pItem pointer.  Bump a bad item 
			// handle count and try to process then next item:
			++cdwBadItemHandles;
			continue;
			}

		// Issue a TRACE message if item read resulted in an error. This is 
		// for debugging purposes.  You could call GetErrorString() to get
		// meaning of server specific error codes and log them if you wish.
		if (FAILED (pErrors [dwItem]))
			{
			TRACE (_T("OPC: OnDataChange 2.0 - item '%s' failure %08X\r\n"), 
				pItem->GetItemID (), pErrors [dwItem]);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -