📄 group.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
//
// OPC DataAccess VC++ Client: Group.CPP
// (Source File)
//
/////////////////////////////////////////////////////////////////////////////
//
// Author: Raphael Imhof
// Initial Date: 11/04/98
// $Workfile: Group.cpp $
// $Revision: 2 $
// $Date: 9/09/99 11:01a $
// Target System: Microsoft Windows NT 4.0
// Environment: Visual C++ 5.0 / OPC DataAccess 1.0/2.0
// Remarks:
//
/////////////////////////////////////////////////////////////////////////////
//
// Description: implementation of the CGroup class.
// Encapsulation of group related methods.
//
//
/////////////////////////////////////////////////////////////////////////////
//
// History of Changes (Please remove very old comments and blank lines!)
// $Log: /IDK/OPCServer/clients/VC++/InfoServerExplorer/Group.cpp $
//
// 2 9/09/99 11:01a Imhof
// DCS 3227: Set changed flag to true and set the timestamp for read sync
//
// 1 7/27/99 5:22p Imhof
//
// 1 7/27/99 5:18p Imhof
//
// 1 4/26/99 4:07p Imhof
// Readded after SS problems.
//
// 14 2/24/99 2:02p Imhof
// Added ValidateItem option and support
//
// 13 1/15/99 6:43p Imhof
// Updated legal notice.
//
// 12 12/16/98 2:52p Imhof
//
// 11 12/14/98 4:46p Imhof
// Modifications for OPC 2.0
//
// 10 12/11/98 5:58p Imhof
// Made modifications for OPC 2.0.
//
// 9 12/03/98 1:53p Imhof
// Removed read after additems
//
// 8 11/12/98 2:39p Imhof
// Reenabled the remove item
//
// 7 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 "Group.h"
#include "IOPCItemMgt.h"
#include "IOPCSyncIO.h"
#include "IOPCAsyncIO.h"
#include "IOPCAsyncIO2.h"
#include "AddItemDlg.h"
#include "IEnumOPCItemAttributes.h"
#include "IDataObject.h"
#include "OpcError.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CGroup, CObject)
CGroup::CGroup()
{
m_dwUpdateRate = 100;
m_lTimeBias = 0;
m_fDeadBand = 1.0f;
m_dwLCID = 0;
m_bDataChange = TRUE;
m_dwOPCSTMFormatWriteCompleteConnection = 0;
m_dwOPCSTMFormatDataTimeConnection = 0;
m_dwOPCSTMFormatDataConnection = 0;
m_dwOPCDataAccessConnectionPoint = 0;
m_pInfoServer = NULL;
m_dwCurrentTransactionID = 0;
m_dwCancelID = 0;
}
CGroup::~CGroup()
{
//should be already done => size = 0 !
/*
int size = m_Items.GetSize();
CItem* pItem;
for (int d=0; d < size; d++)
{
pItem = m_Items[0];
RemoveItem(&pItem);
}
*/
}
void CGroup::Serialize(CArchive& ar)
{
CBase<IOPCGroupStateMgt>::Serialize(ar);
m_Items.Serialize(ar);
for(int i = 0; i < m_Items.GetSize(); i++)
{
if(ar.IsLoading())
{
TRACE("we should use ptr array instead !\n");
m_Items[i] = new CItem;
}
m_Items[i]->Serialize(ar);
}
if (ar.IsStoring())
{
// TODO: add storing code here
ar << m_dwUpdateRate;
ar << m_lTimeBias;
ar << m_fDeadBand;
ar << m_dwLCID;
ar << m_bDataChange;
}
else
{
// TODO: add loading code here
ar >> m_dwUpdateRate;
ar >> m_lTimeBias;
ar >> m_fDeadBand;
ar >> m_dwLCID;
ar >> m_bDataChange;
}
}
BOOL CGroup::AddItem()
{
CAddItemDlg dlg(this);
dlg.DoModal();
return TRUE;
}
BOOL CGroup::ReloadItems()
{
USES_CONVERSION;
HRESULT res, res_next;
CIOPCItemMgt opcItemMgt(GetInterface());
CComPtr<IEnumOPCItemAttributes> pEnum;
CComPtr<IEnumOPCItemAttributes> pEnumClone;
BOOL bRet = FALSE;
res = opcItemMgt.CreateEnumerator(IID_IEnumOPCItemAttributes, (LPUNKNOWN*)&pEnum);
if(SUCCEEDED(res))
{
CIEnumOPCItemAttributes opcIEnum(pEnum);
//integrated test of clone
res = opcIEnum.Clone(&pEnumClone);
if(SUCCEEDED(res))
{
CIEnumOPCItemAttributes opcIEnumClone(pEnumClone);
OPCITEMATTRIBUTES* pItemArray = NULL;
ULONG ulRequested = m_pInfoServer->GetReloadEnumAttributesNextElements();
ULONG ulRetrieved = 0;
res = opcIEnumClone.Reset();
if(SUCCEEDED(res))
{
do
{
res_next = opcIEnumClone.Next(ulRequested, &pItemArray, &ulRetrieved);
//used for read
OPCHANDLE* phServer = new OPCHANDLE[ulRetrieved];
for(ULONG e = 0; e < ulRetrieved; e++)
{
//we need to save the new client handle !
CItem* pNewItem = new CItem;
HRESULT* pSetHandleErrors;
OPCHANDLE hNewClientHandle = (OPCHANDLE) pNewItem;
phServer[e] = NULL;
res = opcItemMgt.SetClientHandles(1, &(pItemArray[e].hServer), &hNewClientHandle, &pSetHandleErrors);
if(SUCCEEDED(res))
{
if(SUCCEEDED(pSetHandleErrors[0]))
{
pNewItem->SetName(OLE2A((pItemArray)[e].szItemID));
TRACE("%s\n", pNewItem->GetName());
pNewItem->SetHandle((pItemArray)[e].hServer);
TRACE("---> welchen DatenTyp ist wirklich vom Server momentan supported ?\n");
pNewItem->SetDataType((pItemArray)[e].vtRequestedDataType);
pNewItem->SetGroup(this);
m_Items.Add(pNewItem);
phServer[e] = pNewItem->GetHandle();
}
else
{
GetInfoServer()->DisplayError(pSetHandleErrors[e]);
delete pNewItem;
}
}
else
{
GetInfoServer()->DisplayError(res);
delete pNewItem;
}
CoTaskMemFree(pSetHandleErrors);
CoTaskMemFree(pItemArray[e].szItemID);
pItemArray[e].szItemID = NULL;
CoTaskMemFree(pItemArray[e].szAccessPath);
pItemArray[e].szAccessPath = NULL;
} //end for
CoTaskMemFree(pItemArray);
//now read the values (from cache)
ReadItemsSync(OPC_DS_CACHE, ulRetrieved, phServer);
delete[] phServer;
}
while(res_next == S_OK);
if(FAILED(res_next)) ((CInfoServerExplorerApp*)AfxGetApp())->DisplayText(_T("IEnumUnknown::Next()"), res_next);
//now we know how many enum items we have
//lets check now the ::Skip
res = opcIEnumClone.Reset();
if(SUCCEEDED(res))
{
res = opcIEnumClone.Skip(m_Items.GetSize());
if(SUCCEEDED(res))
{
//no output.
}
else
{
//skip
GetInfoServer()->DisplayError(res);
}
}
else
{
//reset
GetInfoServer()->DisplayError(res);
}
bRet = TRUE;
}
else
{
//reset
GetInfoServer()->DisplayError(res);
}
}
else
{
//clone
GetInfoServer()->DisplayError(res);
}
pEnumClone.Release();
}
else
{
GetInfoServer()->DisplayError(res);
}
pEnum.Release();
return bRet;
}
BOOL CGroup::ReCreateItemOnServer(CItem** item)
{
USES_CONVERSION;
HRESULT res;
CIOPCItemMgt opcItemMgt(GetInterface());
OPCITEMRESULT* pAddResults = NULL;
HRESULT* pErrors = NULL;
OPCHANDLE hItem;
const unsigned short usItems = 1;
OPCITEMDEF add_items[usItems];
add_items[0].szItemID = A2OLE((*item)->GetName());
add_items[0].szAccessPath = A2OLE("");
add_items[0].bActive = TRUE;
add_items[0].hClient = (OPCHANDLE)*item;
add_items[0].dwBlobSize = 0;
add_items[0].pBlob = NULL;
add_items[0].vtRequestedDataType = (*item)->GetDataType();
if(GetInfoServer()->UseValidateItems()) //only if option is set
{
//validate
if(!ValidateItems(usItems, add_items))
{
//cleanup
return FALSE;
}
}
res = opcItemMgt.AddItems(usItems, add_items, &pAddResults, &pErrors);
if(SUCCEEDED(res))
{
hItem = pAddResults->hServer;
(*item)->SetHandle(hItem);
if(VT_EMPTY == add_items[0].vtRequestedDataType) //native
{
if(SUCCEEDED(pErrors[0]))
//if asked for native we want the server given type
(*item)->SetDataType(pAddResults->vtCanonicalDataType);
else
((CInfoServerExplorerApp*)AfxGetApp())->DisplayText(_T("CIOPCItemMgt::AddItems()"), pErrors[0]);
}
else
{
if(SUCCEEDED(pErrors[0]))
//requested one
(*item)->SetDataType(add_items[0].vtRequestedDataType);
else if(pErrors[0] == OPC_E_BADTYPE)
(*item)->SetDataType(pAddResults->vtCanonicalDataType);
else
((CInfoServerExplorerApp*)AfxGetApp())->DisplayText(_T("CIOPCItemMgt::AddItems()"), pErrors[0]);
}
(*item)->SetGroup(this);
CoTaskMemFree(pAddResults);
CoTaskMemFree(pErrors);
//read it !
/*
HRESULT* pReadErrors;
OPCITEMSTATE* pItemValues;
CIOPCSyncIO opcSyncIO(GetInterface());
//read from cache
OPCHANDLE hServer = (*item)->GetHandle();
res = opcSyncIO.Read(OPC_DS_CACHE,usItems,&hServer,&pItemValues,&pReadErrors);
if(SUCCEEDED(res))
{
//get the values
(*item)->SetQuality(pItemValues->wQuality);
(*item)->SetValue(pItemValues->vDataValue);
TRACE("--->time stamp ??\n");
VariantClear( &pItemValues->vDataValue );
CoTaskMemFree(pItemValues);
CoTaskMemFree(pReadErrors);
}
else
{
GetInfoServer()->DisplayError(res);
}
*/
return TRUE;
}
else
{
GetInfoServer()->DisplayError(res);
return FALSE;
}
}
BOOL CGroup::RemoveItem(CItem** item)
{
HRESULT res;
HRESULT* pErrors = NULL;
CIOPCItemMgt opcItemMgt(GetInterface());
const unsigned short usItems = 1;
OPCHANDLE remove_items[usItems];
remove_items[0] = (*item)->GetHandle();
res = opcItemMgt.RemoveItems(usItems, remove_items, &pErrors);
if(SUCCEEDED(res))
{
CoTaskMemFree(pErrors);
for(int i = 0; i < m_Items.GetSize() ; i++)
{
if( *item == m_Items[i] )
{
m_Items.RemoveAt(i,1);
m_Items.FreeExtra();
delete *item;
}
}
return TRUE;
}
else
{
GetInfoServer()->DisplayError(res);
return FALSE;
}
}
BOOL CGroup::RemoveItems(CArray<CItem*, CItem*>* remove_items)
{
HRESULT res;
HRESULT* pErrors = NULL;
CIOPCItemMgt opcItemMgt(GetInterface());
const unsigned short usItems = remove_items->GetSize();
OPCHANDLE* hServer = new OPCHANDLE[usItems];
for(int i = 0; i < remove_items->GetSize(); i++)
{
hServer[i] = (*remove_items)[i]->GetHandle();
}
res = opcItemMgt.RemoveItems(usItems, hServer, &pErrors);
if(SUCCEEDED(res))
{
CoTaskMemFree(pErrors);
for(int r = 0; r < remove_items->GetSize() ; r++)
{
for(int i = 0; i < m_Items.GetSize() ; i++)
{
if( (*remove_items)[r] == m_Items[i] )
{
m_Items.RemoveAt(i,1);
m_Items.FreeExtra();
delete (*remove_items)[r];
break;
}
}
}
return TRUE;
}
else
{
GetInfoServer()->DisplayError(res);
return FALSE;
}
}
unsigned int CGroup::GetItems(CArray<CItem*, CItem*>** items)
{
*items = &m_Items;
return((*items)->GetSize());
}
void CGroup::SetOPCSTMFormatWriteCompleteConnection(DWORD dwConnection)
{
m_dwOPCSTMFormatWriteCompleteConnection = dwConnection;
}
void CGroup::SetOPCSTMFormatDataTimeConnection(DWORD dwConnection)
{
m_dwOPCSTMFormatDataTimeConnection = dwConnection;
}
void CGroup::SetOPCSTMFormatDataConnection(DWORD dwConnection)
{
m_dwOPCSTMFormatDataConnection = dwConnection;
}
DWORD CGroup::GetOPCSTMFormatWriteCompleteConnection()
{
return m_dwOPCSTMFormatWriteCompleteConnection;
}
DWORD CGroup::GetOPCSTMFormatDataTimeConnection()
{
return m_dwOPCSTMFormatDataTimeConnection;
}
DWORD CGroup::GetOPCSTMFormatDataConnection()
{
return m_dwOPCSTMFormatDataConnection;
}
void CGroup::SetOPCDataAccessConnectionPoint(DWORD dwConnection)
{
m_dwOPCDataAccessConnectionPoint = dwConnection;
}
DWORD CGroup::GetOPCDataAccessConnectionPoint()
{
return m_dwOPCDataAccessConnectionPoint;
}
CInfoServer* CGroup::GetInfoServer()
{
return m_pInfoServer;
}
void CGroup::SetInfoServer(CInfoServer* pInfoServer)
{
m_pInfoServer = pInfoServer;
}
BOOL CGroup::Refresh(OPCDATASOURCE dwSource)
{
//value gets returned over the IAdvise sink
HRESULT res;
CheckForOpenTransactions();
if(GetInfoServer()->GetOPCVersion() >= OPC_VERSION_20)
{
CIOPCAsyncIO2 opcAsyncIO2(GetInterface());
DWORD dwTransactionID = TRANSACTION_REFRESH; //in (returned in OnDataChange()) can be any number
DWORD dwCancelID; //out
res = opcAsyncIO2.Refresh2(dwSource, dwTransactionID, &dwCancelID);
SetCurrentTransactionID(dwTransactionID);
SetCurrentCancelID(dwCancelID);
}
else
{
CIOPCAsyncIO opcAsyncIO(GetInterface());
DWORD dwTransactionID; //out
if(GetInfoServer()->GetDataChangeType() > 0) //0 = no timestamp; 1 = with timestamp
res = opcAsyncIO.Refresh(GetOPCSTMFormatDataTimeConnection(), dwSource, &dwTransactionID);
else
res = opcAsyncIO.Refresh(GetOPCSTMFormatDataConnection(), dwSource, &dwTransactionID);
SetCurrentTransactionID(dwTransactionID);
}
if(SUCCEEDED(res))
{
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -