上次研究了.Net版本的OPC API dll,這次我采用OPCDAAuto.dll來介紹使用方法。
以下為我的源代碼,有詳細的注釋無需我多言。
編譯平台:VS2008SP1、WINXP、KEPServer
除此之外,我也安裝了西門子的Net2006和Step7,其中Net2006是負責OPC的,可能會在系統中創建一些dll之類的,並提供幾個OPC服務器
以下是我Program.cs(基於控制台的)的全部內容,仍舊采用C#語言:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Collections; using OPCAutomation; using System.Threading; namespace OPCDAAutoTest { class Tester { static void Main(string[] args) { Tester tester=new Tester(); tester.work(); } #region 私有變量 /// <summary> /// OPCServer Object /// </summary> OPCServer MyServer; /// <summary> /// OPCGroups Object /// </summary> OPCGroups MyGroups; /// <summary> /// OPCGroup Object /// </summary> OPCGroup MyGroup; OPCGroup MyGroup2; /// <summary> /// OPCItems Object /// </summary> OPCItems MyItems; OPCItems MyItems2; /// <summary> /// OPCItem Object /// </summary> OPCItem[] MyItem; OPCItem[] MyItem2; /// <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 //測試用工作方法 public void work() { //初始化item數組 MyItem = new OPCItem[4]; MyItem2 = new OPCItem[4]; GetLocalServer(); //ConnectRemoteServer("TX1", "KEPware.KEPServerEx.V4");//用計算機名的局域網 //ConnectRemoteServer("192.168.1.35", "KEPware.KEPServerEx.V4");//用IP的局域網 if (ConnectRemoteServer("", "KEPware.KEPServerEx.V4"))//本機 { if (CreateGroup()) { Thread.Sleep(500);//暫停線程以讓DataChange反映,否則下面的同步讀可能讀不到 //以下同步寫 MyItem[3].Write("I love you!");//同步寫 MyItem[2].Write(true);//同步寫 MyItem[1].Write(-100);//同步寫 MyItem[0].Write(120);//同步寫 //以下同步讀 object ItemValues; object Qualities; object TimeStamps;//同步讀的臨時變量:值、質量、時間戳 MyItem[0].Read(1,out ItemValues,out Qualities,out TimeStamps);//同步讀,第一個參數只能為1或2 int q0 = Convert.ToInt32(ItemValues);//轉換后獲取item值 MyItem[1].Read(1, out ItemValues, out Qualities, out TimeStamps);//同步讀,第一個參數只能為1或2 int q1 = Convert.ToInt32(ItemValues);//轉換后獲取item值 MyItem[2].Read(1, out ItemValues, out Qualities, out TimeStamps);//同步讀,第一個參數只能為1或2 bool q2 = Convert.ToBoolean(ItemValues);//轉換后獲取item值 MyItem[3].Read(1, out ItemValues, out Qualities, out TimeStamps);//同步讀,第一個參數只能為1或2 string q3 = Convert.ToString(ItemValues);//轉換后獲取item值,為防止讀到的值為空,不用ItemValues.ToString() Console.WriteLine("~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); Console.WriteLine("0-{0},1-{1},2-{2},3-{3}",q0,q1,q2,q3); //以下為異步寫 //異步寫時,Array數組從下標1開始而非0! int[] temp = new int[] { 0,MyItem[0].ServerHandle,MyItem[1].ServerHandle,MyItem[2].ServerHandle, MyItem[3].ServerHandle }; Array serverHandles = (Array)temp; object[] valueTemp = new object[5] { "",255,520,true, "Love" }; Array values = (Array)valueTemp; Array Errors; int cancelID; MyGroup.AsyncWrite(4, ref serverHandles, ref values, out Errors, 1, out cancelID);//第一參數為item數量 //由於MyGroup2沒有訂閱,所以以下這句運行時將會出錯! //MyGroup2.AsyncWrite(4, ref serverHandles, ref values, out Errors, 1, out cancelID); //以下異步讀 MyGroup.AsyncRead(4, ref serverHandles, out Errors, 1, out cancelID);//第一參數為item數量 /*MyItem[0] = MyItems.AddItem("BPJ.Db1.dbb96", 0);//byte MyItem[1] = MyItems.AddItem("BPJ.Db1.dbw10", 1);//short MyItem[2] = MyItems.AddItem("BPJ.Db16.dbx0", 2);//bool MyItem[3] = MyItems.AddItem("BPJ.Db11.S0", 3);//string*/ Console.WriteLine("************************************** hit <return> to Disconnect..."); Console.ReadLine(); //釋放所有組資源 MyServer.OPCGroups.RemoveAll(); //斷開服務器 MyServer.Disconnect(); } } //END Console.WriteLine("************************************** hit <return> to close..."); Console.ReadLine(); } //枚舉本地OPC服務器 private void GetLocalServer() { //獲取本地計算機IP,計算機名稱 strHostName = Dns.GetHostName(); //或者通過局域網內計算機名稱 strHostName = "TX1"; //獲取本地計算機上的OPCServerName try { MyServer = new OPCServer(); object serverList = MyServer.GetOPCServers(strHostName); foreach (string server in (Array)serverList) { //cmbServerName.Items.Add(turn); Console.WriteLine("本地OPC服務器:{0}", server); } } catch (Exception err) { Console.WriteLine("枚舉本地OPC服務器出錯:{0}",err.Message); } } //連接OPC服務器 /// <param name="remoteServerIP">OPCServerIP</param> /// <param name="remoteServerName">OPCServer名稱</param> private bool ConnectRemoteServer(string remoteServerIP, string remoteServerName) { try { MyServer.Connect(remoteServerName, remoteServerIP);//連接本地服務器:服務器名+主機名或IP if (MyServer.ServerState == (int)OPCServerState.OPCRunning) { Console.WriteLine("已連接到:{0}",MyServer.ServerName); } else { //這里你可以根據返回的狀態來自定義顯示信息,請查看自動化接口API文檔 Console.WriteLine("狀態:{0}",MyServer.ServerState.ToString()); } MyServer.ServerShutDown+=ServerShutDown;//服務器斷開事件 } catch (Exception err) { Console.WriteLine("連接遠程服務器出現錯誤:{0}" + err.Message); return false; } return true; } //創建組 private bool CreateGroup() { try { MyGroups = MyServer.OPCGroups; MyGroup = MyServer.OPCGroups.Add("測試");//添加組 MyGroup2 = MyGroups.Add("測試2"); OPCGroup MyGroup3 = MyGroups.Add("測試3");//測試刪除組 //以下設置組屬性 { MyServer.OPCGroups.DefaultGroupIsActive = true;//激活組。 MyServer.OPCGroups.DefaultGroupDeadband = 0;// 死區值,設為0時,服務器端該組內任何數據變化都通知組。 MyServer.OPCGroups.DefaultGroupUpdateRate = 200;//默認組群的刷新頻率為200ms MyGroup.UpdateRate = 100;//刷新頻率為1秒。 MyGroup.IsSubscribed = true;//使用訂閱功能,即可以異步,默認false } MyGroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(GroupDataChange); MyGroup.AsyncWriteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(GroupAsyncWriteComplete); MyGroup.AsyncReadComplete += new DIOPCGroupEvent_AsyncReadCompleteEventHandler(GroupAsyncReadComplete); //由於MyGroup2.IsSubscribed是false,即沒有訂閱,所以以下的DataChange回調事件不會發生! MyGroup2.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(GroupDataChange2); MyGroup.AsyncWriteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(GroupAsyncWriteComplete); MyServer.OPCGroups.Remove("測試3");//移除組 AddGroupItems();//設置組內items } catch (Exception err) { Console.WriteLine("創建組出現錯誤:{0}", err.Message); return false; } return true; } private void AddGroupItems()//添加組 { //itmHandleServer; MyItems = MyGroup.OPCItems; MyItems2 = MyGroup2.OPCItems; //添加item MyItem[0] = MyItems.AddItem("BPJ.Db1.dbb96", 0);//byte MyItem[1] = MyItems.AddItem("BPJ.Db1.dbw10", 1);//short MyItem[2] = MyItems.AddItem("BPJ.Db16.dbx0", 2);//bool MyItem[3] = MyItems.AddItem("BPJ.Db11.S0", 3);//string //移除組內item Array Errors; int []temp=new int[]{0,MyItem[3].ServerHandle}; Array serverHandle = (Array)temp; MyItems.Remove(1, ref serverHandle, out Errors); MyItem[3] = MyItems.AddItem("BPJ.Db11.S0", 3);//string MyItem2[0] = MyItems2.AddItem("BPJ.Db1.dbb96", 0);//byte MyItem2[1] = MyItems2.AddItem("BPJ.Db1.dbw10", 1);//short MyItem2[2] = MyItems2.AddItem("BPJ.Db16.dbx0", 2);//bool MyItem2[3] = MyItems2.AddItem("BPJ.Db11.S0", 3);//string } public void ServerShutDown(string Reason)//服務器先行斷開 { Console.WriteLine("服務器已經先行斷開!"); } /// <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>1 ` void GroupDataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps) { Console.WriteLine("++++++++++++++++DataChanged+++++++++++++++++++++++"); /*for (int i = 1; i <= NumItems; i++) { Console.WriteLine("item值:{0}", ItemValues.GetValue(i).ToString()); //Console.WriteLine("item句柄:{0}", ClientHandles.GetValue(i).ToString()); //Console.WriteLine("item質量:{0}", Qualities.GetValue(i).ToString()); //Console.WriteLine("item時間戳:{0}", TimeStamps.GetValue(i).ToString()); //Console.WriteLine("item類型:{0}", ItemValues.GetValue(i).GetType().FullName); }*/ } void GroupDataChange2(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps) { Console.WriteLine("----------------------DataChanged2------------------"); /*for (int i = 1; i <= NumItems; i++) { Console.WriteLine("item2值:{0}", ItemValues.GetValue(i).ToString()); //Console.WriteLine("item2質量:{0}", Qualities.GetValue(i).ToString()); //Console.WriteLine("item2時間戳:{0}", TimeStamps.GetValue(i).ToString()); }*/ } /// <summary> /// 異步寫完成 /// 運行時,Array數組從下標1開始而非0! /// </summary> /// <param name="TransactionID"></param> /// <param name="NumItems"></param> /// <param name="ClientHandles"></param> /// <param name="Errors"></param> void GroupAsyncWriteComplete(int TransactionID, int NumItems, ref Array ClientHandles, ref Array Errors) { Console.WriteLine("%%%%%%%%%%%%%%%%AsyncWriteComplete%%%%%%%%%%%%%%%%%%%"); /*for (int i = 1; i <= NumItems; i++) { Console.WriteLine("Tran:{0} ClientHandles:{1} Error:{2}", TransactionID.ToString(), ClientHandles.GetValue(i).ToString(), Errors.GetValue(i).ToString()); }*/ } /// <summary> /// 異步讀完成 /// 運行時,Array數組從下標1開始而非0! /// </summary> /// <param name="TransactionID"></param> /// <param name="NumItems"></param> /// <param name="ClientHandles"></param> /// <param name="ItemValues"></param> /// <param name="Qualities"></param> /// <param name="TimeStamps"></param> /// <param name="Errors"></param> void GroupAsyncReadComplete(int TransactionID, int NumItems, ref System.Array ClientHandles, ref System.Array ItemValues, ref System.Array Qualities, ref System.Array TimeStamps, ref System.Array Errors) { Console.WriteLine("****************GroupAsyncReadComplete*******************"); for (int i = 1; i <= NumItems; i++) { //Console.WriteLine("Tran:{0} ClientHandles:{1} Error:{2}", TransactionID.ToString(), ClientHandles.GetValue(i).ToString(), Errors.GetValue(i).ToString()); Console.WriteLine("Vaule:{0}",Convert.ToString(ItemValues.GetValue(i))); } } } }