目录

一、实现效果

二、准备内容

1.1、KepServer 6.5软件

1.2、OPCDAAuto.dll

三、实现思路

四、补充知识

4.1、OPC逻辑对象模型

4.2、OPC Server对象

4.3、OPC Group对象

4.4、OPC Item对象

4.5、OPC通信

4.6、OPC测试常用的OPCClient和OPCServer软件推荐


一、实现效果

①点击刷新获自动获取取本机的计算机名称

②点击服务节点的下拉框选择该计算机名称,可以自动获取到该计算机的OPC服务名称(或者手动输入)

③选择服务名称的下选择该就算机上的服务名称(或者可以手动输入)

④当【服务节点、服务名称】都存在时,点击连接按钮,即可获取到该计算机服务器上的所有节点内容。

⑤点击获取到的服务器任意节点内容,即可显示该节点的实时数据信息。

C#实现OPC客户端通过OPCDA方式与KepServer通讯项目下载

局域网环境下远程连接 OPC 配置方法下载

二、准备内容

1.1、KepServer 6.5软件

KepServer6.5软件下载

1.2、OPCDAAuto.dll

OPCDAAuto.dll下载

三、实现思路

①获取OPC网络服务器和OPC服务名称

②打开与OPC服务的连接,通过OPCGroups、OPCGroup获取对应的OPCItem项

③建立OPCItem项目需要展示的内容实体展现数据

/***
*	Title:"数据采集" 项目
*		主题:OPCDA与kepserver通讯帮助类
*	Description:
*		功能:
*		    1、获取到OPC服务器
*		    2、打开OPCServe连接
*		    3、获取到OPC服务器的所有节点内容
*		    4、进行OPCGroups设置
*		    5、进行OPCGroup设置
*		    6、关闭OPCServe连接
*	Date:2021
*	Version:0.1版本
*	Author:Coffee
*	Modify Recoder:
*/

using OPCAutomation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Utils
{
    class OPCDAHelper
    {
        #region   基础参数
        //OPCServer服务器
        private OPCServer oPCServer;
        //OPC浏览对象
        private OPCBrowser oPcBrower;

        #endregion

        //构造函数
        public OPCDAHelper()
        {
            oPCServer = new OPCServer();
        }


        /// <summary>
        /// 获取到OPC服务器
        /// </summary>
        /// <param name="serverNode">服务器节点</param>
        /// <returns>返回该服务器节点对应的所有服务器列表</returns>
        public Array GetOPCServerList(string serverNode)
        {
            try
            {
                object serverListObj = oPCServer.GetOPCServers(serverNode);

                Array serverList = (Array)serverListObj;

                return serverList;
            }
            catch (Exception ex)
            {
                MessageBox.Show("获取服务器列表出错!!!" + ex.Message, "一般错误", MessageBoxButtons.YesNo, MessageBoxIcon.Error);
                return null;
            }
        }


        /// <summary>
        /// 打开连接
        /// </summary>
        /// <param name="serverName">服务器的名称</param>
        /// <param name="serverIP">服务器的IP地址</param>
        /// <returns>true:表示连接成功</returns>
        public bool OpenConnect(string serverName,string serverIP)
        {
            bool success = false;
            if (!string.IsNullOrEmpty(serverIP) &&!string.IsNullOrEmpty(serverName))
            {
                try
                {
                    if (oPCServer==null)
                    {
                        oPCServer = new OPCServer();
                    }
                    oPCServer.Connect(serverName,serverIP);
                    success = true;

                }
                catch (Exception ex)
                {
                    success = false;
                    MessageBox.Show(ex.Message, "严重错误", MessageBoxButtons.YesNo, MessageBoxIcon.Error);
                }   
            }

            return success;
        }


        /// <summary>
        /// 获取到OPC服务器的所有节点内容
        /// </summary>
        /// <returns>返回OPC服务器的所有节点内容</returns>
        public OPCBrowser GetAllBrowser()
        {
            try
            {
                oPcBrower = oPCServer.CreateBrowser();
                oPcBrower.ShowBranches();
                oPcBrower.ShowLeafs(true);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message,"严重错误",MessageBoxButtons.YesNo,MessageBoxIcon.Error);
            }

            return oPcBrower;
           
        }

        /// <summary>
        /// OPCGroups设置
        /// </summary>
        /// <param name="oPCGroups">需要设置的OPCGroups</param>
        public void OPCGroupsSettings(ref OPCGroups oPCGroups)
        {
            oPCGroups = oPCServer.OPCGroups;
            oPCGroups.DefaultGroupDeadband = 0;
            oPCGroups.DefaultGroupIsActive = true;
        }

        /// <summary>
        /// OPCGroup设置
        /// </summary>
        /// <param name="oPCGroups">OPCGroups</param>
        /// <param name="oPCGroup">OPCGroup</param>
        /// <param name="oPCGroupName">oPCGroupName</param>
        /// <param name="updateRate">更新频率</param>
        public void OPCGroupSettings(OPCGroups oPCGroups,ref OPCGroup oPCGroup,string oPCGroupName,int updateRate=250)
        {
            if (oPCGroups!=null && 
                !string.IsNullOrEmpty(oPCGroupName)&& updateRate>0)
            {
                oPCGroup = oPCGroups.Add(oPCGroupName);
                oPCGroup.IsActive = true;
                oPCGroup.IsSubscribed = true;
                oPCGroup.UpdateRate = updateRate;
            }
        }



        /// <summary>
        /// 关闭连接
        /// </summary>
        /// <returns>true:表示关闭</returns>
        public bool CloseConnect()
        {
            bool success = false;

            try
            {
                if (oPCServer!=null)
                {
                    oPCServer.Disconnect();
                    success = true;
                }
            }
            catch (Exception ex)
            {
                success = false;
                MessageBox.Show(ex.Message, "严重错误", MessageBoxButtons.YesNo, MessageBoxIcon.Error);
            }

            return success;
        }

    }//Class_end

}
/***
*	Title:"数据采集" 项目
*		主题:OPC数据项实体
*	Description:
*		功能:XXX
*	Date:2021
*	Version:0.1版本
*	Author:Coffee
*	Modify Recoder:
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace OPCDAOfKEPServer.Model
{
    class OPCBrowserItem
    {
        //变量ID
        public string ItemID { get; set; }
        //变量值
        public string Value { get; set; }
        //更新时间
        public string UpdateTime { get; set; }
        //质量
        public string Quality { get; set; }


    }//Class_end

}

四、补充知识

4.1、OPC逻辑对象模型

OPC逻辑对象模型包括3类对象:OPC server对象、OPC group对象、OPC item对象,每类对象都包括一系列接口。

 

OPC概念介绍

这里最需要注意的是项并不是数据源,项代表了到数据源的连接。

例如一个在一个DCS 系统中的TAG 不论OPC 客户程序是否访问都是实际存在的。项应该被认为是到一个地址的数据。大家一定要注意项的概念。不同的组对象里可以拥有相同的项,如组1 中有对应于一个开关的Itemaaa,组2 中也可以有同样意义对应于一个开关的Itemaaa,即

同样的项可以出现在不同的组中。

4.2、OPC Server对象

主要功能:

1、创建和管理OPC Group对象;

2、管理服务器内部的状态信息。

4.3、OPC Group对象

主要功能:

1、管理OPC Group对象的内部状态信息;

2、创建和管理Items对象;

3、OPC服务器内部的实时数据存取服务(同步与异步方式)。

属性:

name:组的名字,由客户端自己定义。

active:组的激活状态,如果为false则组内全部Item将不再从数据源取数据,在客户端中的表现是读取不到数据,同时写数据也影响不到服务器端。

update rate:服务器向客户端提交变化数据的更新速率(这个数值应比服务器设定的最小值大)。

Percent Dead band:数据死区,即能引起数据变化的最小数值百分比。

4.4、OPC Item对象

主要功能

用来描述实时数据,代表了与服务器数据源的连接,而不是数据源。一个项不能被OPC客户端访问,因此在OPC规范中没有对应于项的COM接口,所有对项的访问都需要通过OPC Group对象来实现

属性:

name:项的名称,在服务器对应于Item ID。

active:项的激活状态。

value:项的数据值。

quality:项的品质,代表数值的可信度。

The OPC_QUALITY_xxx 定义了一个过程值或者事件的品质。并且分为3类,good, uncertain和bad。

下面的类型为合法的:

类型 值 说明

OPC_QUALITY_GOOD 0xC0 值是好的。

OPC_QUALITY_LOCAL_OVERRIDE 0xD8 值被覆盖。典型意思为输入失去连接和手动被强制。

下面的类型为不确定:

类型 值 说明

OPC_QUALITY_UNCERTAIN 0x40 没有指定原因说明值为什么不确定。

OPC_QUALITY_LAST_USABLE 0x44 最后的可用值。

OPC_QUALITY_SENSOR_CAL 0x50 传感器达到了它的一个限值或者超过了它的量程。

OPC_QUALITY_EGU_EXCEEDED 0x54 返回值越限。

OPC_QUALITY_SUB_NORMAL 0x58 值有几个源,并且可用的源少于规定的品质好的源。

下面的类型为坏的:

类型 值 说明

OPC_QUALITY_BAD 0x00 值为坏的,没有标明原因。

OPC_QUALITY_CONFIG_ERROR 0x04 服务器特定的配置问题。

OPC_QUALITY_NOT_CONNECTED 0x08 输入没有可用的连接。

OPC_QUALITY_DEVICE_FAILURE 0x0c 设备故障。

OPC_QUALITY_LAST_KNOWN 0x14 通讯失败。最后的值是可用的。

OPC_QUALITY_COMM_FAILURE 0x18 通讯失败,最后的值不可用。

OPC_QUALITY_OUT_OF_SERVICE 0x1C 块脱离扫描或者被锁。

OPC_QUALITY_SENSOR_FAILURE 0x10 传感器故障。

The OPC_LIMIT_xxx定义了值的限制范围。

类型 值 说明

OPC_LIMIT_OK 0x00 值在上低限,高限之内。

OPC_LIMIT_LOW 0x01 值低限。

OPC_LIMIT_HIGH 0x02 值高限。

OPC_LIMIT_CONST 0x03 值是常数。

Timestamp:时间戳,代表数据的存取时间。

 

OPC概念介绍

注:

1.Item的存储类型————VARIANT(编写程序时使用的主要也是它)

2.Item的数据类型(VARTYPE):

3.Item的Alias:项的别名,由服务器设置,避免了项名称过长所带来的麻烦。

4.Group类型:公共组和私有组。公共组由多个客户共享,私有组只属于某一OPC客户。公共组对连接到服务器的所有客户都有效,而私有组只能对建立它的客户程序有效。(大多服务器未实现有公共组)

5.Item在服务器端定义,对应于硬件实际地址,客户端连接服务器端后创建并添加OPC Group,并创建一系列OPC Item(连接到服务器端定义的Item),将逻辑上等价的一组OPCItem添加到OPC Group中才能通过组对象来对数据进行存取操作。

4.5、OPC通信

1. 同步通信:OPC客户端对OPC服务端进行读取操作时,OPC客户端必须等到OPC服务器端完成对应操作后才能返回,在此期间OPC客户端处于一直等待的状态。

2. 异步通信:OPC客户端对OPC服务器端进行读取操作时,OPC客户端发送请求后立即返回,不用等待服务器端,当OPC服务器端完成操作后再通知客户端程序。

3. 订阅:需要服务器端支持OPC A&E规范,由客户端设定数据的变化限度,如果数据源的实时数据变化超过了该限度,服务器则通过回调返回数据给客户端。

4.6、OPC测试常用的OPCClient和OPCServer软件推荐

OPCDA Client

1、OPCClient.exe

把它放在第一位并不是有多好,而是100KB的体积,单文件,也很符合OPC标准,所以是个超便携的OPCClient。

2、Matrikon公司的OPCClient.

很不错的一个OPCClient,标准,稳定,单文件,通讯过程的信息还比较丰富,我是比较喜欢用它在创建OPC组时定义同步方式或异步方式来验证远程计算机的OPC配置是否正确。缺点就是大了点,2M多。

3、Kepware公司的OPCClient

功能很强大,标准,稳定,日志信息很丰富,最推荐的功能是支持对OPCServer中点名的条件过滤,支持点表的导入导出,支持自动导入OPCServer的所有点,根据点表识别好点坏点,按照列排序,用它可以弥补很多国产组态软件不能在线遍历OPCServer点表的功能、不能过滤OPCServer点的功能、不能识别OPCServer中好点坏点的功能等。缺点就是非单文件。

OPCDA Server

1、Knight.OPCServer

简单,还是简单,单文件运行起来啥都有了,148KB,很适合做简单的测试。

2、Matrikon公司的OPCServer Simulator

简单,单文件注册后,各种数据类型,各种点类型(只读点,只写点,读写点)都有了,更好的一点是,如果想做大规模的测试,10万点,那么只需要在它的Random.下添加任意名称即可,OPCServer会自动给你建出对应的测点,还是随机数变化。

3、Kepware公司的OPCServer

这是一个商业软件,需要花费金钱购买License的,但Kepware公司的OPCServer需要花钱的不是OPCServer本身,而是采集驱动。不过Kepware公司的OPCServer提供了不花钱的仿真驱动,用来测试上正是杀人越货的好东西啊,推荐理由的第三条就是说它老兄了。缺点就是太庞大,不简单,学习成本较高。但为了能满足OPC这类产品的各种测试,它真的是最佳选择。由于它是商业软件,我就不提供下载地址了,各位去它的官方网站可以下载,做好的几万点的测试工程需要的找我要。

4、iFiX

支持双向OPC支持所有类型的ActiveX、OLE,对不健全的控件所引发的错误进行保护,对控件的属性操作完全控制。有全面解决扩展点的报警、报警记录、历史记录的方法,有查找替换功能,可以替换整个图画以及画面中的对象的属性、组态点信息,对于同类型物体,避免重复组态。内嵌VBA,具有自己的内部函数,又有广泛的VB函数,功能扩展更为有利。编辑与运行是切换进行的,这有利于对现场生产安全的保障;有独立的报警监视程序,支持在线修改,具有画面分层功能,运行时可以根据程序很方便地更换对象的连接数据源,可以使控制更灵活。支持Oracle、SQL Server2000、Access等关系型数据库。

5、Cimplicity

支持OPC服务器,编辑与运行分开,有独立的报警、历史趋势运行管理程序,内嵌VBA,具有自己的内部函数,又有广泛的VB函数,组VBA与通用运行方式不一样,支持ActiveX、OLE插入,但对控件其中的一些属性进行了锁定。点的扩展功能与iFIX一样强大,但对于扩展点的报警设定比较难解决,输出问题,历史记录是没问题的。支持Oracle,SQLServer2000,Access关系型数据库。

6、InTouch

提供双向OPC支持,支持ActiveX控件,但不具有第三方控件的出错保护,不健全的控件会造成系统出错。采用有限的内部函数,其功能也只是常用监控的功能,复杂一点的功能如报表就只能借助于其他工具。支持关系型数据库。

7、WinCC

双向OPC支持,支持ActiveX。使用内部语言,环境如同C语言。同样使得其功能扩展变得容易。最新的WinCC 6.0只支持连接SQL2000数据库。

4.7、开源OPC项目

LIGHTOPC:OPC服务器,是C/C++语言开发的,http://www.ipi.ac.ru/lab43/lopc-en.html

OpenOpcUa:是C/C++语言开发的跨平台项目,http://www.openopcua.org/

OpenOPC:是基于Python语言的项目,http://openopc.sourceforge.net/

freeopcua:https://github.com/FreeOpcUa/freeopcua

open source and free implementation of OPC UA:https://github.com/open62541/open62541

OPC-Client-X64:https://github.com/edimetia3d/OPC-Client-X64

node-opcda:https://github.com/lizhengzhou/node-opcda

Utgard:OpenSCADA项目底下的子项目,纯Java编写,具有跨平台特性,全部基于DCOM实现(划重点),目前只支持DA 2.0协议,3.0协议的支持还在开发中。http://openscada.org/projects/utgard/

JEasyOPC Client:底层依赖JNI,只能跑在windows环境,不能跨平台。整个类库比较古老,使用的dll是32位的,整个项目只能使用32位的JRE运行。同时支持DA 2.0与3.0协议。但64位系统兼容性不好,容易出错。https://sourceforge.net/projects/jeasyopc/

 

 

 

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐