在工业自动化领域,以往应用软件开发商要为每一个硬件开发驱动程序,而由于硬件的种类繁多,特征各异,软件开发商的负担可想而知,尤其是如果硬件特征发生了变动,整个应用软件相应的驱动程序也要相应地改动,这对开发商,对整个工程都是很不利的。而且由于驱动程序的不同,不同应用程序访问同一硬件设备时常常产生冲突。OPC(OLEForProcessControl)技术正是在这种情况下应运而生。当现场设备发生变化或系统中加入新设备时,由于服务器所提供的接口的一致性,工控软件不作更改即可继续使用,只是某些情况下可能需要重新组态(如添加新的PLC站点等),但是这也大大减小了软件维护的工作量;另一方面,工控软件的升级不依赖于服务器,可独立进行。正如OPC规范里所说,OPC将软件和硬件划清了界限。
目录OPC概述
OPC方法和属性
OPC原理逻辑图
OPC案例
01-OPC概述OPC服务器有两类接口:定制接口(Custominterface)、自动化接口(Automationinterface),定制接口比较低级,它提供更多的功能,效率比后者高,可以用C++语言调用此类接口,自动化接口主要用于VB,Delphi等开发工具。按照OPC规范,定制接口是服务商必须提供的,而自动化接口则是可选的,不过OPC基金会提供了一个叫做“自动化包装器”的动态连接库,用于在两者间转换。
在OPC的早期规范里主要包括OPC数据存取规范、OPC报警和事件、OPC历史数据存取规范。OPC数据存取规范详细规定了客户程序和服务器程序进行数据通信的机制,它类型的OPC服务器往往是在数据存取服务器的基础上通过增加对象、扩展接口而来的,所以该规范也是其它OPC规范的基础。OPC数据存取规范规定的基本对象有三类:OPCServer、OPCGroup和OPCItem,OPCServer包含服务器的所有信息,也是OPCGroup的容器,OPCGroup除了包含它自身信息外,还负责管理OPCItem。每一个OPCItem代表到数据源的一个连接,但它没有提供外部接口,客户端程序无法对OPCItem直接进行操作,应用程序必须依靠OPCItem的容器OPCGroup来对它进行操作。
OPC客户程序对OPC服务器中数据的存取方式分为同步读写方式和异步读写方式。客户程序可按照一定的周期调用OPCGroup对象的IOPCSyncIO接口对服务器程序进行数据同步存取操作,此时客户方的调用函数一直运行到所有数据读写完成,然后才能执行其它操作,因此,这种方法适合与读取少量数据,如果数据多的话,会使系统处于假死状态,无法进行操作。IOPCSyncIO2是从3.0版才出现的,是对IOPCSyncIO的增强。IOPCAsyncIO2和IOPCAsyncIO3是异步方式中使用的接口,异步访问时,当客户端对服务器提出访问要求后,立即返回到OPC应用程序执行其它操作,无须等待,当OPC服务器完成数据读取后通知OPC应用程序,应用程序从而得到数据。其中前者是在2.0版本重新定义的,具有较高的通信性能;后者则是在3.0版本中才刚刚出现,同IOPCSyncIO2类似,IOPCAsyncIO3是对IOPCAsyncIO2的增强。在异步方式下,服务器程序收到读请求后,调用客户程序方的IOPCDataCallback接口,将数据发送给客户程序。异步方式中允许服务器将读写操作进行排队,使客户方的调用函数可立刻返回,当服务器读写操作完成后再通知客户程序。显然,异步通报方式的通信效率更高,这种方式也是本文所要讨论的方式,但有多个客户程序与服务器相连时,同步读写方式更具时效性。对于每个组对象,客户程序可根据需要采用其中一种数据存取方式,而不能两者都使用。
异步读取还有一种特殊的方式,叫做订阅方式(Subscribe)这种情况下,应用程序不需要发出读请求,OPC服务器在定期更新数据的时候,如果发现数据有一定变化,则自动向应用程序发出通知和传输变化的数据。
02-OPC方法和属性1.OPCServer:
服务器对象OPCServer的一个实例,OPC服务器自动含有一个OPC组集合对象,并可在其基础上生成一个OPC浏览器对象。OPCServer服务器对象在使用其它OPC对象前必须生成,也就是说在引用其他对象之前必须先创建OPCServer。OPCServer对象提供了对数据源访问和通信的方法,其提供了“Connect”方法来连接OPC自动化服务器。
主要属性:
StartTime(只读属性,服务器启动运行的时间)
CurrentTime(只读属性,返回服务器显示的当前时间)
LastUpdateTime(对于本OPC应用程序的最后数据更新时间)
MajorVersion(只读属性,OPC服务器的主版本号)
MinorVersion(只读属性,OPC服务器的次版本号)
Bandwith(只读属性,返回OPC服务器的不敏感区的百分比)
ServerState(只读属性,返回服务器的运行状态,这个属性是比较重要的,方便客户端程序查询服务器的状态,从而达到排除故障的目的)
ServerName(只读属性,返回客户端程序所要连接的服务器的名字,也就是OPC服务器的ProgID)
ServerNode(服务器所在计算机名,或计算机的IP,用于连接远程的计算机)
主要方法:
GetOPCServers(获得已注册的OPC服务器的程序,即ProgID)
Connect(用来建立与OPC数据存储服务器的连接)
Disconnect(断开与服务器的连接)
CreateBrowser(创建OPC浏览器的对象)
事件:
只有一个ServerShutDown(关闭服务器,这个事件在服务器即将关闭之前发生,OPC服务器以此通知OPC客户程序预告即将关闭,OPC客户程序应该在接到此事件通知后,立即清除所有的OPC组并断开与OPC服务器的连接)。

2.OPCGroups
组集合对象OPC组的容器,包含所有客户端创建的OPCGroup对象的自动化集合。这个对象的用途是添加、清除和管理OPC组。
主要属性:
DefaultGroupIsActive(新添加的OPC组的活动状态的默认值。默认初始值是活动状态)
DefaultGroupUpdateRate(新添加的OPC组的默认数据更新周期,默认初始值是1000亳秒)、DefaultGrouPDeadband(新添加的OPC组的默认不敏感区的默认值,即能引起数据变化的最小数值百分比,默认值是0%)
DefaultGroupLocaleID(新添加的OPC组区域标识符的默认值)
DefaultGroupTimeBias(新添加的OPC组的时间偏差的默认值)等。
主要方法:
Item(OPC组集合的默认方法。返回由集合索引指定的OPC组对象)
Add(在OPC组集合对象中添加一个组对象)
GetOPCGroup(返回指定的OPC组)
RemoveAll(为服务器关机作准备,删除所有组和标签)
Remove(删除--个指定的组)
ConnectPublicGroup(连接到公共组)等。
事件:
AllGroupsDataChange(多个OPC组的数据变化而引发的事件)。

3.OPCGroup
组对象,OPCGroup的一个实例,它包含自身的信息,同时向OPCItems对象提供数据获取服务,它自动含有一个Items集合对象,允许客户端来组织它们需要访问的数据。OPCGroup可以作为一个单元来进行激活或停止激活操作。
主要属性:
Name(OPC组的名称)
IsPublic(判断是否公共组)
IsActive(控制组的激活状态。只有活动状态的OPC组才进行定期的数据更新)
IsSubscribed(控制组的订阅状态)
ClientHandle(客户句柄是由客户端程序指定的用于识别某个OPC组的长整型数。当进行数据访问或询问OPC组状态时,服务器将这个数值和结果--起返回给OPC客户程序)、TimeBias(数据采样时间的时间偏差值,用于调整设备时间和OPC服务器时间的偏差)、DeadBand(不敏感区,只有数据变化超过此不敏感区时,服务器才触发数据变化事件发生)
UpdateRate(数据更新周期)
OPCItems(OPC组的默认属性,OPC标签集合对象)。
主要方法:
SyncRead(同步读OPC组内单个或多个OPC项的数据值、质量标志和采样时间)
Syncwrite(同步写入OPC组内单个或多个OPC项的数据值)
AsyncRead(异步读)、Asyncwrite(异步写)
AsyncRefresh(触发数据变化事件发生,刷新OPC组内所有活动的OPC标签.的数据。结果有数据变化事件DataChange返回)等。
主要事件:
DataChange(在OPC组内任何OPC项的数据值或质量标志变化时触发的事件)、AsyncReadComplete(异步读结束时发生的事件)
AsyncWriteComplete(异步写结束时发生的事件)等。

4.OPCItems
项集合对象,是OPC项对象的容器,自动化客户程序创建的OPCGroup对象所包含的所有OPCItems对象的自动化集合。
主要属性:
Parent(返回所属的OPC组对象)
DefaultRequestedDataType(添加OPC项时,默认的要求的数据类型。初始值是控制设备的固有数据类型,既是VT__Empty)
DefaultAccessPath(添加OPC项时,默认的数据访问路径。初始值是空)
DefaultIsActive(添加OPC项时,默认的激活状态,初始值是真)
Count(集合对象的固有属性。OPC项集合中的OPC项数)。
主要方法:
Item(返回OPC标签集合中由集合索引指定的OPC标签)
GetOPCItem(返回OPC项集合中由服务器句柄指定的OPC项)
Addltem(在OPC项集合中添加新的OPC项)
Remove(删除指定的项)
Aalidate(检查项创建的有效性)SetActive(分别设置项为活动或非活动状态)
SetClientHandles(设置OPC项的客户句柄)
SetDataTypes(设置OPC项要求的数据类型)。

5.OPCItem
项对象表示与OPC服务器内某个数据的连接。各个项包含了数据值、质量标志以及采样时间。数据值的类型为VARIANT。
主要属性:
ClientHandle(客户句柄是由客户端程序指定的用于识别某个OPC组的长整型数。当OPC组事件发生时,服务器将这个客户句柄和结果--起返回给OPC客户程序)
ServerHandle(服务器句柄是有OPC服务器设置的用于识别某个OPC标签的一个全局唯一长整型数)
AccessPath(返回OPC客户程序指定的访问路径)
AccessRights(返回OPC项的访问权)
ItemID(返回识别这个OPC项的标识符)
IsActive(用以控制OPC项的活动状态)
RequestedDataType(获取项的值的数据类型)
Value(返回从OPC服务器读取的最新数据值)
Quality(返回从OPC服务器读取的最新数据值的质量标志)
TimeStamp(时间戳)等。
主要方法:
Read(从服务器读取OPC项的数值)、Write(向服务器写入OPC项的数值)。

6.OPCBrowser
浏览器对象OPCBrowser是OPC服务器名称空间的枝和叶的集合,可以浏览服务器配置中项的名字,一个OPCServer对象实例中只能有一个OPCBrowser对象的实例。浏览器功能是选用功能,OPC服务器不支持浏览器的时候,即使执行CreateBrowser也不生成这个对象。
主要属性:
Organization(OPC服务器的名称空间的类型,有平面型和树型两种类型)
Filter(使用ShowBrancher或ShowLeafs方法时的浏览对象过滤器,使用这个过滤器可以缩小被浏览的名称范围)
DataType(使用ShowLeafs方法时,希望浏览的标签的数据类型)
Count(浏览结果中的浏览标签数)。
主要方法:
Item(返回浏览结果中按集合索引ItemSpecifier指定的对象)
ShowBranches(将现在位置下的所有符合过滤条件的枝加入到浏览结果中)
ShowLeafs(将现在位置下的所有符合过滤条件的叶加入到浏览结果中)
MoveUp(向现在位置的上层移动)
MoveToRoot(向名称空间的最上层移动)
MoveDown(向现在位置的下层移动)
MoveTo(向浏览器的绝对位置移动)
GetItemID(由浏览标签的名称返回OPC标签的标识符)。
03-OPC原理逻辑图
OPCServer对象的结构


OPCClient与OPCServer交互结构


OPCServer的连接与断开


Part01

KepServer预先设定100个Tag,作为OPCServer的数据源
Part02
打开新建工程,勾选引用库
Part03
绘出OPC客户端的窗口各个控件以及布局
窗口主要结构为
业务栏:联系人、人员组、历史信息、设置
动作栏:连接、断开、添加、导出导入
数据结构栏:服务器、组、TAG
数据显示栏:动态报表
Part04
运行效果
Part05
功能解析
添加OPCServer服务器
浏览OPCServer服务器,选择本地或者远程节点的所有OPCServer
添加组
添加Tag
选择Tag,并为Tag设置属性(报警限、名称、注释、报警组等)
选择删除Tag
难点分析
还原/保存OPCServer、OPCGroup、OPCItem的数据关系
连接/断开多个OPCServer、OPCGroup的多线程并发设计
数据报表栏实时更新监控Tag数据
判断实时数据的值是否在合理范围并提示预警
系统可扩展性
Part06
系统介绍及功能扩展
这个OPC客户端可以是一个基础性的实时数据采集系统,可采集目前各个数据服务器的数据。并对数据进行一些逻辑运算,比如对Intouch模拟量的数据同步设置报警限,预警报警并以电话、语音、短信、邮件、微信等形式通知对应级别的人员,发生的报警会存为历史记录以供追溯。
连接GPRS模块或者外网可将数据上云,以web网页或者app/小程序的方式发布数据报表和画面动态显示,以实现远程监控。
OPC基础代码
OptionBase1DimWithEventsServerObjAsOPCServerDimGroupsObjAsOPCGroupsDimWithEventsGroupObjAsOPCGroupDimItemsObjAsOPCItemsDimServerHandles()AsLongDimClientHandles()AsLongDimItemId(2)AsStringDimErrors()AsLongIfServerObjIsNothingThenSetServerObj==("")IfIfGroupsObjIsNothingThenSetGroupsObj====TrueItemId(1)=""ItemId(2)=""ClientHandles(1)=1ClientHandles(2)=2(2,ItemId,ClientHandles,ServerHandles,Errors)DimTempServerHandles(1)AsLongDimTransactionIDAsLongDimCancelIDAsLongDimErrorNr()AsLongTempServerHandles(1)=ServerHandles(1),TempServerHandles,ErrorNr,TransactionID,CancelIDPrivateSubGroupObj_AsyncReadComplete(ByValTransactionIDAsLong,ByValNumItemsAsLong,ClientHandles()AsLong,ItemValues()AsVariant,Qualities()AsLong,TimeStamps()AsDate,Errors()AsLong)DimTempServerHandles(1)AsLongDimVValue(1)AsVariantDimErrorNr()AsLongDimTransactionIDAsLongDimCancelIDAsLongTempServerHandles(1)=ServerHandles(2)VValue(1)=1,TempServerHandles,VValue,ErrorNr,TransactionID,CancelIDPrivateSubgroupObj_AsyncWriteComplete(ByValTransactionIDAsLong,ByValNumItemsAsLong,ClientHandles()AsLong,Errors()AsLong),ServerHandles,ErrorsSetItemsObj===NothingIf以上即是一些关于OPC的基础内容,搞懂了OPC的逻辑原理以后就基本上可以自行解决很多通信的问题并设计自己想要的程序了。
PS:这个OPC客户端不一定要用开发,还可以用C#,C++,C等软件开发,但是性能各有差异,以下是我了解的开发的软件时效性对照表:
各个开发软件的性能时效表
乔柯里:我们是一群信息技术爱好者,我们乐于分享技术成果,只要能够帮助到更多的人。我们有共同的理想,那就是诗和远方,期待您加入我们,共创辉煌。
●InTouch-学习非常实用的手册大全
●InTouch-鼠标悬停自定义下拉菜单(含核心代码·耐心看)毫不逊色于Web网页菜单效果
●InTouch-警、历史报警详细步骤介绍
●Intouch-历史曲线一个不为人知的小“秘密”,真香
●Intouch-自行下拉菜单用法以及系统管理
●Intouch-利用SQL数据库发送邮件真实学习案例
●Intouch-历史报警/操作记录导出为EXCEL实例
●Intouch-历史数据库之报表曲线Historian客户端开发





