Board logo

Subject: DELPHI编写OPC(一):用 Automation(自动化)编写OPC客户端 [Print This Page]

Author: skyjacker    Time: 2007-11-5 17:08     Subject: DELPHI编写OPC(一):用 Automation(自动化)编写OPC客户端

DELPHI编写OPC():在 Delphi 下用 Automation(自动化)编写OPC 客户端

{* |<PRE>
======================================================================
* 版权声明:Copyright ? SkyJacker. 未经原作者同意,禁止任何形式的编辑、转载
*                   WITHOUT AUTHORAGREEMENT, FORBIDDEN TRANSSHIPMENT.
* 声明版权的两点原因:
* 1、我在网上看到一篇很不错的文章,作者说如果需要源代码可以跟他联系,可是我搜不
* 到作者是谁。因为原作者太多了。
* 2、同样是一片好文章,结果被某些网站分成了N份,夹杂着一些大型花边广告图像。通
* 过广告赚钱我很理解也很佩服,但是你们不应该把原文删得乱七八糟。
================================================================================
* 软件名称:DELPHI编写OPC
* 单元名称:在 Delphi 下用 Automation(自动化)编写OPC 客户端
* 单元作者:SkyJacker(Msn&Email: HeMiaoYu@gmail.com)
*     注:
* 开发平台:Win2003 + Delphi 6.0 UP2
* 兼容测试:无
* 化:该单元中的字符串不符合本地化处理方式
* 单元标识:
* 发布目的:互相交流学习,共同完善《DELPHI 编写 OPC》系列。“这不是一个人的战斗!”
* 发布地址:http://bbs.cnpack.org 我在这儿等着您的指导
* 修改记录:2007.11.03
*                创建单元
================================================================================
|</PRE>}

一、什么是OPC
OPCOLE for Process Control,用于过程控制的OLE)是 Microsoft COM/DCOM 技术在工控领域的应用。
OPC提供一套统一的标准,采用 C/S 模式,硬件厂商或其外包公司完成具有统一OPC接口标准的Server程序,软件厂商只需按照OPC标准编写Client程序访问Server程序,即可实现与硬件设备的通信。

二、OPCAutomation 安装步骤:
1)、使用regsvr32 注册 OPCDAAuto.dll
2)、在 Delphi 中导入类型库OPC Automation 2.0。如图Figure 1-1



方法一:人工创建 OPCAutomation

(1)、声明 OPC 特有的类与接口

       OPCItems Automation 中没有实现的类,因此直接声明其接口。
    {Private declarations }
   FOPCServer: TOPCServer;
   FOPCGroup: TOPCGroup;
   FOPCItems: OPCItems; // interface
   FOPCItem: OPCItem; // interface

   // OPC 常用操作函数
   function OPCServerConnect(AServerProgID: WideString): Boolean;
   {* 连接 OPC Server}
   function OPCGroupConnect(AGroupName: OleVariant): Boolean;
   {* 连接 OPC Group}
    procedure OPCItemCreateOne(AItemName:OleVariant);
   {* 创建一个 OPCItem}
   function OPCItemOneStart(): Boolean;
   {* 为了读写 Item,定位到 OPCServer 的一个 Item}
   procedure OPCServerDisconnect;
   {* 断开与 OPC 服务器的连接}
   procedure OPCItemReadWrite;
   {* 读写 Item 数据}

const
cnServerProgID = 'www.cnpack.org OpcServer 0.01'; // 替换成你的 OPC 服务器
cnGroupName = 'Group1';
cnItemName = 'Voltage.PV'; // 读取的具体项值

var
FrmMain: TFrmMain;

implementation

{$R *.dfm}

// 连接 OPC Server
function TFrmMain.OPCServerConnect(AServerProgID:WideString): Boolean;
begin
Result := True;
  try
   FOPCServer := TOPCServer.Create(Self);
   FOPCServer.Connect1(AServerProgID);
except
   Result := False;
end;
end;

// 连接 OPC Group
functionTFrmMain.OPCGroupConnect(AGroupName: OleVariant): Boolean;
begin
Result := True;
  try
   FOPCGroup := TOPCGroup.Create(Self);
   FOPCGroup.ConnectTo(FOPCServer.OPCGroups.Add(AGroupName));

   FOPCGroup.IsActive := True;   
   FOPCGroup.IsSubscribed := True; // 事件支持
except
   Result := False;
end;
end;

// 创建一个 OPCItem
procedureTFrmMain.OPCItemCreateOne(AItemName: OleVariant);
var
NumItems: Integer;
OVItemID: OleVariant;
OVClientHandles: OleVariant;
OVServerHandles: OleVariant;
OVErrors: OleVariant;
OleErr: string;
begin
FOPCItems := FOPCGroup.OPCItems;

NumItems := 1;

OVItemID := VarArrayCreate([1, 1], varOleStr);
OVItemID[1] := AItemName;

OVClientHandles := VarArrayCreate([1, 1], varInteger);
OVClientHandles[1] := 1;

OVServerHandles := VarArrayCreate([1, 1], varInteger);
OVServerHandles[1] := 0; // 初始化

OVErrors := VarArrayCreate([1, 1], varOleStr);
OVErrors := EmptyParam;

FOPCItems.AddItems(
   NumItems,
   PSafeArray(TVarData(OVItemID).VOleStr),
   PSafeArray(TVarData(OVClientHandles).VInteger),
   PSafeArray(TVarData(OVServerHandles).VInteger),
   PSafeArray(TVarData(OVErrors).VInteger),
   EmptyParam,
   EmptyParam
   );
//OleErr := OPCServer1.GetErrorString(OVErrors[1]); // 如果 ItemID 无效,则此命令也无效
  ifOVServerHandles[1] >0 then
   FOPCItem := FOPCItems.GetOPCItem(OVServerHandles[1])
else
begin
   raise EOleError.Create('失败: 连接' +AItemName + #13#10 + OleErr);
  end
end;

// 定位到一个 Item
function TFrmMain.OPCItemOneStart():Boolean;
begin
Result := False;
  ifnot OPCServerConnect(cnServerProgID) then
begin
    OPCServerDisconnect;
   Exit;
end;
  ifnot OPCGroupConnect(cnGroupName) then
begin
   OPCServerDisconnect;
   Exit;
end;
  try
   OPCItemCreateOne(cnItemName);
   Result := True;
except on E: Exception do
   begin
     OPCServerDisconnect;
     ShowMessage(E.Message);
   end;
end;
end;

// 断开与 OPC 服务器的连接
procedure TFrmMain.OPCServerDisconnect;
begin
  ifAssigned(FOPCServer) then
begin
   if Assigned(FOPCGroup) then
   begin
     FOPCServer.OPCGroups.RemoveAll;
     FOPCGroup.Free;
     FOPCGroup := nil;
   end;
   FOPCItems := nil;
   FOPCItem := nil;

   FOPCServer.Disconnect;
   FOPCServer.Free;
   FOPCServer := nil;
end;
end;

procedure TFrmMain.OPCItemReadWrite;
var
Value, Quality, TimeStamp: OleVariant;
begin
  ifnot Assigned(FOPCItem) then Exit;

  //
  //FOPCItem.Write(10);

  //
FOPCItem.Read(OPCDevice, Value, Quality, TimeStamp);
edtValue.Text := Value;
edtQua.Text := Quality;
edtTimeStamp.Text := TimeStamp;
end;

procedure TFrmMain.btnOPCItemStartClick(Sender:TObject);
begin
  ifOPCItemOneStart then
   btnOPCItemStart.Enabled := False;
end;

procedure TFrmMain.btnStopClick(Sender:TObject);
begin
OPCServerDisconnect;
btnStart.Enabled := True;
btnOPCItemStart.Enabled := True;
end;

procedureTFrmMain.btnReadWriteClick(Sender: TObject);
begin
OPCItemReadWrite;
end;

方法一的代码确实有点繁,但是却可以加深理解。下面有个代码少的。

方法二:利用 ActiveX面板的OPC 控件

选择 OPCServer,OPCGroup 控件。如图Figure 1-2


// 使用控件连接 OPC Server
procedureTFrmMain.btnCtrlStartClick(Sender: TObject);
var
NumItems: Integer;
OVItemID: OleVariant;
OVClientHandles: OleVariant;
OVServerHandles: OleVariant;
OVErrors: OleVariant;
OleErr: string;
begin
OPCServer1.Connect1(cnServerProgID);
OPCGroup1.ConnectTo(OPCServer1.OPCGroups.Add(cnGroupName));
FOPCItems := OPCGroup1.OPCItems;


NumItems := 1;

OVItemID := VarArrayCreate([1, 1], varOleStr);
OVItemID[1] := cnItemName;

OVClientHandles := VarArrayCreate([1, 1], varInteger);
OVClientHandles[1] := 1;

OVServerHandles := VarArrayCreate([1, 1], varInteger);
OVServerHandles[1] := 0; // 初始化

OVErrors := VarArrayCreate([1, 1], varOleStr);
OVErrors := EmptyParam; // 初始化

FOPCItems.AddItems(
   NumItems,
   PSafeArray(TVarData(OVItemID).VOleStr),
   PSafeArray(TVarData(OVClientHandles).VInteger),
   PSafeArray(TVarData(OVServerHandles).VInteger),
   PSafeArray(TVarData(OVErrors).VInteger),
   EmptyParam,
   EmptyParam
   );

  ifOVServerHandles[1] >0 then
   FOPCItem := FOPCItems.GetOPCItem(OVServerHandles[1])
else
begin
   raise EOleError.Create('失败: 连接' +cnItemName + #13#10 + OleErr);
  end
end;

procedureTFrmMain.btnCtrlReadWriteClick(Sender: TObject);
begin
OPCItemReadWrite;
end;

如果你是刚开始学习编写 OPC Client,千万不要指望仅仅这篇文章就可以完成你的第一个“Hello World”。而且,我知道你要的不仅仅是这点代码,其实你要的也许是OPC Server demoOPC*.dll
不过不要紧,http://www.cnpack.org,《DELPHI编写OPC》,热心网友会帮助你的。
我相信等《DELPHI编写OPC》系列快结束时, www.cnpack.org OpcServer 0.01会出来的,作者也许就是你。
给你一些链接,让我们来记住这些值得尊敬的文章和作者吧。吃水不忘挖井人嘛。
(在我发布这些链接的时候,我已经点开了这些链接,并且我没有中毒或木马,Good Luck!

三、本文参考资料:

http://bbs.gongkong.com/Detail.Asp?id=98664&page=2
http://blog.gongkong.com/Index.Asp?Id=10434
http://www.opcfoundation.org/forum/viewtopic.php?t=2042
http://www.cnblogs.com/Phoenix-Rock/archive/2007/09/05/541696.html
http://www.cnpack.org 本文的版权部分与代码格式摘抄于此处喔
……

四、OPC DLL 下载

2005-11-25  09:10            86,016 opchda_ps.dll
2005-11-25  09:10           102,400 opcproxy.dll
2005-11-25  09:10            69,632 opc_aeps.dll
2005-11-25  09:10            61,440 opccomn_ps.dll
2005-11-25  09:11            98,304 OPCENUM.EXE
1999-11-17  07:51           105,984 OPCDAAuto.dll

[ 本帖最后由 skyjacker 于 2007-11-30 15:32 编辑 ]

Image Attachment: 1-1.GIF (2007-11-5 17:08, 46.19 K) / Download count 753
http://bbs.cnpack.org/attachment.php?aid=355



Image Attachment: 1-2.GIF (2007-11-5 17:08, 1.94 K) / Download count 713
http://bbs.cnpack.org/attachment.php?aid=356



Attachment: OPCDll.rar (2007-11-30 15:31, 185.1 K) / Download count 2966
http://bbs.cnpack.org/attachment.php?aid=363
Author: zzzl    Time: 2007-11-11 09:55

报告楼主,前两张图显示不了
Author: hjusea    Time: 2008-10-30 23:31

你好我想问一下OPC接口读取和接收数据的详细写法有吗?
我用你做的不能连接远程机为什么?
QQ:308564493
Author: kendling    Time: 2008-11-6 15:49

不错的文章,支持一个。
Author: lixupeng    Time: 2008-12-9 16:46

不太懂不过还是支持下




Welcome to CnPack Forum (http://bbs.cnpack.org/) Powered by Discuz! 5.0.0