在物联网兴起之前,OPC这玩意就出来了,但是知道和用的人并不多。 OPC技术从某些角度来说,可以说还是掌握在比较少数的一部分人手中。这可能也是由于工控行业相对闭塞和保守的原因造成的。
就目前来说关于OPC开发的SDK或者开源项目还是比较多的,我就说几个基于C++的主流项目,LightOPC、OpcWorkshop、WtopcSvr,国内的也还有一些公司就是基于这几个主流项目然后发布了一些付费版的SDK,什么EasyOPC、OPCData等等,就不多讲啦。
在我目前的项目研究和实战开发中,主流的几款OPC服务器SDK基本上都轮了一边,比较起来个人真心推荐的还是WtopcSvr。区别其他的好处主要有两个:
1、开发真心轻松简单。因为高度封装,而且Api的调用对用户还是相当有好的,可以省很多开发时间。一天搭建服务器框架,在包装润润色,一两周就可以快速出一个项目了。这是LightOPC、OpcWorkshop做不到的(当然,如果能力特别强,这句话当我没说?)
2、WtOPCSvr是目前测试阶段唯一支持中文标签的(中国企业怎么可能不适用中文标签,而且工控行业的很多资深人士都是比较大‘老’的,纯因为也不合适)。当然支持中文标签的版本是在(9,0,3,2)以后,网上流传的有这个版本,但是没有授权码给出,所以您可以享受30分钟的happy time。其他版本有一个(9,0,1,7)的,网上有流传授权码,可惜美中不足的是,这个版本只支持英文。我手中是因为公司最后权衡利弊,向相关机构购买了WtOPC的服务器源码,所以说比较爽....需要源码和相关资源的可以通过链接 wtopc各版本DLL.rar WTOPCSvr服务器源码下载
好了,前面扯了很多的废话哈,下面就直接讲讲基于WtOPCSvr.dll的OPC DA服务器相关开发知识要点啊。
一、开发环境配置
注册OPC服务器相关库。资源的话网上一大堆,不多说了,实在找不到的可以给我留言。
重点看一下注册脚本:
@ECHO ON
if "%PROCESSOR_ARCHITECTURE%"=="x86" goto x86
if "%PROCESSOR_ARCHITECTURE%"=="AMD64" goto x64
exit
:x64
@ECHO X64系统配置模式..
set systemdir=C:\Windows\SysWOW64
exit
:x86
@ECHO X86系统配置模式..
set systemdir=C:\Windows\System32
@ECHO copy to OPC Common ........
copy opcproxy.dll %systemdir%
copy opccomn_ps.dll %systemdir%
copy opc_aeps.dll %systemdir%
copy opchda_ps.dll %systemdir%
copy opcdaauto.dll %systemdir%
copy aprxdist.exe %systemdir%
copy opcenum.exe %systemdir%
cd %systemdir%
@ECHO Register OPC Common ........
REGSVR32 /s opcproxy.dll
REGSVR32 /s opccomn_ps.dll
REGSVR32 /s opc_aeps.dll
REGSVR32 /s opchda_ps.dll
regsvr32 /s opcdaauto.dll
aprxdist.exe
opcenum /regserver
@ECHO 配置完成!
需要注意32位和64位系统的差异。当然如果直接使用这个脚本肯定是没有问题的。另外需要注意的是,在后面将项目实战的时会教大家如何将应用程序和OPC库注册服务打包到安装包中。
二、Wtopc主要函数和应用
(容我把老项目打开先..........丢了有段时间了..............也是怕忘了才决定捡起来简单记录分享一下....................................)
1、SDK授权(无需授权或者没有授权码的小伙伴就跳过)
// QString 转 LPCSTR
static LPCSTR QString2LPCSTR(QString q_str){
return (LPCSTR)q_str.toLocal8Bit().constData();
}
QString NumberSerial= QString("JVRPS53R5V64226N62H4"); // 9,0,0,6
int retval = Deactivate30MinTimer(QString2LPCSTR(NumberSerial)); // 注册成功返回1,否则返回0
授权的函数调用必须放在WtOPCSvr的SDK中其他API调用之前,否则可能无效。
这里我为小伙伴么提供了9006版本的授权码,测试可用,不过是不支持中文的。你自己在使用的过程中授权码记得和版本对应。如果需要最新版本(9,0,3,2)的可以联系我。
2、wtopc服务器注册
BOOL initInstance( )
{
CHAR SvrName[]("TestOPCServer");
CHAR SvrDesc[]("Test OPC Server Simulator");
QString qExepath = QCoreApplication::applicationFilePath();
if (!UpdateRegistry ((BYTE *)&CLSID_OPCSimSvr,SvrName,SvrDesc,QString2LPCSTR(qExepath))) return false;
SetVendorInfo (SvrDesc);
UINT ServerRate = 1000;
if( !InitWTOPCsvr((BYTE *)&CLSID_OPCSimSvr, ServerRate )) return false;
/// 注册事件回调函数
if( !EnableWriteNotification2 (reinterpret_cast(WriteNotifyProc2), TRUE)) return false;
if( !EnableDisconnectNotification (reinterpret_cast(DisconnectProc)) ) return false;
if( !EnableDeviceRead (reinterpret_cast(DeviceReadProc)) ) return false;
/// 获取服务器SDK版本信息
//WORD version = WTOPCsvrRevision(); // 获取opc服务器版本
/// 创建标签: XX.XX.XX
QList infos;
addTagsForRealTimeData(infos); /// 创建所有数据标签
return true;
}
服务器注册部分,我们具体做了如下几个工作:
(1)指定服务器名,服务器描述信息等 。
(2)初始化过程中指定了服务器的刷新效率。
(3)注册了客户端写值、读值、断开连接等事件的回调函数。
具体实现部分就不细说了,有兴趣跟后面看吧。
3、创建数据标签
这里是比较重要的部分,我们在初始化服务器过程中可以预先给用户创建有意义的数据标签,用户在客户端中可以直接对标签进行读写操作,当然还可以提供动态标签创建的交互接口给用户,但实现的核心是一样的。
这里还是给出伪代码和逻辑部分:
// 标签属性
class CTag
{
public:
CTag(){}
~CTag(){}
public:
HANDLE Handle; // 每个标签创建后存在唯一的一个handle
QString Name; // 标签名
QString Description; // 标签描述信息
QString Units; // 标签单位
VARIANT Value; // 标签值
DWORD ReadAccessLevel; // 标签的读写属性。默认可读
DWORD WriteAccessLevel; // 标签的写属性
};
QString tagname = "xxx.xxx.xxx";
CTag *pTag = new CTag;
pTag->Handle = CreateSecureTag (
const_cast(FromUnicode(tagname).c_str()), // 标签名
pTag->Value, // 标签值
InitialQuality, // 标签的品质
pTag->ReadAccessLevel, // 标签的读权限
pTag->WriteAccessLevel); // 标签的写权限
要下班了.....改天继续.......