OPC Client .NET 开发类库

1. 背景

OPC Data Access 规范是基于COM/DCOM定义的,因此大多数的OPC DA Serverclient都是基于C++开发的,因为C++COM/DCOM有最好的支持。现在,随着微软的开发平台渐渐的转移到.NET框架上,好多OPC Client程序都需要建立在.NET平台上,用.NET提供的技术开发OPC Client就成为一种需求。网上很多网友都有提过,.NET开发OPC Client不外乎下面三种方法:

  • 使用OPCNetAPI 2.0,需要用到OPCNetAPI.dllOPCNetAPI.Com.dll
  • 使用自动化接口,需要用到OPCDAAuto.dll
  • 使用自定义接口,需要用到多个.NET WrapperOpcRcw.Ae.dllOpcRcw.Batch.dllOpcRcw.Comn.dllOpcRcw.Da.dllOpcRcw.Dx.dllOpcRcw.Hda.dllOpcRcw.Sec.dll

       

    OPCNetAPI 2.0OPC foundation提供,只有注册会员才能得到,是需要付费的。其他的dll不需要付费,很容易得到。网上有网友已经介绍过使用OPCDAAuto.dll开发.NET Client的方法, 这种方法的优点是比较简单,缺点是不够灵活。本文使用自定义接口,借助OpcRcw.Da.dll,开发出一个OPC .NET Client的类库,可供其他client程序调用。

     

  • 必要文件:

    OpcRcw.Comn.dll --- 包含对IConnectionPointContainer的包装。

    OpcRcw.Da.dll ---.NET OPC COM 接口 定义的包装。

     

  • 适应版本:

    OPC Data Access specification 2.05

     

  • 说明:

    该类库正在开发中,这是第一个版本,只实现了一些基本功能,好多功能如OPC Browse等还未实现,代码也未经过测试,存在bug在所难免,感兴趣的朋友请继续关注。。。

       

2. VS2008工程项目文件

  1. 基本类库视图

       

    下图是OpcDa.Client组件实现的基本类库:

       

       

3. 类库实现的基本功能

OpcServer:

Connect

连接OPC Server

Disconnect

断开Server

GetStatus

获得Server的当前状态,返回ServerStatus

AddGroup

添加group

RemoveGroup

删除group

FindGroupByName

通过名字获取OpcGroup对象

   

Opc Group

AddItems

添加Opc Items到组

RemoveItems

删除items

AsyncRead

异步读取Items,调用IOPCAsyncIO2::Read接口

AsyncWrite

异步写items,调用IOPCAsyncIO2::Write接口

Refresh

刷新当前group,调用IOPCAsyncIO2::Refresh接口

GetState

获得当前group状态,返回GroupState

SetState

设置当前group状态,返回设置后的group状态

DataChanged

事件,客户端注册,可用来接收OnDataChange事件

   

4. 类库使用方法

1) 连接OPC DA server

        string serverProgID = "OPCSample.OpcDa20Server.1"; // opc da sample server prog id
        string hostName = string.Empty; //local server
        Type tp = Type.GetTypeFromProgID(serverProgID);
        this._opcServer = new OpcServer(tp.GUID.ToString(), hostName);

        try
        {
            this._opcServer.Connect();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message,
                "Error",
                MessageBoxButtons.OK,
                MessageBoxIcon.Error);
        }

 

  

2) 断开OPC Server

       if (this._opcServer != null)
        {
            this._opcServer.Disconnect();
            this._opcServer = null;
        }

 

3) 添加Group

 

 

        string groupName = "grp_0";  // group name
        int updateRate = 1000;
        bool active = true;
        try
        {
            OpcGroup grp = this._opcServer.AddGroup(groupName, updateRate, active);
            grp.DataChanged += OnDataChange; //register OnDataChange Event
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message,
                                "Error",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Error);

        }

 

其中OnDataChange 定义为DataChangedEventHandler类型:

public delegate void DataChangedEventHandler(object subscriptionHandle, object requestHandle, ItemValueResult[] values); 

private void OnDataChange(object subscriptionHandle, object requestHandle, ItemValueResult[] values); 

 

 

4) 删除Group

try
{
     OpcGroup grp = this._opcServer.FindGroupByName(groupName );
     if (grp != null)
     {
              grp.DataChanged -= OnDataChange; //unregister OnDataChange Event
              this._opcServer.RemoveGroup(grp);
     }
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message, 
	             "Error", 
	              MessageBoxButtons.OK, 
	              MessageBoxIcon.Error);
}

 

5) 添加Items

        List<string> items = new List<string>();
        Items.Add("itemname");
        OpcGroup grp = this._opcServer.FindGroupByName(groupName);
        if (grp != null)
        {
            try
            {
                ItemResult[] results = grp.AddItems(items.ToArray());
                foreach (ItemResult result in results)
                {
                    if (result.ResultID.Failed())
                    {
                        string message = "Failed to add item \'" + result.ItemName + "\'" + " Error: " + result.ResultID.Name;
                        MessageBox.Show(message);
                    }
                    else
                    {
                        AddItemToList(result); // add item to view list
                    }
                }
            } // end try
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message,
                                    "Error",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Error);

            } // end catch
        } // end if

 

6) 删除Items

        // remove items
        // List<object> itemsClientHandle = new List<object>();   //
        if (itemsClientHandle.Count > 0)
        {
            try
            {
                // get group
                OpcGroup grp = this._opcServer.FindGroupByName(groupName);
                if (grp != null)
                {
                    IdentifiedResult[] results = grp.RemoveItems(itemsClientHandle.ToArray());
                    for (int i = 0; i < results.Length; i++)
                    {
                        if (results[i].ResultID.Succeeded())
                        {
                            // remove opc item from server successfully, remove it from list
                            RemoveItemFromList(results[i]);
                        }
                        else
                        {
                            string message = "Remove item \'" + results[i].ItemName + "\' error: " + results[i].ResultID.ToString();
                            MessageBox.Show(message);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message,
                                    "Error",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Error);

            } // end catch
        }

 

7) 异步读取Items

        List<object> clientHandles = new List<object>();
        foreach (ListViewItem lvItem in items)
        {
            ItemResult item = (ItemResult)lvItem.Tag;
            if (item != null)
            {
                clientHandles.Add(item.ClientHandle);
            }
        }
        if (clientHandles.Count > 0)
        {
            // get group
            OpcGroup grp = this._opcServer.FindGroupByName(groupName);
            if (grp != null)
            {
                try
                {
                    IdentifiedResult[] results = grp.AsyncRead(clientHandles.ToArray(), ++this._handle, new ReadCompleteEventHandler(OnReadComplete), out this._request);
                    for (int i = 0; i < results.Length; i++)
                    {
                        if (results[i].ResultID.Failed())
                        {
                            string message = "Failed to read item \'" + results[i].ItemName + "\' error: " + results[i].ResultID.ToString();
                            MessageBox.Show(message);
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

   

其中OnReadComplete用来接收异步读取的数据结果,其定义为:

private void OnReadComplete(object clientHandle, ItemValueResult[] values); 

   

8) 异步写Items

       // get group
        OpcGroup grp = this._opcServer.FindGroupByName(groupName);
        if (grp != null)
        {
            try
            {
                IdentifiedResult[] results = grp.AsyncWrite(new ItemValue[] { itemValue }, ++_handle, new WriteCompleteEventHandler(this.OnWriteComplete), out _request);
                for (int i = 0; i < results.Length; i++)
                {
                    if (results[i].ResultID.Failed())
                    {
                        string message = "Failed to write item \'" + results[i].ItemName + "\' error: " + results[i].ResultID.ToString();
                        MessageBox.Show(message);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

其中OnWriteComplete用来接收异步写的返回结果,其定义为:

private void OnWriteComplete(object clientHandle, IdentifiedResult[] results)

   

类库的具体使用举例可以参照OpcTestClient程序。

 

5. OpcTestClient 用户界面

 

OPC 接口 .NET 包装组件下载:

OpcRcw.zip

源代码下载:

OpcDaClient.zip

posted @ 2010-12-17 11:12  OPC connect  阅读(16744)  评论(9编辑  收藏  举报