基于OPC规范的客户应用程序实现
石林锁,王涛,刘顺波
(第二炮兵工程学院机电工程系,陕西西安 710025)摘要:介绍了过程控制领域中引进的一种新技术-OPC数据访问标准,论述了OPC相关概念、基础及OPC标准接口,并以OPC数据访问定制接口规范(1.0A)为蓝本,给出了利用Visual C++实现OPC客户应用程序的详细步骤。关键词:过程控制;OPC规范;接口;客户应用中图分类号:TP 文献标码:A
The Realization of Client Application Based on OPC Specification
SHI Lin-suo
,
WANG Tao
,
LIU Shun-bo
(Dept. of Mechanical and Electronic, 2nd Artillery Engineering College, Xi'an 710025, China)
Abstract:
The paper introduces the OPC data access standard which was introduced into process control field recently, and discusses relative concepts, fundamentals and standard interfaces of OPC (Ole for Process Control). On the basis of OPC Data Access Custom Interface Specification (1.0A), the author gives out the detailed procedures to realize OPC client application using Visual C++.
Key Words:
Process control; OPC specification; Interface; Client application
随着计算机技术与控制技术的不断发展,现代工业过程控制系统逐渐发展成为由现场设备管理、过程管理和商业管理三个层次组成的系统。在这种新的过程工业信息体系结构中,从现场设备管理层、过程控制管理层到商业管理层包含了各种信息。为了实现整个过程控制系统的信息集成,需要解决许多问题,其中最重要的是通信兼容问题。因为现场管理层中大量的现场数据信息必须以一致的形式提供给用户或应用程序;过程管理层必须将现场管理层送来的信息及时加以处理并递交商业管理层;在商业管理层中这些信息又以一致的形式送给客户应用程序以简化信息的综合过程。所以,解决这些问题的关键在于为过程控制系统的数据访问提供一种开放有效的通信标准。
在传统系统中,解决客户应用程序从数据源(如:现场设备、
SCADA
系统等)读取数据的方法是为不同的客户应用程序编写不同的驱动程序。但是,这种方式存在许多问题,如同一个设备为适应不同的应用程序可能需要多种驱动程序,不同的驱动程序之间存在着不一致性,驱动程序对硬件存在着极大的依赖性等等。为了解决这些问题,一些与微软公司合作的自动化硬件和软件供应商联合制定了一套称为
OPC
规范的
OLE/COM
接口协议,以此来提高过程控制工业中的自动化
/
控制应用程序,现场系统
/
设备以及商业
/
办公室应用程序之间的互操作性。可以说
OPC
是工业监控软件的现场总线,其基本思想是:每个硬件供应商为其设备开发一个通用的数据接口(即
OPC Server
),供其它系统读写信息,客户应用软件也可以通过
OPC
规范的接口来读写硬件设备的信息(作为
OPC Client
)。由于硬件供应商通常将硬件驱动程序封装成
OPC Server
单独出售,这样作为
OPC
数据客户端的上层应用,可以不包含任何通讯接口程序,不必关心底层硬件内部的具体细节,只需遵循
OPC
数据接口协议,就能够从不同的硬件供应商提供的
OPC
数据服务器中取得数据。
OPC
规范提供了两套接口方案,即定制接口和自动化接口。定制接口效率高,通过该接口,客户能够发挥
OPC
服务器的最佳性能,采用
C
++语言的客户一般采用定制接口方案;自动化接口使解释性语言和宏语言访问
OPC
服务器成为可能,采用
VB
等语言的客户一般采用自动化接口。本文详细介绍了在
Visual C++
环境下,使用
OPC
定制接口访问
OPC
服务器的通用实现方法。
1 OPC
的基本结构
OPC
由两套接口组成:
OPC
定制接口和
OPC
自动化接口,如图
1
所示。
OPC
服务器必须实现定制接口,可选择实现自动化接口。这两套标准接口的制定极大地方便了服务器和用不同语言开发的客户应用之间的通信,使用户对开发工具的选择有了较大的自由。
SCADA
图
1 OPC
接口
OPC
接口可以潜在地应用在许多应用程序中。它们可以用于从最低层设备中读取未加工的数据,再转化至
SCADA
或者
DCS
系统;也可以用于从
SCADA
或者
DCS
系统中采集数据输入到应用程序中。
OPC
是为从某一网络节点中的某一服务器中采集数据而设计的,同时又能够形成
OPC
服务器。该服务器允许客户应用软件在由许多不同的
OPC
供应商提供的服务器中传输数据,并可通过单一的对象在不同的节点上运行,其工作特点如图
2
所示。
图
2 OPC
客户
/
服务器关系
2 OPC
定制接口
用
C
或
C
++编写
OPC
客户应用程序时可以使用定制接口,也可以使用自动化接口。由于定制接口具有更高的性能,建议尽可能使用定制接口。本文在
VC
下实现的客户应用程序采用的是
OPC
定制接口
1.0
。
OPC
定制接口的类模式可以根据其接口及其方法划分为
3
组,依次呈包含关系,如图
3
所示。
图
3 OPC
定制接口的类模式
2.1 OPC Server
对象
OPC Server
即
OPC
启动服务器,通过它获得其他对象和服务的起始类,并用于返回
OPC Group
类对象。
OPC Server
级别有多种属性,其中包含一个
OPC
服务器对象的状态和版本等信息。这种级别中的对象由客户应用创建。
IOPCServer
接口包含管理
OPC Group
级别中的对象的方法。如将组加入服务器或从服务器中删除组的方法(
"
AddGroup
"
,
"
RemoveGroup
"
)。
IOPCBrowseServerAddressSpace
接口包含查找服务器地址空间的方法。
IOPCCommon
接口方法用于通知服务器语言的设置和客户机的名称。同时还存在以下接口:图
4
说明了
OPC Server
对象及其定制接口。
图
4 OPC Server
对象
2.2 OPC Group
对象
OPC Group
存储由若干
OPC Item
组成的
Group
信息,并用于返回
OPC Item
类对象。
OPC Group
级别管理被称为
OPC Item
的各个过程变量。
IOPCItemMgt
接口提供将项加入组或从组中删除项的方法(
"
AddItem
"
,
"
RemoveItem
"
)。
IOPCGroupStateMgt
接口的方法用于处理组专用的参数或复制组。同时还存在以下接口:图
5
说明了
OPC Group
对象及其定制接口。
图
5 OPC Group
对象
2.3 OPC Item
对象
OPC Item
存储具体
Item
的定义、数据值、状态值等信息。
OPC Item
级别的一个对象代表与一个过程变量的连接。该对象的唯一接口是
OPCItemDisp
。关于
OPC Item
的信息可以在属性表中找到,例如数值(
"
Value
"
)属性或存取路径(
"
AccessPath
"
)属性。图
6
说明了
"
OPC Item
"
对象及其接口。
图
6 OPC Item
对象
由于本文使用定制接口实现
OPC
客户应用程序,所以不使用
IOPCItemDisp
接口,而是使用枚举器对象
EnumOPCItemAttributes
的
IEnumOPCItemAttributes
接口枚举服务器中的所有
OPC Item
。如图
7
所示。
图
7 EnumOPCItemAttributes
对象
3 OPC
客户应用程序的实现
3.1
操作
OPC
的类模型
按照
OPC
的类模型,当对象方法调用
OPC
对象时必须遵循一定的顺序。如果要创建一个
OPC Item
类的实例,则首先需要一个
OPC Group
对象。而要创建一个
OPC Group
对象的前提是存在一个
OPC Server
类的实例,并建立一个与该服务器的连接。图
8
说明了操作
OPC
类模型的流程。
图
8
操作
OPC
类模型的流程
3.2
编程顺序
本文在
Visual C++
环境中实现的
OPC
客户应用程序包括所有通常在典型客户应用下都会有的部分,如:建立与服务器的连接,初始化变量的组,以及为一个项读写数据。下面详细介绍一下在
VC
环境下
OPC
应用的基本结构。
第一步:登陆
COM
如果程序要调用
COM
库的某一函数,必须先登陆
COM
。函数
CoInitialize()
可以完成此功能。从函数
CoGetMalloc()
可以得到一个指向
COM
内存管理接口的指针。
HRESULT r1;
r1= CoInitialize(NULL);
r1= CoGetMalloc(MEMCTX_TASK,&g_pIMalloc);
第二步:将
ProgID
变换为
CLSID
每个
COM
服务器有一个字符串类型的
ProgID
,通过它可以得到一个全球唯一的
CLSID
。用
CLSIDFromProgID()
函数可以实现这个转换。
ProgID
用变量
szName
进行参数传递。
r1= CLSIDFromProgID(szName,&clsid);
第三步:建立与
OPC
服务器的连接
CoCreateInstance()
函数创建一个
OPC Server
类实例,其
CLSID
值设定如下。
r2=CoCreateInstance(clsid,NULL,CLSCTX_LOCAL_SERVER,IID_IUnkown,(void**)&pUNK);
这段程序的结果是得到一个指向服务器对象
IUnkown
接口的指针(变量
pUNK
)。
第四步:请求其它接口指针
从
IUnkown
接口,通过
QueryInterface()
方法可以得到其它接口的指针。
HRESULT r3;
r3=punk->QueryInterface(IID_IOPCServer,(void**)&m_pOPC);
这段程序的结果是得到一个指向服务器对象
IOPCSever
接口的指针(变量
m_pOPC
)。
第五步:创建
OPC
组
IOPCServer
接口的
AddGroup()
方法可以创建
OPC
组。
HRESULT r1;
r1=m_pOPC->AddGroup(szName,TRUE,500,&TimeBias,&PercDeadband,dwLCID,&m_GrpServerHandle,
&RevUpRate,IID_IOPCItemMgt,(LPUNKNOWN*)&m_pItemMgt);
这段程序的执行结果是创建一个有指定名称和属性的组。在返回的参数中,有一个指向所需要的进程组对象
IOPCItemMgt
接口的指针(变量
m_pItemMgt
)。
第六步:添加项
IOPCItemMgt
接口的
AddItems()
方法可以添加
OPC
项。
HRESULT r1;
r1=m_pItemMgt->AddItems(NumItems,pItems,&m_pItResult,&pErrors);
这段程序的结果是添加具有特殊属性的指定数量的项。除此之外,事件结构变量
m_pItResult
(服务器句柄,目标系统上的项数据类型等)也被赋值。
第七步:用
OPC
项执行所需的操作
用于执行所需操作的指针需要通过现有的指向
IOPCItemMgt
接口的指针得到。如:如果用户要进行异步通信,就需要指向
IOPCAsyncIO
接口的指针。
HRESULT r1;
r1=m_pItemMgt->QueryInterface(IID_IOPCAsyncIO,(void**)&pAsyncIO);
通过该接口的
Read()
和
Write()
两个方法,就可以读写项的数值。
HRESULT r2;
r2=pAsyncIO->Read(m_dwConnection,OPC_DS_CACHE,dwNumItems,phServer,&m_TransactionID,
&pErrors);
这段程序的执行结果是,
OPC
项的数据被送到客户程序的
IAdviseSink
接口。
HRESULT r3;
r3=pAsyncIO->Write((m_dwConnection,dwNumItems,phServer, pItemValues,&m_TransactionID,&pErrors);
这段程序的执行结果是,
OPC
服务器代替
OPC
客户刷新物理设备的数据。
第八步:删除对象,释放内存
在程序停止运行之前,必须删除已创建的
OPC
对象并释放内存。到目前为止,用到的接口都有相应的函数。
r1=m_pItemMgt->RemoveItems(dwNumItems,phServer,&pErrors);
r1=m_pOPC->RemoveGroup(m_GrpServerHandle,TRUE);
m_pItemMgt->Release();
m_pOPC->Release();
3.3
异步通信的说明
OPC
客户和
OPC
服务器进行数据交换可以有两种不同的方式,即同步方式和异步方式。同步方式实现较为简单,当客户数目较少而且同服务器交互的数据量也比较少的时候可以采用这种方式;异步方式实现较为复杂,需要在客户程序中实现服务器回调函数。然而当有大量客户和大量数据交互时,异步方式的效率更高,能够避免客户数据请求的阻塞,并可以最大限度地节省
CPU
和网络资源。本文中用
VC
实现的
OPC
客户程序可以执行异步读写数据,异步意味着程序继续执行后面的操作,只要读或写的任务送达马上申请读写,并由
OPC
服务器返回回调函数的执行结果。为了实现异步通信,客户程序必须提供
IAdviseSink
接口与服务器方的
IDataObject
接口通信。下面详细描述一下用
VC
实现
OPC
客户应用程序中异步通讯的基本步骤。
第一步:得到指向
IDataObject
接口的指针
可以用这个接口在客户和服务器之间建立连接。为此目的,可以在程序中创建由
IAdviseSink
接口派生的
COPCData
类,并建立一个此类的实例
m_pOPCIData
,指向
IDataObject
接口的指针临时保存在这个类的
m_pDataObject
成员变量中。
m_pOPCIData=new COPCData(pWnd);
..........
r1=m_pItemMgt->QueryInterface(IID_IDataObject,(LPVOID*)&m_pOPCIData->m_pDataObject);
第二步:取得指向
IAdviseSink
接口的指针
客户必须能够和服务器建立联系,借此可以收到服务器的通知。
IAdviseSink
接口可以完成这个任务。通过
QueryInterface()
方法可以得到这个接口的指针并把它赋给变量
pAdviseSink
。
m_pOPCIData-> QueryInterface(IID_IAdviseSink,(LPVOID*)&pAdviseSink);
第三步:建立连接
如果有关接口都存在,就可以建立连接。这可由
IDataObject
接口的
DAdvise()
方法完成,在这个方法中指向
IAdviseSink
接口的指针被传递给服务器。
r1=m_pOPCIData->m_pDataObject->DAdviseSink(&formatEtc,ADVF_PRIMEFIRST,pAdviseSink,
&m_dwConnection);
第四步:收到服务器的通知
如果数据发生变化,服务程序将调用
IAdviseSink
接口的
OnDataChange()
方法。这个方法是在客户应用程序中执行的。
OPC
项的实际数据被赋值给用户定义的成员变量
m_ItemValues,
这就意味着在客户应用程序中可以获得这些想要的数据。
r2=VariantChangeType(&(g_pOPCServer->m_ItemValues[hItClient]),&Value,0,VT_BSTR);
第五步:显示读出的数据
在这里,
OnDataChange()
方法发送
Windows
消息
WM_DATA_CHANGE
启动下一步的处理。
SendMessage(*m_pWnd,WM_DATA_CHANGE,0,0);
通过在
OPC
客户应用程序的显示程序中定义消息映射,如果收到上述消息,则调用
OnDataChange()
事件过程。
ON_MESSAGE(WM_DATA_CHANGE,OnDataChange);
这个事件过程很简单,它只是调用用户自定义的
ItemsView()
函数在
OPC
客户应用程序的显示界面上显示实际的数据。
ItemView(g_pOPCServer->m_pItAttr,g_pOPCServer->m_ItemValues,4);
4
结束语
OPC
规范把硬件供应商和应用软件开发者分离开来,使得双方的工作效率都有了很大提高。软件开发商无需了解硬件的实质和操作过程,只要遵循
OPC
规范进行开发,就能够访问
OPC
服务器中的数据。
OPC
十分适应过程控制的需要,开发商可用
C++
等高级语言编写软件程序,大大简化了过去从设备传输数据的复杂过程。本文介绍的在
Visual C++
环境下开发使用定制接口访问数据的
OPC
客户程序,能够发挥
OPC
服务器的最佳性能,完全可以满足过程控制领域对数据的实时、高效的要求。
参考文献:
[1] OPC Data Access Specification 1.0A[S].OPC Fundation
,
1997.
[2] OPC Overview 1.0[S]. OPC Fundation
,
1998.
[3] OPC Common Definations and Interfaces 1.0[S]. OPC Fundation
,
1998.
[4] Dale Rogerson,
杨秀章
江英译
.COM
技术内幕
[M].
北京:清华大学出版社,
1999.
[5]
潘爱民
. COM
原理与应用
[M].
北京:清华大学出版社,
1999.
[6] Michael J. Young .
邱仲潘等译
.Visual C++6
从入门到精通
[M].
北京:电子工业出版社
,1999.
[7] Al Chisholm. A Technical Overview of the OPC DadaAccess Interface[J]. Intellution Inc.1999.
[8]
马国华
.
监控组态软件及其应用
[M].
北京:清华大学出版社
, 2001.
作者简介:
石林锁(
1959
-),男,硕士,教授,主要从事自动控制、自动检测方面的教学和研究;王涛(
1977
-),男,硕士,研究生,主攻计算机应用;刘顺波(
1963
-),男,博士后,副教授,主要从事制冷空调装置自动化方面的教学和研究。
通讯地址:
西安市第二炮兵工程学院
502
室
邮编
710025
王
涛(收)
电话:
029
-
3344102