📄 libopc.cpp
字号:
#include "stdAfx.h"
#include "LibApp.h"
#include "LibOPC.h"
#include "opcda_i.c"
#include <comdef.h>
const int _OPC_DUPLICATE_GROUP_NAME = -101 ;
const int _OPC_INVALID_OBJECT = -102 ;
const int _OPC_TOO_MANY_ITEMS = -103 ;
const int _OPC_INVALID_GROUP_NAME = -104 ;
const int _OPC_SERVER_NOT_CONNECTED = -105 ;
const int _OPC_MAX_HANDLE = 2000 ;
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
CAppServer::CAppServer() :
m_nGroupNo(-1),
m_nTotalGroups(0),
m_GroupHandle (0)
{
for (int i=0; i<_OPC_MAX_GROUP; i++)
{
GroupNumber[i].m_szGrpName[0] = L'\0' ;
GroupNumber[i].m_GroupHandle = 0 ;
GroupNumber[i].m_NoOfItems = 0 ;
GroupNumber[i].m_nGroupNo = -1 ;
}
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
CAppServer::~CAppServer()
{
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
CAppServer::CAppServer(wchar_t* svrName, wchar_t* svrType) :
m_nGroupNo(-1),
m_nTotalGroups(0),
m_GroupHandle (0)
{
wcscpy (m_wstrServerName, svrName) ;
wcscpy (m_wstrServerType, svrType) ;
for (int i=0; i<_OPC_MAX_GROUP; i++)
{
GroupNumber[i].m_szGrpName[0] = L'\0' ;
GroupNumber[i].m_GroupHandle = 0 ;
GroupNumber[i].m_NoOfItems = 0 ;
GroupNumber[i].m_nGroupNo = -1 ;
}
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
CAppServer::CAppServer (const CAppServer &rhs) :
m_nGroupNo (rhs.m_nGroupNo),
m_nTotalGroups(rhs.m_nTotalGroups),
m_GroupHandle (rhs.m_GroupHandle),
m_pIOPCServer (rhs.m_pIOPCServer),
m_pIOPCSyncIO (rhs.m_pIOPCSyncIO)
{
wcscpy (m_wstrServerName, rhs.m_wstrServerName) ;
wcscpy (m_wstrServerType, rhs.m_wstrServerType) ;
for (int i=0; i<_OPC_MAX_GROUP; i++)
{
GroupNumber[i] = rhs.GroupNumber[i] ;
m_pIOPCGroupStateMgt[i] = rhs.m_pIOPCGroupStateMgt[i] ;
}
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
CAppServer& CAppServer::operator=(const CAppServer &rhs)
{
m_nGroupNo = rhs.m_nGroupNo ;
m_nTotalGroups = rhs.m_nTotalGroups ;
m_GroupHandle = rhs.m_GroupHandle ;
m_pIOPCServer = rhs.m_pIOPCServer ;
m_pIOPCSyncIO = rhs.m_pIOPCSyncIO ;
wcscpy(this->m_wstrServerName, rhs.m_wstrServerName) ;
wcscpy(this->m_wstrServerType, rhs.m_wstrServerType) ;
for (int i=0; i<_OPC_MAX_GROUP; i++)
{
GroupNumber[i] = rhs.GroupNumber[i] ;
m_pIOPCGroupStateMgt[i] = rhs.m_pIOPCGroupStateMgt[i] ;
}
return *this ;
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
HRESULT CAppServer::OPCConnect(wchar_t* svrName, wchar_t* svrType)
{
CLSID clsid ;
COSERVERINFO csvrinfo;
MULTI_QI queryInterface;
LPUNKNOWN pUnkn = NULL;
HRESULT hr ;
wcscpy (m_wstrServerName, svrName) ;
wcscpy (m_wstrServerType, svrType) ;
// Get the Class ID from the Program ID
// Take note that the server name and type must be wide-character
hr = CLSIDFromProgID(m_wstrServerType, &clsid );
if ( FAILED (hr))
return hr ;
// Assign GUID of IOPCServer Interface to the MULTI_QI structure
queryInterface.pIID = &IID_IOPCServer ;
queryInterface.pItf = NULL ;
queryInterface.hr = 0 ;
memset(&csvrinfo, 0, sizeof(COSERVERINFO));
csvrinfo.pAuthInfo = NULL ;
// If the server name is blank, assume the server is
// the Local Server, and set it to NULL
if (!wcslen(m_wstrServerName))
csvrinfo.pwszName = NULL ;
else
csvrinfo.pwszName = m_wstrServerName ;
// Create an instance and retrieve the IOPCServer Interface
hr = ::CoCreateInstanceEx(clsid, NULL, CLSCTX_SERVER, &csvrinfo, 1, &queryInterface);
m_pIOPCServer = queryInterface.pItf ;
if( FAILED(hr) || m_pIOPCServer == NULL)
return hr ;
queryInterface.pItf->Release() ;
return hr ;
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
HRESULT CAppServer::OPCConnect()
{
CLSID clsid ;
COSERVERINFO csvrinfo;
MULTI_QI queryInterface;
LPUNKNOWN pUnkn = NULL;
HRESULT hr ;
// Get the Class ID from the Program ID
// Take note that the server name and type must be wide-character
hr = CLSIDFromProgID(m_wstrServerType, &clsid );
if ( FAILED (hr))
return hr ;
// Assign GUID of IOPCServer Interface to the MULTI_QI structure
queryInterface.pIID = &IID_IOPCServer ;
queryInterface.pItf = NULL ;
queryInterface.hr = 0 ;
memset(&csvrinfo, 0, sizeof(COSERVERINFO));
csvrinfo.pAuthInfo = NULL ;
// If the server name is blank, assume the server is
// the Local Server, and set it to NULL
if (!wcslen(m_wstrServerName))
csvrinfo.pwszName = NULL ;
else
csvrinfo.pwszName = m_wstrServerName ;
// Create an instance and retrieve the IOPCServer Interface
hr = ::CoCreateInstanceEx(clsid, NULL, CLSCTX_SERVER, &csvrinfo, 1, &queryInterface);
m_pIOPCServer = queryInterface.pItf ;
if( FAILED(hr) || m_pIOPCServer == NULL)
return hr ;
queryInterface.pItf->Release() ;
return hr ;
}
///////////////////////////////////////////////////////////////////////////
// This Method adds a group to the OPC Server
// Note that when a group is added, the group becomes the
// current default group. This means that all subsequent operation
// i.e. addition of tags, reading or writing of tags will use this group.
// If operation on a different group is to be carried out, then the group
// must be changed first by using the method, OPCChangeGroup().
///////////////////////////////////////////////////////////////////////////
HRESULT CAppServer::OPCAddGroup(LPWSTR szGrpName)
{
HRESULT hr ;
bool bActive = TRUE ;
OPCHANDLE hClientGroupHandle = 1000 ;
DWORD dwLCID = 0 ;
DWORD dwRtnUpdateRate ;
long *pTimeBias = NULL ;
DWORD dwReqUpdateRate = 1000 ;
float pPercentDeadband = 0.0;
CGroup GrpNum ;
// _wcsupr(szGrpName) ; // Convert all Uppercase for easy comparison
if (AddGroupName (szGrpName, GrpNum))
return _OPC_DUPLICATE_GROUP_NAME ;
m_nGroupNo = GrpNum.m_nGroupNo ;
// Add a group
hr = m_pIOPCServer->AddGroup( szGrpName, TRUE, 1000, //szGrpName, TRUE, 1000,
1324, NULL, &pPercentDeadband, //hClientGroupHandle, NULL, NULL,
dwLCID, &m_GroupHandle, &dwRtnUpdateRate,
IID_IOPCGroupStateMgt,
reinterpret_cast<IUnknown**> (&m_pIOPCGroupStateMgt[m_nGroupNo]));
if (FAILED (hr))
{
GroupNumber[m_nGroupNo].m_szGrpName[0] = L'\0' ;
m_pIOPCGroupStateMgt[m_nGroupNo].Release() ;
return hr ;
}
GroupNumber[m_nGroupNo].m_GroupHandle = m_GroupHandle ;
m_nTotalGroups++ ;
return hr ;
}
///////////////////////////////////////////////////////////////////////////
// This Method adds tags to the current group. If tags are to be added
// to a different group, then the group must be changed first by using
// OPCChangeGroup() method.
// ItemIDs is an array of tagnames.
// ClientHandles is an array of arbitarily assigned integers by the caller.
// ServerHandles is an array corresponding to the ClientHandles array returned
// by OPC Server.Use the ServerHandles for all reading or writing of items to
// the OPC Server. The OPC Server knows only the ServerHandles.
///////////////////////////////////////////////////////////////////////////
HRESULT CAppServer::OPCAddTags (wchar_t* ItemIDs[], DWORD NoOfItems, OPCHANDLE ClientHandles[],
OPCHANDLE ServerHandles[], CErrors* pErr, int &nErr)
{
HRESULT hr ;
DWORD index ;
OPCITEMDEF* idef ;
OPCITEMRESULT* pResults ;
HRESULT* pErrors ;
// Assign the variable pItemMgt of type IOPCItemMgt Interface using the
// smart pointer, CComQIPtr. CComQIPtr will add and release references automatically
CComQIPtr <IOPCItemMgt, &IID_IOPCItemMgt> pItemMgt (m_pIOPCGroupStateMgt[m_nGroupNo]) ;
if (!m_pIOPCServer || !m_pIOPCGroupStateMgt[m_nGroupNo] || NoOfItems <= 0)
return _OPC_INVALID_OBJECT ;
if (NoOfItems > _OPC_MAX_HANDLE)
return _OPC_TOO_MANY_ITEMS ;
// for (DWORD idx=0; idx<NoOfItems; idx++)
// _wcsupr(ItemIDs[idx]) ; // OPC requuires items to be Uppercase. May not be necessary now.
GroupNumber[m_nGroupNo].m_NoOfItems += NoOfItems ;
// create a new OPC Item Definition pointer
idef = new OPCITEMDEF [NoOfItems] ;
for ( index=0; index<NoOfItems ; index++ )
{
idef[index].szItemID = (LPTSTR)(LPCTSTR)ItemIDs[index];
idef[index].bActive = TRUE;
idef[index].dwBlobSize = 0;
idef[index].pBlob = NULL;
idef[index].szAccessPath = NULL;
idef[index].hClient = ClientHandles[index] ;
idef[index].vtRequestedDataType = VT_EMPTY;
}
// Add items using the IOPCItemMgt pointer
hr = pItemMgt->AddItems (NoOfItems, idef, &pResults, &pErrors) ;
delete []idef;
if (FAILED(hr))
return hr ;
DWORD setNum = 0 ;
nErr = 0 ;
for (index=0; index<NoOfItems; index++)
{
if ( SUCCEEDED(pErrors[index]) )
ServerHandles[index] = pResults[index].hServer ;
else
nErr++ ;
pErr[index].pErrors = pErrors[index] ;
}
CoTaskMemFree( pResults );
CoTaskMemFree( pErrors );
return hr ;
}
///////////////////////////////////////////////////////////////////////////
// This Method Read 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::OPCReadTags (CItem* pValues, DWORD NoOfItems, OPCHANDLE ServerHandles[],int &nErr)
{
// Test to see if the Interface is still connected to the server
if (!CoIsHandlerConnected (m_pIOPCGroupStateMgt[m_nGroupNo]))
{
m_pIOPCGroupStateMgt[m_nGroupNo].Release() ;
}
OPCITEMSTATE* pItemState;
HRESULT hr, *pErrors;
// Assign the variable opcSyncIO of type IOPCSyncIO Interface using the
// smart pointer, CComQIPtr. CComQIPtr will add and release references automatically
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) ;
// Read the items using the IOPCSyncIO Interface pointer.
hr = opcSyncIO->Read(OPC_DS_CACHE, NoOfItems, ServerHandles, &pItemState, &pErrors);
if( SUCCEEDED(hr) )
{
nErr = 0 ;
for(DWORD index=0; index < NoOfItems; index++)
{
if ( FAILED(pErrors[index]) )
nErr++ ;
pValues[index].quality = pItemState[index].wQuality ;
pValues[index].timestamp = pItemState[index].ftTimeStamp ;
pValues[index].hClient = pItemState[index].hClient ;
pValues[index].type = pItemState[index].vDataValue.vt ;
pValues[index].value.vt = pItemState[index].vDataValue.vt ;
pValues[index].nResult = pErrors[index] ;
ReadDataValues(pValues, pItemState, index) ;
}
CoTaskMemFree( pItemState );
CoTaskMemFree( pErrors );
}
else
{
CoTaskMemFree( pItemState );
CoTaskMemFree( pErrors );
}
// if hr = S_OK, all the data is guarantee to be good.
// if hr = S_FALSE, there are good and bad data.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -