【轉】(C#)OPC客戶端源碼

http://www.cnblogs.com/badnewfish/archive/2009/04/11/1374966.htmlhtml

本例下載/Files/badnewfish/OPC測試經過.rar程序員

轉載申明

申明:本文爲轉載,如需轉載本文,請獲取原文做者大尾巴狼啊的贊成,謝謝合做!web

轉自:大尾巴狼啊windows

原文出處:http://www.cnblogs.com/xiaosacao/archive/2009/01/13/1374895.html數組

 

前幾天我就發佈過這篇文章,惋惜的是,發佈後代碼有的卻看不到,後來我就刪了,至今不明白什麼緣由- -!服務器

關於C++、VB來開發OPC客戶端的資料網上有不少,但C#的至今沒發現有多少。網絡

因爲近期項目的須要,就開發了OPC客戶端的一個模塊。在我想來,程序員挺累的,緣由我很累。因此我想你們也很累~~~嘿嘿。工具

特別是剛接手OPC客戶端開發的前幾天,每天盯住顯示器,百度、GOOGLE不停的搜索。天天早上醒來,眼睛都瑟瑟的。開發工具

從事3年以上軟件開發的朋友們,估計都會腰痠背痛吧!反正我是這樣的。測試

不說那麼多廢話了,貼上源碼,讓須要的同行看看吧,代碼的質量並不高,就當作拋磚引玉吧!

 


 

一、枚舉本地服務器

二、獲取服務器信息

三、列出了服務器上Tag

四、能夠設置組的屬性

五、讀\寫功能

六、可進行遠程鏈接(DCOM需配置)

先看圖:

引用類庫:

OPC服務器:

開發工具:

當前環境:

 

源碼:

  1 Code
  2 
  3 ///摘要
  4 
  5 ///程式使用C#.NET 2005 編寫
  6 
  7 ///引用類庫OPCDAAuto.dll
  8 
  9 ///OPCServer採用KEPWare
 10 
 11 ///在windows xp sp二、sp三、windows 2003上測試經過
 12 
 13 ///完成於:2008年12月31日
 14 
 15 ///測試於:2009年01月05日
 16 
 17 ///
 18 
 19 ///做者:瀟灑草
 20 
 21 ///Email:zhkai868@163.com
 22 
 23 ///QQ:44649029
 24 
 25 /// 
 26 
 27 ///如分發,請保留此摘要。
 28 
 29 ///鄙視那些拿代碼當寶貝的人,鄙視那些你不拿源碼換就不稀罕你的人,鄙視那些自私的人。
 30 
 31 ///別人看到你的代碼,你能死啊?對你有多大威脅啊?強烈鄙視~~~
 32 
 33 ///若是你是這樣的人,趕忙關了。。偶不歡迎。。
 34 
 35 using System;
 36 
 37 using System.Collections.Generic;
 38 
 39 using System.ComponentModel;
 40 
 41 using System.Data;
 42 
 43 using System.Drawing;
 44 
 45 using System.Text;
 46 
 47 using System.Windows.Forms;
 48 
 49 using System.Net;
 50 
 51 using System.Collections;
 52 
 53 using OPCAutomation;
 54 
 55 
 56 
 57 namespace OPC測試經過
 58 
 59 {
 60 
 61     public partial class MainFrom : Form
 62 
 63     {
 64 
 65         public MainFrom()
 66 
 67         {
 68 
 69             InitializeComponent();
 70 
 71         }
 72 
 73 
 74 
 75         #region 私有變量
 76 
 77         /// <summary>
 78 
 79         /// OPCServer Object
 80 
 81         /// </summary>
 82 
 83         OPCServer KepServer;
 84 
 85         /// <summary>
 86 
 87         /// OPCGroups Object
 88 
 89         /// </summary>
 90 
 91         OPCGroups KepGroups;
 92 
 93         /// <summary>
 94 
 95         /// OPCGroup Object
 96 
 97         /// </summary>
 98 
 99         OPCGroup KepGroup;
100 
101         /// <summary>
102 
103         /// OPCItems Object
104 
105         /// </summary>
106 
107         OPCItems KepItems;
108 
109         /// <summary>
110 
111         /// OPCItem Object
112 
113         /// </summary>
114 
115         OPCItem KepItem;
116 
117         /// <summary>
118 
119         /// 主機IP
120 
121         /// </summary>
122 
123         string strHostIP = "";
124 
125         /// <summary>
126 
127         /// 主機名稱
128 
129         /// </summary>
130 
131         string strHostName = "";
132 
133         /// <summary>
134 
135         /// 鏈接狀態
136 
137         /// </summary>
138 
139         bool opc_connected = false;
140 
141         /// <summary>
142 
143         /// 客戶端句柄
144 
145         /// </summary>
146 
147         int itmHandleClient = 0;
148 
149         /// <summary>
150 
151         /// 服務端句柄
152 
153         /// </summary>
154 
155         int itmHandleServer = 0;
156 
157         #endregion
158 
159 
160 
161         #region 方法
162 
163         /// <summary>
164 
165         /// 枚舉本地OPC服務器
166 
167         /// </summary>
168 
169         private void GetLocalServer()
170 
171         {
172 
173             //獲取本地計算機IP,計算機名稱
174 
175             IPHostEntry IPHost = Dns.Resolve(Environment.MachineName);
176 
177             if (IPHost.AddressList.Length > 0)
178 
179             {
180 
181                 strHostIP = IPHost.AddressList[0].ToString();
182 
183             }
184 
185             else
186 
187             {
188 
189                 return;
190 
191             }
192 
193             //經過IP來獲取計算機名稱,可用在局域網內
194 
195             IPHostEntry ipHostEntry = Dns.GetHostByAddress(strHostIP);
196 
197             strHostName=ipHostEntry.HostName.ToString();
198 
199 
200 
201             //獲取本地計算機上的OPCServerName
202 
203             try
204 
205             {
206 
207                 KepServer = new OPCServer();
208 
209                 object serverList = KepServer.GetOPCServers(strHostName);
210 
211 
212 
213                 foreach (string turn in (Array)serverList)
214 
215                 {
216 
217                     cmbServerName.Items.Add(turn);
218 
219                 }
220 
221 
222 
223                 cmbServerName.SelectedIndex = 0;
224 
225                 btnConnServer.Enabled = true;
226 
227             }
228 
229             catch(Exception err)
230 
231             {
232 
233                 MessageBox.Show("枚舉本地OPC服務器出錯:"+err.Message,"提示信息",MessageBoxButtons.OK,MessageBoxIcon.Warning);
234 
235             }
236 
237 
238 
239         }
240 
241         /// <summary>
242 
243         /// 建立組
244 
245         /// </summary>
246 
247         private bool CreateGroup()
248 
249         {
250 
251             try
252 
253             {
254 
255                 KepGroups = KepServer.OPCGroups;
256 
257                 KepGroup = KepGroups.Add("OPCDOTNETGROUP");
258 
259                 SetGroupProperty();
260 
261                 KepGroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange);
262 
263                 KepGroup.AsyncWriteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(KepGroup_AsyncWriteComplete);
264 
265                 KepItems = KepGroup.OPCItems;
266 
267             }
268 
269             catch (Exception err)
270 
271             {
272 
273                 MessageBox.Show("建立組出現錯誤:"+err.Message,"提示信息",MessageBoxButtons.OK,MessageBoxIcon.Warning);
274 
275                 return false;
276 
277             }
278 
279             return true;
280 
281         }
282 
283         /// <summary>
284 
285         /// 設置組屬性
286 
287         /// </summary>
288 
289         private void SetGroupProperty()
290 
291         {
292 
293             KepServer.OPCGroups.DefaultGroupIsActive =Convert.ToBoolean(txtGroupIsActive.Text);
294 
295             KepServer.OPCGroups.DefaultGroupDeadband = Convert.ToInt32(txtGroupDeadband.Text);
296 
297             KepGroup.UpdateRate = Convert.ToInt32(txtUpdateRate.Text);
298 
299             KepGroup.IsActive = Convert.ToBoolean(txtIsActive.Text);
300 
301             KepGroup.IsSubscribed =Convert.ToBoolean(txtIsSubscribed.Text);
302 
303         }
304 
305         /// <summary>
306 
307         /// 列出OPC服務器中全部節點
308 
309         /// </summary>
310 
311         /// <param name="oPCBrowser"></param>
312 
313         private void RecurBrowse(OPCBrowser oPCBrowser)
314 
315         {
316 
317             //展開分支
318 
319             oPCBrowser.ShowBranches();
320 
321             //展開葉子
322 
323             oPCBrowser.ShowLeafs(true);
324 
325             foreach (object turn in oPCBrowser)
326 
327             {
328 
329                 listBox1.Items.Add(turn.ToString());
330 
331             }
332 
333         }
334 
335         /// <summary>
336 
337         /// 獲取服務器信息,並顯示在窗體狀態欄上
338 
339         /// </summary>
340 
341         private void GetServerInfo()
342 
343         {
344 
345             tsslServerStartTime.Text ="開始時間:"+ KepServer.StartTime.ToString()+"    ";
346 
347             tsslversion.Text ="版本:"+ KepServer.MajorVersion.ToString() + "." + KepServer.MinorVersion.ToString()+"."+KepServer.BuildNumber.ToString();
348 
349         }
350 
351         /// <summary>
352 
353         /// 鏈接OPC服務器
354 
355         /// </summary>
356 
357         /// <param name="remoteServerIP">OPCServerIP</param>
358 
359         /// <param name="remoteServerName">OPCServer名稱</param>
360 
361         private bool ConnectRemoteServer(string remoteServerIP, string remoteServerName)
362 
363         {
364 
365             try
366 
367             {
368 
369                 KepServer.Connect(remoteServerName, remoteServerIP);
370 
371 
372 
373                 if (KepServer.ServerState == (int)OPCServerState.OPCRunning)
374 
375                 {
376 
377                     tsslServerState.Text = "已鏈接到-" + KepServer.ServerName + "   ";
378 
379                 }
380 
381                 else
382 
383                 {
384 
385                     //這裏你能夠根據返回的狀態來自定義顯示信息,請查看自動化接口API文檔
386 
387                     tsslServerState.Text = "狀態:" + KepServer.ServerState.ToString() + "   ";
388 
389                 }
390 
391             }
392 
393             catch (Exception err)
394 
395             {
396 
397                 MessageBox.Show("鏈接遠程服務器出現錯誤:" + err.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
398 
399                 return false;
400 
401             }
402 
403             return true;
404 
405         }
406 
407         #endregion
408 
409 
410 
411         #region 事件
412 
413         /// <summary>
414 
415         /// 寫入TAG值時執行的事件
416 
417         /// </summary>
418 
419         /// <param name="TransactionID"></param>
420 
421         /// <param name="NumItems"></param>
422 
423         /// <param name="ClientHandles"></param>
424 
425         /// <param name="Errors"></param>
426 
427         void KepGroup_AsyncWriteComplete(int TransactionID, int NumItems, ref Array ClientHandles, ref Array Errors)
428 
429         {
430 
431             lblState.Text = "";
432 
433             for (int i = 1; i <= NumItems; i++)
434 
435             {
436 
437                 lblState.Text += "Tran:" + TransactionID.ToString() + "   CH:" + ClientHandles.GetValue(i).ToString() + "   Error:" + Errors.GetValue(i).ToString();
438 
439             }
440 
441         }
442 
443         /// <summary>
444 
445         /// 每當項數據有變化時執行的事件
446 
447         /// </summary>
448 
449         /// <param name="TransactionID">處理ID</param>
450 
451         /// <param name="NumItems">項個數</param>
452 
453         /// <param name="ClientHandles">項客戶端句柄</param>
454 
455         /// <param name="ItemValues">TAG值</param>
456 
457         /// <param name="Qualities">品質</param>
458 
459         /// <param name="TimeStamps">時間戳</param>
460 
461         void KepGroup_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps)
462 
463         {
464 
465             //爲了測試,因此加了控制檯的輸出,來查看事物ID號
466 
467             //Console.WriteLine("********"+TransactionID.ToString()+"*********");
468 
469             for (int i = 1; i <= NumItems; i++)
470 
471             {
472 
473                 this.txtTagValue.Text = ItemValues.GetValue(i).ToString();
474 
475                 this.txtQualities.Text = Qualities.GetValue(i).ToString();
476 
477                 this.txtTimeStamps.Text = TimeStamps.GetValue(i).ToString();
478 
479             }
480 
481         }
482 
483         /// <summary>
484 
485         /// 選擇列表項時處理的事情
486 
487         /// </summary>
488 
489         /// <param name="sender"></param>
490 
491         /// <param name="e"></param>
492 
493         private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
494 
495         {
496 
497             try
498 
499             {
500 
501                 if (itmHandleClient != 0)
502 
503                 {
504 
505                     this.txtTagValue.Text = "";
506 
507                     this.txtQualities.Text ="";
508 
509                     this.txtTimeStamps.Text = "";
510 
511 
512 
513                     Array Errors;
514 
515                     OPCItem bItem = KepItems.GetOPCItem(itmHandleServer);
516 
517                     //注:OPC中以1爲數組的基數
518 
519                     int[] temp = new int[2] { 0, bItem.ServerHandle };
520 
521                     Array serverHandle = (Array)temp;
522 
523                     //移除上一次選擇的項
524 
525                     KepItems.Remove(KepItems.Count, ref serverHandle, out Errors);
526 
527                 }
528 
529                 itmHandleClient = 1234;
530 
531                 KepItem = KepItems.AddItem(listBox1.SelectedItem.ToString(), itmHandleClient);
532 
533                 itmHandleServer = KepItem.ServerHandle;
534 
535             }
536 
537             catch(Exception err)
538 
539             {
540 
541                 //沒有任何權限的項,都是OPC服務器保留的系統項,此處可不作處理。
542 
543                 itmHandleClient = 0;
544 
545                 txtTagValue.Text = "Error ox";
546 
547                 txtQualities.Text = "Error ox";
548 
549                 txtTimeStamps.Text = "Error ox";
550 
551                 MessageBox.Show("此項爲系統保留項:"+err.Message,"提示信息");
552 
553             }
554 
555         }
556 
557         /// <summary>
558 
559         /// 載入窗體時處理的事情
560 
561         /// </summary>
562 
563         private void MainFrom_Load(object sender, EventArgs e)
564 
565         {
566 
567             GetLocalServer();
568 
569         }
570 
571         /// <summary>
572 
573         /// 關閉窗體時處理的事情
574 
575         /// </summary>
576 
577         private void MainFrom_FormClosing(object sender, FormClosingEventArgs e)
578 
579         {
580 
581             if (!opc_connected)
582 
583             {
584 
585                 return;
586 
587             }
588 
589 
590 
591             if (KepGroup != null)
592 
593             {
594 
595                 KepGroup.DataChange -= new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange);
596 
597             }
598 
599 
600 
601             if (KepServer != null)
602 
603             {
604 
605                 KepServer.Disconnect();
606 
607                 KepServer = null;
608 
609             }
610 
611 
612 
613             opc_connected = false;
614 
615         }
616 
617         /// <summary>
618 
619         /// 【按鈕】設置
620 
621         /// </summary>
622 
623         private void btnSetGroupPro_Click(object sender, EventArgs e)
624 
625         {
626 
627             SetGroupProperty();
628 
629         }
630 
631         /// <summary>
632 
633         /// 【按鈕】鏈接OPC服務器
634 
635         /// </summary>
636 
637         private void btnConnLocalServer_Click(object sender, EventArgs e)
638 
639         {
640 
641             try
642 
643             {
644 
645                 if (!ConnectRemoteServer(txtRemoteServerIP.Text,cmbServerName.Text))
646 
647                 {
648 
649                     return;
650 
651                 }
652 
653 
654 
655                 btnSetGroupPro.Enabled = true;
656 
657 
658 
659                 opc_connected = true;
660 
661 
662 
663                 GetServerInfo();
664 
665 
666 
667                 RecurBrowse(KepServer.CreateBrowser());
668 
669 
670 
671                 if (!CreateGroup())
672 
673                 {
674 
675                     return;
676 
677                 }
678 
679             }
680 
681             catch (Exception err)
682 
683             {
684 
685                 MessageBox.Show("初始化出錯:" + err.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
686 
687             }
688 
689         }
690 
691         /// <summary>
692 
693         /// 【按鈕】寫入
694 
695         /// </summary>
696 
697         private void btnWrite_Click(object sender, EventArgs e)
698 
699         {
700 
701             OPCItem bItem = KepItems.GetOPCItem(itmHandleServer);
702 
703             int[] temp = new int[2] { 0, bItem.ServerHandle };
704 
705             Array serverHandles=(Array)temp;
706 
707             object[] valueTemp = new object[2] {"",txtWriteTagValue.Text };
708 
709             Array values=(Array)valueTemp;
710 
711             Array Errors;
712 
713             int cancelID;
714 
715             KepGroup.AsyncWrite(1,ref serverHandles,ref values,out Errors, 2009,out cancelID);
716 
717             //KepItem.Write(txtWriteTagValue.Text);//這句也能夠寫入,但並不觸發寫入事件
718 
719             GC.Collect();
720 
721         }
722 
723         #endregion
724 
725     }
726 
727 }

 

 

自動化接口API文檔:

關於DCOM的配置:

 

update:

一、本文中是在2009年元月寫的,可能有不少過期之處,如今最新(2014年)的OPC官網已經有關於C#調用的例子:http://www.opcfoundation.org/default.aspx/classicdownloads.asp?MID=Developers

二、客戶端鏈接OPC服務器注意事項:

a、本例採用的OPCDAAuto.dll版本是2.2.5.20。 b、須要使用「regsvr32 /s OPCDAAuto.dll」命令在客戶端計算機上註冊這個程序集。 c、首先保證客戶機和服務器的網絡是聯通的。
相關文章
相關標籤/搜索