第一個隨筆,使用了OPEN Live Write,作為客戶端.最近使用c#開發一個小軟體,主要功能是OPC客戶端.以後會開發各類別的協議,作為,協議的轉發棧.因為我本人是搞自動化的,所以搞自動化小伙伴像我這樣喜歡編程的可能有,但是一般是邏輯思維強,但是底子相對還是弱的.1,C# 開發OPC的準備工作... ...
第一個隨筆,使用了OPEN Live Write,作為客戶端.最近使用c#開發一個小軟體,主要功能是OPC客戶端.以後會開發各類別的協議,作為,協議的轉發棧.
因為我本人是搞自動化的,所以搞自動化小伙伴像我這樣喜歡編程的可能有,但是一般是邏輯思維強,但是底子相對還是弱的.
1,C# 開發OPC的準備工作
軟體:VS2019;
DLL:C:\Program Files (x86)\Common Files\MatrikonOPC\Common\OPCDAAuto.dll
並且將其拷貝到C:\Windows\SysWOW64中,並且使用DLL註冊.(記得註冊必須在這個文件夾中)
然後在,VS2019的引用添加引用
2, 查看OPC手冊,不過是英文的VB版本的,以上資料可以在我的百度網盤裡面下載.或者私信我.
3, 如何查詢 opc伺服器數量和連接伺服器
private void BtGetList_Click(object sender, EventArgs e) { KepServer = new OPCServer(); MessageBox.Show(Environment.MachineName); object serverList = KepServer.GetOPCServers(); //枚舉網路所有OPC伺服器並寫入ComboBox控制項 foreach (string turn in (Array)serverList) { cmbServerName.Items.Add(turn); } }4,連接伺服器(可以去下載一個MatrikonOPCSimulation)
private void Form1_Load(object sender, EventArgs e) { KepServer = new OPCServer(); KepServer.Connect("Matrikon.OPC.Simulation.1"); if (KepServer.ServerState == (int)OPCServerState.OPCRunning) { tsslServerState.Text = "已連接到-" + KepServer.ServerName + " "; opcBrowser = KepServer.CreateBrowser(); } TreeNode Root = treeView1.Nodes.Add(KepServer.ServerName); Root.Tag = KepServer; opcBrowser.MoveToRoot(); ShowInTreeView(opcBrowser,Root); }
其中主要函數說明:
其同時支持IP或者電腦名的方式
本地電腦第二個參數.第一個參數是伺服器名稱.
5,對於OPCBrower 對象.
從上面可以看到OPCBrowser 來自 OpcServer.CreateBrower(),其主要用來查看伺服器相關信息.
其本身是一個集合(collection),但是,這個時候,其items=0;
ShowBranchs():該函數用於將當前節點的名稱集合寫入到Collection中.
ShowLeafs():該函數用於將當前節點的Tags 寫入到Collection中.
ShowLeafs(True):將顯示該節點下麵所有的itemsID--------------很重要,在添加ITEM時可以用到.
private void ShowInTreeView(OPCBrowser brower,TreeNode node) { TreeNode childNode = null; brower.ShowBranches(); int BranchCount = brower.Count; List<string> lst = null; if (brower.Count>0) //回溯的添加branch { lst = new List<string>(); foreach (string t in brower) lst.Add(t); foreach (string branch in lst) { childNode = new TreeNode(branch); childNode.Tag = brower.GetItemID(branch); node.Nodes.Add(childNode); brower.MoveDown(branch); ShowInTreeView(brower, childNode); brower.MoveUp(); } } brower.ShowLeafs(); int LeafsCount = brower.Count; foreach (string leaf in brower) { childNode = new TreeNode(brower.GetItemID(leaf)); childNode.Tag = brower.GetItemID(leaf); node.Nodes.Add(childNode); } }
這樣就可以把伺服器的信息讀取到樹裡面了.
brower對象主要作用就是可以知道伺服器裡面的信息了.
6,Group對象及Item對象.
首先:需要創建Group對象:
private void Button3_Click(object sender, EventArgs e) { KepGroups = KepServer.OPCGroups; KepGroups.DefaultGroupIsActive = true; KepGroups.DefaultGroupUpdateRate = 200; KepGroups.DefaultGroupDeadband = 0; KepGroup = KepGroups.Add("mxb"); KepGroup.IsSubscribed = true; KepGroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler( DataChangeHandlerFunc); KepItems = KepGroup.OPCItems; // KepItem = KepItems.AddItem("Random.ArrayOfReal8", 1); textBox1.Text = KepItem.ServerHandle + ":" + KepItem.RequestedDataType; }
說明:
如果該參數是IsSubscribed=True;則其支持訂閱功能:也就是當改組中的參數有改變的時候,其會觸發DataChange事件.
其中:ItemID是一個關鍵的參數,可以通過 OpcBrower.ShowLeafs(true)查看.
AddItem(string ItemID,int ClientHandle):其中Client Handle是客戶端自行填寫的.
一個Item 有一個ServerHandle,由伺服器提供,ItemID:由伺服器提供;ClientHandle:由客戶端提供.
事件處理函數
private void DataChangeHandlerFunc(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps) { // for(int i = 1;i<=NumItems;i++) { if((int)ClientHandles.GetValue(i) == KepItem.ClientHandle) { dynamic t = ItemValues.GetValue(i); object[] ary; ary = Array.ConvertAll<double, object>(t, new Converter<double, object>((x) =>x)); listBox1.Items.Clear(); listBox1.Items.AddRange(ary); } } }
使用該函數可以快速定位數據變更的Item.註意:所有的Array都是1開頭的,所以不能直接轉換成int[]或者double[];需要編寫一個轉換
的函數,轉換成object[].另外,需要註意到 ClientHandles雖然是一個int數組,但是是無法直接轉換到int[]的,因為首先,其起始index=1.
其他還有一些非同步寫入啊,什麼的,可以參考手冊.