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