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

📄 uopcdemo.pas

📁 delphi 开发OPc工业通讯 delphi 开发OPc工业通讯
💻 PAS
字号:
unit uOPCDemo;

{$IFDEF VER150}
{$WARN UNSAFE_TYPE OFF}
{$ENDIF}

interface

uses
{$IFDEF VER140}
  Variants,
{$ENDIF}
{$IFDEF VER150}
  Variants,
{$ENDIF}
  SysUtils, ActiveX, OPCDA, uOPCNode, uOPC;

// OPC functions
procedure OnInitAddressSpace;
procedure OnRead(OPCNode: sOPCNode; Path: string; DataType: TVarType);
procedure OnWrite(OPCNode: sOPCNode; Value: variant; Path: string; DataType: TVarType);

// Value functions
procedure IncrementValues;
procedure ResetValues;

var
  // actual values (Tags)
  Values: array[101 .. 404] of integer;

implementation

procedure IncrementValues;
var
  i: integer;
begin
  for i := Low(Values) to High(Values) do Values[i] := Values[i] + 1;
end;

procedure ResetValues;
var
  i: integer;
begin
  for i := Low(Values) to High(Values) do Values[i] := 0;
end;

procedure OnInitAddressSpace;
// initialize address space
begin
  with OPC do begin
    // add leaf (tag)
    AddLeaf(0, 101, 'String',  VT_BSTR,          OPC_READABLE);
    AddLeaf(0, 102, 'Integer', VT_I4,            OPC_READABLE + OPC_WRITEABLE);
    AddLeaf(0, 103, 'Double',  VT_R8,            OPC_READABLE + OPC_WRITEABLE);
    AddLeaf(0, 104, 'Array',   VT_R8 + VT_ARRAY, OPC_READABLE);

    // add branch
    AddBranch(0, 200, 'Branch 1');
      AddLeaf(200, 201, 'String',  VT_BSTR,          OPC_READABLE);
      AddLeaf(200, 202, 'Integer', VT_I4,            OPC_READABLE + OPC_WRITEABLE);
      AddLeaf(200, 203, 'Double',  VT_R8,            OPC_READABLE + OPC_WRITEABLE);
      AddLeaf(200, 204, 'Array',   VT_R8 + VT_ARRAY, OPC_READABLE);

      AddBranch(200, 300, 'Branch 1.1');
        AddLeaf(300, 301, 'String',  VT_BSTR,          OPC_READABLE);
        AddLeaf(300, 302, 'Integer', VT_I4,            OPC_READABLE + OPC_WRITEABLE);
        AddLeaf(300, 303, 'Double',  VT_R8,            OPC_READABLE + OPC_WRITEABLE);
        AddLeaf(300, 304, 'Array',   VT_R8 + VT_ARRAY, OPC_READABLE);

    AddBranch(0, 400, 'Branch 2');
      AddLeaf(400, 401, 'String',  VT_BSTR,          OPC_READABLE);
      AddLeaf(400, 402, 'Integer', VT_I4,            OPC_READABLE + OPC_WRITEABLE);
      AddLeaf(400, 403, 'Double',  VT_R8,            OPC_READABLE + OPC_WRITEABLE);
      AddLeaf(400, 404, 'Array',   VT_R8 + VT_ARRAY, OPC_READABLE);
  end;
end;

procedure OnRead(OPCNode: sOPCNode; Path: string; DataType: TVarType);
type
  DoubleArray = array[0 .. 65535] of double;
  PDoubleArray = ^DoubleArray;
var
  pda: PDoubleArray;
  i: integer;
begin
  case OPCNode.Ident of

    // string
    101, 201, 301, 401: begin
      VarClear(OPCNode.CurrentValue);
      OPCNode.LastUpdate := Now;
      OPCNode.Quality := OPC_QUALITY_GOOD;
      OPCNode.CurrentValue := Format('Value %d is %d', [OPCNode.Ident, Values[OPCNode.Ident]]);
    end;

    // integer
    102, 202, 302, 402: begin
      { When the Tag represent a status information or when a Tag is changing
        unregularly and you want to generate a data callback only when the value
        has changed, then set the OPCNode fields only when the cached value
        (CurrentValue) is not equal to the actual value.
        The Result is, that the timestamp on the client will be updated only
        when the Tag has changed!
      }
      // On the first OnRead call, CurrentValue is empty!
      if not VarIsEmpty(OPCNode.CurrentValue) then begin
        // Tag has not changed -> no data callback -> exit
        if Values[OPCNode.Ident] = OPCNode.CurrentValue then exit;
      end;
      VarClear(OPCNode.CurrentValue);
      OPCNode.LastUpdate := Now;
      OPCNode.Quality := OPC_QUALITY_GOOD;
      OPCNode.CurrentValue := Values[OPCNode.Ident];
    end;

    // double
    103, 203, 303, 403: begin
      VarClear(OPCNode.CurrentValue);
      OPCNode.LastUpdate := Now;
      OPCNode.Quality := OPC_QUALITY_GOOD;
      OPCNode.CurrentValue := Values[OPCNode.Ident] / 100;
    end;

    // array of double
    104, 204, 304, 404: begin
      VarClear(OPCNode.CurrentValue);
      OPCNode.LastUpdate := Now;
      OPCNode.Quality := OPC_QUALITY_GOOD;
      OPCNode.CurrentValue := VarArrayCreate([0, 31], VT_R8);
      pda := VarArrayLock(OPCNode.CurrentValue);
      for i := 0 to 31 do pda[i] := Values[OPCNode.Ident] / 100;
      VarArrayUnlock(OPCNode.CurrentValue);
    end;

  end;
end;

procedure OnWrite(OPCNode: sOPCNode; Value: variant; Path: string; DataType: TVarType);
begin
  OPCNode.LastUpdate := Now;
  Values[OPCNode.Ident] := Value;
  OPCNode.CurrentValue := Value;
end;

initialization
  FillChar(Values, sizeof(Values), 0);
end.

⌨️ 快捷键说明

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