作者: 叶帆(http://blog.csdn.net/yefanqiu) ,2005-12-2 22:01:00 发表于:《OPC论坛》 共有9人回复,792次点击 加为好友 发送留言
好像技术一沾上工业,便有了很高的价值,大家三缄其口,谁都不点破这层窗户纸,好多的思路和源码都要从国站获得,国内总是有条件,有--就是不告诉你,怕教会徒弟,饿死吧。 研究了N天,开发了一个基于我的组态后台的OPC客户端驱动,考虑到驱动的特殊性,所以只开发了同步接口操作。测试一段时间后,还可以。现把核心代码公开出来,有点VC基础的人可以直接拿来用。 源码网址:http://blog.csdn.net/yefanqiu/archive/2005/12/02/542447.aspx |
以下是对《OPC Client 核心源码(MFC)》的回复: | |
共有9人回复 分页: 1 | |
叶帆(http://blog.csdn.net/yefanqiu): | 引用 加为好友 发送留言 2005-12-2 23:15:00 |
//************************************************************************* //函 数 名:ConnectOPC //所属类名:COPCClien //输 入:CString SvrName //输 出: //功能描述:连接OPC服务器 //全局变量: //调用模块: //作 者:叶帆 //日 期:2005年12月1日 //修 改 人: //日 期: //版 本: //************************************************************************* long COPCClient::ConnectOPC(CString cSvrName) { HRESULT hr; CLSID clsid; WCHAR wszProgID [512]; //---------------------------------- //初始化COM hr =CoInitialize(NULL); if (FAILED(hr)) return 8; //com初始化失败
//----------------------------------- if(strSvrName!="") //判断是否已经连接OPC { if (strSvrName==cSvrName) return 2; //OPC服务器已经连接 else return 4; //只能连接一个OPC服务器 } //----------------------------------- try {
//---------------------------------- //把字符串形式的对象标识转化为CLSID结构形式 _mbstowcsz (wszProgID, cSvrName, sizeof (wszProgID) / sizeof (WCHAR)); hr= CLSIDFromProgID(wszProgID, // [in] &clsid); // [out] if(FAILED(hr)) { CoTaskMemFree(&clsid); //COM 内存释放函数 CoUninitialize(); //终止COM库功能服务 return 16; //获取clsid失败 }
//-------------------------------- //创建Server实例 hr=CoCreateInstance(clsid, //[in] NULL, //[in] CLSCTX_SERVER, //[in] IID_IUnknown, //[in] (void**)&pUNK); //[out] if(FAILED(hr)) { CoTaskMemFree(&clsid); if(pUNK) pUNK->Release(); pUNK=NULL; CoUninitialize(); return 32; //创建Server实例失败 }
//------------------------------------ //查询pOPC接口 hr=pUNK->QueryInterface(IID_IOPCServer,// [in] (void**)&pOPC);// [out] if(FAILED(hr)) { CoTaskMemFree(&clsid); if(pOPC) pOPC->Release(); if(pUNK) pUNK->Release(); pOPC=NULL; pUNK=NULL; return ; //查询pOPC接口失败 } CoTaskMemFree(&clsid); //--------------------------- strSvrName=cSvrName; //赋值当前OPC服务名称
} catch(...) { return 128; //连接服务器时出现严重错误 } return 0; //成功 } //************************************************************************* //函 数 名:DisconnectOPC //所属类名:COPCClient //输 入: //输 出:long //功能描述:断开OPC服务器 //全局变量: //调用模块: //作 者:叶帆 //日 期:2005年12月1日 //修 改 人: //日 期: //版 本: //************************************************************************* long COPCClient::DisconnectOPC() { if(strSvrName=="") return 1; //OPC服务器尚未连接 HRESULT *pErrors = NULL; DWORD dwCount=mIOMDevice->mItem.GetSize(),i; strSvrName=""; //服务器名称清空 //--------------- OPCHANDLE *phServer = NULL; //停止异步操作 pIAsync2->SetEnable(false);
//移除标签 phServer = (OPCHANDLE *) CoTaskMemAlloc (dwCount * sizeof (OPCHANDLE)); for(i=0;i phServer, // [in] &pErrors); // [out] arrhServer.RemoveAll(); arrhServer.FreeExtra(); arrItemType.RemoveAll(); arrItemType.FreeExtra(); //删除组 pOPC->RemoveGroup(hServer, //[in] true); //[in] //--------------- CoTaskMemFree(&hServer); CoTaskMemFree(&hGroup); if(pErrors) CoTaskMemFree(pErrors); if(pResults) CoTaskMemFree(pResults); if(pIAsync2) pIAsync2->Release(); if(pISync) pISync->Release(); if(pIItemMgt) pIItemMgt->Release(); if(pOPC) pOPC->Release(); if(pUNK) pUNK->Release(); pOPC=NULL; pUNK=NULL; pIItemMgt=NULL; pIAsync2=NULL; pISync=NULL; hGroup=0; hServer=0; CoUninitialize(); //关闭COM return 0; } //************************************************************************* //函 数 名:AddGroup //所属类名:COPCClient //输 入: //输 出:long //功能描述:添加组 //全局变量: //调用模块: //作 者:叶帆 //日 期:2005年12月1日 //修 改 人: //日 期: //版 本: //************************************************************************* long COPCClient::AddGroup() { HRESULT hr; WCHAR wchBuffer[255]; long lBias=0; float fDeadband=0; DWORD dwRevUpdateRate=0; IUnknown *pUNKgroup; //组接口指针 MultiByteToWideChar(CP_ACP, 0, mIOMDevice->ConfigMessage, -1, wchBuffer, 255); //添加组 hr = pOPC->AddGroup ( wchBuffer, // [in] group name TRUE, // [in] active state mIOMDevice->Scantime, // [in] requested update rate hGroup, // [in] our handle to this group &lBias, // [unique,in] time bias &fDeadband, // [in] percent deadband 1033, // [in] requested language ID &hServer, // [out] server handle to this group &dwRevUpdateRate, // [out] revised update rate IID_IUnknown, // [in] REFIID riid, (LPUNKNOWN*)&pUNKgroup); // [out, iid_is(riid)] LPUNKNOWN *pUNKgroup if(FAILED(hr)) //加入组失败 { CoTaskMemFree(&hServer); CoTaskMemFree(&dwRevUpdateRate); if(pUNKgroup) pUNKgroup->Release(); pUNKgroup=NULL; return 1; } //-------------------------------------- //查询pIItemMgt hr=pUNKgroup->QueryInterface(IID_IOPCItemMgt, // [in] (void**)&pIItemMgt); // [out] //查询失败 if(FAILED(hr)) { CoTaskMemFree(&hServer); CoTaskMemFree(&dwRevUpdateRate); if(pUNKgroup) pUNKgroup->Release(); pUNKgroup=NULL; if(pIItemMgt) pIItemMgt->Release(); pIItemMgt=NULL; return 2; } if(pUNKgroup) pUNKgroup->Release(); pUNKgroup=NULL; CoTaskMemFree(&dwRevUpdateRate); return 0; } //************************************************************************* //函 数 名:AddItem //所属类名:COPCClient //输 入: //输 出:long //功能描述:加入项 //全局变量: //调用模块: //作 者:叶帆 //日 期:2005年12月1日 //修 改 人: //日 期: //版 本: //************************************************************************* long COPCClient::AddItem() { HRESULT hr; OPCITEMDEF *pItemArray = NULL; HRESULT *pErrors = NULL; DWORD dwCount,dwLen,i; //-------------------------------------- //添加标签 dwCount=mIOMDevice->mItem.GetSize(); pItemArray = (OPCITEMDEF *) CoTaskMemAlloc (dwCount * sizeof (OPCITEMDEF)); //分配内存 for(i=0;i dwLen = lstrlen (mIOMDevice->mItem[i].strTab); pItemArray [i].szItemID = (WCHAR *) CoTaskMemAlloc ((dwLen + 1) * sizeof (WCHAR)); MultiByteToWideChar (CP_ACP, 0, mIOMDevice->mItem[i].strTab, -1, pItemArray [i].szItemID, dwLen + 1); pItemArray [i].szAccessPath=NULL; pItemArray [i].bActive = true; // active state pItemArray [i].hClient = (OPCHANDLE)i; // our handle to item pItemArray [i].dwBlobSize = 0; // no blob support pItemArray [i].pBlob = NULL; pItemArray [i].vtRequestedDataType =VT_EMPTY; // Requested data type pItemArray [i].wReserved=0; } //添加 hr = pIItemMgt->AddItems (dwCount, //[in] DWORD dwCount,Item count pItemArray, //[in, size_is(dwCount)] OPCITEMDEF * pItemArray, Array of item definition structures &pResults, //[out, size_is(,dwCount)] OPCITEMRESULT ** ppAddResults, Result array &pErrors); //[out, size_is(,dwCount)] HRESULT ** ppErrors Error array //添加失败 if(FAILED(hr)) { if(pResults) CoTaskMemFree(pResults); if(pErrors) CoTaskMemFree(pErrors); CoTaskMemFree(&hServer); CoTaskMemFree(pItemArray); return 2; } //同步接口 hr=pIItemMgt->QueryInterface(IID_IOPCSyncIO, // [in] (void**)&pISync); // [out] if(FAILED (hr)) { CoTaskMemFree(&hServer); if(pISync) pISync->Release(); if(pResults) CoTaskMemFree(pResults); if(pErrors) CoTaskMemFree(pErrors); pISync=NULL; return 3; //查询pISync接口失败 } //异步接口 hr=pIItemMgt->QueryInterface(IID_IOPCAsyncIO2,(void**)&pIAsync2); if(FAILED (hr)) { CoTaskMemFree(&hServer); if(pIAsync2) pIAsync2->Release(); if(pResults) CoTaskMemFree(pResults); if(pErrors) CoTaskMemFree(pErrors); pIAsync2=NULL; return 4; //查询pIAsync2接口失败 } //--------------------- arrhServer.SetSize(dwCount); arrItemType.SetSize(dwCount); for(i=0;i arrhServer.SetAt(i,pResults[i].hServer ); arrItemType.SetAt(i,(WORD)pResults[i].vtCanonicalDataType); } //--------------------- if(pErrors) CoTaskMemFree(pErrors); CoTaskMemFree(pItemArray); return 0; } //************************************************************************* //函 数 名:SyncRead //所属类名:COPCClient //输 入:long lngNo, // CString strData //输 出:long //功能描述:同步读取数据 //全局变量: //调用模块: //作 者:叶帆 //日 期:2005年12月1日 //修 改 人: //日 期: //版 本: //************************************************************************* long COPCClient::SyncRead(long lngNo,CString &strData) { HRESULT hr = E_FAIL; DWORD dwCount=1; OPCDATASOURCE dwSource = OPC_DS_CACHE; OPCHANDLE *phServer = NULL; OPCITEMSTATE *pValues = NULL; HRESULT *pErrors = NULL; ::Sleep(0); try { phServer = (OPCHANDLE *) CoTaskMemAlloc (dwCount * sizeof (OPCHANDLE)); if (phServer == NULL) { return 1; //分配内存时出错 } phServer[0] =(OPCHANDLE)arrhServer.GetAt(lngNo); hr=pISync->Read(dwSource, //[in] dwCount, //[in] phServer, //[in] &pValues, //[out] &pErrors); //[out] if(FAILED(hr)) { if (phServer) CoTaskMemFree (phServer); if (pValues) CoTaskMemFree (pValues); if (pErrors) CoTaskMemFree (pErrors); VariantClear (&pValues[0].vDataValue); return 2; //同步读数据时出错 } //数据转换 Variant2Str(pValues[0].vDataValue,strData); VariantClear (&pValues[0].vDataValue); if (phServer) CoTaskMemFree (phServer); if (pValues) CoTaskMemFree (pValues); if (pErrors) CoTaskMemFree (pErrors); } catch (...) { return 3; } return 0; } //************************************************************************* //函 数 名:SyncWrite //所属类名:COPCClient //输 入:long lngNo, // CString &strData //输 出:long //功能描述:同步写 //全局变量: //调用模块: //作 者:叶帆 //日 期:2005年12月1日 //修 改 人: //日 期: //版 本: //************************************************************************* long COPCClient::SyncWrite(long lngNo,CString strData) { DWORD dwIndex = 0; OPCHANDLE *phServer = NULL; VARIANT *pValues = NULL; HRESULT *pErrors = NULL; HRESULT hr = E_FAIL; DWORD cdwItems=1; phServer = (OPCHANDLE *) CoTaskMemAlloc (cdwItems * sizeof (OPCHANDLE)); pValues = (VARIANT *) CoTaskMemAlloc (cdwItems * sizeof (VARIANT)); if (phServer == NULL || pValues == NULL) { return 1; } ::Sleep(0); try { //同步写数据 phServer[0] =(OPCHANDLE)arrhServer.GetAt(lngNo); //数据转换 Str2Variant(strData,pValues[0],arrItemType.GetAt(lngNo)); hr = pISync->Write ( 1, // Item count phServer, // Array of server handles for items pValues, // Array of values &pErrors); // Array of errors if(FAILED(hr)) { if (phServer) CoTaskMemFree (phServer); if (pValues) CoTaskMemFree (pValues); if (pErrors) CoTaskMemFree (pErrors); VariantClear (&pValues[0]); return 2; //同步读数据时出错 } VariantClear (&pValues[0]); } catch (...) { return 3; } if(phServer)CoTaskMemFree (phServer); if (pValues)CoTaskMemFree (pValues); if (pErrors) CoTaskMemFree (pErrors); return 0; } |