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

📄 opc_cpt.cpp

📁 工业标准通讯OPC协议的客户端测试源代码
💻 CPP
字号:
// opc_cpt.cpp - connection point test code
//
//
// (c) Copyright 1998 The OPC Foundation
// ALL RIGHTS RESERVED.
//
// DISCLAIMER:
//  This sample code is provided by the OPC Foundation solely to assist 
//  in understanding the OPC Specifications and may be used
//  as set forth in the License Grant section of the OPC Specification.
//  This code is provided as-is and without warranty or support of any sort
//  and is subject to the Warranty and Liability Disclaimers which appear
//  in the printed OPC Specification.
//
// CREDITS:
//  This code was generously provided to the OPC Foundation by
//  Al Chisholm, Intellution Inc.
//
// CONTENTS:
//
//
// Modification Log:
//	Vers    Date   By    Notes
//	----  -------- ---   -----
// 2.00  04/03/97 acc   
//       01/14/98 acc   update per final spec
//       02/06/98 acc   fix to not free 'in' parameters - the server does that.
//       06/17/98 acc   renamed some asyncio2 methods;cancel2,setenable,getenable
//       10/14/98 acc   rename refresh to refresh2
//

#include <stdio.h>
#include <conio.h>
#include "opcda.h"
#include "OLECTL.h"

extern	IMalloc *pIMalloc;
void TryConnectionPoint(IOPCGroupStateMgt * pGRP, int nItem, OPCHANDLE *sh);
//void TryConnectionPoint(IOPCGroupStateMgt * pGRP);

static void flip_mode(OPCDATASOURCE *mode);
static void	DumpValue(int i, VARIANT *v, WORD q, OPCHANDLE h, HRESULT err);
extern void	DumpVariant(VARIANT *v);

static	DWORD tid = 0;

// Define an actual implementation of the IOPCCallback interface
// based on the 'virtual' definition in the header file
//
class IXXXCallback : public IOPCDataCallback
{
public:
	IXXXCallback( void );
	~IXXXCallback( void );

	// the IUnknown Functions
	STDMETHODIMP         QueryInterface( REFIID iid, LPVOID* ppInterface);
	STDMETHODIMP_(ULONG) AddRef( void);
	STDMETHODIMP_(ULONG) Release( void);

	// Member Functions 
	STDMETHODIMP OnDataChange(
	 DWORD       Transid, 
	 OPCHANDLE   grphandle, 
	 HRESULT     masterquality,
	 HRESULT     mastererror,
	 DWORD       count, 
	 OPCHANDLE * clienthandles, 
	 VARIANT   * values, 
	 WORD      * quality,
	 FILETIME  * time,
	 HRESULT   * errors
	);

	STDMETHODIMP OnReadComplete(
	 DWORD       Transid, 
	 OPCHANDLE   grphandle, 
	 HRESULT     masterquality,
	 HRESULT     mastererror,
	 DWORD       count, 
	 OPCHANDLE * clienthandles, 
	 VARIANT   * values, 
	 WORD      * quality,
	 FILETIME  * time,
	 HRESULT   * errors
	);

	STDMETHODIMP OnWriteComplete(
	 DWORD       Transid, 
	 OPCHANDLE   grphandle, 
	 HRESULT     mastererr, 
	 DWORD       count, 
	 OPCHANDLE * clienthandles, 
	 HRESULT   * error
	);

	STDMETHODIMP OnCancelComplete(
	 DWORD       transid, 
	 OPCHANDLE   grphandle
	);

private:
	DWORD mRefCount;
};



// Utility help function used below
void	test1help(void)
{
	printf("Press 'a' to set active, i to set inactive\n");
	printf("'r to Read, w to Write\n");
	printf("'f to Refresh, c to cancel\n");
	printf("'d' to disable callbacks, 'e' to enable callbacks\n");
	printf("'m' to change Cache/Device mode, 'x' to disconnect\n");
	printf("'?' to repeat this message\n");
}

//---------------------------------------------------------
// TryConectionPoint
// Function to exercise the ConntionPoint logic for a group
// 
//void TryConnectionPoint(IOPCGroupStateMgt * pGRP)
void TryConnectionPoint(IOPCGroupStateMgt * pGRP, int nItem, OPCHANDLE *sh)
{
	IConnectionPointContainer *pCPC = 0;
	IConnectionPoint *pCallbackCP = 0;
	OPCDATASOURCE mode = OPC_DS_CACHE;
	IOPCAsyncIO2 *pASIO = 0;
	DWORD MyCookie = 0L;
	IXXXCallback *MyCallback;
	HRESULT r1;
	BOOL Active = 1;
	BOOL InActive = 0;
	DWORD RequestedRate = 2123;
	DWORD Rate;
	DWORD cid;
	HRESULT *hr;
	
	cputs("Hit Enter to Try OnDataChange...\n");
	getch();

	// Create a callback instance
	//
	MyCallback = new IXXXCallback;
	MyCallback -> AddRef();

	// Establish a connection
	//
	r1 = pGRP->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPC);
	if (FAILED(r1))
	{
		printf("No ConnectionPointContainer:(%lx)\n", r1);
		return;
	}

	r1 = pGRP->QueryInterface(IID_IOPCAsyncIO2, (void**)&pASIO);
	if (FAILED(r1))
	{
		printf("No AsyncIO2 interface:(%lx)\n", r1);
		pCPC->Release();
		return;
	}

	r1 = pCPC->FindConnectionPoint(IID_IOPCDataCallback, &pCallbackCP);
	if (FAILED(r1))
	{
		printf("No ConnectionPoint for OPCCallback:(%lx)\n", r1);
		pASIO->Release();
		pCPC->Release();
		return;
	}

	r1 = pCallbackCP->Advise(MyCallback, &MyCookie);
	if (FAILED(r1))
	{
		printf("Advise Failed:(%lx)\n", r1);
		pCallbackCP->Release();
		pASIO->Release();
		pCPC->Release();
		return;
	}

	printf("Callback is Connected - monitoring for activity...\n");
	printf("Mode = DEVICE\n");
	test1help();


	// Run test until terminated by user.
	// We must dispatch messages (in single apartment model)
	// for callbacks to work!
	//
	pGRP->SetState(&RequestedRate, &Rate, &Active,0,0,0,0);
	printf("Requested rate: %ld, Revised rate: %ld\n", RequestedRate, Rate);
	while(1)
	{
		if(kbhit())
		{
			char c;
			c = getch();
			if (c == 'x') 
				break;
			if (c == 'a') 
				pGRP->SetState(0, &Rate, &Active, 0,0,0,0);
			if (c == 'i') 
				pGRP->SetState(0, &Rate, &InActive, 0,0,0,0);

			if (c == 'd') 
				pASIO->SetEnable(0);
			if (c == 'e') 
				pASIO->SetEnable(1);

			if (c == 'f') 
			{
				r1= pASIO->Refresh2(mode, tid, &cid);
				if (FAILED(r1))	printf("Refresh Error:%lx\n", r1);
				else printf("Refresh started/TID=%ld, CID=%ld\n", tid, cid);
				tid++;
			}
			if (c == 'c') 
			{
				r1 = pASIO->Cancel2(cid);
				if(FAILED(r1)) printf("Cancel Error=%lx\n", r1);
			}
			if (c == 'm') 
				flip_mode(&mode);

			if(c == '?') 
				test1help();

			if (c == 'r') 
			{
				r1 = pASIO->Read(nItem, 
					sh, tid++, &cid, &hr);
				// check r1 and hr array and also free hr
				if(r1 != S_OK)
				{
					printf("Async ReadFailed:(%lx)\n", r1);
				}
				if(hr) pIMalloc->Free(hr);
			}

			if (c == 'w') 
			{
				VARIANT v[2];

				v[0].vt = VT_R4;
				v[0].fltVal = (float)12.34;
				v[1].vt = VT_R4;
				v[1].fltVal = (float)56.78;

				r1 = pASIO->Write(nItem, 
					sh, v, tid++, &cid, &hr);

				// check r1 and hr array and also free hr
				if(r1 != S_OK)
				{
					printf("Async WriteFailed:(%lx)\n", r1);
				}
				if(hr) pIMalloc->Free(hr);
			}
		}else
		{
			MSG msg;
			while(PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE))
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}
	}


	// User has terminated the test
	//
	printf("Disconnecting...\n");
	r1 = pCallbackCP->Unadvise(MyCookie);
	if (FAILED(r1))
	{
		printf("UnAdvise Failed:(%lx)\n", r1);
	}

	// Release the interfaces
	//
	pASIO->Release();
	pCallbackCP->Release();
	pCPC->Release();

	MyCallback -> Release();
}

static void flip_mode(OPCDATASOURCE *mode)
{
	switch(*mode)
	{
	case OPC_DS_CACHE:
		*mode = OPC_DS_DEVICE;
		printf("Mode changed to DEVICE\n");
		break;
	case OPC_DS_DEVICE:
		*mode = OPC_DS_CACHE;
		printf("Mode changed to CACHE\n");
		break;
	}
}



///////////////////////////////////////
// The rest of this file contains the 
// Client specific impementation of
// his IOPCCallback Methods
//
///////////////////////////////////////
//
///////////////////////////////////////
IXXXCallback:: IXXXCallback()
{
	mRefCount = 0;
}

///////////////////////////////////////
//
///////////////////////////////////////
IXXXCallback:: ~IXXXCallback()
{
}


///////////////////////////////////////
//
///////////////////////////////////////
STDMETHODIMP_(ULONG) IXXXCallback:: AddRef( void)
{
	return ++mRefCount;
}



///////////////////////////////////////
//
///////////////////////////////////////
STDMETHODIMP_(ULONG) IXXXCallback:: Release( void)
{
	ULONG currentCount = --mRefCount; 

	// If no references left for this object
	if ( currentCount == 0)
	{
		// Then delete this group.
		delete this;
	}
	return currentCount;
}


///////////////////////////////////////
//
///////////////////////////////////////
STDMETHODIMP IXXXCallback:: QueryInterface( REFIID iid, LPVOID* ppInterface)
{
	if ( ppInterface == NULL)
		return E_INVALIDARG;

	if ( iid == IID_IUnknown )
		*ppInterface = (IUnknown*) this;

	else if ( iid == IID_IOPCDataCallback)
	{
		*ppInterface = (IUnknown*) this;
	}
	else
	{
		*ppInterface = NULL;
	}
	
	if ( *ppInterface == NULL)
		return E_NOINTERFACE;

	AddRef();
	return S_OK;
}


///////////////////////////////////////
//
///////////////////////////////////////
STDMETHODIMP IXXXCallback:: OnDataChange(
	 DWORD       Transid, 
	 OPCHANDLE   grphandle, 
	 HRESULT     masterquality,
	 HRESULT     mastererror,
	 DWORD       count, 
	 OPCHANDLE * clienthandles, 
	 VARIANT   * value, 
	 WORD      * quality,
	 FILETIME  * time,
	 HRESULT   * errors
)
{
	unsigned int i;

	printf("OnDataChange: Transid=%ld count=%ld GrpHandle=%ld\n", Transid, count, grphandle);
	for(i=0; i<count; i++)
	{
		DumpValue(i, &value[i], quality[i], clienthandles[i], errors[i]);
	}

	return S_OK;
}

///////////////////////////////////////
//
///////////////////////////////////////
STDMETHODIMP IXXXCallback:: OnReadComplete(
	 DWORD       Transid, 
	 OPCHANDLE   grphandle, 
	 HRESULT     masterquality,
	 HRESULT     mastererror,
	 DWORD       count, 
	 OPCHANDLE * clienthandles, 
	 VARIANT   * value, 
	 WORD      * quality,
	 FILETIME  * time,
	 HRESULT   * errors
)
{
	unsigned int i;

	printf("OnReadComplete: Transid=%ld count=%ld GrpHandle=%ld\n", Transid, count, grphandle);
	for(i=0; i<count; i++)
	{
		DumpValue(i, &value[i], quality[i], clienthandles[i], errors[i]);
	}

	return S_OK;
}

///////////////////////////////////////
//
///////////////////////////////////////
STDMETHODIMP IXXXCallback:: OnWriteComplete(
	 DWORD       Transid, 
	 OPCHANDLE   grphandle, 
	 HRESULT     mastererr, 
	 DWORD       count, 
	 OPCHANDLE * clienthandles, 
	 HRESULT   * error
)
{
	DWORD i;

	printf("OnWriteComplete: Transid=%ld count=%ld GrpHandle=%ld\n", Transid, count, grphandle);
	for(i=0; i<count; i++)
	{
		printf("  [%d]-handle=%d, HR=%x\n", i, clienthandles[i], error[i]);
	}
	
	return S_OK;
}

///////////////////////////////////////
//
///////////////////////////////////////
STDMETHODIMP IXXXCallback:: OnCancelComplete(
	 DWORD       transid, 
	 OPCHANDLE   grphandle
)
{
	printf("OnCancelComplete: Transid=%ld GrpHandle=%ld\n", transid, grphandle);

	return S_OK;
}

//---------------------------------------------------------
// DumpValue
// This shows the value of a Variant
static void	DumpValue(int i, VARIANT *v, WORD q, OPCHANDLE h, HRESULT err)
{
	printf("  [%d]-handle=%d, Qual=%2x, Err=%8lx", i, h, q, err);
	DumpVariant(v);
	printf("\n");
}

⌨️ 快捷键说明

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