PC软件开发技术之二:用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对象。接下来简要描述一下这些对象的主要功能。

2.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.2、OPCBrowser对象

OPCBrowser对象是在服务器中存在的分支或项目名称的集合。其是可选的。如果服务器不支持,将不会创建这个对象。

主要的属性:

Organization

Filter

DataType

AccessRights

CurrentPosition

Count

主要的方法:

Item

ShowBranches

ShowLeafs

MoveUp

MoveToRoot

MoveDown

MoveTo

GetItemID

GetAccessPaths

2.3、OPCGroups对象

OPCGroups是OPCGroup对象的集合,以及创建、删除和管理它们的方法。

该对象还具有OPCGroup默认属性。当添加OPCGroups时,DefaultGroupXXXX属性设置其初始状态。可以更改默认值,以添加具有不同初始状态的opc组。更改默认值并不会影响已经创建的组。添加OPCGroup后,它的属性可以被修改。这减少了调用Add方法所需的参数数量。

主要的属性:

Parent

DefaultGroupIsActive

DefaultGroupUpdateRate

DefaultGroupDeadband

DefaultGroupLocaleID

DefaultGroupTimeBias

Count

 

 

主要的方法:

Item

Add

GetOPCGroup

Remove

RemoveAll

ConnectPublicGroup

RemovePublicGroup

 

 

2.4、OPCGroup对象

OPC组为客户组织数据提供了一种方式。例如,组可能表示特定操作符显示或报告中的项。数据可以读写。基于异常的连接也可以在客户端和组中的项之间创建,可以根据需要启用和禁用。OPC客户机可以配置OPC服务器应该向OPC客户机提供数据更改的速率。

主要的属性:

Parent

Name

IsPublic

IsActive

IsSubscribed

ClientHandle

ServerHandle

LocaleID

TimeBias

DeadBand

UpdateRate

OPCItems

主要的方法:

SyncRead

SyncWrite

AsyncRead

AsyncWrite

AsyncRefresh

AsyncCancel

2.5、OPCItems对象

这个对象还具有OPCItem默认的属性。当添加OPCItem时,DefaultXXXX属性设置其初始状态。可以更改默认值,以添加具有不同初始状态的OPCItems。当然,一旦添加了OPCItem,它的属性可以被修改。这减少了调用Add方法所需的参数数量。

主要的属性:

Parent

DefaultRequestedDataType

DefaultAccessPath

DefaultIsActive

Count

 

主要的方法:

Item

GetOPCItem

AddItem

AddItems

Remove

Validate

SetActive

SetClientHandles

SetDataTypes

2.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 = 0;UpdateRate = 250;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;}}}

最后就是使用前述的封装,实现客户端应用。

欢迎关注:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499437.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

标记符控制的分水岭算法原理及matlab实现

-------------------------------------------------------------------------------------------------------------------- 附录A 教程【3】给出的matlab源码&#xff0c;附详细注释 function [ ] MarkerControlled_Watershed_tutorial( ) %标记符控制的分水岭算法教程 …

PC软件开发技术之三:C#操作SQLite数据库

我们在开发应用是经常会需要用到一些数据的存储&#xff0c;存储的方式有多种&#xff0c;使用数据库是一种比较受大家欢迎的方式。但是对于一些小型的应用&#xff0c;如一些移动APP&#xff0c;通常的数据库过于庞大&#xff0c;而轻便的SQLite则能解决这一问题。不但操作方便…

自动搜索数据增强方法分享——fast-autoaugment

前言 简短的介绍下分享fast-autoaugment的原因 毫无疑问数据增强对于训练CNN非常有效&#xff0c;大家也在不断发明新的数据增强方法 拿到一份数据集&#xff0c;我们凭借之前的经验组合不同的增强方法形成一个数据增强策略&#xff0c;通常可以得到一个还不错的baseline。但…

SSD之硬的不能再硬的硬核解析

本文是对经典论文 SSD: Single Shot MultiBox Detector 的解析&#xff0c;耗时3周完成&#xff0c;万字长文&#xff0c;可能是你能看到的最硬核的SSD教程了&#xff0c;如果想一遍搞懂SSD&#xff0c;那就耐心读下去吧~ 一句话总结SSD效果就是&#xff1a;比YOLO快一点且准很…

C语言学习及应用笔记之五:C语言typedef关键字及其使用

在C语言中有一个typedef关键字&#xff0c;其用来定义用户自定义类型。当然&#xff0c;并不是真的创造了一种数据类型&#xff0c;而是给已有的或者符合型的以及复杂的数据类型取一个我们自己更容易理解的别名。总之&#xff0c;可以使用typedef关键字定义一个我们自己的类型名…

Modbus协议栈开发笔记之五:Modbus RTU Slave开发

Modbus在串行链路上分为Slave和Master&#xff0c;这一节我们就来开发Slave。对于Modbus RTU从站来说&#xff0c;需要实现的功能其实与Modbus TCP的服务器端是一样的。其操作过程也是一样的。首先接收到主站的访问命令&#xff0c;对该命令报文进行解析&#xff0c;这里我们也…

Modbus协议栈开发笔记之六:Modbus RTU Master开发

这一节我们来封装最后一种应用&#xff08;Modbus RTU Master应用&#xff09;&#xff0c;RTU主站的开发与TCP客户端的开发是一致的。同样的我们也不是做具体的应用&#xff0c;而是实现RTU主站的基本功能。我们将RTU主站的功能封装为函数&#xff0c;以便在开发具体应用时调用…

PID控制器开发笔记之十三:单神经元PID控制器的实现

神经网络是模拟人脑思维方式的数学模型。神经网络是智能控制的一个重要分支&#xff0c;人们针对控制过程提供了各种实现方式&#xff0c;在本节我们主要讨论一下采用单神经元实现PID控制器的方式。 1、单神经元的基本原理 单神经元作为构成神经网络的基本单位&#xff0c;具…

基于STM32L476的锂电池SOC检测

便携式设备由于使用需求而配备了锂电池&#xff0c;但使用过程中需要掌握电源的状态才能保证设备正常运行。而且在电池充放电的过程中&#xff0c;监控电池的充放电状态也是保证设备安全的需要。 1、硬件设计 电池SOC检测是一个难题&#xff0c;有很多的模型和检测电路。但对…

C语言学习及应用笔记之六:C语言extern关键字及其使用

在C语言中&#xff0c;修饰符extern用在变量或者函数的声明前&#xff0c;用来以标识变量或者函数的定义在别的文件中&#xff0c;提示编译器遇到此变量或者函数时&#xff0c;在其它文件中寻找其定义。extern关键字的用法有几种&#xff0c;我们下面对其进行说明。 1、extern…

TCP/UDP 常用端口列表

计算机之间依照互联网传输层TCP/IP协议不同的协议通信&#xff0c;都有不同的对应端口。所以&#xff0c;利用短信&#xff08;datagram&#xff09;的UDP&#xff0c;所采用的端口号码不一定和采用TCP的端口号码一样。以下为两种通信协议的端口列表链接&#xff1a; 目录 1端…

C语言学习及应用笔记之七:C语言中的回调函数及使用方式

我们在使用C语言实现相对复杂的软件开发时&#xff0c;经常会碰到使用回调函数的问题。但是回调函数的理解和使用却不是一件简单的事&#xff0c;在本篇我们根据我们个人的理解和应用经验对回调函数做简要的分析。 1、什么是回调函数 既然谈到了回调函数&#xff0c;首先我们…

STM32与SHT1X温湿度传感器通讯

在这次项目开发中应用到了SHT1X温湿度传感器&#xff0c;该系列有SHT10、SHT11和SHT15&#xff0c;属于Sersirion温湿度传感器家族中的贴片封装系列。包括一个电容性聚合体测湿敏感元件、一个用能隙材料制成的测温元件&#xff0c;传感器内部有一个精度高达14为位的A/D转换器。…

STM32与MS5837压力传感器的I2C通讯

MS5837压力传感器是一种可用于电路板上&#xff0c;适用于检测10-1200mbar压力范围的传感器&#xff0c;灵敏度非常高&#xff0c;理论上能够检测到0.01mbar的压力变化&#xff0c;实际使用过程中测试并无明显的变化。 MS5837采用I2C总线通讯&#xff0c;与STM32的MCU可以实现…

STM32F0使用LL库实现MS5536C通讯

在本次项目中&#xff0c;限于空间要求我们选用了STM32F030F4作为控制芯片。这款MCU不但封装紧凑&#xff0c;而且自带的Flash空间也非常有限&#xff0c;所以我们选择了LL库实现。在本文中我们说明一下&#xff0c;使用LL库实现MS5536C的SPI通讯。 1、MS5536C简述 MS5536C是…

STM32F0使用LL库实现DMA方式AD采集

在本次项目中&#xff0c;限于空间要求我们选用了STM32F030F4作为控制芯片。这款MCU不但封装紧凑&#xff0c;而且自带的Flash空间也非常有限&#xff0c;所以我们选择了LL库实现。在本文中我们将介绍基于LL库的ADC的DMA采集方式。 1、概述 这次我们使用DMA方式实现对AD的采集…

STM32与宇电设备实现AI-BUS通讯

宇电的设备使用基于RS-485的自定义协议&#xff0c;协议本身比较简单&#xff0c;只有2条指令&#xff1a; 读&#xff1a;地址代号52H&#xff08;82&#xff09; 要读的参数代号00校验码 写&#xff1a;地址代号43H&#xff08;67&#xff09;要写的参数代号写入数低字节写…

FreeRTOS如何结束和重新启动调度程序

大多数主机或桌面系统&#xff08;比如Linux&#xff0c;Mac或Windows&#xff09;都有一个正常的用例&#xff0c;你可以在早上启动操作系统&#xff0c;然后在晚上关闭它&#xff0c;然后你就离开机器。嵌入式系统是不同的&#xff1a;他们没有参加&#xff0c;他们应该“永远…

先进过程控制之一:浅说APC

先进过程控制&#xff08;APC&#xff09;技术作为在生产装置级的信息化应用&#xff0c;在优化装置的控制水平和提高生产过程的管理水平的同时&#xff0c;还为企业创造了可观的经济效益。 1、什么是APC 先进过程控制&#xff0c;简称APC&#xff0c;并不是什么新概念。它仅…

STM32与多台MS5803压力传感器I2C通讯

MS5803压力传感器支持SPI和I2C总线通讯&#xff0c;拥有24位AD转换。能够同时获得压力值和温度值&#xff0c;其中压力测量范围为10-1100mbar&#xff0c;温度的测量范围是-40-85摄氏度。各引脚功能及参数如下&#xff1a; 传感器内部结构图如下&#xff1a; 通讯协议的选择通过…