国产欧美日韩精品a在线观看-国产欧美日韩精品一区二区三区-国产欧美日韩精品综合-国产欧美中文字幕-一区二区三区精品国产-一区二区三区精品国产欧美

ACS880-07C
關(guān)注中國自動化產(chǎn)業(yè)發(fā)展的先行者!
CAIAC 2025
2024
工業(yè)智能邊緣計算2024年會
2023年工業(yè)安全大會
OICT公益講堂
當前位置:首頁 >> 案例 >> 案例首頁

案例頻道

Delphi環(huán)境下使用定制接口開發(fā)OPC數(shù)據(jù)訪問客戶程序
  • 企業(yè):控制網(wǎng)     領(lǐng)域:電源    
  • 點擊數(shù):5743     發(fā)布時間:2005-07-13 17:23:40
  • 分享到:
簡要的介紹了OPC以及使用定制接口開發(fā)OPC數(shù)據(jù)訪問客戶程序的背景知識。文中較為詳細的講述了如何Delphi環(huán)境下使用定制接口開發(fā)OPC數(shù)據(jù)訪問客戶程序。



1  引言


圖1  OPC應(yīng)用架構(gòu)



    OPC(用于過程控制的OLE)是一個工業(yè)標準。它由一些世界上占領(lǐng)先地位的自動化系統(tǒng)和硬件、軟件公司與微軟公司緊密合作而建立的。這個標準定義了應(yīng)用Microsoft操作系統(tǒng)在基于PC 的客戶機之間交換自動化實時數(shù)據(jù)的方法。管理這個標準的國際組織是OPC基金會。因為應(yīng)用程序要和不同的設(shè)備,比如PLC、變頻器、現(xiàn)場總線的儀表等通訊,如果不同的設(shè)備廠家都遵守一個相同的程序接口標準的話,那么程序和不同設(shè)備的溝通將變得非常容易。OPC 就是這樣一種工業(yè)標準,它是OLE for Process Control 的英文縮寫。OPC 是基于微軟的COM(Component Object Model,組件對象模型)和OLE(Object Linking and Embedding,對象鏈接與嵌入)技術(shù)之上的。和以前不同的是,現(xiàn)在設(shè)備廠家提供
不同的OPC Server。OPC Server負責從設(shè)備中取數(shù)據(jù)和寫數(shù)據(jù)。人們所要做的就是利用統(tǒng)一的COM 規(guī)范編寫OPC Client。客戶程序和OPC Server 打交道。OPC Server是一座在客戶和硬件設(shè)備之間的橋梁,通過它,人們可以很容易的取得現(xiàn)場的溫度、壓力、流量、位置等信號,以及控制現(xiàn)場的閥門開度、電機轉(zhuǎn)速等。注意客戶程序和服務(wù)器程序可以在同一臺計算機上,也可以在不同的計算機上,區(qū)別是使用COM 還是使用DCOM(Distributed Component Object Model,分布式組件對象模型)。如圖1所示。

2  OPC數(shù)據(jù)訪問服務(wù)器接口方式

    OPC數(shù)據(jù)訪問規(guī)范提供了兩套接口方案,即定制接口(Custom Interface)和自動化接口(Automation Interface)。其中自動化接口是對定制接口的進一步封裝。定制接口效率高,采用它能夠發(fā)揮OPC服務(wù)器的最佳性能。用C++編寫訪問OPC服務(wù)器的程序一般采用定制接口方案;對于VB、VBA、EXCEL等編程軟件或工具,不能直接訪問通用接口,而要通過自動化接口,因此使用VB或VBA等語言的客戶程序一般使用自動化接口。


圖2  OPC數(shù)據(jù)訪問方式

3  OPC數(shù)據(jù)訪問服務(wù)器的數(shù)據(jù)訪問方法

(1)  同步數(shù)據(jù)訪問處理
    OPC 服務(wù)器把按照OPC 客戶應(yīng)用程序的要求得到的數(shù)據(jù)訪問結(jié)果,作為方法的參數(shù)返回給OPC 客戶程序。OPC 客戶應(yīng)用程序在結(jié)果被返回之前必須處于等待狀態(tài)。
(2)  異步數(shù)據(jù)訪問處理
    OPC 服務(wù)器接到 OPC 應(yīng)用程序的要求后,幾乎立即將方法返回。OPC 客戶應(yīng)用程序隨后可以進行其他處理。當OPC 完成數(shù)據(jù)訪問時,觸發(fā)OPC 客戶應(yīng)用程序的一部訪問事件,將數(shù)據(jù)訪問結(jié)果傳送給OPC 應(yīng)用程序。OPC 應(yīng)用程序在事件處理程序中接受OPC 服務(wù)器傳送來的數(shù)據(jù)。
(3)  訂閱方式數(shù)據(jù)采集
    此種方式是OPC 客戶應(yīng)用程序不需要向OPC 服務(wù)器程序提出數(shù)據(jù)請求,而是自動接收OPC 服務(wù)器送來的變化通知信號的訂閱方式數(shù)據(jù)采集。服務(wù)器按照一定的更新周期更新OPC 服務(wù)器的數(shù)據(jù)緩沖器的數(shù)值,如果發(fā)現(xiàn)數(shù)值有變化時,就會以數(shù)據(jù)變化事件通知OPC 客戶應(yīng)用程序。OPC 服務(wù)器支持不敏感帶寬 (Dead Band),當OPC標簽的數(shù)據(jù)類型是模擬量時,只有當前值與上一次值的偏差的絕對值超過一定的限度時,才更新緩沖器的數(shù)據(jù)并通知OPC 客戶應(yīng)用程序。這樣就可以忽略模擬量的微小變化,從而減輕OPC 服務(wù)器和OPC 客戶的負擔。
(4)  刷新方式
    刷新是一種特殊形式的訂閱,它強制更新活動組中的所有活動項數(shù)據(jù),而不管這些數(shù)據(jù)與以前相比是否有了變化。

4  使用Delphi進行COM程序開發(fā)的優(yōu)點

    Delphi是功能強大的應(yīng)用程序開發(fā)工具。它具有功能強大、運行速度快、易于學習、使用和開發(fā)效率高等特點。它是可視化應(yīng)用編程環(huán)境,可重用性面向?qū)ο缶幊陶Z言,快速編譯器和數(shù)據(jù)庫的完美組合。編寫OPC定制接口的客戶程序的本質(zhì)就是編寫COM客戶程序,而使用Delphi進行COM開發(fā)時,人們會發(fā)現(xiàn)Object Pascal為COM提供了強大的語言支持。主要有以下幾點:
(1)  Variant 和 OleVariant支持
    直接使用C和C++處理變體需要調(diào)用VariantInit(),VariantCopy(),VariantClear()等函數(shù)。而Object Pascal對變體的支持,使得在使用Variant和OleVariant類型的情況下,編譯器能夠自動生成對API的變體支持程序的調(diào)用。
(2)  可變數(shù)組支持
    在Delphi中一旦一個Variant包含了一個可變數(shù)組,就可以用標準數(shù)組的下標來訪問數(shù)組元素。與C和C++中手工生成的安全數(shù)組相比,Object Pascal的封裝功能要簡潔的多,且不易出錯。
(3)  后期綁定Automation支持
    Object Pascal對于Variant和OleVariant的支持使得編寫后期綁定的自動化(Automation)客戶程序成為可能。因此使用Delphi來開發(fā)基于自動化接口的OPC客戶程序也是很方便的。
(4)  寬字符串支持
    Delphi提供的寬字符串(WideString)類型是一個和COM BSTR字符串兼容的字符串。而傳統(tǒng)方式下,使用標準的諸如SysStringLen()等API函數(shù)與BSTR一起工作是一件相當麻煩的事。
(5)  接口支持
    Object Pascal為合乎COM規(guī)范的接口提供了完全自包容的實現(xiàn)代碼,接口的實現(xiàn)不需要任何的COM API函數(shù)。程序員不需要考慮在傳統(tǒng)COM編程中的引用計數(shù)和接口查詢等底層細節(jié)。
(6)  Dispinterface接口支持
    Object Pascal對于Dispinterface的支持使得編寫支持雙接口的COM程序非常容易。

5  Delphi環(huán)境下使用定制接口開發(fā)OPC數(shù)據(jù)訪問客戶程序

    OPC規(guī)范中規(guī)定OPC服務(wù)器必須提供定制接口,而自動化接口則可以有選擇地提供。因此編寫使用定制接口的OPC客戶程序更具有一般意義,而且使用定制接口的效率要遠遠高于使用自動化接口的效率。本文限于篇幅只討論針對OPC數(shù)據(jù)訪問服務(wù)器的客戶應(yīng)用程序。
5.1  OPC數(shù)據(jù)訪問服務(wù)器簡介
    OPCDataAccess服務(wù)器是最基本的OPC服務(wù)器,它包括OPCServer、OPCGroup和OPCItem三類典型的對象。OPC服務(wù)器對象維護有關(guān)服務(wù)器的信息并用作OPC組對象的容器,而OPC組對象維護組的信息,提供包容OPC項的機制,并管理OPC項。OPC組提供了客戶程序組織數(shù)據(jù)的手段。有兩種類型的組:公共(Public)組和局部(Local)組。公共組可以被多個客戶共享,而局部組只能被一個客戶使用。每個組中都可以定義一個或多個OPC項。OPC項代表了與服務(wù)器中的數(shù)據(jù)的連接。客戶程序?qū)PC項的操作都是通過包容此項的OPC組來進行的,而不是直接把OPC項作為一個對象來操作。每個OPC項都有值(Value)、品質(zhì)(Quality)和時間戳(Time Stamp)三個屬性。



圖3  OPC數(shù)據(jù)訪問服務(wù)器的數(shù)據(jù)組織方式

    人們要的就是上面的item,這就是點,人們所謂的點,就是PLC的I/O點、儀表的數(shù)值等。編寫客戶端的程序的過程實際上就是對在OPC服務(wù)器中的數(shù)據(jù)項目(Item)進行操作。這就要求人們要了解OPC數(shù)據(jù)訪問服務(wù)器不同對象的接口的功能:
(1)  OPCServer對象接口
    OPCServer對象是OPC中的首要對象,它提供了如下接口:
    IUnknown接口是COM的標準接口;
   IOPCServer接口可對OPCGroup對象進行有關(guān)操作;
   IOPCServerPublicGroups接口為客戶和服務(wù)器提供了管理公共組的功能;
   IOPCBrowseServerAddressSpace接口提供了客戶瀏覽服務(wù)器數(shù)據(jù)項的功能;
   IOPCItemProperties接口讓客戶能夠瀏覽與ItemID相關(guān)的可訪問屬性;
   IOPCCommon接口提供了設(shè)置和詢問LocaleID的功能;
   IPersistFile接口允許客戶裝載和保存服務(wù)器的配置信息;
   IConnectionPointContainer接口允許用戶探查發(fā)現(xiàn)連接點。
(2)  OPCGroup對象接口
   OPCGroup對象是管理數(shù)據(jù)項集合的對象,它提供的接口如下:
   IUnknown接口是COM的標準接口;
   IOPCItemMgt接口為客戶提供了添加,刪除和控制組中數(shù)據(jù)項的功能;
   IOPCGroupStateMgt接口允許客戶管理組中的所有狀態(tài)信息;
   IOPCPublicGroupStateMgt接口用來將私有組轉(zhuǎn)換為公共組;
   IOPCSyncIO接口允許用戶對服務(wù)器執(zhí)行同步讀寫操作;
   IOPCAsyncIO接口允許客戶對服務(wù)器執(zhí)行異步讀寫操作;
   IOPCAsyncIO2接口用來替代IOPCAsyncIO接口;
   IConnectionPointContainer接口允許用戶探查發(fā)現(xiàn)連接點;
   IDataObject接口允許客戶和使用OPC數(shù)據(jù)流格式的組之間產(chǎn)生連接。
5.2  同步讀寫方式編程
   編程部分限于篇幅只列出核心代碼,關(guān)于一些類型定義,接口描述均省略了。
(1)  COM庫的初始化
   在調(diào)用任何COM或OLE API函數(shù)之前,必須要用CoIntialize()函數(shù)來對COM庫進行初始化,為了關(guān)閉COM庫在最后一次調(diào)用COM庫后,要調(diào)用CoUnitialize()函數(shù)。使用Delphi開發(fā)時,事情就簡化了,人們只需要在程序中包括ComObj單元即可,這樣應(yīng)用程序在調(diào)用Application.Initialize()時會自動調(diào)用CoInitialize()函數(shù),而ComObj單元的finalization部分會自動調(diào)用CoUnitialize()函數(shù)。只需要一句代碼:
Uses ComObj;
(2)  創(chuàng)建服務(wù)器對象
   Const ServerProgID = 'hua.da2.1';//OPC服務(wù)器的注冊名稱
   Var 
   ServerIf: IOPCServer;//聲明服務(wù)器對象接口
   HR: HResult;//用來保存函數(shù)返回值
   ServerIf := CreateComObject(ProgIDToClassID(ServerProgID)) as IOPCServer;
   / /本函數(shù)用來獲取服務(wù)器對象的IOPCServer接口,這是一個COM庫函數(shù)
(3)  添加組對象
   Var  
   GroupIf: IOPCItemMgt; 
   GroupHandle: OPCHANDLE;
   HR:=ServerAddGroup(ServerIf, 'MyGroup', True, 500, 0, GroupIf, GroupHandle);
   //本函數(shù)用來對IOPCServer.AddGroup方法進行包裝,在服務(wù)器對象中添加一個名為MyGroup的組對象,激活狀態(tài)為true,更新率為500毫秒。如果組對象添加成功,則組對象接口保存在GroupIf中,組對象句柄保存在GroupHandle中。其實現(xiàn)過程如下:
   function ServerAddGroup(ServerIf: IOPCServer; Name: string; Active: BOOL;
        UpdateRate: DWORD; ClientHandle: OPCHANDLE; var GroupIf: IOPCItemMgt;
        var ServerHandle: OPCHANDLE): HResult;
var
  PercentDeadBand: Single;
  RevisedUpdateRate: DWORD;
begin
  Result := E_FAIL;
  if ServerIf <> nil then
  begin
    PercentDeadBand := 0.0;
    Result := ServerIf.AddGroup(PWideChar(WideString(Name)), Active, UpdateRate,
                            ClientHandle, nil, @PercentDeadBand, 0,
                            ServerHandle, RevisedUpdateRate, IOPCItemMgt,
                            IUnknown(GroupIf));
  end;
  if Failed(Result) then
  begin
    GroupIf := nil;
  end;
end;
(4)  添加項目
const  Item0Name = 'item.hua.bstr';//要添加的項目名稱
Var 
ItemType: TVarType;
Item0Handle: OPCHANDLE;
HR := GroupAddItem(GroupIf, Item0Name, 0, VT_EMPTY, Item0Handle,ItemType);
//本函數(shù)用來對IOPCItemMgt.AddItems進行包裝,在組對象中添加一個類型為VT_EMPTY,名稱為item.hua.bstr的項目,如果添加成功,則項目句柄保存在Item0Handle中,實際項目類型保存在ItemType中。其實現(xiàn)過程如下:
function GroupAddItem(GroupIf: IOPCItemMgt; ItemID: string;
          ClientHandle: OPCHANDLE; DataType: TVarType;
          var ServerHandle: OPCHANDLE; var CanonicalType: TVarType): HResult;
var
  ItemDef: OPCITEMDEF;
  Results: POPCITEMRESULTARRAY;
  Errors: PResultList;
begin
  if GroupIf = nil then
  begin
    Result := E_FAIL;
    Exit;
  end;
  with ItemDef do
  begin
    szAccessPath := '';
    szItemID := PWideChar(WideString(ItemID));
    bActive := True;
    hClient := ClientHandle;
    dwBlobSize := 0;
    pBlob := nil;
    vtRequestedDataType := DataType;
  end;
  Result := GroupIf.AddItems(1, @ItemDef, Results, Errors);
  if Succeeded(Result) then
  begin
    Result := Errors[0];
    try
      if Succeeded(Result) then
      begin
        ServerHandle := Results[0].hServer;
        CanonicalType := Results[0].vtCanonicalDataType;
      end;
    finally
      CoTaskMemFree(Results[0].pBlob);
      CoTaskMemFree(Results);
      CoTaskMemFree(Errors);
    end;
  end;
end;
(5)  同步讀
Var
ItemValue: string;
ItemQuality: Word;
HR := ReadOPCGroupItemValue(GroupIf, Item0Handle, ItemValue, ItemQuality);
//本函數(shù)用來同步讀取組中的項目值,如果讀取成功,則項目值保存在ItemValue中,項目質(zhì)量保存在ItemQuality中,其實現(xiàn)過程如下:
function ReadOPCGroupItemValue(GroupIf: IUnknown; ItemServerHandle: OPCHANDLE;
          var ItemValue: string; var ItemQuality: Word): HResult;
var
  SyncIOIf: IOPCSyncIO;
  Errors: PResultList;
  ItemValues: POPCITEMSTATEARRAY;
begin
  Result := E_FAIL;
  try
    SyncIOIf := GroupIf as IOPCSyncIO;
  except
    SyncIOIf := nil;
  end;
  if SyncIOIf <> nil then
  begin
    Result := SyncIOIf.Read(OPC_DS_CACHE, 1, @ItemServerHandle, ItemValues,
                            Errors);
    if Succeeded(Result) then
    begin
      Result := Errors[0];
      CoTaskMemFree(Errors);
      ItemValue := VarToStr(ItemValues[0].vDataValue);
      ItemQuality := ItemValues[0].wQuality;
      VariantClear(ItemValues[0].vDataValue);
      CoTaskMemFree(ItemValues);
    end;
  end;
end;
(6)  同步寫
ItemValue:='hello,the operation is sync-write';
HR := WriteOPCGroupItemValue(GroupIf, Item0Handle, ItemValue);
//本函數(shù)用來將ItemValue同步寫入Item0Handle所代表的項目中,其實現(xiàn)過程如下:
function WriteOPCGroupItemValue(GroupIf: IUnknown; ItemServerHandle: OPCHANDLE;
          ItemValue: OleVariant): HResult;
var
  SyncIOIf: IOPCSyncIO;
  Errors: PResultList;
begin
  Result := E_FAIL;
  try
    SyncIOIf := GroupIf as IOPCSyncIO;
  except
    SyncIOIf := nil;
  end;
  if SyncIOIf <> nil then
  begin
    Result := SyncIOIf.Write(1, @ItemServerHandle, @ItemValue, Errors);
    if Succeeded(Result) then
    begin
      Result := Errors[0];
      CoTaskMemFree(Errors);
    end;
  end;
end;
(7)  斷開服務(wù)器連接
   HR := ServerIf.RemoveGroup(GroupHandle, False);
   //本函數(shù)用來將在服務(wù)器中創(chuàng)建的組GroupHandle刪除,服務(wù)器對象在程序結(jié)束時會自動銷毀。
5.3  異步讀寫方式編程
    使用異步方式進行讀寫編程,需要客戶提供IOPCDataCallback接口,還需要使用到COM的連接點容器,連接點和接收器等相關(guān)知識。以下關(guān)于異步讀寫方式編程中和同步方式相同的部分均未給出其實現(xiàn)部分。下面給出異步讀寫方式編程的主要步驟:
   (1)  COM庫的初始化   //實現(xiàn)過程同上
   (2)  創(chuàng)建服務(wù)器對象 //實現(xiàn)過程同上
   (3)  添加組對象 //實現(xiàn)過程同上
   (4)  添加項目  //實現(xiàn)過程同上
   (5)  實現(xiàn)IOPCDataCallback接口
   為了使用連接點,客戶必須創(chuàng)建同時支持IUnknown和IOPCDataCallback接口的對象。下面的TOPCDataCallback從TInterfacedObject繼承所以支持IUnknown接口,它實現(xiàn)了IOPCDataCallback接口。
type
   // 本類用來接收 IConnectionPointContainer 的數(shù)據(jù)變化回調(diào)
  TOPCDataCallback = class(TInterfacedObject, IOPCDataCallback)
  public
    function OnDataChange(dwTransid: DWORD; hGroup: OPCHANDLE;
      hrMasterquality: HResult; hrMastererror: HResult; dwCount: DWORD;
      phClientItems: POPCHANDLEARRAY; pvValues: POleVariantArray;
      pwQualities: PWordArray; pftTimeStamps: PFileTimeArray;
      pErrors: PResultList): HResult; stdcall;
    function OnReadComplete(dwTransid: DWORD; hGroup: OPCHANDLE;
      hrMasterquality: HResult; hrMastererror: HResult; dwCount: DWORD;
      phClientItems: POPCHANDLEARRAY; pvValues: POleVariantArray;
      pwQualities: PWordArray; pftTimeStamps: PFileTimeArray;
      pErrors: PResultList): HResult; stdcall;
    function OnWriteComplete(dwTransid: DWORD; hGroup: OPCHANDLE;
      hrMastererr: HResult; dwCount: DWORD; pClienthandles: POPCHANDLEARRAY;
      pErrors: PResultList): HResult; stdcall;
    function OnCancelComplete(dwTransid: DWORD; hGroup: OPCHANDLE):
      HResult; stdcall;
  end;
(6)  連接IOPCDataCallback接口
   客戶程序除了實現(xiàn)接收器對象外,還必須建立接收器與連接點對象之間的連接關(guān)系
var 
  AsyncConnection: Longint;
  OPCDataCallback: IOPCDataCallback;
  OPCDataCallback := TOPCDataCallback.Create;//創(chuàng)建接收器對象
  HR := GroupAdvise2(GroupIf, OPCDataCallback, AsyncConnection);
//本函數(shù)實現(xiàn)了接收器對象與連接點對象之間建立關(guān)系的過程,如果連接成功則用AsyncConnection來標識這個連接,其具體實現(xiàn)如下:
function GroupAdvise2(GroupIf: IUnknown; OPCDataCallback: IOPCDataCallback;
          var AsyncConnection: Longint): HResult;
var
  ConnectionPointContainer: IConnectionPointContainer;
  ConnectionPoint: IConnectionPoint;
begin
  Result := E_FAIL;
  try
    ConnectionPointContainer := GroupIf as IConnectionPointContainer;
  except
    ConnectionPointContainer := nil;
  end;
  if ConnectionPointContainer <> nil then
  begin
    Result := ConnectionPointContainer.FindConnectionPoint(IID_IOPCDataCallback,
      ConnectionPoint);
    if Succeeded(Result) and (ConnectionPoint <> nil) then
    begin
      Result := ConnectionPoint.Advise(OPCDataCallback as IUnknown,
        AsyncConnection);
    end;
  end;
end;
(7)  異步讀寫
   客戶進行異步讀寫操作只需要簡單的調(diào)用IOPCAsyncIO2接口的Read,Write等方法,這個過程不需要客戶程序等待,函數(shù)的返回值中并不包括操作的結(jié)果,而操作的具體結(jié)果會由服務(wù)器通過調(diào)用客戶的IOPCDataCallback接口中的OnDataChange,OnReadComplete,OnWriteComplete,OnCancelComplete等方法來返回給客戶。下面給出IOPCAsyncIO2接口的Delphi描述:
IOPCAsyncIO2 = interface(IUnknown)
    ['{39C13A71-011E-11D0-9675-0020AFD8ADB3}']
    function Read(
            dwCount:                    DWORD;
            phServer:                   POPCHANDLEARRAY;
            dwTransactionID:            DWORD;
      out   pdwCancelID:                DWORD;
      out   ppErrors:                   PResultList): HResult; stdcall;
    function Write(
            dwCount:                    DWORD;
            phServer:                   POPCHANDLEARRAY;
            pItemValues:                POleVariantArray;
            dwTransactionID:            DWORD;
      out   pdwCancelID:                DWORD;
      out   ppErrors:                   PResultList): HResult; stdcall;
    function Refresh2(
            dwSource:                   OPCDATASOURCE;
            dwTransactionID:            DWORD;
      out   pdwCancelID:                DWORD): HResult; stdcall;
    function Cancel2(
            dwCancelID:                 DWORD): HResult; stdcall;
    function SetEnable(
            bEnable:                    BOOL): HResult; stdcall;
    function GetEnable(
      out   pbEnable:                   BOOL): HResult; stdcall;
  end;
   當服務(wù)器中的數(shù)據(jù)發(fā)生變化時,服務(wù)器會調(diào)用客戶的IOPCDataCallback接口中OnDataChange函數(shù),當服務(wù)器異步讀完成后會調(diào)用客戶的IOPCDataCallback接口中OnReadComplete函數(shù),當服務(wù)器異步寫完成后會調(diào)用客戶的IOPCDataCallback接口中OnWriteComplete函數(shù),當服務(wù)器撤銷操作完成后會調(diào)用客戶的IOPCDataCallback接口中OnCancelComplete函數(shù)。限于篇幅,這里只給出客戶的IOPCDataCallback接口中OnDataChange函數(shù)實現(xiàn),其他函數(shù)的實現(xiàn)過程類似。
function TOPCDataCallback.OnDataChange(dwTransid: DWORD; hGroup: OPCHANDLE;
  hrMasterquality: HResult; hrMastererror: HResult; dwCount: DWORD;
  phClientItems: POPCHANDLEARRAY; pvValues: POleVariantArray;
  pwQualities: PWordArray; pftTimeStamps: PFileTimeArray;
  pErrors: PResultList): HResult;
var
  ClientItems: POPCHANDLEARRAY;
  Values: POleVariantArray;
  Qualities: PWORDARRAY;
  I: Integer;
  NewValue: string;
begin
  Result := S_OK;
  ClientItems := POPCHANDLEARRAY(phClientItems);
  Values := POleVariantArray(pvValues);
  Qualities := PWORDARRAY(pwQualities);
  for I := 0 to dwCount - 1 do
  begin
    if Qualities[I] = OPC_QUALITY_GOOD then
    begin
      NewValue := VarToStr(Values[I]);
      Form1.LblValue.Caption :=NewValue;
    end
    else begin
      ShowMessage('Callback received for item , but quality not good');
    end;
  end;
end;
(8)  斷開IOPCDataCallback接口
GroupUnadvise2(GroupIf, AsyncConnection);
//斷開客戶與組對象GroupIf之間用AsyncConnection標識的IOPCDataCallback接口連接,其實現(xiàn)過程如下:
function GroupUnadvise2(GroupIf: IUnknown; var AsyncConnection: Longint): HResult;
var
  ConnectionPointContainer: IConnectionPointContainer;
  ConnectionPoint: IConnectionPoint;
begin
  Result := E_FAIL;
  try
    ConnectionPointContainer := GroupIf as IConnectionPointContainer;
  except
    ConnectionPointContainer := nil;
  end;
  if ConnectionPointContainer <> nil then
  begin
    Result := ConnectionPointContainer.FindConnectionPoint(IID_IOPCDataCallback,
      ConnectionPoint);
    if Succeeded(Result) and (ConnectionPoint <> nil) then
    begin
      Result := ConnectionPoint.Unadvise(AsyncConnection);
    end;
  end;
end;
(9)  斷開服務(wù)器連接 //實現(xiàn)過程同上

6  結(jié)語

    使用OPC的定制接口進行客戶程序的編程,需要一些COM知識的理解以及對于以下開發(fā)工具的熟練使用,因此相對于自動化接口的編程來說時比較困難的,但是使用定制接口的效率和靈活性卻是使用其他方式所無法比擬的。本文只是粗淺的介紹了在Delphi環(huán)境下使用定制接口進行OPC客戶程序的開發(fā),希望能達到拋磚引玉的效果。

熱點新聞

推薦產(chǎn)品

x
  • 在線反饋
1.我有以下需求:



2.詳細的需求:
姓名:
單位:
電話:
郵件:
主站蜘蛛池模板: 亚洲精品中文字幕一区在线| 欧美性一级| 2018av男人天堂| 亚洲欧美日韩精品久久亚洲区| 在线有码| 久草免费手机视频| 国产码一区二区三区| 成年人黄页| 综合色久七七综合七七蜜芽| 午夜免费成人| 日韩美三级| 九九在线免费观看视频| 国产日产韩产麻豆1区| bt天堂午夜国产精品| 亚洲第一区在线| 三级黄色片网址| 久久久国产99久久国产久| 久草com| 国产精品亚洲二区| 97在线视频观看| 亚洲图片在线视频| 久久久这里只有精品加勒比| 精品亚洲成a人片在线观看| 成人久久18免费网| 日本美女福利视频| 男人扒开双腿女人爽视频免费| 国产国产成人精品久久| 亚洲一区二区久久| 日本在线视频播放| 国产精品久久免费| 亚洲女人网| 欧美一级片手机在线观看| 国产免费久久精品久久久| 一本色道久久爱88av| 日韩欧美亚洲每的更新在线| 国产一级做a爱免费观看| 伊在人亚洲香蕉精品区| 台湾精品视频在线播放| 国产网站免费| 亚洲精品高清久久| 国产日韩一区二区三区在线观看|