here is an example of subscribing to OPC item changes in C++, using the ItemChanged event on the EasyDAClient object:
// This example shows how to subscribe to changes of multiple items and display the value of the item with each change.
// SubscribeMultipleItems.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <atlcom.h>
#include <atlsafe.h>
#include <comutil.h>
#import "libid:FAB7A1E3-3B79-4292-9C3A-DF39A6F65EC1" version(5.2) // EasyOpcLib
using namespace EasyOpcLib;
#define DISPID_EASYDACLIENTEVENTS_ITEMCHANGED 1002
//
class CSubscribeMultipleItemsModule : public ATL::CAtlModuleT< CSubscribeMultipleItemsModule >
{
};
CSubscribeMultipleItemsModule _AtlModule;
// CCoEasyDAClientEvents
class CCoEasyDAClientEvents :
public CComObjectRoot,
public IDispEventImpl<1, CCoEasyDAClientEvents, &__uuidof(DEasyDAClientEvents), &__uuidof(__EasyOpcLib), 5, 2>
{
BEGIN_COM_MAP(CCoEasyDAClientEvents)
COM_INTERFACE_ENTRY_IID(__uuidof(IDispatch), CCoEasyDAClientEvents)
COM_INTERFACE_ENTRY_IID(__uuidof(DEasyDAClientEvents), CCoEasyDAClientEvents)
END_COM_MAP()
BEGIN_SINK_MAP(CCoEasyDAClientEvents)
// Event handlers must have the __stdcall calling convention
SINK_ENTRY_EX(1, __uuidof(DEasyDAClientEvents), DISPID_EASYDACLIENTEVENTS_ITEMCHANGED,
&CCoEasyDAClientEvents::ItemChanged)
END_SINK_MAP()
public:
// The handler for EasyDAClient.ItemChanged event
STDMETHOD(ItemChanged)(VARIANT varSender, VARIANT varEventArgs)
{
// Obtain the event arguments
IEasyDAItemChangedEventArgsPtr EasyDAItemChangedEventArgsPtr(varEventArgs);
IDAItemDescriptorPtr DAItemDescriptorPtr(EasyDAItemChangedEventArgsPtr->ItemDescriptor);
IDAVtqPtr VtqPtr(EasyDAItemChangedEventArgsPtr->Vtq);
// Not shown in this example: You should test the VtqPtr against NULL.
_tprintf(_T("%s: %s\n"), COLE2CT(_bstr_t(DAItemDescriptorPtr->ItemId)), COLE2CT(_bstr_t(VtqPtr->ToString())));
return S_OK;
}
};
//
int _tmain(int argc, _TCHAR* argv[])
{
// Initialize the COM library
CoInitializeEx(NULL, COINIT_MULTITHREADED);
// Instatiate the EasyOPC-DA client object
IEasyDAClientPtr EasyDAClientPtr(__uuidof(EasyDAClient));
// Hook the event handler
IConnectionPointContainerPtr ConnectionPointContainerPtr(EasyDAClientPtr);
IConnectionPointPtr ConnectionPointPtr;
ConnectionPointContainerPtr->FindConnectionPoint(__uuidof(DEasyDAClientEvents), &ConnectionPointPtr);
CComObject<CCoEasyDAClientEvents>* pCoEasyDAClientEvents = NULL;
CComObject<CCoEasyDAClientEvents>::CreateInstance(&pCoEasyDAClientEvents);
DEasyDAClientEventsPtr EasyDAClientEventsPtr(pCoEasyDAClientEvents);
DWORD Cookie;
ConnectionPointPtr->Advise(EasyDAClientEventsPtr, &Cookie);
// Create array of OPC item IDs
CComSafeArray<BSTR> ItemIdArray(4);
ItemIdArray[0] = _T("Simulation.Random");
ItemIdArray[1] = _T("Trends.Ramp (1 min)");
ItemIdArray[2] = _T("Trends.Sine (1 min)");
ItemIdArray[3] = _T("Simulation.Register_I4");
CComVariant vResults(EasyDAClientPtr->SubscribeMultipleItems(
/*varMachineNames:*/ _T(""),
/*varServerClasses:*/ _T("OPCLabs.KitServer.2"),
/*varItemIds:*/ CComVariant(ItemIdArray.Detach()),
/*varRequestedUpdateRates:*/ 1000));
CComSafeArray<VARIANT> ResultArray(vResults.parray);
for (int i = ResultArray.GetLowerBound(0); i <= ResultArray.GetUpperBound(0); i++)
{
IHandleResultPtr HandleResultPtr(ResultArray[i]);
// Not shown in this example: Obtain the handle of the subscribed item from HandleResultPtr.
// The handle is needed if you later wish to unsubscribe from certain items individually.
}
_tprintf(_T("Processing item changed events for 1 minute..."));
Sleep(60*1000);
// Unsubscribe from changes to all OPC items
EasyDAClientPtr->UnsubscribeAllItems();
// Release all interface pointers BEFORE calling CoUninitialize()
ResultArray.Destroy();
vResults.Clear();
EasyDAClientEventsPtr = NULL;
ConnectionPointPtr = NULL;
ConnectionPointContainerPtr = NULL;
EasyDAClientPtr = NULL;
CoUninitialize();
return 0;
}