📄 opcdata.cpp
字号:
// 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 + -