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