1.What is OPC? OPC 是 OLE for Process Control 的縮寫。顧名思義,OPC 是一種利用微軟的 COM/DCOM 技術來達成自動化控制的協定,根據 OPC Specification 的定義,OPC is "a standard mechanism for communicating to numerous data sources, either devices on the factory floor, or a database in a control room." 在現今的工業自動化中,我們需 要一套整合的資訊系統,由底層的各項裝置擷取資訊 (Field Management),中層的控制系統或圖控應用程式進行程序的控制 (Process Management),再由最上層的整合軟體將這些資訊整合起來以供企業決策或效能提昇,如下圖所示: OPC 為硬體製造商與軟體發展商提供了一條橋樑,透過硬體廠商提供的 OPC Server 介面,軟體發展者不必考慮各項不同硬體間的差異,便可自硬體端取得所需的資訊,所以軟體發展者僅需專注於程式本身的控制流程的運作。此外,由於 COM/DCOM 實作並隱藏了網路的細節,透過 OPC 可以很容易地達成遠端控制的理想。 2.How does OPC work? 在說明 OPC Server/Client 運作方式之前,我們先簡單介紹一下 Microsoft 發展的 COM/DCOM 是什麼? COM 是一種發展軟體元件的方法,所謂的軟體元件,是指一個可以提供應用程式、作業系統、以及其他元件服務的二進位可執行程式。事實上,發展自訂的 COM 物件就好像是在建構一套可以動態執行的物件導向 API 一般。你可以在應用程式執行的時期隨意拼上或移除所需要的元件。依據 COM 這樣的概念,發展應用程式就像是堆積木一樣,每一個 COM 元件就是一塊積木,你可以利用各式各樣不同的積木,拼湊出你所需要的應用程式。 在實作上,COM 透過一組一組的介面 (Interface) 提供服務,所有 COM 元件的使用者,都必須透過這些 Interface 來使用元件提供的功能。OPC 的規格中便定義了許多 OPC Server 應該提供的 Interface,要撰寫一個 OPC Server 的 COM 元件,你必須在你的元件中加入這些介面,並提供它們的實作,Client 便可以透過這些介面,操作連接到 OPC Server 的硬體裝置,這也就是 OPC Server/Client 運作的方式。以下的圖示可以讓這樣的概念更清晰: 3. OPC Server 架構 如前面所述,OPC Server 透過一組一組的介面提供服務,不過在實作的架構上,OPC Server 共分為三層:分別是 OPCServer, OPCGroup, OPCItem。 其中每一個 OPCItem 對應到一個實際的硬體裝置上的某一個 channel 或 port;每一個 OPCGroup 則包含了許多的 OPCItem,同時並定義這些 OPCItem 更新的時間、方式,以及提供讀取 OPCItem 值的介面;而每一個 OPCServer 則包含若干個 OPCGroup,同時提供操作這些 OPCGroup 的介面。 下圖可以較清楚地說明 OPCServer/OPCGroup/OPCItem 間的關係: 4. OPC Custom Interface 接下來的這一節,我們將討論 OPC Serve 的重點,也就是每一組介面的定義,以及它所提供的功能。 OPCServer 提供的介面 IOPCCommon
HRESULT |
SetLocaleID ( dwLcid ) 設定位置資訊 |
|
HRESULT |
GetLocaleID ( pdwLcid ) 取得位置資訊 |
|
HRESULT |
QueryAvailableLocaleIDs ( pdwCount, pdwLcid ) 查詢可用的位置ID |
|
HRESULT |
GetErrorString ( dwError, ppString) 取得錯誤資訊字串 |
|
HRESULT |
SetClientName (szName) 設定 Clinet 的名稱 |
|
IOPCServer
HRESULT |
AddGroup(szName, bActive, dwRequestedUpdateRate, hClientGroup, pTimeBias, pPercentDeadband, dwLCID, phServerGroup, pRevisedUpdateRate, riid, ppUnk) 新增一個 OPCGroup |
|
HRESULT |
GetErrorString(dwError, dwLocale, ppString) 取得錯誤資訊字串 |
|
HRESULT |
GetGroupByName(szName, riid, ppUnk) 依據名稱取得 OPCGroup 的介面 |
|
HRESULT |
GetStatus(ppServerStatus) 取得 OPCServer 的狀態資訊 |
|
HRESULT |
RemoveGroup(hServerGroup, bForce) 移除一個 OPCGroup |
|
HRESULT |
CreateGroupEnumerator(dwScope, riid, ppUnk) 產生一個 OPCGroup 列舉器 |
|
IConnectionPointContainer
HRESULT |
EnumConnectionPoints( IEnumConnectionPoints ppEnum) 列舉所有的 Connection Points |
|
HRESULT |
FindConnectionPoint( REFIID riid, IConnectionPoint ppCP) 找出一個 Connection Point |
|
IOPCItemProperties
HRESULT |
QueryAvailableProperties(szItemID, pdwCount,ppPropertyIDs, ppDescriptions, ppvtDataTypes ); 查詢可用的 OPCItem 屬性 |
|
HRESULT |
GetItemProperties (szItemID, dwCount, pdwPropertyIDs,ppvData, ppErrors ) 取得 OPCItem 的屬性 |
|
HRESULT |
LookupItemIDs( szItemID, dwCount, pdwPropertyIDs,ppszNewItemIDs, ppErrors ) 使用名稱查詢 OPCItem 的 ID |
|
IOPCBrowseServerAddressSpace (optional)
HRESULT |
QueryOrganization(pNameSpaceType ) 查詢組織名稱 |
|
HRESULT |
ChangeBrowsePosition(dwBrowseDirection, szString ) 變更瀏覽的位置 |
|
HRESULT |
BrowseOPCItemIDs( dwBrowseFilterType, szFilterCriteria, vtDataTypeFilter, dwAccessRightsFilter, ppIEnumString ) 瀏覽 OPCServer 內所有定義的 OPCItem |
|
HRESULT |
GetItemID( szItemDataID, szItemID ) 取得 OPCItem 的 ID |
|
HRESULT |
BrowseAccessPaths( szItemID, ppIEnumString ) 瀏覽存取 OPCItem 的路徑 |
|
OPCGroup Object 提供的介面 IOPCGroupStateMgt
HRESULT |
GetState(pUpdateRate, pActive, ppName, pTimeBias, pPercentDeadband, pLCID, phClientGroup, phServerGroup) 取得 OPCGroup 的狀態即設定資訊 |
|
HRESULT |
SetState(pRequestedUpdateRate, pRevisedUpdateRate, pActive, pTimeBias, pPercentDeadband, pLCID, phClientGroup) 設定 OPCGroup 的狀態資訊 |
|
HRESULT |
SetName(szName) 設定 OPCGroup 的名稱 |
|
HRESULT |
CloneGroup(szName, riid, ppUnk) 複製一個 OPCGroup |
|
IOPCSyncIO
HRESULT |
Read(dwSource, dwCount, phServer, ppItemValues, ppErrors); 以同步方式讀取 OPCGroup 內的 OPCItem(s) 的值 |
|
HRESULT |
GetItemProperties (szItemID, dwCount, pdwPropertyIDs,ppvData, ppErrors ) 取得 OPCItem 的屬性 |
|
HRESULT |
Write(dwCount, phServer, pItemValues, ppErrors) 以同步方式將值寫入OPCGroup 內的 OPCItem(s) |
|
IOPCAsyncIO2
HRESULT |
Read(dwCount, phServer, dwTransactionID, pdwCancelID, ppErrors,) 以非同步方式讀取 OPCGroup 內的 OPCItem(s) 的值,值會在讀取硬體的動作結束後以 callback 的形式傳回 |
|
HRESULT |
SetState(pRequestedUpdateRate, pRevisedUpdateRate, pActive, pTimeBias, pPercentDeadband, pLCID, phClientGroup) 設定 OPCGroup 的狀態資訊 |
|
HRESULT |
Write(dwCount, phServer, pItemValues, dwTransactionID, pdwCancelID, ppErrors) 以非同步方式將值寫入OPCGroup 內的 OPCItem(s) |
|
HRESULT |
Cancel2 (dwCancelID) 取消前一次的非同步讀取/寫入 |
HRESULT |
Refresh2(dwSource, dwTransactionID, pdwCancelID) 更新 OPCGroup 內 OPCItem(s) 的值 |
|
HRESULT |
SetEnable(bEnable) 將 OPCGroup 設為 Enable |
|
HRESULT |
GetEnable(pbEnable) 傳回 OPCGroup 是否為 Enable |
|
IOPCItemMgt
HRESULT |
AddItems(dwCount, pItemArray, ppAddResults, ppErrors); 在 OPCGroup 內新增 OPCItem(s) |
|
HRESULT |
ValidateItems(dwCount, pItemArray, bBlobUpdate, ppValidationResults, ppErrors) 檢查 OPCItem(s) 的名稱是否可用 |
|
HRESULT |
RemoveItems(dwCount, phServer, ppErrors) 移除 OPCGroup 內的 OPCItem(s) |
|
HRESULT |
SetActiveState(dwCount, phServer, bActive, ppErrors) 設定 OPCItem(s) 是否為 Avtive |
|
HRESULT |
SetClientHandles(dwCount, phServer, phClient, ppErrors) 設定 OPCItem(s) 的 handle |
|
HRESULT |
SetDatatypes(dwCount, phServer, pRequestedDatatypes, ppErrors) 設定 OPCItem(s) 的資料型別 |
|
HRESULT |
CreateEnumerator(riid, ppUnk) 產生 OPCItems 的列舉器 |
|
|
IConnectionPointContainer
HRESULT |
EnumConnectionPoints( IEnumConnectionPoints ppEnum) 列舉所有的 Connection Points |
|
HRESULT |
FindConnectionPoint( REFIID riid, IConnectionPoint ppCP) 找出一個 Connection Point |
|
5. 結論 OPC Server/Client 是一套利用微軟的 COM/DCOM 技術達成工業自動化資料取得的架構。OPC Server 提供了許多的介面,Client 端透過這些介面,可以取得與 OPC Server 相連的硬體裝置的資訊,而無須瞭解這些硬體裝置的細節資訊。也就是說,程式設計者可以使用相同的程式碼,操作不同的硬體裝置,充分達成 software reuse 的理想。同時,由於 COM/DCOM 已實作了網路部分的細節,也使得 Client 對 OPC Server 進行遠端存取非常容易,使程式設計者很容易地達成遠端控制的目標。 |