//////////////////////////////////////////////////////////////////////// // 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 // #include #include #include #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); }