zoukankan      html  css  js  c++  java
  • 【转】(C#)OPC客户端源码

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

    本例下载/Files/badnewfish/OPC测试通过.rar

    转载申明

    申明:本文为转载,如需转载本文,请获取原文作者大尾巴狼啊的同意,谢谢合作!

    转自:大尾巴狼啊

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

    前几天我就发布过这篇文章,可惜的是,发布后代码有的却看不到,后来我就删了,至今不明白什么原因- -!

    关于C++、VB来开发OPC客户端的资料网上有很多,但C#的至今没发现有多少。

    由于近期项目的需要,就开发了OPC客户端的一个模块。在我想来,程序员挺累的,原因我很累。所以我想大家也很累~~~嘿嘿。

    特别是刚接手OPC客户端开发的前几天,天天盯住显示器,百度、GOOGLE不停的搜索。每天早上醒来,眼睛都瑟瑟的。

    从事3年以上软件开发的朋友们,估计都会腰酸背痛吧!反正我是这样的。

    不说那么多废话了,贴上源码,让需要的同行看看吧,代码的质量并不高,就当做抛砖引玉吧!


    1、枚举本地服务器

    2、获取服务器信息

    3、列出了服务器上Tag

    4、可以设置组的属性

    5、读写功能

    6、可进行远程连接(DCOM需配置)

    先看图:

    引用类库:

    OPC服务器:

    开发工具:

    当前环境:

     

    源码:

      1 Code
      2 
      3 ///摘要
      4 
      5 ///程式使用C#.NET 2005 编写
      6 
      7 ///引用类库OPCDAAuto.dll
      8 
      9 ///OPCServer采用KEPWare
     10 
     11 ///在windows xp sp2、sp3、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:

    1、本文中是在2009年元月写的,可能有很多过时之处,现在最新(2014年)的OPC官网已经有关于C#调用的例子:http://www.opcfoundation.org/default.aspx/classicdownloads.asp?MID=Developers

    2、客户端连接OPC服务器注意事项:

    a、本例采用的OPCDAAuto.dll版本是2.2.5.20。
    b、需要使用“regsvr32 /s OPCDAAuto.dll”命令在客户端计算机上注册这个程序集。
    c、首先保证客户机和服务器的网络是联通的。
  • 相关阅读:
    Android驱动开发
    LCD控制器时序参数的确定(基于TFT LCD: KD50G9-40NM-A3)
    Delphi IDHTTP用法详解
    Delphi开发Android的几个注意
    Delphi 调试连接 任意Android手机/平板/盒子
    Delphi XE10在 Android下调用静态库a文件
    Delphi的FIFO实现
    Delphi获取Android下GPS的NMEA 0183数据
    【CJOJ1603】【洛谷1220】关路灯
    【洛谷2986】【USACO10MAR】伟大的奶牛聚集
  • 原文地址:https://www.cnblogs.com/zouhao/p/6306499.html
Copyright © 2011-2022 走看看