用BCB和DELPHI开发OPC监控程序
--wyddr
QQ:490124
Email:wyddr@whnew.com
看到论坛里面有人问BCB和DELPHI开发opc的问题,本人先前已做过摸索,这是本人的原创文章,希望给想做OPC客户端的朋友引个路。如果你想转载,麻烦注明作者wyddr。
1、本文介绍的方法,适用于快速开发小型的监控程序,主要使用了opc da,包括opc的读写。该方法已在我做过的几个工程中得到应用;
2、本文涉及的软件和控件,如果你用于商业用途,请购买正版;
3、你最好掌握OPC的基本概念,掌握bcb和delphi的基本使用,包括控件的编写、安装与程序的调试,相关内容参阅有关书籍;
4、如果感兴趣的人多,我还考虑写用Delphi开发OPC Server,你有兴趣么?
一、一切得益于面向控件的开发
使用BCB和DELPHI可以快速开发出OPC客户端程序,用于小型的监控系统。我们需要以下控件包:
iocomp For Delphi BCB 当前的版本为 3.0.2。它有多余60个控件,包括各种样式的文字,实时曲线控件,流向棒图,风闸状态图,opc数据写入等等。它可以设置所有控件的界面主题(类似与windows xp的主题桌面),它甚至提供了clx控件安装(我还没有在Linux下用过)。最重要的是,他的所有动态控件的各种属性可以直接绑定到opc上,可以不用写一行代码完成对opc数据的读出与写入。
BCB和delphi使用控件的情况大同小异,我采用delphi示例(受不了bcb的编译速度),在深入分析的时候,它的源码都是delphi的。
二、起步:基本的读出与写入
安装完iocomp后,IDE上面会出现三个栏目的控件集(如下图)。
各种控件的用法请参考它的Demo,我们只关心opc部分。
例1 界面上放一个文字,用于显示opc server上的数据。由于控件采用了OleVariant变量,我们可以不考虑数据的类型,是否为single,int,string等。
在Form上放一个iLabel控件,双击控件弹出属性编辑页,这一点和一般的组态软件很类似,其实delphi也算是一个复杂的组态软件(扯远了,ok,看下面的界面):
属性的第一页是Label的一般属性,包括颜色、位置、阴影的。你可以自己尝试。
属性的第三页是主题选择,第四页是版权信息,都不做过多介绍。
第二页就是opc设置,我们最关心的了:
点击[Add]按钮,出现了该Label的所有属性,由于我们只是想Label显示数据,所以选择Caption。你如果需要更复杂的实现效果,可以定义到其他属性上,但是千万小心数据类型的对应。如果定义了多个属性,使用iLabel 中的数组OPCItem[int i]区分,I 从0开始,它的opc事件中,例如:procedure TForm1.iLabel1NewOPCData(Index: Integer);中的 Index也就是区分不同的属性事件。(这个事件将在后面介绍)。添加后界面如下:
右边的编辑框变为可用,点击Property后面的[…]按钮可以改变该属性,点击Computer的[…]查找网络opc server ,如果想使用网络的server,请参阅opc server的网络配置。
点击Opc Server的[…]查找该 computer上的所有server ,例如:
Edopc.xl.1为我编写的测试用的opc server ,OPCServer.WinCC为wincc的服务器。前面的数据2代表为opc da 2.0版本,1-2为1.0和2.0版本同时兼容。
选择Edopc.xl.1后,Item对话框变为可用状态。点击[…],将列出该opc Server所有的Item,如下图:
选择对应的item,设置好Update Rate(刷新率),Auto Connect(自动连接),Auto Error(自动报错)就Ok了。
编译运行,你的服务器自动运行了么?你的iLabel读取了数据么?如果一切顺利,恭喜,你的第一个opc客户端出来了。但是,世界上的事往往不是那么美好,这时你要检查,你的opc 中间件安装好了么?你的Server是否有问题(用第三方工具查看一下)?数据类型是否正确?Item的属性是否可读?调试的经验就是在一次次错误中积累的。
好了,我们回过头来看看我们这几步,其实和Wincc基本数据设定也差不多,但是Wincc有很好的容错性,我们只有靠小心,小心,再小心,除非你写了容错处理的代码。
其他控件的用法也差不多,最复杂的是曲线图控件—iPlot,怎么用?看它的DEMO和自己的摸索吧,我不是他们厂商的中国代理(^_^)。但是我强烈建议,你在使用每个控件前,最好写个测试Demo,熟悉它的各种属性与函数。
前面完成了基本的读出,现在看例2:写入:
Form上放iEdit控件,只有这个控件能够写入,设置与前面是一样的,但是千万要注意写入前检查数据的合法性,我是这么做的,iEdit的为不可视,另外放一个Edit,先检查Edit的数据的合法性,再iEdit.Value := Edit1.Text,很啰嗦,怎么办?没想好。
三、进阶:随心所欲的数据表现
这套控件的表现控件很多了,但是还是不能完成我们的要求,例如:电力系统的刀闸、发电机状态等,没有Wincc的矢量作图和随心所欲属性变化那么强大,它是从比较底层的基类开始具有变量属性,那我们该怎么办?还好,我们有事件。
例如我需要在界面上放一个刀闸,对应于一个opc server 中的 Item,当数据为1的时候是一个形态,当数据为0的时候是另一个形态。你可以考虑用位图表示,但是我建议你自己写个控件,从TGraphicControl 开始继承(具体的的实现请参阅Delphi书籍)。与使用位图相比,在界面上需要很多这样的刀闸的时候,界面刷新较为平滑与不闪烁。说到控制界面不闪烁,我有两点建议:
1、 考虑把父窗体的DoubleBuffered打开;
2、 千万小心,如果你的动态控件是从TGraphicControl 继承下来的,千万不要和其他的TGraphicControl 子控件重合。如果你确实需要放,可以把动态控件放到一个Panel上。这句话是什么意思,我们做个试验,界面上放100个Label,然后放一个Shape,设置为alClient,然后用一个Timer 把100个Label的Caption刷新起来(方法为:遍历所有控件—判断控件的类—改变其Caption),界面会很闪烁,虽然这时CPU的使用率很小,追究其原因,请参阅李维的《VCL架构剖析》。如果你把Label放在Panel上这个情况就好多了。
言归正传,还是说刀闸(TSwitch)吧,设置它的一个属性为Stat(int),当Stat为1的时候,控件OnPain成一个形态;当Stat为0的时候,控件OnPain成另一个形态。具体怎么实现,看看TShape的源码就知道了。这个控件我们自己写的控件,当然没有OPC的属性,如何与数据捆绑起来了,最简单的方法是:
1、 放一个iLabel,其为不可视;
2、 与OPC Server的Item连接起来;
3、 添加iLabel的OnNewOPCData的事件,例如,当我们确信这个Item只有1和0两种数据时,就可以写成:
procedure TForm1.iLabel1NewOPCData(Index: Integer);
begin
Switch1.Stat := StrToInt(iLabel1.Caption);
end;
4、iLabel还有一个事件procedure iLabel1BeforeNewOPCData(Index: Integer;var Data: OleVariant); 我们可以用来进行数据拦截或者添加系数等操作,如何灵活的应用,看你自己罗。
5、iLabel的OPC事件中,都有Index: Integer,这是区分iLabel的多重OPC属性,就像Wincc任意属性变换都可以穿插事件,这里还做不到那么方便。
OK,你的刀闸开合自如了么?又出错了?请检查你的控件写的正确么,你的数据是否越限?调试吧,我也只能帮到这里了。
上面介绍的方法是最简单、最快捷、最易懂的方法,也是最笨拙(没有新意)、工作量最大(刀闸很多的时候)、最难看(写程序成了复制粘贴的劳动)的方法,我忍不住骂自己的懒惰,可能要贻害大家。好,下面就让我们从头开始,看看iLabel到底是怎么工作的,也可以学着写opc控件。沉思吧……
看到这里,你自己写一个小型的监控应该没有什么问题了,你还想要什么?
1、历史归档:Delphi玩数据库比Wincc方便多了,找本书看看吧,无非就是把需要的变量捆绑到iLabel上,定时的把iLabel的Caption存进数据库,我就不敢献丑了。
2、语音报警与归档:还不是事件驱动,把需要的信息存储。
3、plc操作:把变位信息告诉OPC Server,Server发操作指令,这是Server的功能。由于我的Server是自己写的,所以采用了和PLC相同的机制(循环扫描)。那位前辈又没有更好的方法,请指点一下。
四、沉思:控件的架构剖析
开始这节的时候,我考虑了很久,要把这个问题讲清楚,不是几页纸能够讲清楚的。所以麻烦你做两件事:
1、 阅读一下李维的《VCL架构剖析》,VCL是个宝库,以至于Iocomp的开发者也借鉴了VCL的继承机制,如何实现接口,如何定义类的。细节部分我不做过多分析,只是引导你窥视一下如何开发OPC控件。
2、 下载看一下我写的OPC简易的客户端(含全部源码,opc-China有下载),里面所有以i开头的Pas文件,是我从Iocomp中提取出来的,可以把你带进这个大门。
(待续。。。)
(待续。。。)
五、幻想:来吧,做自己的组态软件