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

📄 opcdata.cpp

📁 OPC Client 源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// 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 + -