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

📄 opcdata.cpp

📁 OPC Client 源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:

	// 2-D array:
	else if (pvtSrc->parray->cDims == 2)
		{
		cnRows = pvtSrc->parray->rgsabound [0].cElements;
		cnCols = pvtSrc->parray->rgsabound [1].cElements;
		}

	// Do not support more than 2 dimensions:
	else
		{
		ASSERT (FALSE);
		return (false);
		}

	// Initialize destination array:
	VariantInit (pvtDst);

	// Set destination array type:
	pvtDst->vt = pvtSrc->vt;

	// Allocate memory for destination array:
	pvtDst->parray = SafeArrayCreate (pvtSrc->vt & ~VT_ARRAY, 
		pvtSrc->parray->cDims, pvtSrc->parray->rgsabound);

	// Copy data to destination array:
	VariantCopy (pvtDst, pvtSrc);

	// Overwrite fields with data:
	int nIndex = 0;
	GETARRELEMRET eRet;
	BYTE HUGEP *pVal = (BYTE *) pvtDst->parray->pvData;
	int cnRowElements = 0;

	// Loop over all array elements:
	for (int i = 0; i < cnRows * cnCols; i++)
		{
		// Create a scratch buffer for parsed array element string:
		TCHAR szBuffer [DEFBUFFSIZE];

		// Parse next element in string:
		eRet = GetArrayElement (szValue, &nIndex, szBuffer, DEFBUFFSIZE);

		// If parse resulted in done code, the break out of loop:
		if (eRet == tDone)
			break;

		// If parse resulted in invalid code, return false:
		if (eRet == tInvalid)
			{
			TRACE (_T("OTC: Invalid character parsing array value\r\n"));
			return (false);
			}

		// If parse reslted in overflow code, return false:
		if (eRet == tOverflow)
			{
			TRACE (_T("OTC: Buffer overflow parsing array value\r\n"));
			return (false);
			}

		// If we make it here, we expect to have element or end of row code:
		ASSERT (eRet == tElement || eRet == tEndRow);

		// If element is not NULL string, then overwrite field in destination:
		if (*szBuffer != _T('\0'))
			{
			// Cast string to proper type:
			switch (pvtDst->vt & ~VT_ARRAY)
				{
				case VT_UI1	:	*pVal = (BYTE) _ttol (szBuffer); break;
				case VT_I1	:	*pVal = (char) _ttol (szBuffer);	break;
				case VT_UI2	:	*(WORD *)pVal = (WORD) _ttol (szBuffer);	break;
				case VT_I2	:	*(short *)pVal = (short) _ttol (szBuffer); break;
				case VT_UI4 :	*(DWORD *)pVal = (DWORD) _ttol (szBuffer); break;
				case VT_I4	:	*(long *)pVal = (long) _ttol (szBuffer);	break;

				case VT_R4:
					// Text to float conversions can throw exceptions, so 
					// be prepared to handle them:
					try
						{
#ifdef _UNICODE
						*(float *)pVal = (float) wtof (szBuffer);
#else
						*(float *)pVal = (float) atof (szBuffer);
#endif
						}
					
					catch (...)
						{
						*(float *)pVal = 0;
						}

					break;

				case VT_R8:
					// Text to float conversions can throw exceptions, so 
					// be prepared to handle them:
					try
						{
#ifdef _UNICODE
						*(double *)pVal = (double) wtof (szBuffer);
#else
						*(double *)pVal = (double) atof (szBuffer);
#endif
						}
					
					catch (...)
						{
						*(double *)pVal = 0;
						}
					break;

				// Unexpected type:
				default:
					ASSERT (FALSE);
					break;
				}
			}

		// Increment destination array pointer to accept next element:

		// If last element in row:
		if (eRet == tEndRow && cnCols > cnRowElements)
			{
			pVal += (pvtDst->parray->cbElements * (cnCols - cnRowElements));
			cnRowElements = 0;
			}

		// Else next element:
		else
			{
			cnRowElements++;
			pVal += pvtDst->parray->cbElements;
			}
		}

	// If we make it here, then return true to indicate success:
	return (true);
	}

// **************************************************************************
// MapStringValToVariant ()
//
// Description:
//	Map a string value to a variant.
//
// Parameters:
//  CString		&strValue	String to be converted to variant
//	VARIANT		&vtVal		Variant.
//	VARTYPE		vtType		Variant type to force string to.
//
// Returns:
//  bool - true if success.
// **************************************************************************
bool COPCGroup::MapStringValToVariant (CString &strValue, VARIANT &vtVal, VARTYPE vtType)
	{
	// Assume success until a problem arises:
	bool bSuccess = true;

	// Initialize variant for use:
	VariantInit (&vtVal);

	// Set variant type:
	vtVal.vt = vtType;

	// Cast string to proper value:
	switch (vtVal.vt)
		{
		case VT_BOOL:
			{
			unsigned char ucVal = (unsigned char) _ttol (strValue);
			vtVal.boolVal = ucVal ? VARIANT_TRUE : VARIANT_FALSE;
			}
			break;

		case VT_UI1:
			vtVal.bVal = (unsigned char) _ttol (strValue);
			break;

		case VT_I1:
			vtVal.cVal = (char) _ttol (strValue);
			break;

		case VT_UI2:
			vtVal.uiVal = (unsigned short) _ttol (strValue);
			break;

		case VT_I2:
			vtVal.iVal = (short) _ttol (strValue);
			break;

		case VT_UI4:
			vtVal.ulVal = (unsigned long) _ttol (strValue);
			break;

		case VT_I4:
			vtVal.lVal = (long) _ttol (strValue);
			break;

		case VT_R4:
			// Text to Float conversions can threow expections.  Be
			// prepared to handle them:
			try
				{
#ifdef _UNICODE
				vtVal.fltVal = (float) wtof (strValue);
#else
				vtVal.fltVal = (float) atof (strValue);
#endif
				}
			
			catch (...)
				{
				// Set value to zero in case of conversion error:
				vtVal.fltVal = 0;
				}
			break;

		case VT_R8:
			// Text to Float conversions can threow expections.  Be
			// prepared to handle them:
			try
				{
#ifdef _UNICODE
				vtVal.dblVal = (double) wtof (strValue);
#else
				vtVal.dblVal = (double) atof (strValue);
#endif
				}
			
			catch (...)
				{
				// Set value to zero in case of conversion error:
				vtVal.dblVal = 0;
				}
			break;

		case VT_BSTR:
			{
			// Get string length:
			DWORD dwLength = strValue.GetLength () + 1;

			// Alocate memory for string:
			vtVal.bstrVal = SysAllocStringLen (NULL, dwLength);

#ifdef _UNICODE
			// UNICODE build, so do a simple string copy:
			lstrcpyn (vtVal.bstrVal, strValue, dwLength);
#else
			// ANSI build requires string conversion:
			MultiByteToWideChar (CP_ACP, 0, strValue, -1, vtVal.bstrVal, dwLength);
#endif
			}
			break;

		// We don't expect array types.  If so, return false:
		case VT_UI1	| VT_ARRAY:
		case VT_I1	| VT_ARRAY:
		case VT_UI2	| VT_ARRAY:
		case VT_I2	| VT_ARRAY:
		case VT_UI4	| VT_ARRAY:
		case VT_I4	| VT_ARRAY:
		case VT_R4	| VT_ARRAY:
		case VT_R8	| VT_ARRAY:
			ASSERT (FALSE);
			bSuccess = false;
			break;

		default:
			// Unexpected variant type.  Return false:
			bSuccess = false;
			break;
		}

	// Return success:
	return (bSuccess);
	}
// **************************************************************************
// GetArrayElement ()
//
// Description:
//	Parse an element from a comma delimited string of array values.  Called 
//	once per element.  pnStart will be reset to end of current element for 
//	subsequent call.
//
// Parameters:
//  LPCTSTR		szInBuff	Input string.
//	int			*pnStart	Character position to begin parse.
//	LPTSTR		szOutBuff	Array element output string buffer.
//	int			nBuffSize	Size of output buffer.
//
// Returns:
//  GETARRELEMRET - Values enumerated in group.h.
// **************************************************************************
COPCGroup::GETARRELEMRET COPCGroup::GetArrayElement (LPCTSTR szInBuff, int *pnStart, LPTSTR szOutBuff, int nBuffSize)
	{
	// Initialize some variables:
	TCHAR ch = _T('\r');
	BOOL bLeftBracket = FALSE;
	int cnChars = 0;
	
	GETARRELEMRET eRet = tElement;

	// If we are at the end of the buffer then we're done:
	if (!szInBuff [*pnStart])
		return (tDone);

	// Continue to read characters until we hit the next comma or
	// an EOL (End Of Line - "\n") character:
	while (TRUE)
		{
		// Get the next character, and increment start position for next time:
		ch = szInBuff [(*pnStart)++];

		// If the character is NULL, we are at the end of the record and
		// therefore is nothing left to read.  Back up the start position
		// and break out of the loop.
		if (!ch)
			{
			(*pnStart)--;
			break;
			}

		// Trim leading whitespace, if any.  If current character is a space,
		// then continue.  This will force us to process next character without
		// saving current one (a space) in output buffer.
		if (!cnChars && _istspace (ch))
			continue;

		// Brackets and commas delimit the fields:
		if (ch == _T('['))
			{
			if (bLeftBracket)
				{
				eRet = tInvalid;
				break;
				}

			continue;
			}

		if (ch == _T(']'))
			{
			eRet = tEndRow;
			break;
			}

		if (ch == _T(','))
			break;

		// If we make it here, then the current character is "a keeper".
		// Increment the character counter:
		++cnChars;

		// Add the current character to the output buffer as long a there
		// is room:
		if (nBuffSize > 1)
			{
			// There is room, so add the current character to the output 
			// buffer, and move output buffer pointer to next position.
			*szOutBuff++ = ch;

			// Decrement nBuffSize.  When it hits zero we know we have
			// filled the output buffer to capacity.
			--nBuffSize;
			}
		else
			{
			// There is no more room in the output buffer.  Set the bOverflow
			// flag, but don't break out of the loop.  We want to keep going
			// until we hit a field deleimiter.  This will allow us to parse
			// the next field, even though this one is too big to deal with.
			eRet = tOverflow;
			break;
			}
		}

	// Make sure the output string is properly NULL terminated:
	*szOutBuff = 0;

	// Return return code:
	return (eRet);
	}

//////////////////////////////////////////////////////////////////////
//COPCServer: Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_SERIAL( COPCServer, CObject, VERSIONABLE_SCHEMA | 2 )

COPCServer::COPCServer()
{
	m_hTreeItem=NULL;
	m_pOPCRemPC=NULL;

	m_pSelGroup=NULL;
	m_bConnected=FALSE;

	m_strName=_T("OPCServer");
	m_strRemoteMachine=LOACAL_MACHINE;		//远程机器名称
	m_strRemoteIP=LOACAL_MACHINE;

	m_unOPCVersion=OPC_VER_20;			//OPC SERVER 支持的版本:OPC_VER_10,OPC_VER_20,OPC_VER_30
	//OPC Interface
	m_pIServer=NULL;		// interface pointers returned from CoCreateInstanceEx ()
	m_pICommon=NULL;
	m_pIConnPtContainer=NULL;
	m_pIItemProps=NULL;
	m_pIBrowseAddressSpace=NULL;
	m_pIPublicGroups=NULL;
	m_pIBrowse=NULL;				//N/A		N/A			OPC30
	m_pIItemIO=NULL;				//N/A		N/A			OPC30
	m_pIPersistFile=NULL;

	m_pIShutdownSink=NULL;	//服务器对象回调接口
	m_dwCookieShutdownSink=0;
}

COPCServer::~COPCServer()
{
	//断开连接
	if(IsConnected())
		Disconnect();

	COPCGroup* pGroup;
	CString strGroup;
	POSITION pos =m_cMapGroup.GetStartPosition ();
	while(pos)
	{
		m_cMapGroup.GetNextAssoc(pos,strGroup,(void*&)pGroup);
		delete pGroup;
	}
}


BOOL COPCServer::Query_IOPCServer(MULTI_QI& MultiQI)
{
	UINT unEventID=HINT_SERVER_ADD+HINT_EVENT_OFFSET;
	CString strTip=_T("查询接口 IID_IOPCServer 成功");;
	BOOL bQuery_OK=FALSE;

	if (SUCCEEDED (MultiQI.hr))
	{
		m_pIServer = (IOPCServer *)MultiQI.pItf;

		if (m_pIServer == NULL)
		{
			// Warning success but no valid pointer:
			strTip=_T("查询接口 IID_IOPCServer 失败");
			ASSERT (FALSE);
		}
		else
		{
			bQuery_OK=TRUE;
			TRACE (_T("OPC: Succeeded to query IOPCServer \r\n")); 				
		}
	}
	else
	{
		if (MultiQI.pItf != NULL)
		{
			// Warning failure but pointer not set to null
			strTip=_T("查询接口 IID_IOPCServer 失败");
			ASSERT (FALSE);
		}

		TRACE (_T("OPC: Failed to query IOPCServer (%08X).\r\n"), 
			MultiQI.hr); 
		
	}

	//事件视中提示
	LogMsg(unEventID,(CObject *)& strTip);

	return bQuery_OK;
}

BOOL COPCServer::Query_IOPCCommon(MULTI_QI& MultiQI)
{
	UINT unEventID=HINT_SERVER_ADD+HINT_EVENT_OFFSET;
	CString strTip=_T("查询接口 IID_IOPCCOMMON 成功");
	BOOL bQuery_OK=FALSE;

	if (SUCCEEDED (MultiQI.hr))
	{
		m_pICommon = (IOPCCommon *)MultiQI.pItf;

		if (m_pICommon == NULL)
		{
			strTip=_T("查询接口 IID_IOPCCOMMON 失败");

			// Warning success but no valid pointer:
			ASSERT (FALSE);
		}
		else
		{
			bQuery_OK=TRUE;
			TRACE (_T("OPC: Succeeded to query IOPCCommon \r\n")); 				
		}
	}
	else
	{
		if (MultiQI.pItf != NULL)
		{
			// Warning failure but pointer not set to null:
			strTip=_T("查询接口 IID_IOPCCOMMON 失败");

			ASSERT (FALSE);
		}

		TRACE

⌨️ 快捷键说明

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