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
OPC(OLE 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 demo
,OPC*.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 编辑 ]