OPC服务器设计
##总体结构
OPC数据服务器可按如图
所示的系统结构设计。它主要由服务器对象与接口、数据存储区、硬件驱动程序和服务器界面与设置等部分组成。各个部分功能相对独立又相互协作,形成一个统一的整体。OPC对象部分是OPC服务器程序与客户程序进行交互的部分。OPC对象包括服务器对象、组对象、项对象,其中前两个对象是真正的COM对象,能够将各自的接口暴露给客户程序。OPC服务器对象和组对象之间是聚合关系,即OPC服务器对象创建OPC组后,将组对象的指针传递给客户,由客户直接操纵组对象。而组对象只是简单地包容OPC项对象,客户程序通过组对象管理OPC项。在OPC服务器中,OPC对象部分需要与数据存储区和硬件驱动程序相联系,以便获取数据区中的数据或直接访问硬件设备。数据存储区中存放着OPC服务器中定义的数据项。数据项包括值、品质、时间戳三个基本属性,以及与硬件相关的属性,例如设备号、板卡号、通道号等。数据项的基本属性与OPC规范中定义的OPC项属性一致。客户程序通过组对象添加OPC项时,将OPC项与数据项关联起来,读取数据时返回其基本属性。数据存储区是服务器的中心部分,需要动态地管理和维护数据项,并与其他部分进行数据交互。服务器界面与设置部分为用户提供了友善的界面,使用户可以管理数据存储区中数据项并设置其属性。同时该部分负责对硬件的初始设置及在程序运行期间对硬件的监控和诊断,保证与现场设备的正常通信。该部分还负责保存这些设置,在OPC服务器程序每次运行时能够自动完成设置。硬件驱动程序是OPC服务器对硬件进行设置和读/写操作的部分,不同的硬件均需要开发相应的接口函数,并将底层细节封装起来以供服务器中其他部分调用。
设计步骤
由于OPC技术是以微软的COM技术为基础,同时需要直接与底层硬件打交道,所以采用VC实现比较灵活方便。下面给出实现OPC数据服务器的主要步骤。
(1)定义OPC数据服务器的名称(ProgID)和类标识(CLSID),实现COM库的初始化功能和OPC数据服务器类对象的接口功能。
(2)OPC对象部分的设计是关键步骤。首先通过继承IUnknown类派生出OPCServer、OPCGroup和OPCItem三个类,重载IUnknown类中的接口查询和引用计数函数。这三个类的实例分别对应OPC服务器对象、组对象和项对象。
OPC接口采用了一种称为“Tear-of”接口的COM高级技术,即创建一个对象时只实例化IUnknown接口和经常使用的接口,其他不常用的接口在客户程序需要使用时才创建,这样能够改进服务器的性能。OPC规范为每个接口都给出了详细的接口定义,OPC基金会的网站上也提供了相应的头文件。需要将这些头文件添加到工程中,然后通过继承这些接口派生出新的接口类,实现每个接口的成员函数。在OPCServer和OPCGroup类中增加指向相应接口类的指针成员变量。接着修改接口查询函数,当客户程序查询某一接口时实例化接口类,并返回接口指针变量。客户程序再通过该接口指针进一步调用接口成员函数。最后,可根据实际情况定义并实现各个继承类的特殊属性和方法,如增加读取存储区或硬件设备数据的函数等。设计者还可以在服务器对象或组对象中增加自己定义的接口,实现某些特定的功能。
(3)数据存储区的设计可利用C++标准模板库(STL)中的包容器,通过包容器管理OPC服务器中的数据项。由于OPC服务器既要对底层硬件进行读/写操作,又要通过OPC接口与客户程序进行交互,所以对数据存储区的操作需要采用多线程模型以保证数据存取的效率。为避免不同线程同时对数据区中的数据进行操作,还需考虑对临界区的互斥控制。
(4)为了方便用户操作,可以设计类似Windows中资源管理器的用户界面,将各数据项用树型结构表示。然后设计数据项和硬件的设置界面,并与数据存储区和硬件接口联系起来,实现相应的组态功能。在OPC服务器程序关闭时需要将数据项的属性及硬件设置参数作为组态文件保存起来;而在程序运行时能自动调入组态文件,完成初始设置。
(5)根据硬件的种类和特性自行开发驱动程序或者调用硬件厂商提供的I/O DLL,实现对现场设备进行设置及数据存取的功能。
(6)将以上几个部分结合起来,并用对OPC服务器程序进行测试和修改,完成最后的设计。在测试时也需要安装注册OPC基金会提供OPC标准组件,如OPCPROXY.DLL等,然后利用可靠的OPC客户程序进行测试。