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

📄 group.cpp

📁 KepWare的OPC Client 示例.面向C
💻 CPP
📖 第 1 页 / 共 5 页
字号:

				if (pItemArray [dwIndex].szItemID)
					CoTaskMemFree (pItemArray [dwIndex].szItemID);
				}
			
			// COM requires us to free memory allocated for [out] and [in/out]
			// arguments (i.e. pResults, pErrors, and pItemArray).
			if (pResults)
				CoTaskMemFree (pResults);

			if (pErrors)
				CoTaskMemFree (pErrors);

			CoTaskMemFree (pItemArray);

			// Log success status:
			if (cdwSuccess > 0)
				LogMsg (IDS_GROUP_ADD_ITEMS, cdwSuccess, GetName ());
			}
		
		// Failed to allocate memory for item definition array:
		else
			{
			TRACE (_T("OTC: Unable to add items to OPC server %s. (failed to allocate OPCITEMDEF structure)\r\n"),
				m_pServer->GetProgID ());
			}
		}

	// Failed to add items because OPC is not connected or we
	// do not have pointer to IOPCItemMgt interface:
	else
		{
		// Log error message:
		if (!m_pServer->IsConnected ())
			LogMsg (IDS_GROUP_ADD_ITEMS_FAILED_NOCONNECTION, GetName ());
		else
			LogMsg (IDS_GROUP_ADD_ITEMS_FAILED_NOINTERFACE, GetName ());
		}
	}

// **************************************************************************
// RemoveItems ()
//
// Description:
//	Remove OPC Items from associated OPC Group and delete associated CKItems
//	if asked.
//
// Parameters:
//  CObArray	&cItemList		Array of items to remove.
//	DWORD		dwCount			Number of items in dwCount
//	bool		bDelete			Set to true to delete CKItem objects.
//
// Returns:
//  void
// **************************************************************************
void CKGroup::RemoveItems (CObArray &cItemList, DWORD dwCount, bool bDelete /* = true */)
	{
	DWORD dwIndex = 0;
	CKItem *pItem = NULL;

	// We can only remove OPC Items if we are connected:
	if (m_pServer->IsConnected ())
		{
		OPCHANDLE *phServer		= NULL;
		HRESULT *pErrors		= NULL;
		HRESULT hr				= E_FAIL;
		DWORD cdwItemsRemoved	= 0;

		ASSERT (m_pIItemMgt != NULL);
		ASSERT (dwCount > 0);

		// Allocate memory for IOPCServer::RemoveItems() [in] arguments:
		phServer = (OPCHANDLE *) CoTaskMemAlloc (dwCount * sizeof (OPCHANDLE));

		// We can't do anything if allocation failed:
		if (phServer == NULL)
			{
			ASSERT (FALSE);
			return;
			}

		// Get the server handles associated with each item in input list:
		for (dwIndex = 0; dwIndex < dwCount; dwIndex++)
			{
			// Get pointer to item in input list:
			pItem = (CKItem *) cItemList [dwIndex];
			ASSERT (pItem != NULL);

			// Set server handle in request argument:
			phServer [dwIndex] = pItem->GetServerHandle ();
			}
		
		// Issue the remove items request through the IOPCItemMgt interface:
		hr = m_pIItemMgt->RemoveItems (
				dwCount,	// Item count
				phServer,	// Array of server handles for items
				&pErrors);	// Error array

		// Check error result and remove the items from the project:
		cdwItemsRemoved = dwCount;
		for (dwIndex = 0; dwIndex < dwCount; dwIndex++)
			{
			// Get pointer to item in input list:
			pItem = (CKItem *) cItemList [dwIndex];
			ASSERT (pItem != NULL);

			// Check for successful remove:
			if (FAILED (hr))
				{
				// Request failed.  
				TRACE (_T("OTC: Failed to remove item %s on %s\\\\%s. (%08X)\r\n"), 
					pItem->GetItemID (), m_pServer->GetProgID (), GetName (), hr);
				}
			else if (FAILED (pErrors [dwIndex]))
				{
				// Request succeeded, but this item could not be removed.

				// Decrement number of (valid) items removed:
				if (pItem->IsValid ())
					--cdwItemsRemoved;

				TRACE (_T("OTC: Failed to remove item %s on %s\\\\%s. (%08X)\r\n"), 
					pItem->GetItemID (), m_pServer->GetProgID (), GetName (), pErrors [dwIndex]);
				}

			// Delete the CKItems if asked:
			if (bDelete)
				{
				// Remove the item from our item list first:
				RemoveItemFromList (pItem);

				// Now it is safe to delete it:
				delete pItem;
				}
			else
				{
				// Since we didn't delete the item, we need to set it invalid
				// because there is no longer an assoicated OPC Item.
				pItem->SetValid (false);
				}
			}

		// log success or failure
		if (cdwItemsRemoved == dwCount)
			LogMsg (IDS_GROUP_REMOVE_ITEMS, cdwItemsRemoved, GetName ());
		else
			{
			ASSERT (dwCount >= cdwItemsRemoved);
			LogMsg (IDS_GROUP_REMOVE_ITEMS_FAILED, dwCount - cdwItemsRemoved, 
				dwCount, GetName ());
			}

		CoTaskMemFree (phServer);
		CoTaskMemFree (pErrors);
		}

	// If we are not connected, just delete the CKItems if asked:
	else if (bDelete)
		{
		// Loop over items in input array:
		for (dwIndex = 0; dwIndex < dwCount; dwIndex++)
			{
			// Get a pointer to an item in the array:
			pItem = (CKItem *) cItemList [dwIndex];
			ASSERT (pItem != NULL);

			// Remove the item from out list first:
			RemoveItemFromList (pItem);

			// Now it is safe to delete it:
			delete pItem;
			}
		}
	}

// **************************************************************************
// RemoveAllItems ()
//
// Description:
//	Remove all OPC Items from OPC Group, and delete all CKItems if asked.
//
// Parameters:
//  bool		bDelete			Set to true to delete CKItem objects.
//
// Returns:
//  void
// **************************************************************************
void CKGroup::RemoveAllItems (bool bDelete /* = true */)
	{
	CKItem *pItem = NULL;
	HRESULT hr = E_FAIL;

	// If there are no items to remove, then return:
	if (m_cdwItems == 0)
		return;

	ASSERT (m_pItemHead);

	// Search for all valid items, i.e. items that were successfully
	// added to the OPC Server, and remove them.  If we don't have a
	// valid IOPCItemMgt interface pointer, then don't bother since 
	// call to RemoveItems() would fail.  There is no sence in building 
	// a list of items to remove if we won't be able to use it.
	if (m_pIItemMgt != NULL)
		{
		// Declare an object array to hold list of valid items:
		CObArray cItemList;
		DWORD cdwValidItems = 0;

		// Wrap our search with an exception handler in case we get a
		// bad pointer:
		try
			{
			// Allocate enough memory for object array to hold all items:
			cItemList.SetSize (m_cdwItems);

			// Start with head of linked list and work our way up the chain:
			pItem = m_pItemHead;

			// Keep looping until we hit the end of the linked list 
			// (when pItem is NULL):
			while (pItem)
				{
				// Check to see if item is valid:
				if (pItem->IsValid ())
					{
					// Item is valid.  Add it to out list of items to 
					// remove, and increment the item counter:
					cItemList.SetAt (cdwValidItems++, pItem);

					// Set the item invalid since it will no longer have
					// an associated OPC Item if remove request succeeds:
					pItem->SetValid (false);
					}
					
				// Get next item for next time around:
				pItem = pItem->GetNext ();
				}

			// Now remove the valid items (if any) from the OPC Server:
			if (cdwValidItems > 0)
				RemoveItems (cItemList, cdwValidItems, bDelete);
			}
		
		catch (...)
			{
			// Probably hit a bad pointer.  Try to process next item.
			ASSERT (FALSE);
			TRACE (_T("OTC: RemoveAllItems memory exception thrown.\r\n"));
			}
		}

	// Any remaining items (those that were not valid):
	if (bDelete)
		RemoveItemFromList (NULL);
	}

// **************************************************************************
// SetItemActiveState ()
//
// Description:
//	Set active state of OPC Items.
//
// Parameters:
//  CObArray	&cItemList		Array of items to set state.
//	DWORD		cdwItems		Number of items in cItemList.
//	bool		bActive			Set to true to set items active.
//
// Returns:
//  bool - true if success
// **************************************************************************
bool CKGroup::SetItemActiveState (CObArray &cItemList, DWORD cdwItems, bool bActive)
	{
	ASSERT (cdwItems > 0);
	DWORD cdwSuccess = 0;

	// There is no sence in building a request unless we are connected to
	// the OPC Server and have a pointer to the IOPCItemMgt interface.
	if (m_pServer->IsConnected () && m_pIItemMgt)
		{
		DWORD dwIndex		= 0;
		CKItem *pItem		= NULL;
		OPCHANDLE *phServer	= NULL;
		HRESULT *pErrors	= NULL;
		HRESULT hr			= E_FAIL;

		// Allocate storage for server item handles:
		phServer = (OPCHANDLE *) CoTaskMemAlloc (cdwItems * sizeof (OPCHANDLE));

		// Return if allocation fails:
		if (phServer == NULL)
			{
			ASSERT (FALSE);
			return (false);
			}

		// Fill request [in] arguments.
		for (dwIndex = 0; dwIndex < cdwItems; dwIndex++)
			{
			// Get pointer to item in input list:
			CKItem *pItem = (CKItem *) cItemList [dwIndex];
			ASSERT (pItem != NULL);

			// Set server handle:
			phServer [dwIndex] = pItem->GetServerHandle ();
			}

		// Wrap our request processing with an exception handler in case
		// we get a bad pointer:
		try
			{
			// Issue the set state request using the the IOPCItemMgt interface:
			hr = m_pIItemMgt->SetActiveState (
					cdwItems,	// Item count
					phServer,	// Server handles for items
					bActive,	// Array of active states
					&pErrors);	// Error array

			// Check results for each item in input list:
			for (dwIndex = 0; dwIndex < cdwItems; dwIndex++)
				{
				// Get pointer to item in input list:
				CKItem *pItem = (CKItem *) cItemList [dwIndex];
				ASSERT (pItem != NULL);

				// If no errors:
				if (SUCCEEDED (hr) && (pErrors && SUCCEEDED (pErrors [dwIndex])))
					{
					// Success if we are changing the state of the item:
					if (pItem->IsActive () != (BOOL)bActive)
						{
						++cdwSuccess;

						// Update active state:
						pItem->SetActive (bActive);
						}
					}

				// Else errors:
				else
					{
					// Request succeeded, but item state was not changed:
					if (pErrors && FAILED (pErrors [dwIndex]))
						{
						// Issue error message with error code.  (We could use
						// GetErrorString() to get user friendly error text
						// if we wish.)
						LogMsg (IDS_SET_ACTIVE_STATE_FAILED, bActive ? 1 : 0,
							pItem->GetItemID (), GetName (), pErrors [dwIndex]);
						}

					// Request failed:
					else
						{
						// Issue error message with error code.  (We could use
						// GetErrorString() to get user friendly error text
						// if we wish.)
						LogMsg (IDS_SET_ACTIVE_STATE_FAILED, bActive ? 1 : 0,
							pItem->GetItemID (), GetName (), hr);
						}
					}
				}
			}
		
		catch (...)
			{
			// Probably hit a bad pointer.  Try to process next item.

			if (m_pServer->IsConnected ())	
				{
				// We not disconnected so why was an exception thrown?
				ASSERT (FALSE);
				}
			}

		// COM requires us to free memory allocated for [out] and [in/out]
		// arguments (i.e. phServer and pErrors):
		CoTaskMemFree (phServer);

		if (pErrors)
			CoTaskMemFree (pErrors);

		// Log success status:
		if (cdwSuccess > 0)		
			{
			LogMsg (IDS_SET_ACTIVE_STATE_SUCCESS, bActive ? 1 : 0, 
				cdwSuccess, GetName ());
			}
		}

	// Return true if success.  (cdwSuccess will be non-zero if success)
	return (cdwSuccess != 0);
	}

// **************************************************************************
// ReadSync ()
//
// Description:
//	Perform a synchronous read for specified items.
//	
// Parameters:
//	CObArray	&cItemList		Array of items to read.
//	DWORD		cdwItems		Number of items in cItemList.
//	bool		bDeviceRead		Set to true to perform device read, false
//								  for cache read.
//	bool		bPostMsg		Set to true to post successful read message.
//
// Returns:
//  void
// **************************************************************************
void CKGroup::ReadSync (CObArray &cItemList, DWORD cdwItems, bool bDeviceRead, bool bPostMsg /* = true */)
	{
	ASSERT (cdwItems > 0);

	// There is no sence in building a request unless we are connected to
	// the OPC Server and have a pointer to the IOPCSyncIO interface.
	if (m_pServer->IsConnected () && m_pISync)
		{
		DWORD dwIndex			= 0;
		CKItem *pItem			= NULL;
		OPCDATASOURCE dwSource	= bDeviceRead ? OPC_DS_DEVICE : OPC_DS_CACHE;
		OPCHANDLE *phServer		= NULL;
		OPCITEMSTATE *pValues	= NULL;
		HRESULT *pErrors		= NULL;
		HRESULT hr				= E_FAIL;
		DWORD cdwSuccess		= 0;

		// Allocate storage for server item handles:

⌨️ 快捷键说明

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