这段时间公司项目上需要把数据通过OPC SERVER 开放接口,在网上及CSDN上 SEARCH 了好久,感觉CSDN上的资料还是比较专业的,但也有做广告的,我摸索了一周时间,有点心得,并用在工程上,一下是一周体会;
一:WINTECH 的开发包
WINTECH 网站上可下载开发包,WTOPCSVR.DLL 有VB VC VC#的例程,但是DEMO DLL,可运行30分钟,比较容易上手,但对开发者来说不能从内核上了解OPC SERVER ,而且需要银子。
二:南京一位高手写的 OPC 开发指南,并且提供SERVER 代码,代码是可以编译通过的,但是用客户机程序测试,连接也成功,就是添加TAG时提示找系统保留项目,ERROR,我用远程需跟踪了一下,是ADDTIEM 函数中XXXPAN 指针为空,研究一天,没有结果,放弃。说实话书写的确实挺实用的。
三:开源LIGHTOPC 开发
CSDN上下载俄罗斯高手开源LIGHTOPC源代码,很好能编译过去,两个DLL,头文件及LIB库,同时又下载了高手写的MODBUSTOOPC MFC程序,用的就是LIGHTOPC 支持,说实话,MFC是十分灵活,但开发UI就差强人意了,CLOCLEMODBUS 及CMODBUS 两个RTU方式通讯堪称经典,几乎就是MODBUS 的核心,核心是myClassFactory类及opcsrv.cpp ,详细的代码描述了如何引用LIGHTOPC服务器,关键函数是int driver_init(int lflags)初始化TAG及work_loop(unsigned pause, unsigned *nTerminate) 刷新TAG数据,我们只要更改这两个函数的内容就可以将自己的数据放入OPC SERVER ,其他OPC CLIENT 如KEPWARE 及组态王等就可取得我们的数据了。
下面是两个函数的引用
//初始化ITEM TAGS
int driver_init(int lflags)
{
loDriver ld;
VARIANT var;
int ecode;
setlocale(LC_CTYPE, "");
if (my_service)
{
UL_ERROR((LOGID, "Driver already initialized!"));
return 0;
}
memset(&ld, 0, sizeof(ld)); /* basic server parameters: */
// ld.ldRefreshRate = 3;//10;
ld.ldSubscribe = activation_monitor;
ld.ldWriteTags = WriteTags;
ld.ldReadTags = ReadTags;
ld.ldConvertTags = ConvertTags;
#if 0
ld.ldAskItemID = AskItemID;
#endif
ld.ldFlags = lflags | loDF_IGNCASE | /*loDf_FREEMARSH | loDf_BOTHMODEL | */
/*loDF_NOCOMP| */ loDf_NOFORCE & 0 /*| loDF_SUBSCRIBE_RAW*/;
/*Fix the Bug in ProTool *//*|loDF_IGNCASE */ ;
ld.ldBranchSep = '/'; /* Hierarchial branch separator */
ecode = loServiceCreate(&my_service, &ld, TI_MAX /* number of tags in the cache */);
/* 500000 is ok too */
UL_TRACE((LOGID, "%!e loCreate()=", ecode));
if (ecode) return -1;
InitializeCriticalSection(&lk_values);
memset(tv, 0, sizeof(tv)); /* instead of VariantInit() for each of them */
memset(ta, 0, sizeof(ta)); /* instead of VariantInit() for each of them */
VariantInit(&var);
/* OPTIONAL: Tags creation. */
{
char name[64];
unsigned int ii, i;
memset(name, 0, sizeof(name));
V_I2(&var) = 0;
V_VT(&var) = VT_I2; //all tags are 2-byte integers
ii = i = 0;
for(; ii < i + tnum[TI_holding_register] && !ecode; ii++)
{
sprintf(name, "%s%s%02u", ttn, tcn[TI_holding_register], ii-i);
V_I2(&var) = 0;
V_VT(&var) = VT_I2;
ecode = loAddRealTag(my_service, /* actual service context */
&ti[ii+1], /* returned TagId */
(loRealTag) (ii+1), /* != 0 driver's key */
name, /* tag name */
0, /* loTF_ Flags */
OPC_READABLE | OPC_WRITEABLE, &var, 0, 0);
tg[ii+1] = TI_holding_register;<