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

原文:https://www.cnblogs.com/badnewfish/archive/2009/04/11/1374966.htmlhtml

一、枚舉本地服務器web

二、獲取服務器信息windows

三、列出了服務器上Tag數組

四、能夠設置組的屬性服務器

五、讀\寫功能網絡

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

先看圖:開發工具

引用類庫:測試

OPC服務器:ui

開發工具:

當前環境:

 

源碼:

 

複製代碼

///摘要
///程式使用C#.NET 2005 編寫
///引用類庫OPCDAAuto.dll
///OPCServer採用KEPWare
///在windows xp sp二、sp三、windows 2003上測試經過
///完成於:2008年12月31日
///測試於:2009年01月05日
///
///做者:瀟灑草
///Email:zhkai868@163.com
///QQ:44649029
/// 
///如分發,請保留此摘要。
///鄙視那些拿代碼當寶貝的人,鄙視那些你不拿源碼換就不稀罕你的人,鄙視那些自私的人。
///別人看到你的代碼,你能死啊?對你有多大威脅啊?強烈鄙視~~~
///若是你是這樣的人,趕忙關了。。偶不歡迎。。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Collections;
using OPCAutomation;

namespace OPC測試經過
{
    public partial class MainFrom : Form
    {
        public MainFrom()
        {
            InitializeComponent();
        }

        #region 私有變量
        /// <summary>
        /// OPCServer Object
        /// </summary>
        OPCServer KepServer;
        /// <summary>
        /// OPCGroups Object
        /// </summary>
        OPCGroups KepGroups;
        /// <summary>
        /// OPCGroup Object
        /// </summary>
        OPCGroup KepGroup;
        /// <summary>
        /// OPCItems Object
        /// </summary>
        OPCItems KepItems;
        /// <summary>
        /// OPCItem Object
        /// </summary>
        OPCItem KepItem;
        /// <summary>
        /// 主機IP
        /// </summary>
        string strHostIP = "";
        /// <summary>
        /// 主機名稱
        /// </summary>
        string strHostName = "";
        /// <summary>
        /// 鏈接狀態
        /// </summary>
        bool opc_connected = false;
        /// <summary>
        /// 客戶端句柄
        /// </summary>
        int itmHandleClient = 0;
        /// <summary>
        /// 服務端句柄
        /// </summary>
        int itmHandleServer = 0;
        #endregion

        #region 方法
        /// <summary>
        /// 枚舉本地OPC服務器
        /// </summary>
        private void GetLocalServer()
        {
            //獲取本地計算機IP,計算機名稱
            IPHostEntry IPHost = Dns.Resolve(Environment.MachineName);
            if (IPHost.AddressList.Length > 0)
            {
                strHostIP = IPHost.AddressList[0].ToString();
            }
            else
            {
                return;
            }
            //經過IP來獲取計算機名稱,可用在局域網內
            IPHostEntry ipHostEntry = Dns.GetHostByAddress(strHostIP);
            strHostName=ipHostEntry.HostName.ToString();

            //獲取本地計算機上的OPCServerName
            try
            {
                KepServer = new OPCServer();
                object serverList = KepServer.GetOPCServers(strHostName);

                foreach (string turn in (Array)serverList)
                {
                    cmbServerName.Items.Add(turn);
                }

                cmbServerName.SelectedIndex = 0;
                btnConnServer.Enabled = true;
            }
            catch(Exception err)
            {
                MessageBox.Show("枚舉本地OPC服務器出錯:"+err.Message,"提示信息",MessageBoxButtons.OK,MessageBoxIcon.Warning);
            }

        }
        /// <summary>
        /// 建立組
        /// </summary>
        private bool CreateGroup()
        {
            try
            {
                KepGroups = KepServer.OPCGroups;
                KepGroup = KepGroups.Add("OPCDOTNETGROUP");
                SetGroupProperty();
                KepGroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange);
                KepGroup.AsyncWriteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(KepGroup_AsyncWriteComplete);
                KepItems = KepGroup.OPCItems;
            }
            catch (Exception err)
            {
                MessageBox.Show("建立組出現錯誤:"+err.Message,"提示信息",MessageBoxButtons.OK,MessageBoxIcon.Warning);
                return false;
            }
            return true;
        }
        /// <summary>
        /// 設置組屬性
        /// </summary>
        private void SetGroupProperty()
        {
            KepServer.OPCGroups.DefaultGroupIsActive =Convert.ToBoolean(txtGroupIsActive.Text);
            KepServer.OPCGroups.DefaultGroupDeadband = Convert.ToInt32(txtGroupDeadband.Text);
            KepGroup.UpdateRate = Convert.ToInt32(txtUpdateRate.Text);
            KepGroup.IsActive = Convert.ToBoolean(txtIsActive.Text);
            KepGroup.IsSubscribed =Convert.ToBoolean(txtIsSubscribed.Text);
        }
        /// <summary>
        /// 列出OPC服務器中全部節點
        /// </summary>
        /// <param name="oPCBrowser"></param>
        private void RecurBrowse(OPCBrowser oPCBrowser)
        {
            //展開分支
            oPCBrowser.ShowBranches();
            //展開葉子
            oPCBrowser.ShowLeafs(true);
            foreach (object turn in oPCBrowser)
            {
                listBox1.Items.Add(turn.ToString());
            }
        }
        /// <summary>
        /// 獲取服務器信息,並顯示在窗體狀態欄上
        /// </summary>
        private void GetServerInfo()
        {
            tsslServerStartTime.Text ="開始時間:"+ KepServer.StartTime.ToString()+"    ";
            tsslversion.Text ="版本:"+ KepServer.MajorVersion.ToString() + "." + KepServer.MinorVersion.ToString()+"."+KepServer.BuildNumber.ToString();
        }
        /// <summary>
        /// 鏈接OPC服務器
        /// </summary>
        /// <param name="remoteServerIP">OPCServerIP</param>
        /// <param name="remoteServerName">OPCServer名稱</param>
        private bool ConnectRemoteServer(string remoteServerIP, string remoteServerName)
        {
            try
            {
                KepServer.Connect(remoteServerName, remoteServerIP);

                if (KepServer.ServerState == (int)OPCServerState.OPCRunning)
                {
                    tsslServerState.Text = "已鏈接到-" + KepServer.ServerName + "   ";
                }
                else
                {
                    //這裏你能夠根據返回的狀態來自定義顯示信息,請查看自動化接口API文檔
                    tsslServerState.Text = "狀態:" + KepServer.ServerState.ToString() + "   ";
                }
            }
            catch (Exception err)
            {
                MessageBox.Show("鏈接遠程服務器出現錯誤:" + err.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return false;
            }
            return true;
        }
        #endregion

        #region 事件
        /// <summary>
        /// 寫入TAG值時執行的事件
        /// </summary>
        /// <param name="TransactionID"></param>
        /// <param name="NumItems"></param>
        /// <param name="ClientHandles"></param>
        /// <param name="Errors"></param>
        void KepGroup_AsyncWriteComplete(int TransactionID, int NumItems, ref Array ClientHandles, ref Array Errors)
        {
            lblState.Text = "";
            for (int i = 1; i <= NumItems; i++)
            {
                lblState.Text += "Tran:" + TransactionID.ToString() + "   CH:" + ClientHandles.GetValue(i).ToString() + "   Error:" + Errors.GetValue(i).ToString();
            }
        }
        /// <summary>
        /// 每當項數據有變化時執行的事件
        /// </summary>
        /// <param name="TransactionID">處理ID</param>
        /// <param name="NumItems">項個數</param>
        /// <param name="ClientHandles">項客戶端句柄</param>
        /// <param name="ItemValues">TAG值</param>
        /// <param name="Qualities">品質</param>
        /// <param name="TimeStamps">時間戳</param>
        void KepGroup_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps)
        {
            //爲了測試,因此加了控制檯的輸出,來查看事物ID號
            //Console.WriteLine("********"+TransactionID.ToString()+"*********");
            for (int i = 1; i <= NumItems; i++)
            {
                this.txtTagValue.Text = ItemValues.GetValue(i).ToString();
                this.txtQualities.Text = Qualities.GetValue(i).ToString();
                this.txtTimeStamps.Text = TimeStamps.GetValue(i).ToString();
            }
        }
        /// <summary>
        /// 選擇列表項時處理的事情
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                if (itmHandleClient != 0)
                {
                    this.txtTagValue.Text = "";
                    this.txtQualities.Text ="";
                    this.txtTimeStamps.Text = "";

                    Array Errors;
                    OPCItem bItem = KepItems.GetOPCItem(itmHandleServer);
                    //注:OPC中以1爲數組的基數
                    int[] temp = new int[2] { 0, bItem.ServerHandle };
                    Array serverHandle = (Array)temp;
                    //移除上一次選擇的項
                    KepItems.Remove(KepItems.Count, ref serverHandle, out Errors);
                }
                itmHandleClient = 1234;
                KepItem = KepItems.AddItem(listBox1.SelectedItem.ToString(), itmHandleClient);
                itmHandleServer = KepItem.ServerHandle;
            }
            catch(Exception err)
            {
                //沒有任何權限的項,都是OPC服務器保留的系統項,此處可不作處理。
                itmHandleClient = 0;
                txtTagValue.Text = "Error ox";
                txtQualities.Text = "Error ox";
                txtTimeStamps.Text = "Error ox";
                MessageBox.Show("此項爲系統保留項:"+err.Message,"提示信息");
            }
        }
        /// <summary>
        /// 載入窗體時處理的事情
        /// </summary>
        private void MainFrom_Load(object sender, EventArgs e)
        {
            GetLocalServer();
        }
        /// <summary>
        /// 關閉窗體時處理的事情
        /// </summary>
        private void MainFrom_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!opc_connected)
            {
                return;
            }

            if (KepGroup != null)
            {
                KepGroup.DataChange -= new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange);
            }

            if (KepServer != null)
            {
                KepServer.Disconnect();
                KepServer = null;
            }

            opc_connected = false;
        }
        /// <summary>
        /// 【按鈕】設置
        /// </summary>
        private void btnSetGroupPro_Click(object sender, EventArgs e)
        {
            SetGroupProperty();
        }
        /// <summary>
        /// 【按鈕】鏈接OPC服務器
        /// </summary>
        private void btnConnLocalServer_Click(object sender, EventArgs e)
        {
            try
            {
                if (!ConnectRemoteServer(txtRemoteServerIP.Text,cmbServerName.Text))
                {
                    return;
                }

                btnSetGroupPro.Enabled = true;

                opc_connected = true;

                GetServerInfo();

                RecurBrowse(KepServer.CreateBrowser());

                if (!CreateGroup())
                {
                    return;
                }
            }
            catch (Exception err)
            {
                MessageBox.Show("初始化出錯:" + err.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }
        /// <summary>
        /// 【按鈕】寫入
        /// </summary>
        private void btnWrite_Click(object sender, EventArgs e)
        {
            OPCItem bItem = KepItems.GetOPCItem(itmHandleServer);
            int[] temp = new int[2] { 0, bItem.ServerHandle };
            Array serverHandles=(Array)temp;
            object[] valueTemp = new object[2] {"",txtWriteTagValue.Text };
            Array values=(Array)valueTemp;
            Array Errors;
            int cancelID;
            KepGroup.AsyncWrite(1,ref serverHandles,ref values,out Errors, 2009,out cancelID);
            //KepItem.Write(txtWriteTagValue.Text);//這句也能夠寫入,但並不觸發寫入事件
            GC.Collect();
        }
        #endregion
    }
}
複製代碼

 

自動化接口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、首先保證客戶機和服務器的網絡是聯通的。
相關文章
相關標籤/搜索