📄 opcdata.cpp
字号:
// OPCData.cpp: implementation of the COPCData class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "MainFrm.h"
#include "OPCData.h"
#include "SafeLock.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//----------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------
//LogMsg: 向事件窗口发送提示信息
//
void LogMsg(UINT unEventID,CObject * pObject)
{
// First get pointer to the application's main window:
CFrameWnd *pMainWnd = (CFrameWnd *)AfxGetMainWnd ();
try{
if (pMainWnd)
if(pMainWnd->m_hWnd)
{
//视通过unEventID进行识别
pMainWnd->GetActiveDocument()->UpdateAllViews (NULL, unEventID, pObject);
}
}catch(...)
{
CString strError;
strError.Format (_T("LogMsg 错误!"));
AfxMessageBox(strError, MB_OK| MB_ICONQUESTION);
}
}
//
//----------------------------------------------------------------------------------------------
//#pragma comment (lib, "ole32.lib")
//#pragma comment (lib, "oleaut32.lib")
// OPC_XX_DATAXX defines are based on an index in a listbox (do not modify)
#define OPC_10_DATACHANGE 0 // OnDataChange 1.0 no timestamp request
#define OPC_10_DATATIMECHANGE 1 // OnDataChange 1.0 with timestamp request
#define OPC_20_DATACHANGE 2 // OnDataChange 2.0 (always a timestamp) request
// Group defaults
#define GROUP_DEFAULT_ACTIVESTATE TRUE
#define GROUP_DEFAULT_LANGUAGEID MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US)
#define GROUP_DEFAULT_NAME _T("")
#define GROUP_DEFAULT_DEADBAND 0.0f
#define GROUP_DEFAULT_TIMEBIAS 0
#define GROUP_DEFAULT_UPDATERATE 100
#define GROUP_DEFAULT_UPDATEMETHOD OPC_20_DATACHANGE
#define GROUP_DEFAULT_FORCEDELETE FALSE
#define GROUP_DEFAULT_REMOVEITEMSONDELETE TRUE
#define GROUP_DEFAULT_ACTIVATEITEMSONSELECT TRUE
// Item defaults
#define ITEM_DEFAULT_ACCESSPATH _T("")
#define ITEM_DEFAULT_ITEMID _T("")
#define ITEM_DEFAULT_ACTIVESTATE TRUE
#define ITEM_DEFAULT_DATATYPE VT_EMPTY
//--------------------------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////
//COPCQuality:通讯品质
//////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
#define IDS_NONAPPLICABLE "N/A"
#define IDS_UNKNOWN "Unknown"
#define IDS_QUALITY_GOOD "Good"
#define IDS_QUALITY_GOOD_LOCALOVERRIDE "Good (Local Override)"
#define IDS_QUALITY_BAD "Bad"
#define IDS_QUALITY_BAD_CONFIGERROR "Bad (Configuration Error)"
#define IDS_QUALITY_BAD_COMMFAILURE "Bad (Communications Failed)"
#define IDS_QUALITY_BAD_DEVICEFAILURE "Bad (Device Failure)"
#define IDS_QUALITY_BAD_NOTCONNECTED "Bad (Not Connected)"
#define IDS_QUALITY_BAD_LASTKNOWNVALUE "Bad (Last Known Value)"
#define IDS_QUALITY_BAD_SENSORFAILURE "Bad (Sensor Failure)"
#define IDS_QUALITY_BAD_OUTOFSERVICE "Bad (Out of Service)"
#define IDS_QUALITY_NOVALUE "No Value"
#define IDS_QUALITY_UNCERTAIN "Uncertain"
#define IDS_QUALITY_UNCERTAIN_EUEXCEEDED "Uncertain (Engineering Units Exceeded)"
#define IDS_QUALITY_UNCERTAIN_LASTUSEABLEVALUE "Uncertain (Last Useable Value)"
#define IDS_QUALITY_UNCERTAIN_SENSORNOTACCURATE "Uncertain (Sensor Not Accurate)"
#define IDS_QUALITY_UNCERTAIN_SUBNORMAL "Uncertain (Sub-Normal)"
struct COPCQuality
{
public:
// Constructor:
COPCQuality ()
{
Initialize();
}
// Initialize container object.
void Initialize ()
{
// Load quality string resources:
m_strQualityBad=_T(IDS_QUALITY_BAD);
m_strQualityBadConfigError=_T(IDS_QUALITY_BAD_CONFIGERROR);
m_strQualityBadNotConnected=_T(IDS_QUALITY_BAD_NOTCONNECTED);
m_strQualityBadDeviceFailure=_T(IDS_QUALITY_BAD_DEVICEFAILURE);
m_strQualityBadSensorFailure=_T(IDS_QUALITY_BAD_SENSORFAILURE);
m_strQualityBadLastKnownValue=_T(IDS_QUALITY_BAD_LASTKNOWNVALUE);
m_strQualityBadCommFailure=_T(IDS_QUALITY_BAD_COMMFAILURE);
m_strQualityBadOutOfService=_T(IDS_QUALITY_BAD_OUTOFSERVICE);
m_strQualityUncertain=_T(IDS_QUALITY_UNCERTAIN);
m_strQualityUncertainLastUsableValue=_T(IDS_QUALITY_UNCERTAIN_LASTUSEABLEVALUE);
m_strQualityUncertainSensorNotAccurate=_T(IDS_QUALITY_UNCERTAIN_SENSORNOTACCURATE);
m_strQualityUncertainEUExceeded=_T(IDS_QUALITY_UNCERTAIN_EUEXCEEDED);
m_strQualityUncertainSubnormal=_T(IDS_QUALITY_UNCERTAIN_SUBNORMAL);
m_strQualityGood=_T(IDS_QUALITY_GOOD);
m_strQualityGoodLocalOverride=_T(IDS_QUALITY_GOOD_LOCALOVERRIDE);
m_strQualityNoValue=_T(IDS_QUALITY_NOVALUE);
// Load unknown string resource:
m_strUnknown=_T(IDS_UNKNOWN);
// Load non-applicable string resource:
m_strNonApplicable=_T(IDS_NONAPPLICABLE);
}
public:
// Quality strings:
CString m_strQualityBad;
CString m_strQualityBadConfigError;
CString m_strQualityBadNotConnected;
CString m_strQualityBadDeviceFailure;
CString m_strQualityBadSensorFailure;
CString m_strQualityBadLastKnownValue;
CString m_strQualityBadCommFailure;
CString m_strQualityBadOutOfService;
CString m_strQualityUncertain;
CString m_strQualityUncertainLastUsableValue;
CString m_strQualityUncertainSensorNotAccurate;
CString m_strQualityUncertainEUExceeded;
CString m_strQualityUncertainSubnormal;
CString m_strQualityGood;
CString m_strQualityGoodLocalOverride;
CString m_strQualityNoValue;
// Unknown:
CString m_strUnknown;
CString m_strNonApplicable;
} cOPCQuality;
//////////////////////////////////////////////////////////////////////
//COPCItem: Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_SERIAL( COPCItem, CObject, VERSIONABLE_SCHEMA | 2 )
COPCItem::COPCItem()
{
m_hServer=NULL; //数据项服务句柄
//数据
VariantInit (&m_vtValue);
InitializeOPCData();
// VariantInit (&m_vtValue);
// ::GetSystemTimeAsFileTime (&m_ftTimeStamp);
// m_wQuality=OPC_QUALITY_BAD_OUT_OF_SERVICE;
// m_bTimeStamped=FALSE; // TRUE if the last update included a timestamp
// m_dwUpdates=0; //更新次数
m_unDecimalDigits=0; //小数点位数,针对整数型也有效
m_strAccessPath=_T(""); // access path
m_strItemID=_T(""); // 数据项名称
m_bActive=TRUE; // active state
m_vtDataType=VT_EMPTY; //无数据类型
m_dwAccessRights= OPC_READABLE; // access rights
m_bActive= FALSE;
// ZeroMemory (&m_bfFlags, sizeof (m_bfFlags));
cOPCQuality.Initialize ();
}
COPCItem::~COPCItem()
{
}
COPCItem::COPCItem(COPCItem* pItem)
{
m_strItemID =pItem->m_strItemID ;
m_vtValue =pItem->m_vtValue;
m_unDecimalDigits =pItem->m_unDecimalDigits ;
}
COPCItem* COPCItem::operator=(COPCItem* pItem)
{
m_strItemID =pItem->m_strItemID ;
m_vtValue =pItem->m_vtValue;
m_unDecimalDigits =pItem->m_unDecimalDigits ;
return this;
}
CString COPCItem::GetItemID()
{
return m_strItemID;
}
void COPCItem::SetItemID(LPCTSTR strItemID)
{
m_strItemID=strItemID;
}
void COPCItem::SetAlias(LPCTSTR strAlias)
{
m_strAlias=strAlias;
}
void COPCItem::SetServerHandle(OPCHANDLE hServer)
{
m_hServer=hServer;
}
void COPCItem::SetAccessPath(LPCTSTR strAccessPath)
{
m_strAccessPath=strAccessPath;
}
CString COPCItem::GetAccessPath()
{
return m_strAccessPath;
}
OPCHANDLE COPCItem::GetServerHandle()
{
return m_hServer;
}
void COPCItem::SetActive(BOOL bActive)
{
m_bActive=bActive;
}
void COPCItem::InitializeOPCData()
{
::GetSystemTimeAsFileTime (&m_ftTimeStamp);
m_wQuality=OPC_QUALITY_BAD_OUT_OF_SERVICE;
m_bTimeStamped=FALSE;
m_dwUpdates=0; //更新次数
}
BOOL COPCItem::IsActive()
{
return m_bActive;
}
void COPCItem::SetDataType(VARTYPE vtType)
{
m_vtDataType=vtType;
}
OPCITEMDEF COPCItem::GetOPCITEMDEF()
{
OPCITEMDEF OPCItemDef;
//1.szAccessPath
DWORD dwLen;
// COM requires all strings be in UNICODE format. We may have
// to convert format before copying into request structure.
// First process the access path string:
dwLen = lstrlen (m_strAccessPath);
// Access path is optional. If it is not defined, i.e. it's length
// is zero, just set pointer to string to NULL:
if (dwLen)
{
// Allocate memory for the string:
OPCItemDef.szAccessPath = (WCHAR *) CoTaskMemAlloc ((dwLen + 1) * sizeof (WCHAR));
#ifdef _UNICODE
lstrcpyn (OPCItemDef.szAccessPath, m_strAccessPath, dwLen + 1);
#else
MultiByteToWideChar (CP_ACP, 0, m_strAccessPath, -1, OPCItemDef.szAccessPath, dwLen + 1);
#endif
}
else
OPCItemDef.szAccessPath = NULL;
//2.szItemID
dwLen = lstrlen (m_strItemID);
if (dwLen)
{
// Allocate memory for the string:
OPCItemDef.szItemID = (WCHAR *) CoTaskMemAlloc ((dwLen + 1) * sizeof (WCHAR));
#ifdef _UNICODE
lstrcpyn (OPCItemDef.szItemID, m_strItemID, dwLen + 1);
#else
MultiByteToWideChar (CP_ACP, 0, m_strItemID, -1, OPCItemDef.szItemID, dwLen + 1);
#endif
}
else
OPCItemDef.szItemID = NULL;
//3.bActive
OPCItemDef.bActive =m_bActive;
//4.hClient
OPCItemDef.hClient =(OPCHANDLE) this; //将数据地址作为OPCHANDLE,便于数据转换
//5.dwBlobSize
OPCItemDef.dwBlobSize =0;
//6.vtRequestedDataType
OPCItemDef.vtRequestedDataType =m_vtDataType==VT_EMPTY ? m_vtValue.vt : m_vtDataType;
//7.wReserved
OPCItemDef.wReserved =0;
return OPCItemDef;
}
void COPCItem::GetOPCITEMDEF(OPCITEMDEF &OPCItemDef)
{
// OPCITEMDEF OPCItemDef;
//1.szAccessPath
DWORD dwLen;
// COM requires all strings be in UNICODE format. We may have
// to convert format before copying into request structure.
// First process the access path string:
dwLen = lstrlen (m_strAccessPath);
// Access path is optional. If it is not defined, i.e. it's length
// is zero, just set pointer to string to NULL:
if (dwLen)
{
// Allocate memory for the string:
OPCItemDef.szAccessPath = (WCHAR *) CoTaskMemAlloc ((dwLen + 1) * sizeof (WCHAR));
#ifdef _UNICODE
lstrcpyn (OPCItemDef.szAccessPath, m_strAccessPath, dwLen + 1);
#else
MultiByteToWideChar (CP_ACP, 0, m_strAccessPath, -1, OPCItemDef.szAccessPath, dwLen + 1);
#endif
}
else
OPCItemDef.szAccessPath = NULL;
//2.szItemID
dwLen = lstrlen (m_strItemID);
if (dwLen)
{
// Allocate memory for the string:
OPCItemDef.szItemID = (WCHAR *) CoTaskMemAlloc ((dwLen + 1) * sizeof (WCHAR));
#ifdef _UNICODE
lstrcpyn (OPCItemDef.szItemID, m_strItemID, dwLen + 1);
#else
MultiByteToWideChar (CP_ACP, 0, m_strItemID, -1, OPCItemDef.szItemID, dwLen + 1);
#endif
}
else
OPCItemDef.szItemID = NULL;
//3.bActive
OPCItemDef.bActive =m_bActive;
//4.hClient
OPCItemDef.hClient =(OPCHANDLE) this; //将数据地址作为OPCHANDLE,便于数据转换
//5.dwBlobSize
OPCItemDef.dwBlobSize =0;
//6.vtRequestedDataType
OPCItemDef.vtRequestedDataType =m_vtDataType==VT_EMPTY ? m_vtValue.vt : m_vtDataType;
//7.wReserved
OPCItemDef.wReserved =0;
}
HRESULT COPCServer::GetCLSID(CLSID &clsid)
{
#ifdef UNICODE
// If this is a Unicode build, then the prog ID string stored in m_strProgID
// will already be in wide character format. We will be able to pass it
// as is to CLSIDFromProgID.
return (CLSIDFromProgID (m_strProgID, &clsid));
#else
// If this is not a Unicode build, then we need to convert the prog ID string
// stored in m_strProgID to wide character format before calling CLSIDFromProgID().
// Declare a buffer to contain the converted string:
WCHAR wszProgID [DEFBUFFSIZE];
// Convert the string format:
if (!MultiByteToWideChar (CP_ACP, 0, m_strProgID, -1, wszProgID, sizeof (wszProgID) / sizeof (WCHAR)))
{
ASSERT (FALSE);
}
// Now we can call CLSIDFromProgID, using converted string:
return (CLSIDFromProgID (wszProgID, &clsid));
#endif
}
CString COPCServer::GetProgID()
{
return m_strProgID;
}
void COPCServer::SetProgID(CString strProgID)
{
m_strProgID=strProgID;
}
UINT COPCServer::GetOPCVersion()
{
return m_unOPCVersion;
}
void COPCServer::SetOPCVersion(UINT unOPCVersion)
{
m_unOPCVersion=unOPCVersion;
}
COPCRemoteMachine* COPCServer::GetRemoteMachine()
{
return m_pOPCRemPC;
}
void COPCServer::SetRemoteMachine(COPCRemoteMachine* pOPCRemPC)
{
m_pOPCRemPC=pOPCRemPC;
}
CString COPCServer::GetRemoteMachineName()
{
return m_strRemoteMachine;
}
void COPCServer::SetRemoteMachineName(CString strRemoteMachine)
{
m_strRemoteMachine=strRemoteMachine;
}
void COPCServer::SetSelGroup(CString& strGroup)
{
COPCGroup* pGroup;
if(m_cMapGroup.Lookup (strGroup,(void*&)pGroup))
{
m_pSelGroup=pGroup;
return;
}
ASSERT (TRUE);
}
void COPCServer::SetSelGroup(const COPCGroup* pSelGroup)
{
COPCGroup* pGroup;
CString strGroup;
POSITION pos =m_cMapGroup.GetStartPosition ();
while(pos)
{
m_cMapGroup.GetNextAssoc(pos,strGroup,(void*&)pGroup);
if(pSelGroup==pGroup)
{
m_pSelGroup=pGroup;
return;
}
}
ASSERT (TRUE);
}
//服务器对象回调函数:当服务器对象关闭时调用
void COPCServer::ShutdownRequest(LPCTSTR lpwszReason)
{
Disconnect(TRUE);
/*
try{
//1. Remove the OPC Group:
POSITION pos=m_cMapGroup.GetStartPosition ();
COPCGroup* pGroup=NULL;
CString strGroup;
while(pos)
{
m_cMapGroup.GetNextAssoc (pos,strGroup,(void*&)pGroup);
DelGroup(strGroup);
}
//2. Release the interface references:
m_pIServer->Release();
m_pIServer=NULL;
//3. Release the IShutdownSink
m_pIShutdownSink->Release ();
m_pIShutdownSink=NULL;
//
}
catch(...)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -