用C#开发基于自动化接口的OPC客户端
OPC全称是Object Linking and Embedding(OLE) for Process Control,它的出现为基于Windows的应用程序和现场过程控制应用建立了桥梁。OPC作为一整套接口、属性和方法的协议标准集,与具体的开发语言没有关系。
1、OPC客户端接口方式
开发OPC客户端程序,其访问接口方式有多种,根据官方提供的资料大约有如下几种方式:
- 使用OPCNetAPI,需要用到OPCNetAPI.dll,OPCNetAPI.Com.dll
 - 使用自动化接口,需要用到OPCDAAuto.dll
 - 使用自定义接口,需要用到多个Wrapper:OpcRcw.Ae.dll,OpcRcw.Batch.dll,OpcRcw.Comn.dll,OpcRcw.Da.dll,OpcRcw.Dx.dll,OpcRcw.Hda.dll,OpcRcw.Sec.dll
 
对于像C++这样的语言来开发OPC客户端时,一般需要使用自定义接口的方式。而如果采用VB和C#这样的语言来开发OPC客户端时,一般就采用自动化接口。要使用OPC自动化接口,首先要引用OPCDAAuto.dll文件,并在开发环境中做好相关的引用配置。
2、自动化接口简介
自动化接口是OPC基金会组织为了方便并统一OPC客户端开发而发布的一个接口、属性和方法的协议集。其访问服务器的流程如下:

自动化接口中共定义了6类对象:OPCServer对象、OPCBrowser对象、OPCGroups对象、OPCGroup对象、OPCItems对象、OPCItem对象。接下来简要描述一下这些对象的主要功能。
(1)、OPCServer对象
由客户端创建的OPCServer自动化对象。然后客户端通过其方法实现连接到OPC数据访问自定义接口。OPCServer对象现在可以用来获取关于OPC服务器的一般信息,并创建和操作OPCGroup对象的集合。
主要的属性:
| 
 StartTime  | 
 CurrentTime  | 
 LastUpdateTime  | 
| 
 MajorVersion  | 
 MinorVersion  | 
 BuildNumber  | 
| 
 VendorInfo  | 
 ServerState  | 
 LocaleID  | 
| 
 Bandwidth  | 
 OPCGroups  | 
 PublicGroupNames  | 
| 
 ServerName  | 
 ServerNode  | 
 ClientName  | 
主要的方法:
| 
 GetOPCServers  | 
 Connect  | 
 Disconnect  | 
| 
 CreateBrowser  | 
 GetErrorString  | 
 QueryAvailableLocaleIDs  | 
| 
 QueryAvailableProperties  | 
 GetItemProperties  | 
 LookupItemIDs  | 
(2)、OPCBrowser对象
OPCBrowser对象是在服务器中存在的分支或项目名称的集合。其是可选的。如果服务器不支持,将不会创建这个对象。
主要的属性:
| 
 Organization  | 
 Filter  | 
 DataType  | 
| 
 AccessRights  | 
 CurrentPosition  | 
 Count  | 
主要的方法:
| 
 Item  | 
 ShowBranches  | 
 ShowLeafs  | 
| 
 MoveUp  | 
 MoveToRoot  | 
 MoveDown  | 
| 
 MoveTo  | 
 GetItemID  | 
 GetAccessPaths  | 
(3)、OPCGroups对象
OPCGroups是OPCGroup对象的集合,以及创建、删除和管理它们的方法。
该对象还具有OPCGroup默认属性。当添加OPCGroups时,DefaultGroupXXXX属性设置其初始状态。可以更改默认值,以添加具有不同初始状态的opc组。更改默认值并不会影响已经创建的组。添加OPCGroup后,它的属性可以被修改。这减少了调用Add方法所需的参数数量。
主要的属性:
| 
 Parent  | 
 DefaultGroupIsActive  | 
 DefaultGroupUpdateRate  | 
| 
 DefaultGroupDeadband  | 
 DefaultGroupLocaleID  | 
 DefaultGroupTimeBias  | 
| 
 Count  | 
主要的方法:
| 
 Item  | 
 Add  | 
 GetOPCGroup  | 
| 
 Remove  | 
 RemoveAll  | 
 ConnectPublicGroup  | 
| 
 RemovePublicGroup  | 
(4)、OPCGroup对象
OPC组为客户组织数据提供了一种方式。例如,组可能表示特定操作符显示或报告中的项。数据可以读写。基于异常的连接也可以在客户端和组中的项之间创建,可以根据需要启用和禁用。OPC客户机可以配置OPC服务器应该向OPC客户机提供数据更改的速率。
主要的属性:
| 
 Parent  | 
 Name  | 
 IsPublic  | 
| 
 IsActive  | 
 IsSubscribed  | 
 ClientHandle  | 
| 
 ServerHandle  | 
 LocaleID  | 
 TimeBias  | 
| 
 DeadBand  | 
 UpdateRate  | 
 OPCItems  | 
主要的方法:
| 
 SyncRead  | 
 SyncWrite  | 
 AsyncRead  | 
| 
 AsyncWrite  | 
 AsyncRefresh  | 
 AsyncCancel  | 
(5)、OPCItems对象
这个对象还具有OPCItem默认的属性。当添加OPCItem时,DefaultXXXX属性设置其初始状态。可以更改默认值,以添加具有不同初始状态的OPCItems。当然,一旦添加了OPCItem,它的属性可以被修改。这减少了调用Add方法所需的参数数量。
主要的属性:
| 
 Parent  | 
 DefaultRequestedDataType  | 
 DefaultAccessPath  | 
| 
 DefaultIsActive  | 
 Count  | 
主要的方法:
| 
 Item  | 
 GetOPCItem  | 
 AddItem  | 
| 
 AddItems  | 
 Remove  | 
 Validate  | 
| 
 SetActive  | 
 SetClientHandles  | 
 SetDataTypes  | 
(6)、OPCItem对象
OPC项表示与服务器中的数据源的连接。与每个项目相关联的是一个值,质量和时间戳。值以变量的形式出现,质量类似于Fieldbus指定的值。
主要的属性:
| 
 Parent  | 
 ClientHandle  | 
 ServerHandle  | 
| 
 AccessPath  | 
 AccessRights  | 
 ItemID  | 
| 
 IsActive  | 
 RequestedDataType  | 
 Value  | 
| 
 Quality  | 
 TimeStamp  | 
 CanonicalDataType  | 
| 
 EUType  | 
 EUInfo  | 
主要的方法:
| 
 Read  | 
 Write  | 
3、客户端的开发
接下来我们基于C#开发OPC客户端。上面说明了自动化接口具体情况,我们需要进一步针对自己的具体应用编写代码。
首先,封装一斜对象、用于存取相关的属性,如:OPC服务器信息(OPCServerInfo)、OPC数据项(OPCDataItem)、组属性(GroupProperty)等。对于组属性我们还需要赋予默认值。代码如下:
public class OPCServerInfo
    {
        public DateTime StartTime { get; set; }
        public string ServerVersion { get; set; }
    }
    public class OPCDataItem
    {
        public object ItemName { get; set; }
        public object ItemValue { get; set; }
        public object Quality { get; set; }
        public object TimeStamp { get; set; }
    }
    public class GroupProperty
    {
        public bool DefaultGroupIsActive { get; set; }
        public float DefaultGroupDeadband { get; set; }
        public int UpdateRate { get; set; }
        public bool IsActive { get; set; }
        public bool IsSubscribed { get; set; }
        public GroupProperty()
        {
            DefaultGroupIsActive = true;
            DefaultGroupDeadband = ;
            UpdateRate = ;
            IsActive = true;
            IsSubscribed = true;
        }
    }
接下来,为了使用方便我们封装了一个ClientHelper类用于实现相关的操作,应为在一个客户端应用中,该对象是唯一的我们为了使用方便将其声明为静态类,以便于使用。具体代码如下:
    public class ClientHelper
    {
        /// <summary>
        /// 获取可以使用的OPC服务器
        /// </summary>
        /// <param name="hostName">获取OPC服务器的主机名称</param>
        /// <returns>返回OPC服务器列表</returns>
        public static List<string> GetOPCServerName(string hostName)
        {
            try
            {
                OPCServer OpcServer = new OPCServer();
                object opcServers = OpcServer.GetOPCServers(hostName);
                List<string> serverList = new List<string>();
                foreach (string opcServer in (Array)opcServers)
                {
                    serverList.Add(opcServer);
                }
                return serverList;
            }
            catch(Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 连接到指定的OPC服务器
        /// </summary>
        /// <param name="serverName">服务器名称</param>
        /// <param name="serverIP">服务器IP</param>
        /// <returns>返回的OPC服务器</returns>
        public static OPCServer ConnectToServer(string serverName, string serverIP)
        {
            OPCServer opcServer = new OPCServer();
            try
            {
                opcServer.Connect(serverName, serverIP);
                if (opcServer.ServerState != (int)OPCServerState.OPCRunning)
                {
                    opcServer.Disconnect();
                    return null;
                }
            }
            catch
            {
                opcServer.Disconnect();
                return null;
            }
            return opcServer;
        }
        /// <summary>
        /// 获取OPC服务器的相关信息
        /// </summary>
        /// <param name="opcServer">OPC服务器对象</param>
        /// <returns>OPC服务器信息</returns>
        public static OPCServerInfo GetServerInfo(OPCServer opcServer)
        {
            OPCServerInfo serverInfo = new OPCServerInfo();
            serverInfo.StartTime=opcServer.StartTime;
            serverInfo.ServerVersion = opcServer.MajorVersion.ToString() + "." + opcServer.MinorVersion.ToString() + "." + opcServer.BuildNumber.ToString();
            return serverInfo;
        }
        /// <summary>
        /// 展开OPC服务器的节点
        /// </summary>
        /// <param name="opcServer">OPC服务器</param>
        /// <returns>返回展开后的节点数据</returns>
        public static OPCBrowser RecurBrowse(OPCServer opcServer)
        {
            OPCBrowser opcBrowser = opcServer.CreateBrowser();
            //展开分支
            opcBrowser.ShowBranches();
            //展开叶子
            opcBrowser.ShowLeafs(true);
            return opcBrowser;
        }
        public static OPCGroup CreateGroup(OPCServer opcServer, OPCItems opcItems, string opcGroupName, GroupProperty groupProperty)
        {
            try
            {
                OPCGroup opcGroup = opcServer.OPCGroups.Add(opcGroupName);
                opcServer.OPCGroups.DefaultGroupIsActive = groupProperty.DefaultGroupIsActive;
                opcServer.OPCGroups.DefaultGroupDeadband = groupProperty.DefaultGroupDeadband;
                opcGroup.UpdateRate = groupProperty.UpdateRate;
                opcGroup.IsActive = groupProperty.IsActive;
                opcGroup.IsSubscribed = groupProperty.IsSubscribed;
                //opcGroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(OpcGroupDataChange);
                //opcGroup.AsyncWriteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(KepGroup_AsyncWriteComplete);
                //opcItems = opcGroup.OPCItems;
                return opcGroup;
            }
            catch (Exception err)
            {
                throw err;
            }
        }
    }
最后就是使用前述的封装。
用C#开发基于自动化接口的OPC客户端的更多相关文章
- 基于第三方开源库的OPC服务器开发指南(3)——OPC客户端
		
本篇将讲解如何编写一个OPC客户端程序测试我们在前文<基于第三方开源库的OPC服务器开发指南(2)——LightOPC的编译及部署>一篇建立的服务器.本指南的目的是熟悉OPC服务器的开发流 ...
 - OPC协议解析-OPC客户端与服务器通讯解析
		
1 OPC服务器 OPC服务器, 是指按照OPC基金组织规定的OPC规范群开发的软件驱动.OPC服务器作为中间媒介负责从数据源读取数据再跟另外一端的客户端通信.在 OPC客户端/服务器 的结 ...
 - 关于OPC自动化接口编程(OPCDAAuto.dll)几点注意问题
		
为了能够在工作中方便的应用OPC和充分的理解OPC的开发流程.内部机制,这两天正在研究开发OPC客户端程序,一般我们开发OPC客户端程序有以下几种方式: (1) 使用OPCNetAPI,需 ...
 - 基于第三方开源库的OPC服务器开发指南(1)——OPC与DCOM
		
事儿太多,好多事情并不以我的意志为转移,原想沉下心好好研究.学习图像识别,继续丰富我的机器视觉库,并继续<机器视觉及图像处理系列>博文的更新,但计划没有变化快,好多项目要完成,只好耽搁下来 ...
 - 基于C#的MongoDB数据库开发应用(3)--MongoDB数据库的C#开发之异步接口
		
在前面的系列博客中,我曾经介绍过,MongoDB数据库的C#驱动已经全面支持异步的处理接口,并且接口的定义几乎是重写了.本篇主要介绍MongoDB数据库的C#驱动的最新接口使用,介绍基于新接口如何实现 ...
 - 五、利用EnterpriseFrameWork快速开发基于WebServices的接口
		
回<[开源]EnterpriseFrameWork框架系列文章索引> EnterpriseFrameWork框架实例源代码下载: 实例下载 前面几章已完成EnterpriseFrameWo ...
 - NX二次开发-基于MFC界面的NX对Excel读写操作(OLE方式(COM组件))
		
NX二次开发API里没有对EXCAL读写操作的相关函数,市面上有很多种方法去实现,比如UFUN调KF,ODBC,OLE(COM组件)等等.这里我是用的OLE(COM组件)方式去做的,这种在VC上创建的 ...
 - 自动化接口差异测试-diffy  回归测试  charles rewrite 请求
		
https://mp.weixin.qq.com/s/vIxbtQtRRqgYCrDy7XTcrA 自动化接口差异测试-diffy Boris 搜狗测试 2018-08-30 自动化接口差异测试- ...
 - [Intel Edison开发板] 05、Edison开发基于MRAA实现IO控制,特别是UART通信
		
一.前言 下面是本系列文章的前几篇: [Intel Edison开发板] 01.Edison开发板性能简述 [Intel Edison开发板] 02.Edison开发板入门 [Intel Edison ...
 
随机推荐
- sqlserver 备份脚本
			
BACKUP DATABASE 数据库名称 TO DISK='d:\3333.bak' ---根据时间生成文件名 --将SQL脚本赋值给变量declare @SqlBackupDataBase as ...
 - python后端从数据库请求数据给到前端的具体实现
			
先来贴一窜代码让大家理解前端/后端/数据库的工作原理, 首先简要说明:前端向后端请求数据,后端根据前端请求数据的类别分析其需求,并连接到数据库获取相应数据: 来一段简单的实例代码模拟淘宝商城: 前端代 ...
 - vue-CLI踩坑记
			
vue init webpack vue-demo 使用 windows 7 DOS命令行和gitbash都有选择和实际选择结果不一致的问题, DOS命令行只在 Vue build有问题, gitba ...
 - 【CentOS】MySQL的安装
			
版本信息:CentOS 7.2 64位 CentOS(Community Enterprise Operating System,中文意思是:社区企业操作系统)是Linux发行版之一,它是来自于Red ...
 - C - Alphabetic Removals
			
题目链接: You are given a string ss consisting of nn lowercase Latin letters. Polycarp wants to remove e ...
 - Jupyter如何将numpy数据以图像形式展现?
			
示例如下: %matplotlib inline import matplotlib import matplotlib.ptplot as plt img = np.random.random((1 ...
 - Network Architecture Search Survey
 - Springboot 配置 ssl 实现HTTPS 请求  & Tomcat配置SSL支持https请求
			
SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议.TLS与 ...
 - Zookeeper学习笔记3
			
客户端的操作 zkCli.sh 官方文档 ls / [zookeeper] get / cZxid = 0x0 ctime = Thu Jan 01 08:00:00 CST 1970 mZxid = ...
 - SpringMVC中请求路径参数使用正则表达式
			
@GetMapping("/user/{id:\\d+}") //使用正则指定Id为数字 public User getInfo(@PathVariable String id){ ...