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

📄 libopc.cpp

📁 自动化领域的软件标准通讯接口OPC的封装
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	return hr ;
}

///////////////////////////////////////////////////////////////////////////
// This Method Write Tags.
// pValues is a structure of type CItem. See CItem in the header file
// ServerHandles is the array originally used in the OPCAddTags().
///////////////////////////////////////////////////////////////////////////
HRESULT CAppServer::OPCWriteTags(CItem* pValues, DWORD NoOfItems, OPCHANDLE ServerHandles[],int &nErr)
{
	// Test for connectivity
	if (!CoIsHandlerConnected (m_pIOPCGroupStateMgt[m_nGroupNo]))
		m_pIOPCGroupStateMgt[m_nGroupNo].Release() ;

	HRESULT hr, *pErrors = NULL;
	VARIANT vartype[_OPC_MAX_HANDLE];
	CComQIPtr<IOPCSyncIO, &IID_IOPCSyncIO> opcSyncIO (m_pIOPCGroupStateMgt[m_nGroupNo]) ;

	if (NoOfItems <= 0 || NoOfItems > _OPC_MAX_HANDLE)
		return _OPC_TOO_MANY_ITEMS ;

	
	for (DWORD idx=0; idx<NoOfItems; idx++)
	{
//		_wcsupr(pValues[idx].cName) ;

		
		VariantInit(&vartype[idx]);
		//if(pValues[idx].value.vt==VT_BSTR)
	//{
			//vartype[idx].vt=VT_BSTR;
			
	//		vartype[idx].vt=VT_LPSTR;
	//		_tcscpy(ss,pValues[idx].value.bstrVal);
			//vartype[idx].bstrVal=pValues[idx].value.bstrVal;
	//		vartype[idx].pbstrVal=&ss;
	//	}else
	//	{
		VariantClear(&vartype[idx]);	
		if(S_OK!=VariantCopy(&vartype[idx],&(pValues[idx].value)))
		{
			continue;
		}
	//	}
		//vartype[idx].vt  = pValues[idx].value.vt;
		//vartype[idx] = pValues[idx].value;
	}


	// Write the items using the IOPCSyncIO Interface pointer.
	hr = opcSyncIO->Write(NoOfItems, ServerHandles, vartype, &pErrors) ;

	
	if( SUCCEEDED(hr) )
	{
		nErr = 0 ;
		for(DWORD index=0; index < NoOfItems; index++)  
		{
			if ( FAILED(pErrors[index]) )
				nErr++ ;

			pValues[index].nResult = pErrors[index] ;
		}	
		CoTaskMemFree( pErrors );
	}
	else
	{		
		CoTaskMemFree( pErrors );
	}

	return hr ;
}
///////////////////////////////////////////////////////////////////////////
// Extracts the value corresponding to the vt type. Note, if the value is
// of type VT_BSTR, don't forget to release the bstrVal that came from the
// OPC Server. The OPC Server allocates memory for VT_BSTR type. It is the
// responsibility of the client to release the allocated memory
///////////////////////////////////////////////////////////////////////////
void CAppServer::ReadDataValues(CItem* pValues, OPCITEMSTATE* pItemState, DWORD index)
{
	switch (pItemState[index].vDataValue.vt) 
	{
		case VT_UI1:
			pValues[index].value.bVal = pItemState[index].vDataValue.bVal ;
			break;
		case VT_I2:
			pValues[index].value.iVal = pItemState[index].vDataValue.iVal ;
			break;
		case VT_I4:
			pValues[index].value.lVal = pItemState[index].vDataValue.lVal ;
			break;
		case VT_R4:
			pValues[index].value.fltVal = pItemState[index].vDataValue.fltVal ;
			break;
		case VT_R8:
			pValues[index].value.dblVal = pItemState[index].vDataValue.dblVal ;
			break;
		case VT_BOOL:
			pValues[index].value.boolVal = pItemState[index].vDataValue.boolVal ;
			break;
		case VT_BSTR:
			//SysFreString				
			//wcscpy(pValues[index].value.bstrVal, pItemState[index].vDataValue.bstrVal) ;
			pValues[index].value.bstrVal=SysAllocString(pItemState[index].vDataValue.bstrVal);
			SysFreeString(pItemState[index].vDataValue.bstrVal);
			break;
		case VT_NULL:
			break;
		// Note: VT_CY and VT_DATE are not implemented
		default:
			break;
	}
}
///////////////////////////////////////////////////////////////////////////
// This Method is used for checking the validity of a group name
// and returns the appropriate group structure if one is found
///////////////////////////////////////////////////////////////////////////
int CAppServer::CheckGroupName(LPWSTR szGrpName, CGroup &GrpNum)
{
//	_wcsupr(szGrpName) ;
	for (int indx=0; indx<_OPC_MAX_GROUP; indx++)
		if (!wcscmp (szGrpName, GroupNumber[indx].m_szGrpName))
		{
			GrpNum = GroupNumber[indx] ;
			return FALSE ;
		}

	return TRUE;
}

///////////////////////////////////////////////////////////////////////////
// This Method adds a new group name to the array. The maximum group
// is defined in _OPC_MAX_GROUP.
///////////////////////////////////////////////////////////////////////////
int CAppServer::AddGroupName(LPWSTR szGrpName, CGroup &GrpNum)
{
//	_wcsupr(szGrpName) ;
	for (int indx=0; indx<_OPC_MAX_GROUP; indx++)
		if (!GroupNumber[indx].m_szGrpName[0])
		{
			wcscpy(GroupNumber[indx].m_szGrpName, szGrpName) ;
			GroupNumber[indx].m_nGroupNo = indx ;
			GrpNum = GroupNumber[indx] ;
			break ;
		}
		else 
		{
			if (!wcscmp(szGrpName, GroupNumber[indx].m_szGrpName))
				return TRUE ;
		}

	if (indx == _OPC_MAX_GROUP) return TRUE ;

	return FALSE;
}

///////////////////////////////////////////////////////////////////////////
// This Method is used to change to another group. The new group 
// becomes the default group
///////////////////////////////////////////////////////////////////////////
int CAppServer::OPCChangeGroup(LPWSTR szGrpName)
{
//	_wcsupr(szGrpName) ;
	for (int indx=0; indx<_OPC_MAX_GROUP; indx++)
		if (!wcscmp(szGrpName, GroupNumber[indx].m_szGrpName))
		{
			m_nGroupNo = GroupNumber[indx].m_nGroupNo ;
			return FALSE ;
		}
	return TRUE ;
}

///////////////////////////////////////////////////////////////////////////
// This Method is used to remove Items in a specified Group
///////////////////////////////////////////////////////////////////////////
HRESULT CAppServer::OPCRemoveItems (LPWSTR szGrpName, DWORD NoOfItems, OPCHANDLE ServerHandles[], HRESULT pErr[])
{
	HRESULT hr ;
	CGroup GrpNum ;
	HRESULT *pErrors = 0;

	if (!CheckGroupName(szGrpName, GrpNum))
	{
		if (!CoIsHandlerConnected(m_pIOPCGroupStateMgt[GrpNum.m_nGroupNo]))
		{
			m_pIOPCGroupStateMgt[GrpNum.m_nGroupNo].Release() ;
			return _OPC_SERVER_NOT_CONNECTED ;
		}
		CComQIPtr <IOPCItemMgt, &IID_IOPCItemMgt> pItemMgt (m_pIOPCGroupStateMgt[GrpNum.m_nGroupNo]) ;

		hr = pItemMgt->RemoveItems(NoOfItems, ServerHandles, &pErrors) ;
          if( SUCCEEDED(hr) )
             CoTaskMemFree( pErrors );

		if (FAILED(hr))
			return hr ;

		pItemMgt.Release() ;
		return hr ;
	}
	else
		return _OPC_INVALID_GROUP_NAME ;

}

///////////////////////////////////////////////////////////////////////////
// This Method is used to remove a group from the OPC Server
///////////////////////////////////////////////////////////////////////////
HRESULT CAppServer::OPCRemoveGroup (LPWSTR szGrpName)
{
	HRESULT hr ;
	CGroup GrpNum ;

	if (!CheckGroupName(szGrpName, GrpNum))
	{
		hr = m_pIOPCServer->RemoveGroup(GroupNumber[GrpNum.m_nGroupNo].m_GroupHandle, FALSE) ;
		m_pIOPCGroupStateMgt[GrpNum.m_nGroupNo].Release() ;
		// Reset all the Group Variables to initial value
		GroupNumber[GrpNum.m_nGroupNo].m_szGrpName[0] = L'\0' ;
		GroupNumber[GrpNum.m_nGroupNo].m_GroupHandle  = 0 ;
		GroupNumber[GrpNum.m_nGroupNo].m_NoOfItems = 0 ;
		GroupNumber[GrpNum.m_nGroupNo].m_nGroupNo = -1 ;
		m_nGroupNo = -1 ;
		m_nTotalGroups-- ;

		return hr ;
	}
	else
		return _OPC_INVALID_GROUP_NAME ;

}

///////////////////////////////////////////////////////////////////////////
// This Method is for disconnecting the OPC Server
///////////////////////////////////////////////////////////////////////////
HRESULT CAppServer::OPCDisconnect ()
{
	// Check all groups in case some are not released
	for (int nGrpNo=0;nGrpNo<m_nTotalGroups;nGrpNo++)
	{		
		if (GroupNumber[nGrpNo].m_GroupHandle)
			m_pIOPCGroupStateMgt[nGrpNo].Release() ;
	}

	m_pIOPCServer.Release() ;

	return	S_OK ;
}

///////////////////////////////////////////////////////////////////////////
// This Method can be used for testing errors 
///////////////////////////////////////////////////////////////////////////
void CAppServer::OPCpErrors (HRESULT* pErrors, int NoOfItems)
{
	for (int i=0; i<NoOfItems; i++)
	{
		switch (pErrors[i])
		{

			case OPC_E_INVALIDHANDLE:
				wprintf (L"pErrors[i] = OPC_E_INVALIDHANDLE\n") ;
				break ;
		
			case OPC_E_UNKNOWNITEMID:
				wprintf (L"pErrors[i] = OPC_E_UNKNOWNITEMID\n") ;
				break ;

			case OPC_E_RANGE:
				wprintf (L"pErrors[i] = OPC_E_RANGE\n") ;
				break ;

			case E_FAIL:
				wprintf (L"pErrors[i] = E_FAIL\n") ;
				break ;

			default:
				break ;
		}
	}
}

HRESULT CAppServer::BrowseServerAddressSpace(LPWSTR *pzName, unsigned long* cnt)
{

	VARTYPE  m_vt = VT_EMPTY ;
	OPCNAMESPACETYPE  nameSpaceType;
	HRESULT hr = 0;
	nameSpaceType = OPC_NS_HIERARCHIAL;
	IEnumString* pEnumString = NULL;
	const unsigned long NEXT_COUNT = 1000 ;
	LPWSTR pName[NEXT_COUNT];

	CComQIPtr<IOPCBrowseServerAddressSpace, &IID_IOPCBrowseServerAddressSpace> m_pIOPCBrowseServerAddressSpace (m_pIOPCServer);

	if (!m_pIOPCServer || !m_pIOPCBrowseServerAddressSpace)
		return _OPC_INVALID_OBJECT;

	m_pIOPCBrowseServerAddressSpace->QueryOrganization(&nameSpaceType);

	if( nameSpaceType == OPC_NS_HIERARCHIAL ) // show a tree
	{
		hr = m_pIOPCBrowseServerAddressSpace->BrowseOPCItemIDs(OPC_BRANCH,
					L"*RQE*",
					m_vt,
					0,
					&pEnumString);

		if( SUCCEEDED(hr) )
		{
			unsigned long count = 0;
			do
			{
				hr = pEnumString->Next(NEXT_COUNT, &pName[0], &count);
				for( ULONG index=0; index<count; index++ )
				{
					wcscpy (pzName[index], pName[index]) ;
					CoTaskMemFree( pName[index] );
				}
			}
			while( hr == S_OK );
			pEnumString->Release();
			*cnt = count ;
		}

	}
	else
	{
		hr = m_pIOPCBrowseServerAddressSpace->BrowseOPCItemIDs(OPC_LEAF,
				L"*RQE*",
				m_vt,
				0,
				&pEnumString);

		if( SUCCEEDED(hr) )
		{
			unsigned long count = 0;
			do
			{
				hr = pEnumString->Next(NEXT_COUNT, &pName[0], &count);
				for( ULONG index=0; index<count; index++ )
				{
					wcscpy (pzName[index], pName[index]) ;
					CoTaskMemFree( pName[index] );
				}
			}
			while( hr == S_OK );
			pEnumString->Release();
		}
	}

	return hr ;
}

bool CAppServer::IsOK () const { return (m_pIOPCServer != NULL); }


⌨️ 快捷键说明

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