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

📄 opcdrvgroupdo.cpp

📁 基于Intellution开发包的开发的OPC服务器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	int				vsize	= 0;
	VARIANT			vTemp;
	VariantInit(&vTemp);
	for (j = 0; j < nCount; j++)
	{
		// Get serverhandle of items to send
		// (they were in use a millisecond ago and are assumed to be still)
		//
		OPCHandle = ItemHandleList[j];
		pItem = GetItemPtr(OPCHandle);

		// Get the basic ItemHeader info
		//
		pItem->GetValue(dwSource,
						&vTemp, 
						&pItemHdr1->wQuality, 
						&pItemHdr1->ftTimeStampItem);	// with time
		
		pItemHdr1->hClient			= pItem->GetHandle();
		pItemHdr1->dwValueOffset	= pcDataPtr - gp;
		pItemHdr1->wReserved		= 0;
					
		// Plus the variant
		// Note that any 'pointer' in the variant will be meaningless
		//
		vsize = OPCVariantPack(pcDataPtr, &vTemp);
		VariantClear(&vTemp);
			
		// If this is an OnDataChange then clear the item changed flag
		// else if this is an Async Read then do some special quality handling
		//
		if(wMask)
		{
			pItem->ClearChanged(wMask);	//with time
		} 
		else
		{
			// if async read then group must be active
			//
			if((OPC_DS_CACHE == dwSource) && (!m_bActive))
			{
				((QUALITY_STATE *)&pItemHdr1->wQuality)->nQuality = QUALITY_BAD;
				((QUALITY_STATE *)&pItemHdr1->wQuality)->nSubStatus = SS_OUT_OF_SERVICE;
			}
		}

		// The update the pointers
		//
		pItemHdr1++;
		pcDataPtr += vsize;
	}

	// And invoke the callback
	//
	STGMEDIUM stm;
	FORMATETC fe;

	fe.cfFormat			= m_pCImpIDataObject->m_datatime;	// with time
	fe.ptd				= NULL;
	fe.dwAspect			= DVASPECT_CONTENT;
	fe.lindex			= -1;
	fe.tymed			= TYMED_HGLOBAL;

	stm.tymed			= TYMED_HGLOBAL;
	stm.hGlobal			= gh;
	stm.pUnkForRelease	= NULL;

	// Save the last update time
	//
	CoFileTimeNow(&m_pParentServer->m_ftLastUpdate);

	// Pull the IAdviseSink interface pointer out of the stream object.
	//
	if (NULL == m_pdatatimeSink)
	{
		hr = CoGetInterfaceAndReleaseStream (m_pCImpIDataObject->m_pdatatimeStm,
											 IID_IAdviseSink, 
											 (LPVOID *)&m_pdatatimeSink);
		if (FAILED(hr))
		{
			return;
		}
	}

	// Call into the IAdviseSink that the client provided with the data.
	//
	__try
	{
		m_pdatatimeSink->OnDataChange(&fe, &stm);
	}
	__finally
	{
		// And free the storage
		//
		GlobalFree(gh);
	}
}


////////////////////////////////////////////////////////////////
// COPCDrvGroup::SendStream()  (Without Time)
//
// @desc	This function is used to build the stream for OnDataChange and also
//			for async operations such as Read and Refresh
//			The two cases are 'almost' the same except for 
//			a small bit of 'mask' and quality logic as you can see below
//
//			Create the Stream which consists of:
//				GroupHeader
//				ItemHeaders
//				Variants and Related Data.
//
// @parm	IN			int				| nCount		| Count of items to send
// @parm	IN			OPCHANDLE *		| ItemHandleList| Item handle list
// @parm	IN			DWORD			| dwDataSize	| Data size
// @parm	IN			WORD			| wMask			| Mask to clear
// @parm	IN			DWORD			| tid			| Transaction ID
// @parm	IN OPTIONAL OPCDATASOURCE	| dwSource		| Data source (cache or device)
//
// @retval	void
//
// @devnote	We use exception handling around the call to OnDataChange()
//			since this is an open architecture and we have no control
//			over the client's implementation. We want to make sure we
//			don't crash.
//
////////////////////////////////////////////////////////////////
void COPCDrvGroup::SendStream(int				nCount, 
							  OPCHANDLE			*ItemHandleList, 
							  DWORD				dwDataSize, 
							  WORD				wMask, 
							  DWORD				tid,
							  OPCDATASOURCE		dwSource)	/* = OPC_DS_DEVICE */
{
	int			j, 
				nHdrSize, 
				nTotalSize;
	OPCHANDLE	OPCHandle;
	HRESULT		hr;


	// Allocate the Data Stream
	//
	nHdrSize = sizeof(OPCGROUPHEADER) + nCount * sizeof(OPCITEMHEADER2);	// without time
	nTotalSize = nHdrSize + dwDataSize;

	char * gp;
	HGLOBAL gh;

	gh = GlobalAlloc(GMEM_FIXED, nTotalSize);
	if(NULL == gh)
	{
		// If no memory, For now we just give up and return;
		// But a better error handler would be nice
		//
		return;
	}
	gp = (char*)GlobalLock(gh);

	OPCGROUPHEADER	*pGrpPtr;
	OPCITEMHEADER2	*pItemHdr1;	// Without Time
	char			*pcDataPtr;

	pGrpPtr		= (OPCGROUPHEADER *) gp;
	pItemHdr1	= (OPCITEMHEADER2 *) (gp + sizeof(OPCGROUPHEADER));	// without Time
	pcDataPtr	= gp + nHdrSize;

	// Fill in the Group header
	//
	pGrpPtr->dwSize				= nTotalSize;
	pGrpPtr->dwItemCount		= nCount;
	pGrpPtr->hClientGroup		= m_ClientGroupHandle;
	pGrpPtr->hrStatus			= S_OK;
	pGrpPtr->dwTransactionID	= tid;

	// Now fill in the Item Information
	//
	COPCDrvItem		*pItem	= NULL;
	int				vsize	= 0;
	VARIANT			vTemp;
	VariantInit(&vTemp);
	for (j = 0; j < nCount; j++)
	{
		// Get serverhandle of items to send
		// (they were in use a millisecond ago and are assumed to be still)
		// We should be in a critical seciton here
		//
		OPCHandle = ItemHandleList[j];
		pItem = GetItemPtr(OPCHandle);

		// Get the basic ItemHeader info
		//
		pItem->GetValue(dwSource,
						&vTemp,
						&pItemHdr1->wQuality,
						NULL);		// without time

		pItemHdr1->hClient			= pItem->GetHandle();
		pItemHdr1->dwValueOffset	= pcDataPtr - gp;
		pItemHdr1->wReserved		= 0;
					
		// Plus the variant
		// Note that any 'pointer' in the variant will be meaningless
		//
		vsize = OPCVariantPack(pcDataPtr, &vTemp);
		VariantClear(&vTemp);
			
		// If this is an OnDataChange then clear the item changed flag
		// else if this is an Async Read then do some special quality handling
		//
		if(wMask)
		{
			pItem->ClearChanged(wMask);	// without time
		} 
		else
		{
			// If async read from cache then group must be active
			//
			if((OPC_DS_CACHE == dwSource) && (!m_bActive))
			{
				((QUALITY_STATE *)&pItemHdr1->wQuality)->nQuality = QUALITY_BAD;
				((QUALITY_STATE *)&pItemHdr1->wQuality)->nSubStatus = SS_OUT_OF_SERVICE;
			}
		}

		// The update the pointers
		//
		pItemHdr1++;
		pcDataPtr += vsize;
	}

	// And invoke the callback
	//
	STGMEDIUM stm;
	FORMATETC fe;

	fe.cfFormat			= m_pCImpIDataObject->m_data;		// without time
	fe.ptd				= NULL;
	fe.dwAspect			= DVASPECT_CONTENT;
	fe.lindex			= -1;
	fe.tymed			= TYMED_HGLOBAL;

	stm.tymed			= TYMED_HGLOBAL;
	stm.hGlobal			= gh;
	stm.pUnkForRelease	= NULL;

	// Save the last update time
	//
	CoFileTimeNow(&m_pParentServer->m_ftLastUpdate);

	// Pull the IAdviseSink interface pointer out of the stream object.
	//
	if (NULL == m_pdataSink)
	{
		hr = CoGetInterfaceAndReleaseStream (m_pCImpIDataObject->m_pdataStm,
											 IID_IAdviseSink, 
											 (LPVOID *)&m_pdataSink);
		if (FAILED(hr))
		{
			return;
		}
	}
	
	
	// Call into the IAdviseSink that the client provided with the data.
	//
	__try
	{
		m_pdataSink->OnDataChange(&fe, &stm);	// without time
	}
	__finally
	{
		// And free the storage
		//
		GlobalFree(gh);
	}
}


////////////////////////////////////////////////////////////////
// COPCDrvGroup::SendWriteStream()
//
// @desc	This function is used to build the stream for OnWriteComplete
//
//			Create the Stream which consists of:
//				GroupHeader
//				ItemHeaders
//
// @parm	IN			int				| nCount		| Count of items to send
// @parm	IN			OPCHANDLE *		| ItemHandleList| Item handle list
// @parm	IN			DWORD			| tid			| Transaction ID
//
// @retval	void
//
// @devnote	We use exception handling around the call to OnDataChange()
//			since this is an open architecture and we have no control
//			over the client's implementation. We want to make sure we
//			don't crash.
//
////////////////////////////////////////////////////////////////
void COPCDrvGroup::SendWriteStream(int			nCount, 
								   OPCHANDLE	*ItemHandleList, 
								   DWORD		tid)
{
	int			j, 
				nHdrSize, 
				nTotalSize;
	OPCHANDLE	OPCHandle;
	COPCDrvItem	*pItem;

	// Allocate the Data Stream
	//
	nHdrSize = sizeof(OPCGROUPHEADERWRITE) + nCount * sizeof(OPCITEMHEADERWRITE);
	nTotalSize = nHdrSize ;

	char	* gp;
	HGLOBAL	gh;

	gh = GlobalAlloc(GMEM_FIXED, nTotalSize);
	if(NULL == gh)
	{
		// If no memory, For now we just give up and return;
		// But a better error handler would be nice
		//
		return;
	}
	gp = (char *)GlobalLock(gh);

	OPCGROUPHEADERWRITE		*pGrpPtr;
	OPCITEMHEADERWRITE		*pItemHdr1;

	pGrpPtr		= (OPCGROUPHEADERWRITE *) gp;
	pItemHdr1	= (OPCITEMHEADERWRITE *) (gp + sizeof(OPCGROUPHEADERWRITE));

	// Fill in the Group Write header
	//
	pGrpPtr->dwItemCount		= nCount;
	pGrpPtr->hClientGroup		= m_ClientGroupHandle;
	pGrpPtr->dwTransactionID	= tid;
	pGrpPtr->hrStatus			= S_OK;

	// Now fill in the Item Information
	//
	for (j = 0; j < nCount; j++)
	{
		// Get serverhandle of items to send
		// We are be in a critical seciton here
		//
		OPCHandle = ItemHandleList[j];
		pItem = GetItemPtr(OPCHandle);

		// Get the ItemHeader info
		//
		pItem->CheckDeviceWrite(&pItemHdr1->dwError);
		pItemHdr1->hClient = pItem->GetHandle();
					
		// The update the pointers
		//
		pItemHdr1++;
	}

	// And invoke the callback
	//
	STGMEDIUM	stm;
	FORMATETC	fe;

	fe.cfFormat			= m_pCImpIDataObject->m_write;
	fe.ptd				= NULL;
	fe.dwAspect			= DVASPECT_CONTENT;
	fe.lindex			= -1;
	fe.tymed			= TYMED_HGLOBAL;

	stm.tymed			= TYMED_HGLOBAL;
	stm.hGlobal			= gh;
	stm.pUnkForRelease	= NULL;

	// Save the last update time
	//
	CoFileTimeNow(&m_pParentServer->m_ftLastUpdate);
	
	if (NULL == m_pwriteSink)
	{
		HRESULT hr = CoGetInterfaceAndReleaseStream(m_pCImpIDataObject->m_pwriteStm,
													IID_IAdviseSink, 
													(LPVOID *)&m_pwriteSink);
		if (FAILED(hr))
		{
			return;
		}
	}


	// Call into the IAdviseSink that the client provided with the data.
	//
	__try
	{
		m_pwriteSink->OnDataChange(&fe, &stm);
	}
	__finally
	{
		// And free the storage
		//
		GlobalFree(gh);
	}
}


////////////////////////////////////////////////////////////////
// COPCDrvGroup::ComputeSize()
//
// @desc	This function is used to compute the size of the HGLOBAL
//			(a.k.a. 'the stream') needed to contain the OnDataChange
//			info for IAdviseSink
//
// @parm	IN	int			| nCount		| Number of items
// @parm	IN	OPCHANDLE *	| HandleList	| List of item handles
//
// @retval	long	| Size or data in bytes
//
////////////////////////////////////////////////////////////////
long COPCDrvGroup::ComputeSize(int			nCount, 
							   OPCHANDLE	*HandleList)
{
	long lDataSize = 0L;


	for(int i = 0; i < nCount; i++)
	{
		lDataSize += GetItemPtr(HandleList[i])->GetDataSize();
	}
	return lDataSize;
}

⌨️ 快捷键说明

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