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

📄 item.cpp

📁 VisualC OPC Client Example C 程序开发
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// **************************************************************************
// item.cpp
//
// Description:
//	Implements the CKItem class.  On object of this class is associated with
//	each OPC item we wish to exchange data with.
//
// DISCLAIMER:
//	This programming example is provided "AS IS".  As such Kepware, Inc.
//	makes no claims to the worthiness of the code and does not warranty
//	the code to be error free.  It is provided freely and can be used in
//	your own projects.  If you do find this code useful, place a little
//	marketing plug for Kepware in your code.  While we would love to help
//	every one who is trying to write a great OPC client application, the 
//	uniqueness of every project and the limited number of hours in a day 
//	simply prevents us from doing so.  If you really find yourself in a
//	bind, please contact Kepware's technical support.  We will not be able
//	to assist you with server related problems unless you are using KepServer
//	or KepServerEx.
// **************************************************************************


#include "stdafx.h"
#include "opctestclient.h"
#include "item.h"
#include "group.h"

#pragma comment (lib, "ole32.lib")
#pragma comment (lib, "oleaut32.lib") 

#define VERSION_1			1
#define CURRENT_VERSION		VERSION_1


// **************************************************************************
// String container object for items
// **************************************************************************
class CStringContainer
	{
	public:
		// Constructor:
		CStringContainer ()
			{
			LPCTSTR lpszDefault = _T("");

			// Initialize member variables.  Strings set to NULL string.
			m_lpszQualityBad = lpszDefault;
			m_lpszQualityBadConfigError = lpszDefault;
			m_lpszQualityBadNotConnected = lpszDefault;
			m_lpszQualityBadDeviceFailure = lpszDefault;
			m_lpszQualityBadSensorFailure = lpszDefault;
			m_lpszQualityBadLastKnownValue = lpszDefault;
			m_lpszQualityBadCommFailure = lpszDefault;
			m_lpszQualityBadOutOfService = lpszDefault;
			m_lpszQualityUncertain = lpszDefault;
			m_lpszQualityUncertainLastUsableValue = lpszDefault;
			m_lpszQualityUncertainSensorNotAccurate = lpszDefault;
			m_lpszQualityUncertainEUExceeded = lpszDefault;
			m_lpszQualityUncertainSubnormal = lpszDefault;
			m_lpszQualityGood = lpszDefault;
			m_lpszQualityGoodLocalOverride = lpszDefault;
			m_lpszQualityNoValue = lpszDefault;

			m_lpszUnknown = lpszDefault;
			m_lpszNonApplicable = lpszDefault;

			m_bInitialized = false;
			}

		// Initialize container object.
		void Initialize ()
			{
			// Load string resources and assign public pointers if we haven't
			// already done so:
			if (!m_bInitialized)
				{
				// Load quality string resources:
				m_strQualityBad.LoadString (IDS_QUALITY_BAD);
				m_strQualityBadConfigError.LoadString (IDS_QUALITY_BAD_CONFIGERROR);
				m_strQualityBadNotConnected.LoadString (IDS_QUALITY_BAD_NOTCONNECTED);
				m_strQualityBadDeviceFailure.LoadString (IDS_QUALITY_BAD_DEVICEFAILURE);
				m_strQualityBadSensorFailure.LoadString (IDS_QUALITY_BAD_SENSORFAILURE);
				m_strQualityBadLastKnownValue.LoadString (IDS_QUALITY_BAD_LASTKNOWNVALUE);
				m_strQualityBadCommFailure.LoadString (IDS_QUALITY_BAD_COMMFAILURE);
				m_strQualityBadOutOfService.LoadString (IDS_QUALITY_BAD_OUTOFSERVICE);
				m_strQualityUncertain.LoadString (IDS_QUALITY_UNCERTAIN);
				m_strQualityUncertainLastUsableValue.LoadString (IDS_QUALITY_UNCERTAIN_LASTUSEABLEVALUE);
				m_strQualityUncertainSensorNotAccurate.LoadString (IDS_QUALITY_UNCERTAIN_SENSORNOTACCURATE);
				m_strQualityUncertainEUExceeded.LoadString (IDS_QUALITY_UNCERTAIN_EUEXCEEDED);
				m_strQualityUncertainSubnormal.LoadString (IDS_QUALITY_UNCERTAIN_SUBNORMAL);
				m_strQualityGood.LoadString (IDS_QUALITY_GOOD);
				m_strQualityGoodLocalOverride.LoadString (IDS_QUALITY_GOOD_LOCALOVERRIDE);
				m_strQualityNoValue.LoadString (IDS_QUALITY_NOVALUE);

				// Assign to public pointers:
				m_lpszQualityBad = m_strQualityBad;
				m_lpszQualityBadConfigError = m_strQualityBadConfigError;
				m_lpszQualityBadNotConnected = m_strQualityBadNotConnected;
				m_lpszQualityBadDeviceFailure = m_strQualityBadDeviceFailure;
				m_lpszQualityBadSensorFailure = m_strQualityBadSensorFailure;
				m_lpszQualityBadLastKnownValue = m_strQualityBadLastKnownValue;
				m_lpszQualityBadCommFailure = m_strQualityBadCommFailure;
				m_lpszQualityBadOutOfService = m_strQualityBadOutOfService;
				m_lpszQualityUncertain = m_strQualityUncertain;
				m_lpszQualityUncertainLastUsableValue = m_strQualityUncertainLastUsableValue;
				m_lpszQualityUncertainSensorNotAccurate = m_strQualityUncertainSensorNotAccurate;
				m_lpszQualityUncertainEUExceeded = m_strQualityUncertainEUExceeded;
				m_lpszQualityUncertainSubnormal = m_strQualityUncertainSubnormal;
				m_lpszQualityGood = m_strQualityGood;
				m_lpszQualityGoodLocalOverride = m_strQualityGoodLocalOverride;
				m_lpszQualityNoValue = m_strQualityNoValue;

				// Load unknown string resource:
				m_strUnknown.LoadString (IDS_UNKNOWN);
				m_lpszUnknown = m_strUnknown;

				// Load non-applicable string resource:
				m_strNonApplicable.LoadString (IDS_NONAPPLICABLE);
				m_lpszNonApplicable = m_strNonApplicable;
				
				// Set initialized flag so we don't waste time loading string 
				// resources if called again.
				m_bInitialized = true;
				}
			}

	public:
		// Quality strings:
		LPCTSTR m_lpszQualityBad;
		LPCTSTR m_lpszQualityBadConfigError;
		LPCTSTR m_lpszQualityBadNotConnected;
		LPCTSTR m_lpszQualityBadDeviceFailure;
		LPCTSTR m_lpszQualityBadSensorFailure;
		LPCTSTR m_lpszQualityBadLastKnownValue;
		LPCTSTR m_lpszQualityBadCommFailure;
		LPCTSTR m_lpszQualityBadOutOfService;
		LPCTSTR m_lpszQualityUncertain;
		LPCTSTR m_lpszQualityUncertainLastUsableValue;
		LPCTSTR m_lpszQualityUncertainSensorNotAccurate;
		LPCTSTR m_lpszQualityUncertainEUExceeded;
		LPCTSTR m_lpszQualityUncertainSubnormal;
		LPCTSTR m_lpszQualityGood;
		LPCTSTR m_lpszQualityGoodLocalOverride;
		LPCTSTR m_lpszQualityNoValue;

		LPCTSTR m_lpszUnknown;
		LPCTSTR m_lpszNonApplicable;

	private:
		// 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;

		bool m_bInitialized;
	
	} cStringContainer;


/////////////////////////////////////////////////////////////////////////////
// CKItem construction/destruction
/////////////////////////////////////////////////////////////////////////////

// **************************************************************************
// CKItem ()
//
// Description:
//	Constructor
//
// Parameters:
//  CKGroup		*pParent	Pointer to parent group.
//
// Returns:
//  none
// **************************************************************************
CKItem::CKItem (CKGroup *pParent)
	{
	// Initialize string container so we can return strings:
	cStringContainer.Initialize ();

	// Initialize other member variables:
	ASSERT (pParent != NULL);
	m_pGroup = pParent;

	m_bActive			= FALSE;
	m_vtDataType		= VT_EMPTY;
	m_dwAccessRights	= OPC_READABLE;

	m_bValid			= FALSE;
	m_bTimeStamped		= FALSE;

	ZeroMemory (&m_bfFlags, sizeof (m_bfFlags));
	
	GetSystemTimeAsFileTime (&m_ftTimeStamp);
	VariantInit (&m_vtValue);

	m_wQuality	= OPC_QUALITY_BAD_OUT_OF_SERVICE;
	m_cdwUpdates = 0;

	m_hServer	= NULL;
	m_pPrev		= NULL;
	m_pNext		= NULL;

	m_wParam	= 0;
	}

// **************************************************************************
// ~CKItem ()
//
// Description:
//	Destructor
//
// Parameters:
//  none
//
// Returns:
//  none
// **************************************************************************
CKItem::~CKItem ()
	{
	// Make sure our variant members get cleaned up properly:
	VariantClear (&m_vtValue);
	}


/////////////////////////////////////////////////////////////////////////////
// CKItem manipulators
/////////////////////////////////////////////////////////////////////////////

// **************************************************************************
// UpdateData ()
//
// Description:
//	Called to update the item's data and quality.
//
// Parameters:
//  VARIANT		&vtVal		Item's data.
//	WORD		wQuality	Item's quality.
//
// Returns:
//  void
// **************************************************************************
void CKItem::UpdateData (VARIANT &vtVal, WORD wQuality)
	{
	// Create a CSafeLock to make this object thread safe.  Our critical
	// section gets locked here, and will automatically be unlocked when the
	// CSafeLock goes out of scope.
	CSafeLock cs (&m_csDataLock);

	// Update item value:
	VariantCopy (&m_vtValue, &vtVal);

	// Update item quality:
	m_wQuality = wQuality;

	// This function is used for non-timestamped data:
	m_bTimeStamped = FALSE;

	// Increment update count:
	++m_cdwUpdates;
	}

// **************************************************************************
// UpdateData ()
//
// Description:
//	Called to update the item's data, quality and timestamp.
//
// Parameters:
//  VARIANT		&vtVal			Item's data.
//	WORD		wQuality		Item's quality.
//	FILETIME	&ftTimeStamp	Item's timestap.
//
// Returns:
//  void
// **************************************************************************
void CKItem::UpdateData (VARIANT &vtVal, WORD wQuality, FILETIME &ftTimeStamp)
	{
	// Create a CSafeLock to make this object thread safe.  Our critical
	// section gets locked here, and will automatically be unlocked when the
	// CSafeLock goes out of scope.
	CSafeLock cs (&m_csDataLock);

	// Update item value:
	VariantCopy (&m_vtValue, &vtVal);

	// Update item quality:
	m_wQuality = wQuality;

	// Update item timestamp:
	m_bTimeStamped = TRUE;
	m_ftTimeStamp = ftTimeStamp;

	// Increment update count:
	++m_cdwUpdates;
	}

// **************************************************************************
// GetValue ()
//
// Description:
//	Returns a string representation of the current value.
//
// Parameters:
//  CString		&strValue	Output string.
//
// Returns:
//  void
// **************************************************************************
void CKItem::GetValue (CString &strValue)
	{
	// Create a CSafeLock to make this object thread safe.  Our critical
	// section gets locked here, and will automatically be unlocked when the
	// CSafeLock goes out of scope.
	CSafeLock cs (&m_csDataLock);

	// If item is active and valid, we can rely on server's data:
	if (IsValid ())
		{
		TCHAR szNum [32];

		// If data item is an array:
		if (m_vtValue.vt & VT_ARRAY)
			{
			// Format output string:
			switch (m_vtValue.vt)
				{
				// Supported types:
				case VT_UI1	| VT_ARRAY:
				case VT_I1	| VT_ARRAY:
				case VT_UI2	| VT_ARRAY:
				case VT_I2	| VT_ARRAY:
				case VT_UI4	| VT_ARRAY:
				case VT_I4	| VT_ARRAY:
				case VT_R4	| VT_ARRAY:
				case VT_R8	| VT_ARRAY:
					{
					// Get pointer to array data:
					CSafeArray *pSafeArr = (CSafeArray *) m_vtValue.parray;

					// Process array data if pointer appears to be good:
					if (pSafeArr)
						{
						// Get the array dimensions:
						DWORD dwCols = pSafeArr->GetNumCols ();
						DWORD dwSize = pSafeArr->GetByteLength ();
						ULONG cbElements = pSafeArr->cbElements;
						LPBYTE lpByte = (LPBYTE)pSafeArr->pvData;
						DWORD dwCol = 0;

						// Start delimiter out putput string:
						strValue = _T("[ ");

						// Cycle through the elements:
						for (DWORD i = 0; i < dwSize; i += cbElements, lpByte += cbElements)
							{
							// Format a string for each element according to data type:

							// Single-byte types:
							if (cbElements == 1)
								{
								if (m_vtValue.vt ==	(VT_UI1 | VT_ARRAY))
									_stprintf (szNum, _T("%u"), *lpByte);
								else
									_stprintf (szNum, _T("%d"), *(char *)lpByte);
								}
							
							// Two-byte types:
							else if (cbElements == 2)
								{
								if (m_vtValue.vt ==	(VT_UI2 | VT_ARRAY))
									_stprintf (szNum, _T("%u"), *(WORD *)lpByte);
								else 
									_stprintf (szNum, _T("%d"), *(short *)lpByte);
								}
							
							// Four-byte types:
							else if (cbElements == 4)
								{
								if (m_vtValue.vt ==	(VT_R4	| VT_ARRAY))
									_stprintf (szNum, _T("%G"), *(float *)lpByte);
								else if (m_vtValue.vt ==	(VT_UI4	| VT_ARRAY))
									_stprintf (szNum, _T("%u"), *(DWORD *)lpByte);
								else if (m_vtValue.vt ==	(VT_I4	| VT_ARRAY))
									_stprintf (szNum, _T("%d"), *(DWORD *)lpByte);
								}

							// Eight-byte types:
							else if (cbElements == 8)
								_stprintf (szNum, _T("%G"), *(double *)lpByte);

							// Else something is foobar!
							else
								{
								ASSERT (FALSE);
								}

							// Delimit each element within the row:
							if (dwCol != 0)
								strValue += _T(", ");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -