⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 commu.pas

📁 omroln OPC 用delphi描述了同OMROLnOPC通讯的过程
💻 PAS
📖 第 1 页 / 共 2 页
字号:
 *                函数名称:Disconnect
 *                函数功能:中断与OPC服务的连接
 *                入口参数:无
 *                出口参数:无
 *                  返回值:无
 *}

procedure TOPCComm.Disconnect;
begin
  if Assigned(FOPCServer) then
    FOPCServer := nil;
  FStatus := Const_STATUS_DISCONNECT;
end;


{*
 *                函数名称:HaveItemState
 *                函数功能:判断采集点的状态是否存在
 *                入口参数:1、CurrState: Byte
 *                          2、ItemState: Byte
 *                出口参数:无
 *                  返回值:Boolean
 *}

function TOPCComm.HaveItemState(const CurrState, ItemState: Byte): Boolean;
begin
  Result := False;
  if (CurrState = Const_ITEMSTATE_ERROR) then
    Exit;

  if (CurrState and ItemState) <> 0 then
    Result := True;
end;

{*
 *                函数名称:SetItemState
 *                函数功能:设置采集点的状态
 *                入口参数:1、CurrState: Byte
 *                          2、ItemState: Byte
 *                出口参数:无
 *                  返回值:Byte
 *}

function TOPCComm.SetItemState(const CurrState, ItemState: Byte): Byte;
begin
  if CurrState = Const_ITEMSTATE_ERROR then
    Result := Const_ITEMSTATE_NORMAL
  else
    Result := CurrState;

  Result := Result or ItemState;
end;

{*
 *                函数名称:ClrItemState
 *                函数功能:清除采集点的状态
 *                入口参数:1、CurrState: Byte
 *                          2、ItemState: Byte
 *                出口参数:无
 *                  返回值:Byte
 *}
 
function TOPCComm.ClrItemState(const CurrState, ItemState: Byte): Byte;
begin
  if CurrState = Const_ITEMSTATE_ERROR then
  begin
    Result := Const_ITEMSTATE_NORMAL;
    Exit;
  end;

  Result := CurrState and (not ItemState);
end;

{*
 *                函数名称:Create
 *                函数功能:构造函数
 *                入口参数:无
 *                出口参数:无
 *                  返回值:无
 *}

constructor TOPCComm.Create;
begin
  inherited;
  ComObj.CoInitializeEx(nil, 0);
  InitializeCriticalSection(FLock);
  FReadEvent := CreateEvent(nil, True, False, '');
  FOPCServer := nil;
  FOPCItemMgt := nil;
  FOPCSyncIO := nil;
  FOPCDataCallback := nil;
  FConnectionPoint := nil;
  FCookie := 0;
  FStatus := Const_STATUS_DISCONNECT;
  FGroupName := 'GROUP' + IntToStr(GetTickCount);
end;

{*
 *                函数名称:Destroy
 *                函数功能:析构函数
 *                入口参数:无
 *                出口参数:无
 *                  返回值:无
 *}

destructor TOPCComm.Destroy;
begin
  DeleteCriticalSection(FLock);
  CloseHandle(FReadEvent);
  inherited;
end;

{*
 *                函数名称:ReadData
 *                函数功能:读取数据
 *                入口参数:无
 *                出口参数:1、Index: DWord
 *                          2、Value: Variant
 *                          3、ReadTime: TDateTime
 *                  返回值:Boolean
 *}

function TOPCComm.ReadData(var ItemName: string; var Value: Variant; var ReadTime: TDateTime): Boolean;
var
  I: Integer;
begin
  if FStatus = Const_STATUS_DISCONNECT then
  begin
    Result := False;
    Exit;
  end;
  EnterCriticalSection(FLock);
  try
    for I := 0 to FItemNum - 1 do
    begin
      if HaveItemState(FOPCItemInfos[I].wStatus, Const_ITEMSTATE_READ) then
      begin
        ItemName := string(FOPCItemInfos[I].szOPCID);
        Value := FOPCItemInfos[I].vrRValue;
        ReadTime := FOPCItemInfos[I].dtRTime;
        FOPCItemInfos[I].wStatus := ClrItemState(FOPCItemInfos[I].wStatus, Const_ITEMSTATE_READ);
        Result := True;
        Exit;
      end;
    end;
    Result := False;
    ResetEvent(FReadEvent);
  finally
    LeaveCriticalSection(FLock);
  end;
end;

{*
 *                函数名称:QueryData
 *                函数功能:查询数据
 *                入口参数:1、Indexs: array of Word
 *                出口参数:无
 *                  返回值:无
 *}

procedure TOPCComm.QueryData(const ItemNames: array of string);
var
  HRes: HRESULT;
  Errors: PResultList;
  ItemName, FindName: string;
  I, J, ItemLen: Integer;
  TransId, CancelId: Cardinal;
  ItemHandles: array of OPCHANDLE;
begin
  if FStatus = Const_STATUS_DISCONNECT then
    Exit;

  if Length(ItemNames) <= 0 then
    Exit;

  SetLength(ItemHandles, 0);
  for I := 0 to High(ItemNames) do
  begin
    ItemName := ItemNames[I];
    for J := 0 to High(FOPCItemInfos) do
    begin
      FindName := OleStrToString(FOPCItemInfos[J].szOPCID);
      if AnsiCompareText(ItemName, FindName) = 0 then
      begin
        SetLength(ItemHandles, Length(ItemHandles) + 1);
        ItemHandles[High(ItemHandles)] := FOPCItemInfos[J].hOPCItem;
        Break;
      end;
    end;
  end;

  ItemLen := Length(ItemHandles);
  if ItemLen <= 0 then
    Exit;

  ComObj.CoInitializeEx(nil, 0);
  try
    TransId := Random(High(Word));
    HRes := FOPCAsyncIO.Read(ItemLen, @ItemHandles[0], TransId, CancelId, Errors);
    if Failed(HRes) then
    begin
      FStatus := Const_STATUS_DISCONNECT;
      WriteDebugLog(Format('查询采集点数据失败. 接口错误代码(%d)', [HRes]));
      Exit;
    end;
    CoTaskMemFree(Errors);
  finally
    CoUnInitialize;
  end;
end;

{*
 *                函数名称:RefershData
 *                函数功能:刷新数据
 *                入口参数:无
 *                出口参数:无
 *                  返回值:无
 *}

procedure TOPCComm.RefershData;
var
  I: Integer;
  ItemNames: array of String;
begin
  SetLength(ItemNames, Length(FOPCItemInfos));
  for I := 0 to High(FOPCItemInfos) do
    ItemNames[I] := OleStrToString(FOPCItemInfos[I].szOPCID);
  QueryData(ItemNames);
end;

{*
 *                函数名称:SendData
 *                函数功能:发送数据
 *                入口参数:1、Index: DWord
 *                          2、Value: Variant
 *                出口参数:无
 *                  返回值:Boolean
 *}

function TOPCComm.SendData(const ItemName: string; const Value: Variant): Boolean;
var
  I, Idx: Integer;
  HRes: HRESULT;
  Errors: PResultList;
  ItemValues: array of OleVariant;
  ItemHandles: array of OPCHANDLE;
begin
  SetLength(ItemValues, 0);
  SetLength(ItemHandles, 0);
  Result := False;
  if FStatus = Const_STATUS_DISCONNECT then
    Exit;

  Idx := -1;
  for I := 0 to High(FOPCItemInfos) do
  begin
    if AnsiCompareText(FOPCItemInfos[I].szOPCID, ItemName) = 0 then
    begin
      Idx := I;
      Break;
    end;
  end;
  if Idx = -1 then
    Exit;

  SetLength(ItemValues, 1);
  SetLength(ItemHandles, 1);
  ItemValues[0] := Value;
  ItemHandles[0] := FOPCItemInfos[Idx].hOPCItem;

  ComObj.CoInitializeEx(nil, 0);
  try
    HRes := FOPCSyncIO.Write(1, @ItemHandles[0], @ItemValues[0], Errors);
    if Failed(HRes) then
    begin
      FStatus := Const_STATUS_DISCONNECT;
      WriteDebugLog(Format('向采集点(%s)下发数据失败. 接口错误代码(%d)', [FOPCItemInfos[Idx].szOPCID, HRes]));
      Exit;
    end;
    CoTaskMemFree(Errors);
    VariantClear(ItemValues[0]);
    Result := True;
  finally
    CoUnInitialize;
  end;
end;

{*
 *                函数名称:SetItems
 *                函数功能:初始化采集点信息
 *                入口参数:1、ItemNames: array of string
 *                出口参数:无
 *                  返回值:Boolean
 *}

function TOPCComm.SetItems(const ItemNames: array of string): Boolean;
var
  I, Cnt: Integer;
begin
  Result := False;
  if FStatus <> Const_STATUS_DISCONNECT then
    Exit;
  Cnt := Length(ItemNames);
  FItemNum := Cnt;
  SetLength(FOPCItemInfos, FItemNum);
  for I := 0 to FItemNum - 1 do
    FOPCItemInfos[I].szOPCID := StringToOleStr(ItemNames[I]);
  Result := True;
end;

{*
 *                函数名称:StartComm
 *                函数功能:启动通讯接口
 *                入口参数:无
 *                出口参数:无
 *                  返回值:Boolean
 *}

function TOPCComm.StartComm: Boolean;
begin
  Result := False;

  if FStatus = Const_STATUS_CONNECTED then
    StopComm;

  if not Connect then
    Exit;

  if not AddGroup then
  begin
    Disconnect;
    Exit;
  end;

  if not AddItems then
  begin
    RemoveGroup;
    Disconnect;
    Exit;
  end;

  if not AdviseCallback then
  begin
    RemoveItems;
    RemoveGroup;
    Disconnect;
    Exit;
  end;

  FStatus := Const_STATUS_CONNECTED;
  Result := True;
end;

{*
 *                函数名称:StopComm
 *                函数功能:停止通讯接口
 *                入口参数:无
 *                出口参数:无
 *                  返回值:无
 *}

procedure TOPCComm.StopComm;
begin
  if FStatus = Const_STATUS_DISCONNECT then
    Exit;

  //Unadvise Callback for OPC Items
  UnadviseCallback;

  //Call procedure Remove OPC Items
  RemoveItems;

  //Call procedure Remove OPC Group
  RemoveGroup;

  //Call procedure Remove OPC Group
  Disconnect;
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -