⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hotopcserver.cpp

📁 VC 编写的OPC客户端
💻 CPP
📖 第 1 页 / 共 5 页
字号:

			//////////////////////////////////
			// Serialize all of our groups	//
			//////////////////////////////////

			// Start with an empty linked list:
			ASSERT (m_pGroupHead == NULL);

			// Loop over expected number of groups:
			for (dwIndex = 0; dwIndex < m_cdwGroups; dwIndex++)
			{
				CHotOpcGroup *pGroup = NULL;

				// Wrap group serialization with exception handler in case
				// there is a problem, such as bad archive version etc.
				try
				{
					// Instantiate a new CHotOpcGroup (with this server as it's parent):
					pGroup = new CHotOpcGroup (this);

					// Call the group's serialize function so that it can read
					// its properties from the archive:
					pGroup->Serialize (ar);

					// New groups are added to the head of the linked list.

					// That means new the groups's "next" group is old head of list,
					pGroup->SetNext (m_pGroupHead);

					// and the new group is the old head of list's "previous" group,
					if (m_pGroupHead)	
						m_pGroupHead->SetPrev (pGroup);

					// and that new group is now the new "head" of list.
					m_pGroupHead = pGroup;
				}

				catch (...)
				{
					// There was a problem reading group properties.  Delete
					// this object and throw another exception.  This exception
					// must be handled by the calling function.
					delete this;
					AfxThrowArchiveException (CArchiveException::generic);
				}
			}
			break;

		default:
			// Unexpected archive version.  Delete this object and
			// throw an exception that indicates this.  This exception
			// must be handled by the calling function.
			delete this;
			AfxThrowArchiveException (CArchiveException::badSchema);
			break;
		}
	}
}

// **************************************************************************
// Copy ()
//
// Description:
//	Copy server properties to shared memory file.
//
// Parameters:
//  CFixedSharedFile	&sf	Shared memory file to copy properties to.
//
// Returns:
//  void
// **************************************************************************
void CHotOpcServer::Copy (CFixedSharedFile &sf)
{
	int nLen;

	// Since we are saving data to a shared memory file, we can not take
	// advantage of the "smarts" built into the CArchive class like we do
	// in Serialize().  Consequently, to save a string, we must first save
	// its length as an integer, followed by the characters in the string
	// as TCHAR's.

	// Save the prog ID string:
	nLen = m_strServerName.GetLength ();
	sf.Write (&nLen, sizeof (nLen));
	sf.Write (m_strServerName, nLen * sizeof (TCHAR));

	// Save the remote machine name string:
	nLen = m_strRemoteMachine.GetLength ();
	sf.Write (&nLen, sizeof (nLen));
	sf.Write (m_strRemoteMachine, nLen * sizeof (TCHAR));

	// Save the flag bit field:
	sf.Write (&m_bfFlags, sizeof (m_bfFlags));

	// Save the number of groups so we'll know how many to read later:
	sf.Write (&m_cdwGroups, sizeof (m_cdwGroups));

	// Add all of our groups' properties:

	// Start with the head of linked list and work our way through the chain:
	CHotOpcGroup *pGroup = m_pGroupHead;

	// Keep looping until we reach end of linked list (pGroup will be NULL):
	while (pGroup)
	{
		// Call group's copy function so it will add its properties to
		// shared memory file:
		pGroup->Copy (sf);

		// Process next group in list next time around:
		pGroup = pGroup->GetNext ();
	}
}

// **************************************************************************
// Paste ()
//
// Description:
//	Assign properties from shared memory file.
//
// Parameters:
//  CFixedSharedFile	&sf	Shared memory file to get properties from.
//
// Returns:
//  void
// **************************************************************************
void CHotOpcServer::Paste (CFixedSharedFile &sf)
{
	int nLen;

	// Since we are reading data from a shared memory file, we can not take
	// advantage of the "smarts" built into the CArchive class like we do
	// in Serialize().  Consequently, to read a string, we must first read
	// its length as an integer, the read that many characters as TCHAR's.

	// Read the prog ID string:
	sf.Read (&nLen, sizeof (nLen));
	sf.Read (m_strServerName.GetBufferSetLength (nLen), nLen * sizeof (TCHAR));

	// Read the remote machine name string:
	sf.Read (&nLen, sizeof (nLen));
	sf.Read (m_strRemoteMachine.GetBufferSetLength (nLen), nLen * sizeof (TCHAR));

	// Read the flag bit field:
	sf.Read (&m_bfFlags, sizeof (m_bfFlags));

	// Read the group count:
	sf.Read (&m_cdwGroups, sizeof (m_cdwGroups));

	// Add the groups:

	// Start with an empty linked list:
	ASSERT (m_pGroupHead == NULL);

	// Loop over expected number of groups:
	for (DWORD dwIndex = 0; dwIndex < m_cdwGroups; dwIndex++)
	{
		CHotOpcGroup *pGroup = NULL;

		// Wrap group paste with exception handler in case there is a problem:
		try
		{
			// Instantiate a new CHotOpcGroup (with this server as it's parent):
			pGroup = new CHotOpcGroup (this);

			// Call the group's paste function so that it can read its 
			// properties from the shared memory file:
			pGroup->Paste (sf);

			// New groups are added to the head of the linked list. 

			// That means new the groups's "next" group is old head of list,
			pGroup->SetNext (m_pGroupHead);

			// and the new group is the old head of list's "previous" group,
			if (m_pGroupHead)	
				m_pGroupHead->SetPrev (pGroup);

			// and that new group is now the new "head" of list.
			m_pGroupHead = pGroup;
		}

		catch (...)
		{
			// There was a problem reading group properties.
			ASSERT (FALSE);
		}
	}
}

/////////////////////////////////////////////////////////////////////////////
// CHotOpcServer group management
/////////////////////////////////////////////////////////////////////////////

// **************************************************************************
// AddGroup ()
//
// Description:
//	Called to add an OPC Group.  A CHotOpcGroup will be added to this object if
//	needed and a request to add a corresponding OPC Group to the OPC Server
//	will be made.
//
// Parameters:
//  CHotOpcGroup		*pGroup			Pointer to group object to add.
//	bool		bLoadingProject	Set to true if call is made during project 
//								  load so group can be added to this object's
//								  group list.  Otherwise we will assume group
//								  already exists in list, and only needs to
//								  added to OPC Server.
//
// Returns:
//  void
// **************************************************************************
void CHotOpcServer::AddGroup (CHotOpcGroup *pGroup, bool bLoadingProject /*= false */)
{
	ASSERT (pGroup != NULL);

	// If the group is new add it to our list:
	if (!bLoadingProject)
	{
		// New groups are added to the head of the linked list.

		// That means new the groups's "next" group is old head of list,
		pGroup->SetNext (m_pGroupHead);

		// and the new group is the old head of list's "previous" group,
		if (m_pGroupHead)	
			m_pGroupHead->SetPrev (pGroup);

		// and that new group is now the new "head" of list.
		m_pGroupHead = pGroup;

		// Don't forget to bump up the group count:
		++m_cdwGroups;
	}

	// If we are connected to OPC Server, issue a request to add this group:
	if (m_bConnected)
	{
		// Initialize arguments for add group request:
		HRESULT hr				= E_FAIL;
		WCHAR *pszName			= NULL;
		long lBias				= pGroup->GetBias ();
		float fDeadband			= pGroup->GetDeadband ();
		LPCTSTR lpszName		= pGroup->GetName ();
		DWORD dwRevUpdateRate	= 0;
		OPCHANDLE hServer		= NULL;
		IUnknown *pUnknown		= NULL;

		// All strings transmitted by COM must be in wide character (Unicode) format.
		// Declare a buffer to contain name string in wide character format.
		WCHAR wchBuffer	[MAX_PATH];

		// Convert the string format:
		if (lpszName != NULL)
		{
#ifdef _UNICODE
			// String is already in Unicode format, so simply copy into buffer:
			lstrcpyn (wchBuffer, lpszName, sizeof (wchBuffer) / sizeof (WCHAR));
#else
			// String is not in Unicode format, so convert and place result into buffer:
			if (!MultiByteToWideChar (CP_ACP, 0, lpszName, -1, wchBuffer, MAX_PATH))
			{
				ASSERT (FALSE);
				return;
			}
#endif

			// Reassign name pointer to buffer:
			pszName = wchBuffer;
		}

		// Issue add OPC Group request using IOPCServer interface.  Pointer to 
		// the IOPCServer interface, m_pIServer, should have been set in Connect().
		hr = m_pIServer->AddGroup (
			pszName,					// [in] group name
			pGroup->IsActive (),		// [in] active state
			pGroup->GetUpdateRate (),	// [in] requested update rate
			(OPCHANDLE) pGroup,			// [in] our handle to this group
			&lBias,						// [in] time bias
			&fDeadband,					// [in] percent deadband
			pGroup->GetLanguageID (),	// [in] requested language ID
			&hServer,					// [out] server handle to this group
			&dwRevUpdateRate,			// [out] revised update rate
			IID_IUnknown,				// [in] request an IUknown pointer
			&pUnknown);

		// OPC Group was successfully added:
		if (SUCCEEDED (hr))
		{
			
			// Since OPC Group was successfully added, we can go ahead an initialize
			// the associated CHotOpcGroup object.

			// We can now consider group valid:
			pGroup->SetValid (TRUE);

			// We should have gotten a valid pointer to the OPC Groups's IUnknown interface.
			// Set some things that only make sence if we have a vaild IUnknown pointer:
			if (pUnknown)
			{
				// Set the OPC Server's handle for this group:
				pGroup->SetServerHandle (hServer);

				// Reset update rate if OPC Server does not support requested rate:
				if (pGroup->GetUpdateRate () != dwRevUpdateRate)
					pGroup->SetUpdateRate (dwRevUpdateRate);

				// Initialize the CHotOpcGroup object, which will include getting necessary
				// interface pointers from IUnknown:
				pGroup->Initialize (pUnknown);

				// We can release the IUnknown pointer since initialized group
				// should have gotten the interface pointers it needs from it.
				pUnknown->Release ();
			}
			else
			{
				TRACE (_T("OTC: Warning added group %s to OPC server, but IUnknown is invalid.\r\n"),
					pGroup->GetName ());
			}
		}

		// OPC Group was not successfully added:
		else
		{
			
		}
	}

	// No connection:
	else
	{
		
	}
}

// **************************************************************************
// AddClonedGroup ()
//
// Description:
//	Add cloned group to list.  
//
//	This is called from CHotOpcGroup::Clone (), which takes care of instantiating
//  the new CHotOpcGroup object and adding its associated OPC Group to the OPC
//  Server.  All that's left to do here is add the clone to the group list. 
//
// Parameters:
//  CHotOpcGroup		*pClone		Pointer to cloned group.
//
// Returns:
//  void
// **************************************************************************
void CHotOpcServer::AddClonedGroup (CHotOpcGroup *pClone)
{
	// New groups are added to the head of the linked list.

	// That means the clone's "next" group is old head of list,
	pClone->SetNext (m_pGroupHead);

	// and the clone is the old head of list's "previous" group,
	if (m_pGroupHead)	
		m_pGroupHead->SetPrev (pClone);

	// and that clone is now the new "head" of list.
	m_pGroupHead = pClone;

	// Don't forget to bump up the group count:
	++m_cdwGroups;
}

// **************************************************************************
// RemoveGroup ()
//
// Description:
//	Remove an OPC Group from OPC server, and delete associated CHotOpcGroup object
//	if asked.
//
// Parameters:
//  CHotOpcGroup		*pGroup			Pointer to CHotOpcGroup associated with OPC Group
//								  to remove.
//	bool		bDelete			Delete CHotOpcGroup object after removing
//								  associated OPC Group. true by default.
//
// Returns:
//  void
// **************************************************************************
void CHotOpcServer::RemoveGroup (CHotOpcGroup *pGroup, bool bDelete /* = true */)
{
	ASSERT (pGroup != NULL);

	HRESULT hr;

	// Uninitialize group with OPC server.  This means all interfaces it
	// is using are released.  It is good practice to do this BEFORE
	// issuing a remove group request.  Pass the bDelete value so the 
	// group knows to delete its items if any.
	pGroup->Uninitialize (bDelete);

	// remove the group from the OPC server
	if (pGroup->IsValid ())
	{
		ASSERT (m_pIServer != NULL);

		// Issue remove OPC Group request using IOPCServer interface.  Pointer to 
		// the IOPCServer interface, m_pIServer, should have been set in Connect().
		hr = m_pIServer->RemoveGroup (
			pGroup->GetServerHandle (),		// server handle for this group.
			pGroup->IsForceDeletion ());	// force a delete if this client has not released the group properly.

		// Log success or failure:
		if (SUCCEEDED (hr))
			LogMsg (/*IDS_GROUP_REMOVE_SUCCESS*/1, pGroup->GetName (), GetServerName ());
		else
			LogMsg (/*IDS_GROUP_REMOVE_FAILURE*/1, pGroup->GetName (), GetServerName (), hr);
	}

	// Delete the group if asked:
	if (bDelete)
	{
		// We need to remove the group from the linked list before we delete it.

		// To remove a link, we must first get pointers to the adjacent links:
		CHotOpcGroup *pPrev = pGroup->GetPrev ();
		CHotOpcGroup *pNext = pGroup->GetNext ();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -