Skip to content

Instantly share code, notes, and snippets.

@atimin
Created August 3, 2011 11:39
Show Gist options
  • Save atimin/1122431 to your computer and use it in GitHub Desktop.
Save atimin/1122431 to your computer and use it in GitHub Desktop.
Simple OPC Client
////////////////////////////////////////////////////////////////////////
// project: SimpleOPCClient
// version: 2
//
// subject: this is a simple OPC Client that read the value of an item
// from an OPC server.
//
// file: SimpleOPCClient.cpp
//
// writer: Philippe GRAS - CERN / EP
//
//http://lhcb-online.web.cern.ch/lhcb-online/ecs/opcevaluation/opcclienttutorial/SimpleClient.html
#include <atlbase.h>
#include <objbase.h>
#include <iostream>
#include "opc.h"
#include "SimpleOPCClient.h"
#include "opc_i.c"
using namespace std;
#define OPC_SERVER_NAME L"OPC.Evaluation:HV supply.1" // e.g.: L"OPC.Evaluation:HV supply.1"
#define ITEM_ID L"cr02.ch00.V0"
#define VT VT_R4
#define XVAL fltVal
//#define REMOTE_SERVER_NAME L"your_path"
//////////////////////////////////////////////////////////////////////
// Read the value of an item on an OPC server.
//
void main(void)
{
IOPCServer* pIOPCServer = NULL; //pointer to IOPServer interface
IOPCItemMgt* pIOPCItemMgt = NULL; //pointer to IOPCItemMgt interface
OPCHANDLE hServerGroup; // server handle to the group
OPCHANDLE hServerItem; // server handle to the item
// have to be done before using microsoft COM library:
CoInitialize(NULL);
// Let's instantiante the IOPCServer interface and get a pointer of it:
pIOPCServer = InstantiateServer(OPC_SERVER_NAME);
// Add the OPC group the OPC server and get an handle to the IOPCItemMgt
//interface:
AddTheGroup(pIOPCServer, pIOPCItemMgt, hServerGroup);
// Add the OPC item
AddTheItem(pIOPCItemMgt, hServerItem);
//Read the value of the item from device:
VARIANT varValue; //to stor the read value
VariantInit(&varValue);
ReadItem(pIOPCItemMgt, hServerItem, varValue);
// print the read value:
cout << "Read value: " << varValue.XVAL << endl;
// Remove the OPC item:
RemoveItem(pIOPCItemMgt, hServerItem);
// Remove the OPC group:
RemoveGroup(pIOPCServer, hServerGroup);
// release the interface references:
pIOPCItemMgt->Release();
pIOPCServer->Release();
//close the COM library:
CoUninitialize();
}
////////////////////////////////////////////////////////////////////
// Instantiate the IOPCServer interface of the OPCServer
// having the name ServerName. Return a pointer to this interface
//
IOPCServer* InstantiateServer(wchar_t ServerName[])
{
CLSID CLSID_OPCServer;
HRESULT hr;
// get the CLSID from the OPC Server Name:
hr = CLSIDFromString(ServerName, &CLSID_OPCServer);
_ASSERT(!FAILED(hr));
//queue of the class instances to create
LONG cmq = 1; // nbr of class instance to create.
MULTI_QI queue[1] =
{{&IID_IOPCServer,
NULL,
0}};
//Server info:
//COSERVERINFO CoServerInfo =
//{
// /*dwReserved1*/ 0,
// /*pwszName*/ REMOTE_SERVER_NAME,
// /*COAUTHINFO*/ NULL,
// /*dwReserved2*/ 0
//};
// create an instance of the IOPCServer
hr = CoCreateInstanceEx(CLSID_OPCServer, NULL, CLSCTX_SERVER,
/*&CoServerInfo*/NULL, cmq, queue);
_ASSERT(!hr);
// return a pointer to the IOPCServer interface:
return(IOPCServer*) queue[0].pItf;
}
/////////////////////////////////////////////////////////////////////
// Add group "Group1" to the Server whose IOPCServer interface
// is pointed by pIOPCServer.
// Returns a pointer to the IOPCItemMgt interface of the added group
// and a server opc handle to the added group.
//
void AddTheGroup(IOPCServer* pIOPCServer, IOPCItemMgt* &pIOPCItemMgt,
OPCHANDLE& hServerGroup)
{
DWORD dwUpdateRate = 0;
OPCHANDLE hClientGroup = 0;
// Add an OPC group and get a pointer to the IUnknown I/F:
HRESULT hr = pIOPCServer->AddGroup(/*szName*/ L"Group1",
/*bActive*/ FALSE,
/*dwRequestedUpdateRate*/ dwUpdateRate,
/*hClientGroup*/ hClientGroup,
/*pTimeBias*/ 0,
/*pPercentDeadband*/ 0,
/*dwLCID*/0,
/*phServerGroup*/&hServerGroup,
&dwUpdateRate,
/*riid*/ IID_IOPCItemMgt,
/*ppUnk*/ (IUnknown**) &pIOPCItemMgt);
_ASSERT(!FAILED(hr));
}
//////////////////////////////////////////////////////////////////
// Add the Item ITEM_ID to the group whose IOPCItemMgt interface
// is pointed by pIOPCItemMgt pointer. Return a server opc handle
// to the item.
void AddTheItem(IOPCItemMgt* pIOPCItemMgt, OPCHANDLE& hServerItem)
{
HRESULT hr;
// Array of items to add:
OPCITEMDEF ItemArray[1] =
{{
/*szAccessPath*/ L"",
/*szItemID*/ ITEM_ID,
/*bActive*/ FALSE,
/*hClient*/ 1,
/*dwBlobSize*/ 0,
/*pBlob*/ NULL,
/*vtRequestedDataType*/ VT,
/*wReserved*/0
}};
//Add Result:
OPCITEMRESULT* pAddResult=NULL;
HRESULT* pErrors = NULL;
// Add an Item to the previous Group:
hr = pIOPCItemMgt->AddItems(1, ItemArray, &pAddResult, &pErrors);
_ASSERT(!hr);
// Server handle for the added item:
hServerItem = pAddResult[0].hServer;
// release memory allocated by the server:
CoTaskMemFree(pAddResult->pBlob);
CoTaskMemFree(pAddResult);
pAddResult = NULL;
CoTaskMemFree(pErrors);
pErrors = NULL;
}
///////////////////////////////////////////////////////////////////////////////
// Read from device the value of the item having the "hServerItem" server
// handle and belonging to the group whose one interface is pointed by
// pGroupIUnknown. The value is put in varValue.
//
void ReadItem(IUnknown* pGroupIUnknown, OPCHANDLE hServerItem, VARIANT& varValue)
{
// value of the item:
OPCITEMSTATE* pValue = NULL;
//get a pointer to the IOPCSyncIOInterface:
IOPCSyncIO* pIOPCSyncIO;
pGroupIUnknown->QueryInterface(__uuidof(pIOPCSyncIO), (void**) &pIOPCSyncIO);
// read the item value from the device:
HRESULT* pErrors = NULL; //to store error code(s)
HRESULT hr = pIOPCSyncIO->Read(OPC_DS_DEVICE, 1, &hServerItem, &pValue, &pErrors);
_ASSERT(!hr);
_ASSERT(pValue!=NULL);
varValue = pValue[0].vDataValue;
//Release memeory allocated by the OPC server:
CoTaskMemFree(pErrors);
pErrors = NULL;
CoTaskMemFree(pValue);
pValue = NULL;
// release the reference to the IOPCSyncIO interface:
pIOPCSyncIO->Release();
}
///////////////////////////////////////////////////////////////////////////
// Remove the item whose server handle is hServerItem from the group
// whose IOPCItemMgt interface is pointed by pIOPCItemMgt
//
void RemoveItem(IOPCItemMgt* pIOPCItemMgt, OPCHANDLE hServerItem)
{
// server handle of items to remove:
OPCHANDLE hServerArray[1];
hServerArray[0] = hServerItem;
//Remove the item:
HRESULT* pErrors; // to store error code(s)
HRESULT hr = pIOPCItemMgt->RemoveItems(1, hServerArray, &pErrors);
_ASSERT(!hr);
//release memory allocated by the server:
CoTaskMemFree(pErrors);
pErrors = NULL;
}
////////////////////////////////////////////////////////////////////////
// Remove the Group whose server handle is hServerGroup from the server
// whose IOPCServer interface is pointed by pIOPCServer
//
void RemoveGroup (IOPCServer* pIOPCServer, OPCHANDLE hServerGroup)
{
// Remove the group:
HRESULT hr = pIOPCServer->RemoveGroup(hServerGroup, FALSE);
_ASSERT(!hr);
}
////////////////////////////////////////////////////////////////////////
// project: SimpleOPCClient
// version: 2
//
// subject: this is a simple OPC Client that read the value of an item
// from an OPC server.
//
// file: SimpleOPCClient.h
//
// writer: Philippe GRAS - CERN / EP
//
#ifndef SIMPLE_OPC_CLIENT_H
#define SIMPLE_OPC_CLIENT_H
IOPCServer* InstantiateServer(wchar_t ServerName[]);
void AddTheGroup(IOPCServer* pIOPCServer, IOPCItemMgt* &pIOPCItemMgt,
OPCHANDLE& hServerGroup);
void AddTheItem(IOPCItemMgt* pIOPCItemMgt, OPCHANDLE& hServerItem);
void ReadItem(IUnknown* pGroupIUnknown, OPCHANDLE hServerItem, VARIANT& varValue);
void RemoveItem(IOPCItemMgt* pIOPCItemMgt, OPCHANDLE hServerItem);
void RemoveGroup (IOPCServer* pIOPCServer, OPCHANDLE hServerGroup);
#endif // SIMPLE_OPC_CLIENT_H not defined
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment