首先我們先來看一下什么是OPCOPC (OLE for Process Control——用于過程控制的OLE)是基于Microsoft公司的DNA(Distributed Internet Application)構(gòu)架和COM(Component Object Model)技術(shù)的一個工業(yè)標準接口,是根據(jù)易于擴展性而設(shè)計的。 再來了解一下OPC的用途 OPC主要適用于過程控制和制造自動化等應(yīng)用領(lǐng)域。 OPC是以OLE/COM機制作為應(yīng)用程序的通訊標準。OLE/COM是一種客戶/服務(wù)器模式,具有語言無關(guān)性、代碼重用性、易于集成性等優(yōu)點。OPC規(guī)范了接口函數(shù),不管現(xiàn)場設(shè)備以何種形式存在,客戶都以統(tǒng)一的方式去訪問,從而保證軟件對客戶的透明性,使得用戶完全從低層的開發(fā)中脫離出來 然后我們再來看看OPC Server的組成一個設(shè)備的OPC Server主要有兩部組成,一是OPC標準接口的實現(xiàn);二是與硬件設(shè)備的通信模塊。 實現(xiàn)OPC 標準接口[圖1] 在這些接口中,IOPCServer 是OPC Server的主接口,通過它實現(xiàn)OPC Server在操作系統(tǒng)中的安裝和注冊。此接口是必須要實現(xiàn)的,其所有方法也必須實現(xiàn)。其它的接口都是可選的我們就不做介紹了,下面主要來介紹如何實現(xiàn)IOPCServer接口。 在IOPCServer接口中共有六個法: 1、 IOPCServer::AddGroup HRESULT AddGroup( [in, string] LPCWSTR szName, [in] BOOL bActive, [in] DWORD dwRequestedUpdateRate, [in] OPCHANDLE hClientGroup, [unique, in] LONG *pTimeBias, [in] FLOAT * pPercentDeadband, [in] DWORD dwLCID, [out] OPCHANDLE * phServerGroup, [out] DWORD *pRevisedUpdateRate, [in] REFIID riid, [out, iid_is(riid)] LPUNKNOWN * ppUnk ); 此方法是在OPC Server上建立一個組。下在我們來實現(xiàn)這個方法: …. …. 首先要對組名(szName)進行檢查,看是否有效或是否已經(jīng)有這個組。 if (szName != NULL) { RequestedName = szName; if (RequestedName == "") RequestedName = pSvrObject->DefaultGroupName(); } else RequestedName = pSvrObject->DefaultGroupName();
for (i=0; i<pSvrObject->NumbrGroups(); i++) { pGroup = pSvrObject->GetGroup(i); if (RequestedName == pGroup->Name) return (OPC_E_DUPLICATENAME); } 這需要在內(nèi)存中維護OPC Group(組)的列表(還要有OPC 項的列表)。 如果szName(組名)正確并且沒有建立過該組,就開始根據(jù)傳過來的參數(shù)進行組的建立,建立好后將該組加到自己的組列表中以備后用。 最后將新建組的接口指針返回給客戶端。
2、IOPCServer::GetErrorString HRESULT GetErrorString( [in] HRESULT dwError, [in] LCID dwLocale, [out, string] LPWSTR *ppString ); 為Server的錯誤代碼返回相應(yīng)的錯誤字符串。 代碼略 3、 IOPCServer::GetGroupByName HRESULT GetGroupByName( [in, string] LPCWSTR szName, [in] REFIID riid, [out, iid_is(riid)] LPUNKNOWN * ppUnk ); 通過指定的組名(由同一客戶端建立的)找到該組的接口指針。 此方法實現(xiàn)比較簡單,只要根據(jù)提供的名子循環(huán)從組列表中找到該組的接口指針,并返回給客戶端 HRESULT GetStatus( [out] OPCSERVERSTATUS ** ppServerStatus ); 返回當前Server的狀態(tài)信息。 此方法比較簡單,但要注意的是在使用OPCSERVERSTAUS前要進行內(nèi)存分配。 HRESULT RemoveGroup( [in] OPCHANDLE hServerGroup, [in] BOOL bForce ); 從服務(wù)器中刪除指定組 在組列表中找到指定的組,并將其刪除。 6、 IOPCServer::CreateGroupEnumerator HRESULT CreateGroupEnumerator( [in] OPCENUMSCOPE dwScope, [in] REFIID riid, [out, iid_is(riid)] LPUNKNOWN* ppUnk ); 為Server上所提供的組建立不同的列舉器。 上面是直接使用COM技術(shù)進行開發(fā)的,這要求你必須熟悉COM技術(shù)。如果你對COM不是很了解那也沒關(guān)系,可以選擇OPC Server的開發(fā)工具,你只需要簡單的調(diào)用開發(fā)工具的函數(shù)就可以實現(xiàn)OPC Server中的所有接口。 我們雖然實現(xiàn)了IOPCServer接口中的所有方法,但它只是OPC Client與我們通信的一個橋梁,最主要的還是我們要自己維護好OPC Group和OPC Item列表。這樣我們才可以跟OPC Client進行真正的數(shù)據(jù)通信。 與硬件設(shè)備進行通信接口已經(jīng)實現(xiàn)好了,這回我們該從硬件設(shè)備中讀取數(shù)據(jù)提供給OPC Client了。 同硬件設(shè)備通信有多種方法,如果你是設(shè)備的制造商就可以直對硬件進行數(shù)據(jù)操作了;你也可以通過設(shè)備驅(qū)動程序和硬件廠商提供的API或是通過TCP、串口等方法進行操作,這就要看硬件設(shè)備提供的與軟件通信的接口是什么樣的了。 不管你用什么方法只要把數(shù)據(jù)從硬件設(shè)備中讀取上來并與OPC 項進行關(guān)聯(lián),就可以實現(xiàn)OPC Server了。 下面我們?yōu)榍迦A同方的RH2000系統(tǒng)來做一個OPC Server(如圖2)。 [圖2] 因為RH2000系統(tǒng)由一個叫易視的軟件系統(tǒng)進行調(diào)控的,它下面控制多種下位機(硬件設(shè)備)。我們只需要與易視進行通信就可以實現(xiàn)對硬件設(shè)備的操作(易視提供了TCP/IP通信方式)。首先與易視建立好Socket連接,然后發(fā)送控制命令讀取與易視相連的硬件設(shè)備的信息(也就是設(shè)備點信息)。我們根據(jù)讀取到的不同的設(shè)備點相應(yīng)的建立OPC項,這樣OPC Client只要讀取到OPC 項就可以讀取到設(shè)備信息。如果OPC Client對OPC 項進行修改,我們收到OPC項的變化就向易視發(fā)送相應(yīng)命令對設(shè)備進行操作,這樣就實現(xiàn)了OPC Client對硬件設(shè)備的操控了。 結(jié)束語雖然使用開發(fā)工具也可以開發(fā)OPC Server,但還是希望大家能多了解COM技術(shù),這樣對OPC Server的擴展和維護都有好處。并多到OPC基金會的官方網(wǎng)站上去了解OPC的最新知識和下載相關(guān)資料,網(wǎng)址是 http://www.。 由于時間和作者水平的限制,難免有錯誤和不妥之處,敬請大家批評和指正。我的郵件是 yanghongtao@thtf.com.cn。最后感謝清華同限份有限公司的 |
|