使用OpcDaNet.dll实现Opc Server的访问

使用OpcDaNet.dll实现Opc Server的访问

老板只给了一句话:通过Opc将数据传到服务器中。一头雾水,赶紧百度,终于有点眉目,记录下来,供需要的人参考,希望能够对你有所帮助,如果文章中有什么不对的地方,请不吝赐教,如果是你需要的文章就接着往下看吧。

思路

我需要提供开发一个客户端去访问Opc服务器,传递数据给服务器,或者从服务器中获取数据。但是接到项目时,客户还没有提供服务器给我,我就从网上下载了一个测试服务器,用的是Matrikon OPC,其他也看到有网友用KepServer,接下来只是介绍C#开发的客户端如何与Matrikon OPC服务器通信,以及如何知道你的通信是否成功。

Opc测试服务器

下载安装好后如下图所示。
在这里插入图片描述

  1. MatrikonOPC Server for Simulation是服务器,打开之后可以新建Group、Item,然后一个简单的OPC服务器就配置好了,我们开发的客户端就是要访问它,下图是我配置的一个测试服务器。
    在这里插入图片描述
  2. 右上角的黄色标签点开后可以打开MatrikonOPC自带的客户端,如下图所示,结合自带客户端可以轻松实现自己开发的客户端的测试。可以在客户端中添加需要的Item。
    在这里插入图片描述
    简单的OPC服务器配置已经完成。接下来就需要开发我们自己的客户端。

使用OpcDaNet.dll开发OPC客户端

  1. 下载OpcDaNet.dll,它是实现C#与OPC通信的SDK,地址:https://advosol.com/product/1/opcda-net#ProductInfo/
    网站中介绍了该dll如何使用,如下图,其中介绍了每个函数的具体功能,参数设置,内容很多,我只用到了其中几个函数,其他的我没用到也没有看其中的功能介绍。
    在这里插入图片描述
  2. 在项目中添加了dll,我需要在界面上展示服务器的Group和Item,然后在选择需要的Item进行读写,所有我的做法是列出来Group、Item,收集起来,显示在界面上,然后选择需要的Item进行读写。
    下面是具体用法。
    (1)新建一个项目,添加OpcDaNet.dll的引用;
    (2)在项目中新建OPCClient类;
    (3)添加函数OPCServerConnect(),连接至服务器:
OpcServerBrowser opcServerBrower;
string[] str;
public bool OPCServerConnect(OpcServer _opcserver)
        {
            try
            {
                Guid[] ClsIDs;
                opcServerBrower = new OpcServerBrowser();
                opcServerBrower.GetServerList(out str, out ClsIDs);//遍历所有服务器
                int re = 1;
                for (int i = 0; i < str.Length; i++)
                {
                    //Matrikon.OPC.Simulation
                    re = _opcserver.Connect(str[i]);//本地上只有个服务器,连接上
                }
                return re == 0 ? true : false;
            }
            catch
            {
                return false;
            }
        }

(4)获取服务器上所有的Group:

 /// <summary>
        /// 获取服务器中所有的Group
        /// </summary>
        /// <param name="_opcserver"></param>
        /// <param name="_treeNodes"></param>
        /// <returns></returns>
        public void ShowServerGroups(OpcServer _opcserver,out TreeNode[] _treeNodes)
        {
            TreeView treeView = new TreeView();
            ShowBrowseTree show = _opcserver.ShowBrowseTree(treeView);
            show.Show();//必须要加,否则treeNodes为空
            _treeNodes = show.ItemTree;// show all available Tags   
        }

(5)获取服务器上所有的Item:

        /// <summary>
        /// 获取服务器中所有的Items
        /// </summary>
        /// <param name="_opcserver"></param>
        public void ShowServerItems(OpcServer _opcserver,out List<string> _Items)
        {
            string[] nodes;//遍历了Server中所有的Items
            _opcserver.BrowseOPCItemIDs(OPCBROWSETYPE.OPC_FLAT,null, null, OPCACCESSRIGHTS.OPC_READWRITEABLE,out nodes);           
            _Items = new List<string>();
            for (int i = 0; i < nodes.Length; i++)
            {
                if (nodes[i].Equals("#MonitorACLFile"))
                {
                    break;//过滤不需要的Item
                }
                else
                {
                    _Items.Add(nodes[i]);
                }
            }
            string[] str = new string[_Items.Count];
            for (int i = 0; i < _Items.Count; i++)
            {
                str[i] = _Items[i];
            }
        }

(6)读Item、RemoveItems和RemoveGroup:

  /// <summary>
        /// 通过OpcServer读取服务器Item的值
        /// </summary>
        /// <param name="_opcserver">客户服务器</param>
        /// <param name="_Items">ShowServerItems的返回值</param>
        /// <param name="_read">Access Path和DataType</param>
        /// <param name="_read">Read后得到的值</param>
        /// <returns></returns>
       public void ServerReadItems(OpcServer _opcserver, List<string> _Items, out List<AcPathDP> AcPathDPList, out ItemValue[] _read)
        {
         	AcPathDPList = new List<AcPathDP>();
         	try
           	{
           	 string[] str = new string[_Items.Count];
                for (int i = 0; i < _Items.Count; i++)
                {
                	str[i] = _Items[i];
                	#region Get DataType and Access Path
                	AcPathDP AcPathDP = new AcPathDP();
                    	OpcGroup oGrp = _opcserver.AddGroup(_Items[i], true, 0, 1);
                    	OPCItemDef ReadItem = new OPCItemDef(str[i], true, 1, typeof(void));
                    	OPCItemDef[] opcReadItemsArray = new OPCItemDef[1];
                   	opcReadItemsArray[0] = ReadItem;
                   	oGrp.AddItems(opcReadItemsArray, out OPCItemResult[] itemAddRslt);
                    	int[] arrHSrv = new int[1];
                    	arrHSrv[0] = itemAddRslt[0].HandleServer;
                    	oGrp.RemoveItems(arrHSrv, out int[] error);
                    	oGrp.Remove(true);
                    	 AcPathDP.DataType = itemAddRslt[0].CanonicalType.Name;
                    	AcPathDP.AccessPath = ReadItem.AccessPath;
                    	AcPathDPList.Add(AcPathDP);
                    	   #endregion
		}
		 _read = _opcserver.Read(str, _Items.Count);
	 }
	    catch
            {
                _read = null;
            }
        }

(7)写入Item:

 /// <summary>
/// 写数据到Server的Items中
/// </summary>
/// <param name="_opcserver">服务器</param>
/// <param name="item">将要写入的ItemID</param>
/// <param name="WriteValue">写入的数据</param>
 public bool WriteItems(OpcServer _opcserver, string item, object WriteValue)
{
	 OPCItemDef WriteItem = new OPCItemDef(item, true, 1, typeof(void));
            OPCItemDef[] opcWriteItemsArray = new OPCItemDef[1];
            opcWriteItemsArray[0] = WriteItem;
            OPCItemResult[] itemAddRslt;
            OpcGroup oGrp = _opcserver.AddGroup(item, true, 0, 1);
            oGrp.AddItems(opcWriteItemsArray, out itemAddRslt);
            int[] ItemHandlesToWrite = new int[itemAddRslt.Length];
            bool WriteOperationFailed = false;
            for (int index = 0; index < itemAddRslt.Length; index++)
            {
                ItemHandlesToWrite[index] = itemAddRslt[index].HandleServer;//服务器句柄
                if (HRESULTS.Failed(itemAddRslt[index].Error))
                {
                    WriteOperationFailed = true;
                }
            }
             if (!WriteOperationFailed)
            {
                object[] val = new object[ItemHandlesToWrite.Length];
                val[0] = WriteValue;
                oGrp.Write(ItemHandlesToWrite, val, out int[] results);
                #region Remove Group
                int[] aSrvHnd = new int[1];//服务器句柄
                aSrvHnd[0] = itemAddRslt[0].HandleServer;
                oGrp.RemoveItems(aSrvHnd, out int[] error);
                int err = oGrp.Remove(true);
                #endregion
            }
            return WriteOperationFailed;
}

(8)断开与服务器的连接:

OPCServer.Disconnect();
  1. 如何测试:
    使用2中的函数,使用2中的(1),连接到服务器后如下图:
    在这里插入图片描述
    使用2中的(2)~(7),如果服务器自带的Client和我们开发的Client可以相互改值的话就成功了;
    在这里插入图片描述
    最后使用2中的(8)断开与服务器的连接即可。
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
使用opcdanet.dll可以实现OPC服务器的通信和访问OPC(OLE for Process Control)是一种为工业自动化系统设计的标准数据通信协议,旨在实现不同设备和软件的互联互通。 首先,我们需要在计算机上安装opcdanet.dll文件,并注册该动态链接库。安装完成后,我们可以在开发环境中引入opcdanet.dll,并使用其中的功能。 通过opcdanet.dll,我们可以创建OPC Server对象,并指定要访问OPC服务器的程序标识符(progID)。然后,我们可以使用Server对象的方法和属性来获取OPC服务器上的数据,执行读取和写入操作。 例如,我们可以使用Server对象的AddGroup方法创建一个组(group),并设置组的一些属性,如更新速率、活动状态等。接下来,我们可以使用组对象的AddItem方法向组中添加OPC项(item),并设置项的一些属性,如项的标识符、数据类型等。然后,我们可以使用组对象的ReadSync方法来同步读取所有项的值,或使用WriteSync方法来同步写入所有项的值。 此外,opcdanet.dll还提供了一些其他功能,如异步读写、订阅和发布等。我们可以利用这些功能来实现更多复杂的操作,如实时数据更新、事件通知等。 总之,通过使用opcdanet.dll,我们可以方便地实现OPC服务器的访问,并通过其提供的方法和属性来读取和写入数据。这样,我们就可以与OPC服务器进行数据通信,实现工业自动化过程中的数据交互和控制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值