CnPack Forum


 
Subject: DELPHI编写OPC(一):用 Automation(自动化)编写OPC客户端
skyjacker
版主
Rank: 7Rank: 7Rank: 7
茶农


UID 2239
Digest Posts 9
Credits 617
Posts 269
点点分 617
Reading Access 100
Registered 2006-6-8
Status Offline
Post at 2007-11-5 17:08  Profile | Blog | P.M.  | QQ
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)



Image Attachment: 1-2.GIF (2007-11-5 17:08, 1.94 K)



Attachment: OPCDll.rar (2007-11-30 15:31, 185.1 K)
Download count 3049




一壶清茶煮青春.
Top
zzzl (早安的空气)
版主
Rank: 7Rank: 7Rank: 7



UID 590
Digest Posts 0
Credits 399
Posts 199
点点分 399
Reading Access 100
Registered 2004-11-29
Status Offline
Post at 2007-11-11 09:55  Profile | Blog | P.M.  | QQ
报告楼主,前两张图显示不了
Top
hjusea
新警察
Rank: 1



UID 41128
Digest Posts 0
Credits 2
Posts 1
点点分 2
Reading Access 10
Registered 2008-10-20
Status Offline
Post at 2008-10-30 23:31  Profile | Blog | P.M. 
你好我想问一下OPC接口读取和接收数据的详细写法有吗?
我用你做的不能连接远程机为什么?
QQ:308564493
Top
kendling (小冬)
高级版主
Rank: 8Rank: 8
MyvNet


Medal No.1  
UID 703
Digest Posts 5
Credits 978
Posts 580
点点分 978
Reading Access 101
Registered 2005-2-18
Location 广东
Status Offline
Post at 2008-11-6 15:49  Profile | Site | Blog | P.M.  | QQ | Yahoo!
不错的文章,支持一个。




小冬
http://MyvNet.com
Top
lixupeng
普通灌水员
Rank: 2



UID 33687
Digest Posts 0
Credits 66
Posts 31
点点分 66
Reading Access 10
Registered 2007-12-11
Status Offline
Post at 2008-12-9 16:46  Profile | Blog | P.M. 
不太懂不过还是支持下
Top
 




All times are GMT++8, the time now is 2024-11-24 07:12

    本论坛支付平台由支付宝提供
携手打造安全诚信的交易社区 Powered by Discuz! 5.0.0  © 2001-2006 Comsenz Inc.
Processed in 0.032194 second(s), 8 queries , Gzip enabled

Clear Cookies - Contact Us - CnPack Website - Archiver - WAP