天天看點

C# OPC使用

C# OPC使用

OPC用戶端操作主要有4個步驟:

1.連接配接OPC伺服器

2.建立組和項

3.讀寫資料

4.斷開伺服器連接配接

全部代碼:

複制代碼

using System;

using System.Collections.Generic;

using System.Net;

using System.Threading;

using OPCAutomation;

namespace ConsoleOPC

{

public class OPCClient

{

private OPCServer KepServer;

private OPCGroups KepGroups;

public OPCGroup KepGroup;

private OPCItems KepItems;

private OPCItem KepItem;

int itmHandleClient = 0;

int itmHandleServer = 0;

public object readValue;

    public List<string> serverNames = new List<string>();
    public List<string> Tags = new List<string>();

    /// <summary>
    /// 枚舉本地OPC SERVER
    /// </summary>
    public void GetOPCServers()
    {
        IPHostEntry IPHost = Dns.GetHostEntry(Environment.MachineName);

        Console.WriteLine("MAC Address:");
        foreach (IPAddress ip in IPHost.AddressList)
        {
            Console.WriteLine(ip.ToString());
        }
        Console.WriteLine("Please Enter IPHOST");

        string strHostIP = "localhost";//Console.ReadLine();

        IPHostEntry ipHostEntry = Dns.GetHostEntry(strHostIP);
        try
        {
            KepServer = new OPCServer();
            object serverList = KepServer.GetOPCServers(ipHostEntry.HostName.ToString());
            int i = 0;
            foreach (string serverName in (Array)serverList)
            {
                Console.WriteLine(i.ToString() + "." + serverName);
                serverNames.Add(serverName);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("Connect Error:" + ex.Message);
        }
    }

    /// <summary>
    /// 連接配接OPC SERVER
    /// </summary>
    /// <param name="serverName">OPC SERVER名字</param>
    public void ConnectServer(string serverName)
    {
        try
        {
            KepServer.Connect(serverName, "");
            CreateGroup("");
            CreateItems();
        }
        catch (Exception ex)
        {
            Console.WriteLine("Connect Error:" + ex.Message);
        }
    }

    /// <summary>
    /// 建立組,組名無所謂
    /// </summary>
    private void CreateGroup(string groupName)
    {
        try
        {
            KepGroups = KepServer.OPCGroups;
            KepGroup = KepGroups.Add(groupName);
            KepServer.OPCGroups.DefaultGroupIsActive = true;
            KepServer.OPCGroups.DefaultGroupDeadband = 0;
            KepGroup.UpdateRate = 250;
            KepGroup.IsActive = true;
            KepGroup.IsSubscribed = true;
        }
        catch (Exception ex)
        {
            Console.WriteLine("Create group error:" + ex.Message);
        }
    }

    private void CreateItems()
    {
        KepItems = KepGroup.OPCItems;
        KepGroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange);
    }

    private void KepGroup_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps)
    {
        for (int i = 1; i <= NumItems; i++)
        {
            readValue = ItemValues.GetValue(i).ToString();
        }
    }

    private void GetTagValue(string tagName)
    {
        try
        {
            readValue = "";
            if (itmHandleClient != 0)
            {
                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 = 12345;
            KepItem = KepItems.AddItem(tagName, itmHandleClient);
            itmHandleServer = KepItem.ServerHandle;
        }
        catch (Exception err)
        {
            //沒有任何權限的項,都是OPC伺服器保留的系統項,此處可不做處理。
            itmHandleClient = 0;
            Console.WriteLine("Read value error:" + err.Message);
        }
    }

    public void WriteValue(string tagName, object _value)
    {
        GetTagValue(tagName);
        OPCItem bItem = KepItems.GetOPCItem(itmHandleServer);
        int[] temp = new int[2] { 0, bItem.ServerHandle };
        Array serverHandles = (Array)temp;
        object[] valueTemp = new object[2] { "", _value };
        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();
    }

    public object ReadValue(string tagName)
    {
        GetTagValue(tagName);
        Thread.Sleep(500);
        try
        {
            return KepItem.Value;
        }
        catch
        {
            return null;
        }
    }

    public void ReadValue(string tagName,bool wtf)
    {
        GetTagValue(tagName);
        OPCItem bItem = KepItems.GetOPCItem(itmHandleServer);
        int[] temp = new int[2] { 0, bItem.ServerHandle };
        Array serverHandles = (Array)temp;
        Array Errors;
        int cancel;
        KepGroup.AsyncRead(1, ref serverHandles, out Errors, 2009, out cancel);
        GC.Collect();
    }


}
           

}

步驟:

1.使用GetOPCServers方法,将本地所有OPC Server上所有OPC伺服器服務枚舉并寫入serverNames變量中

2.使用ConnectServer方法,連接配接伺服器。此方法自動建立OPC Group,建立方法中的groupname任意寫

3.使用ReadValue及WriteValue方法讀寫資料。

PS:

1.OPCItems是一個清單,每次将舊資料移除,插入新資料,即清單中永遠隻有一個元素;

2.讀的時候有可能舊資料移除,新資料未寫入,報對象為null的錯誤,sleep一下即可

第二條不一定對,使用模拟器的時候也有此問題,連PLC時無此問題

轉載于:https://www.cnblogs.com/punkrocker/archive/2012/09/01/2666307.html