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 + -
显示快捷键?