infoserver.cpp
来自「此为Insight opc client InfoServerExplorer源」· C++ 代码 · 共 1,428 行 · 第 1/3 页
CPP
1,428 行
/////////////////////////////////////////////////////////////////////////////
//
// OPC DataAccess VC++ Client: InfoServer.CPP
// (Source File)
//
/////////////////////////////////////////////////////////////////////////////
//
// Author: Raphael Imhof
// Initial Date: 11/04/98
// $Workfile: InfoServer.cpp $
// $Revision: 1 $
// $Date: 7/27/99 5:22p $
// Target System: Microsoft Windows NT 4.0
// Environment: Visual C++ 5.0 / OPC DataAccess 1.0/2.0
// Remarks:
//
/////////////////////////////////////////////////////////////////////////////
//
// Description: implementation of the CInfoServer class.
// Encapsulation of OPC server related methods.
//
//
/////////////////////////////////////////////////////////////////////////////
//
// History of Changes (Please remove very old comments and blank lines!)
// $Log: /IDK/OPCServer/clients/VC++/InfoServerExplorer/InfoServer.cpp $
//
// 1 7/27/99 5:22p Imhof
//
// 1 7/27/99 5:18p Imhof
//
// 20 2/24/99 2:02p Imhof
// Added ValidateItem option and support
//
// 19 2/08/99 8:02p Imhof
// Removed possible memory leak after a server shutdown.
//
// 18 1/15/99 6:43p Imhof
// Updated legal notice.
//
// 17 12/15/98 8:57a Imhof
// Added comment
//
// 16 12/14/98 4:46p Imhof
// Modifications for OPC 2.0
//
// 15 12/11/98 5:58p Imhof
// Made modifications for OPC 2.0.
//
// 14 11/25/98 3:00p Betrisey
// Added menu item <OPC> <Print Statistic to log file>
// All the InfoServer statistic counters are printed out to the log file.
// Note that we do "misuse" the IPersist::Save() API to do that. This API
// returns "not implemented".
//
// 13 11/10/98 2:20p Imhof
// Added file header's.
//
//
// $Nokeywords:$ (To avoid useless search while checking in.)
/////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1998, Siemens Building Technologies, Inc. Landis Division
//
// SIEMENS BUILDING TECHNOLOGIES, INC. IS PROVIDING THE FOLLOWING
// EXAMPLES OF CODE AS SAMPLE ONLY.
//
// SIEMENS BUILDING TECHNOLOGIES, INC. MAKES NO REPRESENTATIONS
// OR WARRANTIES OF ANY KIND WITH RESPECT TO THE VALIDTY OF THE
// CODES OR DESIRED RESULTS AND DISCLAIMS ALL SUCH
// REPRESENTATIONS AND WARRANTIES, INCLUDING FOR EXAMPLE,
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. SIEMENS BUILIDNG TECHNOLOGIES, INC. DOES NOT
// REPRESENT OR WARRANT THAT THE FOLLOWING CODE SAMPLES ARE
// ACCURATE, VALID, COMPLETE OR CURRENT.
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "InfoServerExplorer.h"
#include "InfoServer.h"
#include "mainfrm.h"
#include "IOPCGroupStateMgt.h"
#include "GroupDlg.h"
#include "ServerStatusDlg.h"
#include "InfoServerExplorerDoc.h"
#include "IPersistFile.h"
#include "ConnectDlg.h"
#include <opcda_i.c> //for linker
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
CComModule _Module;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CInfoServer, CObject)
CInfoServer::CInfoServer()
{
m_fOPCVersion = OPC_VERSION_20; //deafault: OPC 2.0
m_iDataChangeType = 1; //default: with timestamp (= 1)
/*
for simplicity we create both callback sink and connection point
*/
m_pAdviseSink = new CIAdviseSink; // create the advise sink for notifications
m_pAdviseSink->AddRef();
m_pDataAccessConnectionPoint = new CComObject<COPCConnectionPoint>;
m_pDataAccessConnectionPoint->AddRef();
m_pShutDownConnectionPoint = new CComObject<COPCShutDownRequest>;
m_pShutDownConnectionPoint->AddRef();
m_iReloadEnumMethod = 0; //IID_IEnumString
m_iReloadEnumNextElements = 1;
m_iBrowserEnumNextElements = 100;
m_iReloadEnumAttributesNextElements = 1;
m_bUseValidateItems = FALSE; //ValidateItems is not necessary in our case
//AddItem or the browse function are sufficient
m_bConnected = FALSE;
memset(&m_clsidOPCServer,0,sizeof(m_clsidOPCServer));
}
CInfoServer::~CInfoServer()
{
/*
should be already done => size = 0 !
int size = m_Groups.GetSize();
CGroup* pGroup;
for (int d=0; d < size; d++)
{
pGroup = m_Groups[0];
RemoveGroup(&pGroup);
}
*/
m_pAdviseSink->Release(); //if not already done (this deletes the advise object!)
m_pDataAccessConnectionPoint->Release();
m_pShutDownConnectionPoint->Release();
}
/////////////////////////////////////////////////////////////////////////////
// CInfoServer serialization
void CInfoServer::Serialize(CArchive& ar)
{
//1.) options
if(ar.IsLoading())
{
ar >> m_sOPCServer;
ar >> m_sOPCServerComputer;
//clsid struct
ar >> m_clsidOPCServer.Data1;
ar >> m_clsidOPCServer.Data2;
ar >> m_clsidOPCServer.Data3;
for(int i = 0; i < 8; i++)
ar >> m_clsidOPCServer.Data4[i];
ar >> m_iReloadEnumMethod;
ar >> m_iReloadEnumNextElements;
ar >> m_iBrowserEnumNextElements;
ar >> m_iReloadEnumAttributesNextElements;
ar >> m_fOPCVersion;
ar >> m_iDataChangeType;
ar >> m_bUseValidateItems;
}
else
{
ar << m_sOPCServer;
ar << m_sOPCServerComputer;
//clsid struct
ar << m_clsidOPCServer.Data1;
ar << m_clsidOPCServer.Data2;
ar << m_clsidOPCServer.Data3;
for(int i = 0; i < 8; i++)
ar << m_clsidOPCServer.Data4[i];
ar << m_iReloadEnumMethod;
ar << m_iReloadEnumNextElements;
ar << m_iBrowserEnumNextElements;
ar << m_iReloadEnumAttributesNextElements;
ar << m_fOPCVersion;
ar << m_iDataChangeType;
ar << m_bUseValidateItems;
}
m_Groups.Serialize(ar);
for(int i = 0; i < m_Groups.GetSize(); i++)
{
if(ar.IsLoading())
{
TRACE("we should use ptr array instead !\n");
m_Groups[i] = new CGroup;
}
m_Groups[i]->Serialize(ar);
}
/*
if(ar.IsLoading())
{
RecreateOnServer();
}
*/
}
BOOL CInfoServer::ReloadFromServer()
{
USES_CONVERSION;
//delete groups and items on client only
CArray<CGroup*, CGroup*>* pGroups;
unsigned int nGroups = 0;
CMainFrame* pMainFrame = (CMainFrame*) AfxGetMainWnd();
CInfoServerExplorerDoc* pDoc = (CInfoServerExplorerDoc*) pMainFrame->GetActiveDocument();
CGroup* pGroup = NULL;
CItem* pItem = NULL;
HRESULT res, res_next;
nGroups = GetGroups(&pGroups);
for(unsigned int g = 0; g < nGroups ; g++)
{
CArray<CItem*, CItem*>* pItems;
unsigned int nItems = 0;
pGroup = (*pGroups)[0];
//unadvise
TRACE("--> take out if Enum is implemented !\n");
if(!pGroup->UnAdvise()) return FALSE;
nItems = pGroup->GetItems(&pItems);
for(unsigned int i = 0; i < nItems ; i++)
{
pItem = (*pItems)[0];
pItems->RemoveAt(0,1);
delete pItem;
}
pGroups->RemoveAt(0,1);
delete pGroup;
}
CTreeCtrl& tree = pMainFrame->GetBrowserView()->GetTreeCtrl();
tree.SelectItem(tree.GetRootItem()); //DeleteAllItems() sends first (before deleting all items) a SelChangeItem
//this produces a CContentView::OnUpdate() during an inconsistent state
tree.DeleteAllItems();
pDoc->UpdateAllViews(NULL);
CComPtr<IEnumString> pIEnumString;
CComPtr<IEnumUnknown> pIEnumUnknown;
CIOPCServer opcServer(m_pUnkn);
if(0 == GetReloadEnumMethod()) //IID_IEnumString
{
res = opcServer.CreateGroupEnumerator( OPC_ENUM_ALL,
IID_IEnumString,
(LPUNKNOWN*)&pIEnumString);
if(SUCCEEDED(res))
{
ULONG ulRequested = GetReloadEnumNextElements();
ULONG ulRetrieved = 0;
LPWSTR* pStr = new LPWSTR[ulRequested];
pIEnumString->Reset();
do
{
res_next = pIEnumString->Next(ulRequested, pStr, &ulRetrieved);
for(ULONG e = 0; e < ulRetrieved; e++)
{
CString sGroupName(pStr[e]);
CoTaskMemFree(pStr[e]);
pStr[e] = NULL;
CComPtr<IOPCGroupStateMgt> pIStateMgt;
CComPtr<IUnknown> pUnkn;
res = opcServer.GetGroupByName(A2OLE(sGroupName), IID_IOPCGroupStateMgt,(LPUNKNOWN*)&pIStateMgt);
if(SUCCEEDED(res))
{
//retrieve the state data
CIOPCGroupStateMgt opcGroup(pIStateMgt);
BOOL bActive;
OPCHANDLE hClientGroup; //out -> in
OPCHANDLE hServerGroup; //out
DWORD dwUpdateRate; //out: rate
DWORD dwServerUpdateRate; //out: servers rate
long lTimeBias;
float fDeadBand;
LCID dwLCID;
LPWSTR pGroupName = NULL;
res = opcGroup.GetState(&dwUpdateRate, &bActive,
&pGroupName, &lTimeBias,
&fDeadBand, &dwLCID,
&hClientGroup, &hServerGroup);
if(SUCCEEDED(res))
{
CGroup* new_group = new CGroup;
hClientGroup = (OPCHANDLE)new_group;
res = opcGroup.SetState(&dwUpdateRate, &dwServerUpdateRate,
&bActive, &lTimeBias,
&fDeadBand, &dwLCID,
&hClientGroup);
if(SUCCEEDED(res))
{
new_group->SetInterface(pIStateMgt);
new_group->SetInfoServer(this);
new_group->SetName(sGroupName);
new_group->SetHandle(hServerGroup);
new_group->SetActive(bActive);
new_group->SetUpdateRate(dwUpdateRate);
new_group->SetTimeBias(lTimeBias);
new_group->SetDeadBand(fDeadBand);
new_group->SetLCID(dwLCID);
//add it to array
m_Groups.Add(new_group);
//load items
new_group->ReloadItems();
/*
advise
get the connection points or readvise
*/
/*
CIDataObject comDO(pIStateMgt);
IEnumSTATDATA * p;
comDO.EnumDAdvise(&p);
*/
TRACE("--> EnumDAdvise not impl, with it no readvise needed !\n");
new_group->Advise();
}
else
{
delete new_group;
DisplayError(res);
}
}
else
{
DisplayError(res);
}
CoTaskMemFree(pGroupName);
}
else
{
((CInfoServerExplorerApp*)AfxGetApp())->DisplayText(_T("GetGroupByName()"), res);
}
} //end for retrieved
}
while(res_next == S_OK);
if(FAILED(res_next)) ((CInfoServerExplorerApp*)AfxGetApp())->DisplayText(_T("IEnumString::Next()"), res_next);
pDoc->SetModifiedFlag();
pIEnumString.Release();
delete[] pStr;
return TRUE;
}
else
{
((CInfoServerExplorerApp*)AfxGetApp())->DisplayText(_T("CreateGroupEnumerator()"), res);
}
}
else if(1 == GetReloadEnumMethod()) //IID_IEnumUnknown
{
res = opcServer.CreateGroupEnumerator( OPC_ENUM_ALL,
IID_IEnumUnknown,
(LPUNKNOWN*)&pIEnumUnknown);
if(SUCCEEDED(res))
{
ULONG ulRequested = GetReloadEnumNextElements();
ULONG ulRetrieved = 0;
CComPtr<IUnknown>* ppUnkn = new CComPtr<IUnknown>[ulRequested];
pIEnumUnknown->Reset();
do
{
res_next = pIEnumUnknown->Next(ulRequested,(LPUNKNOWN*)ppUnkn,&ulRetrieved);
for(ULONG e = 0; e < ulRetrieved; e++)
{
//retrieve the state data
CIOPCGroupStateMgt opcGroup(ppUnkn[e]);
BOOL bActive;
OPCHANDLE hClientGroup; //out
OPCHANDLE hServerGroup; //out
DWORD dwServerUpdateRate; //out: servers rate
DWORD dwUpdateRate; //out: rate
long lTimeBias;
float fDeadBand;
LCID dwLCID;
LPWSTR pGroupName;
res = opcGroup.GetState(&dwUpdateRate, &bActive,
&pGroupName, &lTimeBias,
&fDeadBand, &dwLCID,
&hClientGroup, &hServerGroup);
if(SUCCEEDED(res))
{
CGroup* new_group = new CGroup;
hClientGroup = (OPCHANDLE)new_group;
res = opcGroup.SetState(&dwUpdateRate, &dwServerUpdateRate,
&bActive, &lTimeBias,
&fDeadBand, &dwLCID,
&hClientGroup);
if(SUCCEEDED(res))
{
//CComPtr<IOPCGroupStateMgt> pGRP = NULL;
IOPCGroupStateMgt* pGRP = NULL;
ppUnkn[e]->QueryInterface(IID_IOPCGroupStateMgt, (void**)&pGRP);
new_group->SetInterface(pGRP);
new_group->SetInfoServer(this);
new_group->SetName(OLE2A(pGroupName));
new_group->SetHandle(hServerGroup);
new_group->SetActive(bActive);
new_group->SetUpdateRate(dwUpdateRate);
new_group->SetTimeBias(lTimeBias);
new_group->SetDeadBand(fDeadBand);
new_group->SetLCID(dwLCID);
//add it to array
m_Groups.Add(new_group);
//load items
new_group->ReloadItems();
new_group->Advise();
}
else
{
delete new_group;
DisplayError(res);
}
}
else
{
DisplayError(res);
}
ppUnkn[e].Release(); // Use CComPtr's release
//ppUnkn[e]->Release();
TRACE("--> Rlease even if function was not valid ?\n");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?