研究C程序與基于COM的OPC數(shù)據(jù)存取服務(wù)器交換數(shù)據(jù)_第1頁
研究C程序與基于COM的OPC數(shù)據(jù)存取服務(wù)器交換數(shù)據(jù)_第2頁
研究C程序與基于COM的OPC數(shù)據(jù)存取服務(wù)器交換數(shù)據(jù)_第3頁
研究C程序與基于COM的OPC數(shù)據(jù)存取服務(wù)器交換數(shù)據(jù)_第4頁
研究C程序與基于COM的OPC數(shù)據(jù)存取服務(wù)器交換數(shù)據(jù)_第5頁
已閱讀5頁,還剩1頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、研究C#程序與基于COM的OPC數(shù)據(jù)存取服務(wù)器交換數(shù)據(jù)何海江(湖南經(jīng)濟(jì)管理干部學(xué)院計(jì)算機(jī)系 ,湖南長沙 410004)摘要:研究了OPC NET COM自動(dòng)化包裝器所封裝的COM編排技術(shù)和OPC NET應(yīng)用程序接口內(nèi)的設(shè)計(jì)模式。在其基礎(chǔ)上使用C#語言編寫了一個(gè)基于.NET的OPC客戶程序,與基于COM的OPC數(shù)據(jù)存取服務(wù)器交換數(shù)據(jù)。有效地實(shí)現(xiàn)了將遵循OPC規(guī)范的代碼從COM平臺(tái)移植到.NET平臺(tái)。關(guān)鍵詞:C#;COM編排;數(shù)據(jù)存取服務(wù)器;設(shè)計(jì)模式 Study C# program to exchange data with COM based OPC data access serverHe

2、Hai-jiang ( Department of Computer Science of Hunan Economic Management College ,Hunan Changsha 410004 )Abstract: The marshal technique from OPC NET COM Wrapper and design patterns from OPC NET API are researched. An OPC client software based on .NET is built on the basis of these technique with C#

3、language,it is employeed to exchange data with OPC data access server based on COM.It is effectively realized to migrate the code following OPC specifications from COM plantform to .NET plantform.Key Words: C#;COM marshal;data access server;design pattern C#是微軟為.NET平臺(tái)量身訂作的新程序語言,特別適合組件的開發(fā),當(dāng)前軟件工業(yè)中許多產(chǎn)品

4、的新版本逐步轉(zhuǎn)移到的.NET平臺(tái)。OPC是工業(yè)軟件中廣泛采用的數(shù)據(jù)交換協(xié)議,許多數(shù)據(jù)采集設(shè)備都要求提供實(shí)現(xiàn)OPC數(shù)據(jù)存取規(guī)范的服務(wù)器,和上層軟件交換數(shù)據(jù)。因此研究在C#中實(shí)現(xiàn)OPC有很大的現(xiàn)實(shí)意義。COM和.NET是兩個(gè)差別很大的分布式應(yīng)用軟件開發(fā)平臺(tái),如果要在.NET 應(yīng)用中使用COM對象,需要通過RCW(runtime-callable wrapper, 運(yùn)行環(huán)境可調(diào)用包裝器)在可管理的.NET代碼和未托管的COM代碼之間生成一個(gè)代理。Visual Studio.NET提供了一個(gè)工具類型庫導(dǎo)入器TlbImp.exe,可以方便地提取COM程序的信息。實(shí)現(xiàn)了自動(dòng)化接口的OPC服務(wù)器可以使用這種

5、方法。但大多數(shù)的OPC服務(wù)器只實(shí)現(xiàn)定制接口,該方法無法實(shí)現(xiàn),需要手工編排COM中的IDL(Interface Definition Language,接口定義語言),工作量非常大。編排過程中會(huì)遇到包括數(shù)據(jù)類型轉(zhuǎn)換、接口實(shí)現(xiàn)、參數(shù)傳遞等許多問題的困擾,自動(dòng)化軟件要求高可靠性,要編寫這樣的軟件,軟件測試和維護(hù)的工作量很大。現(xiàn)在OPC基金會(huì)對會(huì)員提供了OpcRcw動(dòng)態(tài)鏈接庫,OPC NET COM 包裝器和OPC NET API,前兩者完成了前述的工作,后者將OPC復(fù)雜的規(guī)范封狀成簡單易用的C#類。本文分析了這些組件的核心代碼,在此兩種技術(shù)的基礎(chǔ)上,建立一個(gè).NET框架的OPC客戶軟件,與基于COM

6、的OPC數(shù)據(jù)存取服務(wù)器交換數(shù)據(jù)。文中提供一個(gè)應(yīng)用實(shí)例,代碼全部使用C#實(shí)現(xiàn),分五個(gè)步驟說明。1 組件核心內(nèi)容OPC基金會(huì)提供的這些組件,包括源代碼和部分文檔,但文檔部分比較簡單,在軟件設(shè)計(jì)過程中,大量使用了抽象工廠模式和策略設(shè)計(jì)模式。要理解這些設(shè)計(jì)模式,需要閱讀這方面的書籍,設(shè)計(jì)模式經(jīng)典書為Erich Gamma 等四人所著Design Patterns Elements of Reusable Software 。文章將OPC客戶端的典型應(yīng)用逐一列出,讀者理解文章內(nèi)容后,無需花費(fèi)大量時(shí)間去讀懂OPC基金會(huì)的這些代碼,就比較容易編寫相應(yīng)的程序。應(yīng)用程序Opc.IFactoryOpc.IServ

7、erOpc. FactoryOpc.ServerOpcDa.IServerOpcXml. FactoryOpcCom.FactoryFactoryFactoryOpcDa.Server 圖一 Server和Factory的UML描述圖組件內(nèi)實(shí)現(xiàn)了各種類型,各種規(guī)范的OPC服務(wù)器。如圖一所示,采用抽象工廠模式,通過使用接口IFactory和IServer增加了代碼的可重用性。命名空間Opc下包括:接口IServer為所有OPC服務(wù)提供公共功能;接口IFactory為OPC服務(wù)實(shí)例化提供公共功能;IDiscovery搜索網(wǎng)絡(luò)中計(jì)算機(jī)上已安裝的OPC服務(wù)器;類Server,實(shí)現(xiàn)接口IServer,所

8、有OPC服務(wù)的基礎(chǔ)類;類Factory,實(shí)現(xiàn)接口IFactory,所有實(shí)例化工廠的基礎(chǔ)類;還有類ItemIdentifier、Type等。命名空間Opc.Da下包括:接口IServer,為所有數(shù)據(jù)存取服務(wù)提供公共功能;接口ISubscription,對數(shù)據(jù)存取服務(wù)器的訂閱,包含一系列項(xiàng),相當(dāng)于規(guī)范中的組;類Item,實(shí)現(xiàn)一個(gè)項(xiàng)的功能;類Server,實(shí)現(xiàn)本命名空間下的接口IServer,并繼承自O(shè)pc下的類Server,提供所有的數(shù)據(jù)存取服務(wù)功能;還有類Subscription、Property等。命名空間OpcCom下包括:類Factory, 實(shí)例化基于COM的OPC服務(wù);還有類Intero

9、p等。命名空間OpcCom.Da20下包括:類Server,實(shí)現(xiàn)基于COM的OPC數(shù)據(jù)存取服務(wù),類Subscription實(shí)現(xiàn)2.0版本服務(wù)器的訂閱功能。2服務(wù)器的枚舉和連接using Opc;using Opc.Da;using OpcCom; 下面的代碼用來瀏覽某臺(tái)計(jì)算機(jī)上已安裝的數(shù)據(jù)存取規(guī)范服務(wù)器。private Opc.IDiscovery m_discovery = new OpcCom.ServerEnumerator();/定義枚舉基于COM服務(wù)器的接口,用來搜索所有的此類服務(wù)器。Opc.Server servers = m_discovery.GetAvailableServe

10、rs(daver, host, null);/daver表示數(shù)據(jù)存取規(guī)范版本,Specification.COMDA_20等于2.0版本。 /host為計(jì)算機(jī)名,null表示不需要任何網(wǎng)絡(luò)安全認(rèn)證。if (servers != null) /server即為需要連接的OPC數(shù)據(jù)存取服務(wù)器。圖二 添加兩個(gè)組件的引用下面的代碼建立與某服務(wù)器的連接。/定義數(shù)據(jù)存取服務(wù)器/從前文瀏覽到的某一個(gè)OPC數(shù)據(jù)存取服務(wù)器賦給m_server。trym_server.Connect();/建立連接。 catch (Exception f)/捕獲錯(cuò)誤,提高軟件的健壯性。MessageBox.Show(f.Mess

11、age);3 增加、刪除組和項(xiàng)OPC NET API使用類Subscription來封裝組的操作,下面的代碼第一段增加一個(gè)組,第二段刪除一個(gè)組。/定義一個(gè)對服務(wù)器的訂閱者/訂閱者狀態(tài),相當(dāng)于OPC規(guī)范中組的參數(shù),為方便說明,后段用組代替訂閱者。state.Name = 儀表;/組名state.ServerHandle = null;/服務(wù)器給該組分配的句柄。state.ClientHandle = Guid.NewGuid().ToString();/客戶端給該組分配的句柄。state.Active = true;/激活該組。state.UpdateRate = 1000;/刷新頻率為1秒。s

12、tate.Deadband = 0;/ 死區(qū)值,設(shè)為0時(shí),服務(wù)器端該組內(nèi)任何數(shù)據(jù)變化都通知組。state.Locale = null;/不設(shè)置地區(qū)值。/創(chuàng)建組subscription.DataChanged += new DataChangedCallback(m_opcListView.OnDataChange); /注冊事件,一旦服務(wù)器端數(shù)據(jù)有變化,自動(dòng)觸發(fā)。此處使用了C#的事件處理機(jī)制,筆者編寫模塊m_opcListView.OnDataChange,讀該組的數(shù)據(jù),后文中有該模塊的代碼。刪除一個(gè)組Subscription subscription = (Subscription)curr

13、ent.Tag;/應(yīng)該刪除哪一個(gè)組。current為TreeView控件的一個(gè)節(jié)點(diǎn)Node,前文創(chuàng)建的組對象保留在current.Tag中。m_server.CancelSubscription(subscription);/m_server前文已說明,通知服務(wù)器要求刪除組。subscription.Dispose();/強(qiáng)制.NET資源回收站回收該subscription的所有資源。類Item數(shù)據(jù)項(xiàng)對象,是OPC的數(shù)據(jù)單元,一個(gè)組內(nèi)允許定義多個(gè)數(shù)據(jù)項(xiàng),可讀可寫,每個(gè)數(shù)據(jù)項(xiàng)有值(Value)、品質(zhì)(Quality)、時(shí)間戳(TimeStamp)等屬性。下面的代碼第一段增加一個(gè)項(xiàng),第二段刪除一個(gè)

14、項(xiàng)。Item items = new Item1;/本次操作只添加一個(gè)數(shù)據(jù)項(xiàng)。items0 = new Item();/創(chuàng)建一個(gè)項(xiàng)Item對象。items0.ClientHandle = Guid.NewGuid().ToString();/客戶端給該數(shù)據(jù)項(xiàng)分配的句柄。items0.ItemPath = path; /該數(shù)據(jù)項(xiàng)在服務(wù)器中的路徑。items0.ItemName = name; /該數(shù)據(jù)項(xiàng)在服務(wù)器中的名字。Subscription subscription = (Subscription)current.Tag; /在哪一個(gè)組中添加數(shù)據(jù)項(xiàng)。current為TreeView控件的一個(gè)

15、節(jié)點(diǎn)Node,前文創(chuàng)建的組對象保留在current.Tag中。subscription.AddItems(items);刪除一個(gè)數(shù)據(jù)項(xiàng)subscription.RemoveItems(new ItemIdentifier item );/subscription為包含數(shù)據(jù)項(xiàng)item的組,成員函數(shù)RemoveItems只接受ItemIdentifier數(shù)組類型的參數(shù),其中ItemIdentifier是Item的父類。4 瀏覽地址空間要手工鍵入數(shù)據(jù)項(xiàng)的路徑(ItemPath)和名字(ItemName)比較麻煩,應(yīng)用軟件一般提供數(shù)據(jù)存取服務(wù)器的名字空間瀏覽,供操作者選擇。OPC基金會(huì)提供的組件中使用

16、了組合設(shè)計(jì)模式,類BrowseElement實(shí)現(xiàn)了該模式,一個(gè)BrowseElement包含了許多BrowseElement和Item,而一個(gè)Item則不再包含其它元素。文中實(shí)例編寫了一個(gè)如圖三所示的對話框,左邊為TreeView控件,調(diào)用遞歸函數(shù)BrowseAddress列出所有的數(shù)據(jù)項(xiàng)Item;右邊為ListView控件,列出數(shù)據(jù)項(xiàng)對應(yīng)的屬性Property。 圖三 OPC服務(wù)器地址空間瀏覽BrowseFilters m_filters = new BrowseFilters();/選擇性的瀏覽地址空間。m_filters.ReturnAllProperties = true; /獲取數(shù)據(jù)

17、項(xiàng)的屬性m_filters.ReturnPropertyValues = true; /要求返回屬性的值TreeNode node = new TreeNode(m_server.Name);/在控件中加入根節(jié)點(diǎn),即圖二中的OPC服務(wù)器。BrowseAddress(node,null);/瀏覽根節(jié)點(diǎn)所包括的子項(xiàng)BrowseElement。過程Browse下文列出。private void BrowseAddress (TreeNode node,BrowseElement parent)/遞歸函數(shù),瀏覽parent下所有的數(shù)據(jù)項(xiàng),將這些項(xiàng)顯示在控件TreeView的node節(jié)點(diǎn)下。if( pa

18、rent!=null & parent.IsItem=true )return;/如果BrowseElement對象是Item,則說明是組合的最后一級(jí),終止遞歸。tryItemIdentifier itemID = null;/BrowseElement和Item共同的父類。/該節(jié)點(diǎn)是BrowseElement對象,而不是根節(jié)點(diǎn)。parent = (BrowseElement)node.Tag;itemID = new ItemIdentifier(parent.ItemPath, parent.ItemName);BrowsePosition position = null;/地址空間巨大,

19、則需要此使用此對象,一般不用。BrowseElement elements = m_server.Browse(itemID, m_filters, out position);if (elements != null)/瀏覽到服務(wù)器m_server對應(yīng)itemID所包含的元素。foreach (BrowseElement element in elements)TreeNode newnode = AddBrowseElement(node, element);/加入到TreeViewBrowseAddress(newnode,element);/遞歸調(diào)用 private TreeNode

20、AddBrowseElement(TreeNode previou, BrowseElement element)/將瀏覽到的BrowseElement對象加入到控件TreeView中。TreeNode node = new TreeNode(element.Name);node.Tag = element;/將BrowseElement對象記錄到節(jié)點(diǎn)。/將節(jié)點(diǎn)加入到TreeView中。return node;/ 返回node,由遞歸函數(shù)使用。5 讀取數(shù)據(jù)使用了C#的事件處理機(jī)制, 將OnDataChange注冊到事件,一旦服務(wù)器端數(shù)據(jù)有變化,自動(dòng)觸發(fā)此過程。public void OnDat

21、aChange(object subscriptionHandle, ItemValueResult values)if (InvokeRequired)/保證過程運(yùn)行,其它控件響應(yīng)事件也不能影響。BeginInvoke(new DataChangedCallback(OnDataChange), new object subscriptionHandle, values );/系統(tǒng)調(diào)用。return;tryforeach (ItemValueResult item in values)/處理每一個(gè)ItemValueResultif (item.ClientHandle = null)/服務(wù)器發(fā)過來的無用信息。continue;string quality = ;/數(shù)據(jù)品質(zhì)if (item.QualitySpecified) /如果要求了數(shù)據(jù)品質(zhì),則將其轉(zhuǎn)換成為字符串。 string columns = new string/ListView控件有四列。quality, (item.TimestampSpecified) ? : , ;ListViewItem

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論