原文:https://www.cnblogs.com/badnewfish/archive/2009/04/11/1374966.htmlhtml
一、枚舉本地服務器web
二、獲取服務器信息windows
三、列出了服務器上Tag數組
四、能夠設置組的屬性服務器
五、讀\寫功能網絡
六、可進行遠程鏈接(DCOM需配置)工具
先看圖:開發工具
![](http://static.javashuo.com/static/loading.gif)
引用類庫:測試
![](http://static.javashuo.com/static/loading.gif)
OPC服務器:ui
![](http://static.javashuo.com/static/loading.gif)
開發工具:
![](http://static.javashuo.com/static/loading.gif)
當前環境:
![](http://static.javashuo.com/static/loading.gif)
源碼:
///摘要
///程式使用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文檔:
![](http://static.javashuo.com/static/loading.gif)
關於DCOM的配置:
![](http://static.javashuo.com/static/loading.gif)
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、首先保證客戶機和服務器的網絡是聯通的。