📄 group.cpp
字号:
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 + -