日本在线www-日本在线播放一区-日本在线不卡免费视频一区-日本在线不卡视频-成人影院久久久久久影院-成人影院一区二区三区

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

案例頻道

Delphi環(huán)境下使用定制接口開發(fā)OPC數(shù)據(jù)訪問客戶程序
  • 企業(yè):控制網(wǎng)     領(lǐng)域:電源    
  • 點擊數(shù):6207     發(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ā)工具。它具有功能強大、運行速度快、易于學(xué)習、使用和開發(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.詳細的需求:
姓名:
單位:
電話:
郵件:
主站蜘蛛池模板: 伦理片天堂eeuss影院-伦理片秋霞免费影院-伦理片飘花手机在线-伦理片飘花免费影院-最新2017年韩国伦理片在线-最新 国产 精品 精品 视频 | 欧美成人国产一区二区-欧美成人黄色-欧美成人黄色片-欧美成人家庭影院-欧美成人精精品一区二区三区-欧美成人精品a8198v无码 | 国产精品福利久久2020-国产精品分类视频分类一区-国产精品反差婊在线观看-国产精品二区在线-色播99-色y情视频免费看 | 97视频久久久-97视频在线观看播放-97视频制服无码-97丨九色丨国产人妻熟女-97无码欧美熟妇人妻蜜-97无码欧美熟妇人妻蜜桃天美 | 激情www,国产成人爱情动作片在线观看,五月天婷婷在线观看高清,欧美美女福利视频,五月激激激综合网色播免费,国产亚洲欧美日韩综合另类 | 99久久这里只精品国产免费,毛片在线播放网站,狠狠色狠色综合曰曰,国产在线成人精品,欧美色视频网,激情五月婷婷综合 | 91香蕉视频在线播放-91香蕉视频在线看-91香蕉小视频-91香蕉亚洲精品人人影视-91香蕉影院-91香蕉在线视频 | 中文国产成人精品久久下载-中文国产成人精品久久久-中文国产成人精品久久app-中文国产-99精品影视-99精品视频在线免费观看 | 性情网站-性派对交换俱乐部-性派对xxxhd-性派对videos18狂欢-国产中学生-国产中文字幕在线视频 | 91精品在线播放视频大全在线观看-91精品在线国产一区-91精品在线视频观看-91精品中文字幕-91精品专区-91精品专区国产盗摄 | 日本欧美一区-日本欧美一区二区三区片-日本强好片久久久久久AAA-日本-区一区二区三区A片-日本人伦一区二区三区-日本人妻A片成人免费看 | 久久久久久久久国产-久久久久久久久97-久久久久久久国产视频-久久久久久久国产精品影院-午夜精-午夜寂寞院 | 亚洲幼女网-亚洲呦女专区-亚洲永久在线观看-亚洲永久免费视频-精品久久香蕉国产线看观看麻豆-精品久久日日躁夜夜躁AV | 奇米影视一区二区三区-奇米影视一区-奇米影视久久-奇米影视777四色米奇影院-国产高清视频免费-国产高清日韩 | 天天干天天操天天碰-天天干天天操天天摸-天天干天天操天天干-天天干天天操天天插-欧美一级久久久久久久久大-欧美一区二区VA毛片视频 | 亚洲第一视频网-亚洲第一色在线-亚洲第一色网站-亚洲第一人黄所-亚洲第一区在线观看-亚洲第一区在线 | aaak7美国发布站-a v 在线视频 亚洲免费-99综合色-99在线这精品视频-国产成人综合洲欧美在线-国产成人综合在线观看网站 | 欧洲亚洲日本-欧洲亚洲视频-欧洲亚洲一区-欧洲亚洲一区二区三区-国产精品第九页-国产精品第六页 老司机午夜精品网站在线观看-老司机午夜精品视频在线观看免费-老司机午夜精品视频观看-老司机午夜精品视频播放-一本色道久久88一综合-一本色道久久88综合日韩精品 | 波多野结衣中文字幕教师-波多野结衣中文字幕2022免费-波多野结衣中文在线观看-波多野结衣中文在线播放-波多野结衣中文一区-波多野结衣中文丝袜字幕 | 日本欧美一区-日本欧美一区二区三区片-日本强好片久久久久久AAA-日本-区一区二区三区A片-日本人伦一区二区三区-日本人妻A片成人免费看 | 国产夜色福利院在线观看免费-国产夜趣福利免费视频-国产野花视频天堂视频免费-国产亚洲综合一区二区在线-日韩精品在线观看免费-日韩精品在线电影 | 日操夜操天天操-午夜日日日日日日日日日-亚洲欧洲精品无视频一区二区三区四-国产成人精品无码-婷婷福利综合网-日逼影视 | 日本a天堂,亚洲精品乱码久久久久久,欧美精品一区二区三区在线播放,国产亚洲视频在线观看,国产丰满眼镜女在线观看,亚洲日韩欧美综合 | 娇妻在客厅被朋友玩得呻吟漫画-娇小娇小与黑人tubevideos-进去粗粗硬硬紧紧的好爽免费视频-禁欲总裁被C呻吟双腿大张-禁止的爱6浴室吃奶中文字幕-经典乱家庭伦小说 | 99久久这里只精品国产免费,毛片在线播放网站,狠狠色狠色综合曰曰,国产在线成人精品,欧美色视频网,激情五月婷婷综合 | 亚洲欧美日韩在线播放,国产成人综合久久,精品国产91,婷婷综合久久中文字幕蜜桃三电影,国产一区精品在线观看,福利一区三区 | 成人免费视频77777,精品国产福利,欧日韩一区二区三区,国产高清视频在线观看,欧美日韩1区,欧美一区二区三区在线观看 | 天堂网在线观看-天堂网在线www最新版在线-天堂网在线www资源在线-天堂网在线www资源网-精品久久一区二区-精品久久一区 | 免费看a级-免费看a级毛片-免费看a网站-免费看h的网站-97久久久久-97久久人人 | 色视频高清在线观看-色视频播放-色社区-色涩网站在线观看-色涩色-色色综合 | 二区乱码综合无码一区二区三-二区女人观看chinese中国真实乱-二区欧美三-二区欧美无遮挡中文字幕人成人-二区啪视频-二区日本成人动漫电影 | 一区二区不卡久久精品-一区二区播放-一区二区3区免费视频-一区不卡在线观看-久久机热-久久黄网 | 中文无码熟妇人妻av在-中文无码视频三区四区在线观看-中文无码视频-中文无码肉感爆乳在线-中文无码日韩欧免费视频-中文无码日韩欧毛 | 日本xxxxx18护士xxx-日本xxxxwwww-日本xxxx1819黑人-日本xxxbbb0oo-国产精品免费看久久久-国产精品免费久久久免费 | 视频免费观看网址-视频免费观看视频-视频免费观看入口大全-视频免费1区二区三区-国产成人尤物精品一区-国产成人悠悠影院 | 中文字幕第一页亚洲-中文字幕第一页国产-中文字幕第38页永久乱码-中文字幕不卡在线观看-久久久久青草大香线综合精品-久久久久青草 | 我爱52av好色,一级毛片大全免费播放,成人午夜无人区一区二区,国产一区国产二区国产三区,青青青青久久精品国产h,狠狠操五月天 | 国产精品高潮呻吟AV久久-国产精品高潮呻吟AV久久床戏-国产精品高潮呻吟AV久久动漫-国产精品高潮呻吟AV久久黄-国产精品高潮呻吟AV久久无码-国产精品高潮呻吟爱久久AV无码 | 欧美成人免费xxx大片,91在线视频一区,精品日韩一区二区三区,欧美日韩 在线播放,欧美在线aa,亚洲专区路线一路线二天美 | 97色伦人人-97色碰-97视频久久-97视频免费人人观看人人-免费看色片网站-免费看视频的网站 | 亚洲香蕉久久综合网-亚洲香蕉久久一区二区三区四区-亚洲香蕉久久一区二区-亚洲香蕉国产高清在线播放-净空法师最新忏悔文-精油按摩理论片 |