unit IPS7DEMO;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Mask, Grids, IPS7LNK, ExtCtrls;

 const MAX_ITEM_COUNT = 2048;

 const DataAreas: array[0..5] of Char = ('E', 'A', 'M', 'D', 'T','Z');


type
  TFormIPS7Demo = class(TForm)
    IDC_IPADR: TLabel;
    EdIPAddr: TMaskEdit;
    EdRack: TMaskEdit;
    Label1: TLabel;
    EdSlot: TMaskEdit;
    Label2: TLabel;
    Label3: TLabel;
    CbPLCType: TComboBox;
    GroupBox1: TGroupBox;
    RdOP: TRadioButton;
    RdPG: TRadioButton;
    Label4: TLabel;
    CbDataArea: TComboBox;
    EdDBNr: TMaskEdit;
    EdStart: TMaskEdit;
    EdCount: TMaskEdit;
    Label5: TLabel;
    Label6: TLabel;
    Label7: TLabel;
    List: TStringGrid;
    Label8: TLabel;
    EdIPStatus: TEdit;
    Label9: TLabel;
    EdStatus: TEdit;
    BtnOpen: TButton;
    BtnClose: TButton;
    BtnRdDB: TButton;
    BtnRdPlcW: TButton;
    BtnRdDW: TButton;
    BtnRdReal: TButton;
    BtnRdMulti: TButton;
    BtnEnd: TButton;
    Logo: TImage;
    Timer1: TTimer;
    BtnConnect: TButton;
    procedure BtnOpenClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    function GetStatusText (lErr : LongInt) : String;
    function GetFormData : Boolean;
    procedure ShowStatus;
    procedure ShowErr;
    procedure BtnCloseClick(Sender: TObject);
    procedure SetBtnState;
    procedure SetListItemData (Line : LongInt; Item: LongInt; PCDataType:LongInt; PLCDataType:LongInt;
                                         pData : Pointer; bShowHex : Boolean; Result:Integer);
    procedure AddItemsToList (DataArea : LongInt; DBNr : LongInt; Line : LongInt;
                                        StartAt : LongInt; StartBit : LongInt; Cnt : LongInt; PCDataType: LongInt;
                                        PLCDataType : LongInt; pD : Pointer;  bShowHex: Boolean; Res : LongInt);
    function MakeAdrName (DataArea : LongInt; DBNr:LongInt; PLCDataType : LongInt) : String;
    procedure BtnRdPlcWClick(Sender: TObject);
    function ValueInRange(Info : String; sVal: String; var Val : LongInt; Min : LongInt; Max : LongInt): Boolean;
    procedure BtnEndClick(Sender: TObject);
    procedure DelList;
    procedure SetWaitCursor;
    procedure SetNormalCursor;
    procedure BtnRdRealClick(Sender: TObject);
    function  GetPCUnitSize (PCDataType:LongInt) : integer;
    procedure BtnRdDBClick(Sender: TObject);
    procedure BtnRdDWClick(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure BtnConnectClick(Sender: TObject);
    procedure InitRq (pRq : PIPS7_RQ_MULTI; DataArea : Char; DataType:LongInt; PcDataArea:LongInt;
                      DBNr : LongInt; Start:LongInt; StartBit: LongInt; Cnt: LongInt; pData :Pointer);
    procedure BtnRdMultiClick(Sender: TObject);

    procedure ShowErrInList (Line : LongInt; lErr : LongInt);

    private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    m_lRef : LongInt;
    m_lErr : LongInt;
    m_strStatus: String;
    m_lRackNr : LongInt;
    m_lSlotNr : LongInt;
    m_lPLCType : LongInt;
    m_lDBNr : LongInt;
    m_lStart : LongInt;
    m_lCount : LongInt;
    m_lDataArea : LongInt;
    m_strIPAddr : AnsiString;
    m_bUseOP : Boolean;
    m_bOpen  : Boolean;
    m_strAdrName: String;

    m_byteBuf : packed array [0..MAX_ITEM_COUNT] of BYTE;
    m_wordBuf : packed array [0..MAX_ITEM_COUNT] of WORD;
    m_dintBuf : packed array [0..MAX_ITEM_COUNT] of LongInt;
    m_doubleBuf : packed array [0..MAX_ITEM_COUNT] of double;

  end;

var
  FormIPS7Demo: TFormIPS7Demo;


implementation

{$R *.DFM}

procedure TFormIPS7Demo.FormCreate(Sender: TObject);
begin
  m_lRef := -1;
  List.Cells[0,0] := 'Adr/Addr';
  List.Cells[1,0] := 'Wert/Value(Dec.)';
  List.Cells[2,0] := 'Wert/Value(Hex)';
  List.Cells[3,0] := 'ASCII';
  CbPLCType.ItemIndex := 0;
  CbDataArea.ItemIndex := 0;
  RdOP.Checked := True;
  EdIPAddr.EditMask := '!099.099.099.099;1; ';
  EdIPAddr.Text := '192.168.0.80';
  EdRack.Editmask := '!0';
  EdRack.Text := '0';
  EdSlot.Editmask := '!0';
  EdSlot.Text := '2';
//  EdDBNr.EditMask := '!0000';
  EdDBNr.Text := '1';
//  EdStart.EditMask := '!09999';
  EdStart.Text := '0';
//  EdCount.EditMask := '!09999';
  EdCount.Text := '1';
  m_bOpen := False;
  SetBtnState;
end;


function TFormIPS7Demo.ValueInRange(Info : String; sVal: String; var Val : LongInt; Min : LongInt; Max : LongInt): Boolean;
var
bOk : Boolean;
sMsg : String;
begin
  bOk := False;
  sVal := StringReplace (sVal, ' ', '',  [rfReplaceAll, rfIgnoreCase]); // del Spaces
  if sVal = '' then
  begin
    sVal := '0';
  end;
  Val := StrToInt(sVal);
  if (Val < Min) or (Val > Max) then
  begin
    sMsg := Info + ': Wert nicht im Bereich / Value not in range (' + IntToStr (Min) + ' - ' + IntToStr (Max) + ')';
    Application.MessageBox (PChar (sMsg), 'Eingabefehler / Inputerror',  MB_OK);
  end
  else
  begin
    bOK := True;
  end;
  Result := bOK;

end;


function TFormIPS7Demo.GetFormData : Boolean;
var
bOk : Boolean;
begin
  bOk := False;
  m_strIPAddr := StringReplace (EdIPAddr.Text, ' ', '',  [rfReplaceAll, rfIgnoreCase]); // del Spaces
  m_bUseOP := RdOP.Checked;
  if (ValueInRange('Rack-Nr', EdRack.Text, m_lRackNr, 0,2) and
      ValueInRange('Slot-Nr', EdSlot.Text, m_lSlotNr, 0,20) and
      ValueInRange('DB-Nr', EdDBNr.Text, m_lDBNr, 1,65535) and
      ValueInRange('Start', EdStart.Text, m_lStart, 0,65535) and
      ValueInRange('Start', EdCount.Text, m_lCount, 0,MAX_ITEM_COUNT)) then
    bOk := True;
  m_lDataArea := LongInt (DataAreas[CbDataArea.ItemIndex]);
  m_lPLCType := CbPLCType.ItemIndex; // 0 = S7 300/400 1 = S7 200
  Result := bOk;
end;


function TFormIPS7Demo.GetStatusText (lErr : LongInt) : String;
begin

  case (lErr) of
    IPS7_E_NOERR:
      m_strStatus := 'Aktion erfolgreich. / Action was successfull!';

    IPS7_E_NODATA:	       // angeforderter Bereich zu klein
      m_strStatus := 'Datenbereich in der SPS zu klein. / Data area in PLC too small!';

    IPS7_E_CPU_NOTFOUND:	      // z.B wenn zu wenig Daten von übers Netzwerk kommen
      m_strStatus := 'SPS im angegebenen Rack/Slot nicht gefunden! / PLC in the selected rack/slot not found!';

    IPS7_E_TIMEOUT:
      m_strStatus := 'Zeitüberlauf! / Timeout!';

    IPS7_E_SOCKERR:
    m_strStatus := 'Socketfehler Nr:' + IntToStr(IPS7GetSockErr (m_lRef)) + ' aufgetreten. / Socket error no:' + IntToStr(IPS7GetSockErr (m_lRef)) + ' occurred!'; // ', SocketErr, SocketErr)';

    IPS7_E_NOTSUPPORTED:
      m_strStatus := 'Datentyp oder Format wird nicht unterstützt! / Data type or data format not supported!';

    IPS7_E_PC_BUFSIZE:
      m_strStatus := 'Das Ã¼bergebene Array hat zuwenig Elemente. / The Array you passed is to small.';

    IPS7_E_ALREADY_OPENED:
      m_strStatus := 'Die Open-Funktion wurde bereits aufgerufen. / The Open was called already.';

    IPS7_PC_E_S7_DATATYPE_BAD_REL:
      m_strStatus := 'Multi-Access : PC und S7-Datentyp stehen int falscher Relation / PC and S7 -datatype beeing in bad relations';

    IPS7_E_BADDATACOUNT:
      m_strStatus := 'Multi-Access : SPS liefert falsche Anzahl an Daten / PLC sends bad count of data';

    IPS7_E_DEMOEND:
      m_strStatus := 'Demozeit ist abgelaufen. Programm bitte erneut starten! / Demo time is over. Please restart application!';

    else
      m_strStatus := 'Unbekannter Fehler aufgetreten. / Unknown error occured! "' + IntToStr (lErr) + '"';
    end;
    Result := m_strStatus;
end;

procedure TFormIPS7Demo.ShowStatus;
begin
  EdStatus.Text := GetStatusText (m_lErr);
end;

procedure TFormIPS7Demo.ShowErr;
begin
  if (m_lErr <> 0) then
   Application.MessageBox (PChar (m_strStatus), 'Fehler / Error', MB_OK);
end;

procedure TFormIPS7Demo.BtnOpenClick(Sender: TObject);
begin
  if ((m_lRef < 0) and GetFormData) then
  begin
    if m_lPLCType = 1 then // S7 200
      m_lRef := IPS7OpenS7200 (PAnsiChar (m_strIPAddr), m_lRackNr, m_lSlotNr, 5000, 5000, 5000)
    else
    begin
       if m_bUseOP = True then
        m_lRef := IPS7Open (PAnsiChar (m_strIPAddr), m_lRackNr, m_lSlotNr, 5000, 5000, 5000)
      else
        m_lRef := IPS7OpenPG (PAnsiChar (m_strIPAddr), m_lRackNr, m_lSlotNr, 5000, 5000, 5000);
    end;


    if m_lRef >= 0 then
    begin
      IPS7SetKeepAlive (m_lRef, 500, 1000);
      m_lErr := IPS7_E_NOERR;
      m_bOpen := True;
      SetBtnState;
    end
    else
    begin
      m_lErr := m_lRef;
    end;
    ShowStatus;
  end;
end;

procedure TFormIPS7Demo.SetBtnState;
begin
  BtnOpen.Enabled := Not m_bOpen;
  BtnClose.Enabled := m_bOpen;
  BtnRdDB.Enabled := m_bOpen;
  BtnRdPlcW.Enabled := m_bOpen;
  BtnRdDW.Enabled := m_bOpen;
  BtnRdReal.Enabled := m_bOpen;
  BtnRdMulti.Enabled := m_bOpen;
  EdIPAddr.Enabled := Not m_bOpen;
  EdRack.Enabled := Not m_bOpen;
  EdSlot.Enabled := Not m_bOpen;
  CbPLCType.Enabled := Not m_bOpen;
  RdOP.Enabled := Not m_bOpen;
  RdPG.Enabled := Not m_bOpen;
  CbDataArea.Enabled := m_bOpen;
  EdDBNr.Enabled := m_bOpen;
  EdStart.Enabled := m_bOpen;
  EdCount.Enabled := m_bOpen;
  BtnConnect.Enabled := m_bOpen;
end;

procedure TFormIPS7Demo.BtnCloseClick(Sender: TObject);
begin
 if m_lRef >= 0 then
 begin
   m_lErr := IPS7Close (m_lRef);
   ShowStatus;
   m_lRef := -1;
   m_bOpen := False;
   SetBtnState;
 end;
end;

function TFormIPS7Demo.MakeAdrName (DataArea : LongInt; DBNr:LongInt; PLCDataType : LongInt) : String;
var TypeChar : String;
begin
  TypeChar := '';
  case (PLCDataType) of
    IPS7_BIT:
      if (DataArea = LongInt ('D')) then
        TypeChar := 'X';

    IPS7_BYTE:
      TypeChar := 'B';

    IPS7_WORD, IPS7_INT:
      TypeChar := 'W';

    IPS7_DWORD, IPS7_DINT, IPS7_REAL:
      TypeChar := 'D';
  end;

  if (DataArea = LongInt ('D')) then
  begin
    m_strAdrName := 'DB'+IntToStr(DBNr) + '.DB' + TypeChar;
  end
  else if (DataArea = LongInt('T')) then
    m_strAdrName := 'T '
  else if (DataArea = LongInt ('Z')) then
    m_strAdrName := 'Z '
  else
  begin
    m_strAdrName := Char(DataArea) + TypeChar;
  end;
  Result := m_strAdrName;
end;

function TFormIPS7Demo.GetPCUnitSize (PCDataType:LongInt) : integer;
var UnitSize : integer;
begin
  UnitSize := 1;
  case (PCDataType) of
    PC_BYTE:
      UnitSize := sizeof (Byte);

    PC_WORD16, PC_INT16:
      UnitSize := sizeof (Word);

    PC_WORD32, PC_INT32:
      UnitSize := sizeof (LongInt);

    PC_FLOAT:
      UnitSize := sizeof (Single);

    PC_DOUBLE:
      UnitSize := sizeof (double);
  end;
  Result:=UnitSize;
end;


procedure TFormIPS7Demo.ShowErrInList (Line : LongInt; lErr : LongInt);
begin
  List.Cells[1,Line] := GetStatusText (lErr);
end;


procedure TFormIPS7Demo.SetListItemData (Line : LongInt; Item: LongInt; PCDataType:LongInt; PLCDataType:LongInt;
                                         pData : Pointer; bShowHex : Boolean; Result:Integer);
var Str : String;
    i : Integer;
    StrAscii : String;
    ptrByte   : ^BYTE;
    ptrDouble  : ^double;
    ptrFloat   : ^Single;
    ptrInt16   : ^Smallint;
    ptrUInt16  : ^WORD;
    ptrInt32   : ^LongInt;
    ptrUInt32  : ^LongWord;

    HexData  : Array[0..3] of BYTE ;
    UnitSize : Integer;
    PCUnitSize : integer;
    pBuf : Pointer;

begin
  PCUnitSize := GetPCUnitSize (PCDataType);

  pBuf := Ptr (LongInt(pData) + Item * PCUnitSize);

  ptrByte     := pBuf;
  ptrInt16    := pBuf;
  ptrUInt16   := pBuf;
  ptrInt32    := pBuf;
  ptrUInt32   := pBuf;
  ptrDouble := pBuf;
  ptrFloat    := pBuf;

  if (Result <> 0) then
  begin
    ShowErrInList (Line, Result);
    Exit;
  end;
  case (PCDataType) of
    PC_BYTE:
    begin
      Str := IntToStr (WORD (ptrByte^));
    end;

    PC_WORD16:
    begin
      Str := IntToStr (ptrUInt16^);
    end;

    PC_INT16:
    begin
      Str := IntToStr (ptrInt16^);
    end;

    PC_WORD32:
    begin
      Str := IntToStr (ptrUInt32^);
    end;

    PC_INT32:
    begin
      Str := IntToStr (ptrInt32^);
    end;

    PC_FLOAT:
    begin
     Str := FloatToStrF(ptrFloat^,ffFixed,7,2);
    end;

    PC_DOUBLE:
    begin
      Str := FloatToStrF(ptrDouble^,ffFixed,7,2);
      bShowHex := false;
    end;
  end;
  if (PLCDataType = IPS7_TIMER) then
    Str := Str + ' ms';
  List.Cells[1,Line] := Str;

  if (bShowHex = True) then
  begin
    UnitSize := 1;
      case (PLCDataType) of
      IPS7_BIT, IPS7_BYTE:
      begin
        UnitSize := 1;
        HexData[0] := ptrByte^;
      end;

      IPS7_TIMER, IPS7_COUNTER:
      begin
        bShowHex := false;
        UnitSize := 2;
        HexData[1] := ptrByte^;
        ptrByte := Ptr (LongInt(ptrByte) + 1);
        HexData[0] := ptrByte^;
      end;

      IPS7_WORD,IPS7_INT:
      begin
        UnitSize := 2;
        HexData[1] := ptrByte^;
        ptrByte := Ptr (LongInt(ptrByte) + 1);
        HexData[0] := ptrByte^;
      end;

      IPS7_DWORD, IPS7_DINT, IPS7_REAL:
      begin
        UnitSize := 4;
        HexData[3] := ptrByte^;
        ptrByte := Ptr (LongInt(ptrByte) + 1);
        HexData[2] := ptrByte^;
        ptrByte := Ptr (LongInt(ptrByte) + 1);
        HexData[1] := ptrByte^;
        ptrByte := Ptr (LongInt(ptrByte) + 1);
        HexData[0] := ptrByte^;
      end;
    end;

    if bShowHex = True Then
    begin
      Str := '';
      StrAscii := '';
      for i := 0  to  UnitSize  - 1 do
      begin
        Str  := Str + IntToHex(HexData[i], 2);
        if (HexData[i] >= BYTE (#32)) and (HexData[i] <= BYTE (#126)) then
          StrAscii := StrAscii + char (HexData[i])
        else
          StrAscii := StrAScii + '.';
      end;

      List.Cells[2,Line] := Str; // Hex
      List.Cells[3,Line] := StrAscii; // Text
    end

  end
  else
  begin
    List.Cells[2,Line] := ''; // Hex
    List.Cells[3,Line] := ''; // Text
  end;
end;


procedure TFormIPS7Demo.AddItemsToList (DataArea : LongInt; DBNr : LongInt; Line : LongInt;
                                        StartAt : LongInt; StartBit : LongInt; Cnt : LongInt; PCDataType: LongInt;
                                        PLCDataType : LongInt; pD : Pointer;  bShowHex: Boolean; Res : LongInt);
var i, Step, BitNr, S7ItemNr : LongInt;
var S : String;
var bBit : Boolean;
begin
  bBit:= false;
  BitNr := StartBit;
  Step := 1;

  case (PLCDataType) of
    IPS7_BIT:
    begin
      bBit := true;
      Step := 1;
      bShowHex := false;
    end;
    IPS7_TIMER,IPS7_COUNTER:
      bShowHex := false;

    IPS7_BYTE:
    begin
      Step := 1;
    end;

    IPS7_WORD,IPS7_INT:
      Step := 2;

    IPS7_DWORD,IPS7_DINT,IPS7_REAL:
      Step := 4;
  end;
  if (DataArea = LongInt ('Z')) or (DataArea = LongInt ('T')) then
  begin
    Step := 1;
    bShowHex := false;
  end;

  MakeAdrName (DataArea, DBNr, PLCDataType);

  S7ItemNr := StartAt;

  for i := 0  to Cnt - 1 do
  begin
    if bBit then
    begin
      S := m_strAdrName + IntToStr(S7ItemNr)+ '.' + IntToStr (BitNr);
      BitNr := BitNr + 1;
      if (BitNr > 7) then
      begin
        BitNr := 0;
        S7ItemNr := S7ItemNr + 1;
      end;
    end
    else
    begin
      S := m_strAdrName + IntToStr (S7ItemNr);
      S7ItemNr := S7ItemNr + Step;
    end;
    List.RowCount := List.RowCount + 1;
    List.Cells[0,Line] := S; // Address
    SetListItemData (Line, i, PCDataType, PLCDataType, pD, bShowHex, Res);
    Line := Line + 1;
  end;
end;

procedure TFormIPS7Demo.BtnRdPlcWClick(Sender: TObject);
begin
  if ((m_lRef >= 0) and GetFormData) then
  begin
    SetWaitCursor;
    m_lErr := IPS7RdPlcW (m_lRef, m_lDataArea, m_lDBNr, m_lStart, m_lCount, @m_WordBuf);
    if (m_lErr = 0) then
    begin
      DelList;
      AddItemsToList (m_lDataArea, m_lDBNr, 1, m_lStart, 0, m_lCount, PC_WORD16, IPS7_WORD, @m_WordBuf, True, 0);
    end;
    SetNormalCursor;
    ShowStatus;
    ShowErr;
  end;
end;


procedure TFormIPS7Demo.BtnEndClick(Sender: TObject);
begin
  if (m_lRef >= 0) then
    IPS7Close (m_lRef);
  Close;
end;

procedure TFormIPS7Demo.DelList;
begin
  List.RowCount := 2;
  List.Cells[0,2] := '';
  List.Cells[1,2] := '';
  List.Cells[2,2] := '';
  List.Cells[3,2] := '';
end;


procedure TFormIPS7Demo.SetWaitCursor;
begin
  Screen.Cursor := crHourglass;
end;

procedure TFormIPS7Demo.SetNormalCursor;
begin
  Screen.Cursor := crDefault;
end;

procedure TFormIPS7Demo.BtnRdRealClick(Sender: TObject);
begin
  if ((m_lRef >= 0) and GetFormData) then
  begin
    SetWaitCursor;
    m_lErr := IPS7RdReal (m_lRef, m_lDataArea, m_lDBNr, m_lStart, m_lCount, @m_doubleBuf);
    if (m_lErr = 0) then
    begin
      DelList;
      AddItemsToList (m_lDataArea, m_lDBNr, 1, m_lStart, 0, m_lCount, PC_DOUBLE, IPS7_REAL, @m_doubleBuf, True, 0);
    end;
    SetNormalCursor;
    ShowStatus;
    ShowErr;
  end;
end;

procedure TFormIPS7Demo.BtnRdDBClick(Sender: TObject);
begin
  if ((m_lRef >= 0) and GetFormData) then
  begin
    SetWaitCursor;
    m_lErr := IPS7RdB (m_lRef, m_lDataArea, m_lDBNr, m_lStart, m_lCount, @m_byteBuf);
    if (m_lErr = 0) then
    begin
      DelList;
      AddItemsToList (m_lDataArea, m_lDBNr, 1, m_lStart, 0, m_lCount, PC_BYTE, IPS7_BYTE, @m_byteBuf, True, 0);
    end;
    SetNormalCursor;
    ShowStatus;
    ShowErr;
  end;
end;

procedure TFormIPS7Demo.BtnRdDWClick(Sender: TObject);
begin
  if ((m_lRef >= 0) and GetFormData) then
  begin
    SetWaitCursor;
    m_lErr := IPS7RdDW (m_lRef, m_lDataArea, m_lDBNr, m_lStart, m_lCount, @m_dintBuf);
    if (m_lErr = 0) then
    begin
      DelList;
      AddItemsToList (m_lDataArea, m_lDBNr, 1, m_lStart, 0, m_lCount, PC_INT32, IPS7_DINT, @m_dintBuf[0], True, 0);
    end;
    SetNormalCursor;
    ShowStatus;
    ShowErr;
  end;
end;

procedure TFormIPS7Demo.Timer1Timer(Sender: TObject);
var bConnected : boolean;
begin
  bConnected := False;
  if (m_lRef >= 0) then
  begin
    if (IPS7GetConnectStatus (m_lRef)) = 1 then
      bConnected := True;
  end;
  if (bConnected) then
    EdIPStatus.Text := 'verbunden / connected'
  else
    EdIPStatus.Text := 'nicht verbunden / not connected';

end;

procedure TFormIPS7Demo.BtnConnectClick(Sender: TObject);
begin
  if (m_lRef >= 0) then
  begin
    m_lErr := IPS7Connect (m_lRef);
    if (m_lErr = 1) then
      m_lErr := 0;

    ShowStatus ();
   end;

end;

procedure TFormIPS7Demo.InitRq (pRq : PIPS7_RQ_MULTI; DataArea : Char; DataType:LongInt; PcDataArea:LongInt;
                                DBNr : LongInt; Start:LongInt; StartBit: LongInt; Cnt: LongInt; pData :Pointer);
begin
  pRq.DataArea := LongInt (DataArea);
  pRq.DataType := DataType;
  pRq.DBNr := DBNr;
  pRq.Cnt := Cnt;
  pRq.Start := Start;
  pRq.StartBit := StartBit;
  pRq.PcDataType := PcDataArea;
  pRq.Data := pData;
end;

procedure TFormIPS7Demo.BtnRdMultiClick(Sender: TObject);
var
  EBits : array [0..64] of Byte;
  EBytes : array [0..64] of Byte;
  MWords : array [0..32] of Word;
  DB10Words : array [0..150] of Word;
  DB10WordsAsDouble : array [0..150] of double;
  DB20RealAsFloat : array [0..60] of single;
  TimerAsInt : array [0..10] of LongInt;
  DB10Bits : array [0..65] of Byte;
  Cnt : integer;
  Line : integer;
  i : integer;
  Rq : array [0..10] of IPS7_RQ_MULTI; // Max. 10 Aufträge;

begin
  FillChar (Rq, sizeof (Rq), 0);
  Cnt := 0;
  Line := 1;
  // lese ab E 4.0 32 Bit
  InitRq (@Rq[Cnt], 'E', IPS7_BIT, PC_BYTE, 0, 4, 0, 32, @EBits);
  Cnt := Cnt + 1;


  // lese ab DB10.DBX1.1  32 Bit
  InitRq (@Rq[Cnt], 'D', IPS7_BIT, PC_BYTE, 100, 1, 1, 32, @DB10Bits);
  Cnt := Cnt + 1;

  // lese ab EB0 20 Byte und lege diese ab [20] ab
  InitRq (@Rq[Cnt], 'E', IPS7_BYTE, PC_BYTE, 0, 0, 0, 20, @EBytes[20]);
  Cnt := Cnt + 1;

  //lese ab MB 20 10 Worte
  InitRq (@Rq[Cnt], 'M', IPS7_WORD, PC_WORD16, 0, 20, 0, 1, @MWords);
  Cnt := Cnt + 1;

  //lese  DB10 ab Datenbyte 0 150 Worte
  InitRq (@Rq[Cnt], 'D', IPS7_WORD, PC_WORD16, 10, 0, 0, 150, @DB10Words);
  Cnt := Cnt + 1;

  //lese DB20 ab Datenbyte 0 150 Worte lege diese aber als double im PC ab
  InitRq (@Rq[Cnt], 'D', IPS7_WORD, PC_DOUBLE, 10, 0, 0, 150, @DB10WordsAsDouble);
  Cnt := Cnt + 1;

  //lese  DB20 ab Datenbyte 6 60 Realwerte und lege diese als Floatwerte im PC ab
  InitRq (@Rq[Cnt], 'D', IPS7_REAL, PC_FLOAT, 100, 6, 0, 60, @DB20RealAsFloat);
  Cnt := Cnt + 1;

  //lese ab Timer 5 10 Timer und lege diese als int ab
  InitRq (@Rq[Cnt], 'T', IPS7_TIMER, PC_WORD32, 0, 0, 0, 5, @TimerAsInt); // T5 10 Timer
  Cnt := Cnt + 1;

  if (m_lRef >= 0) then
  begin
    SetWaitCursor ();

    m_lErr := IPS7RdMulti(m_lRef, @Rq, Cnt);
    DelList;
    for i := 0 to Cnt do
    begin
      AddItemsToList (Rq[i].DataArea, Rq[i].DBNr, Line, Rq[i].Start, Rq[i].StartBit, Rq[i].Cnt,  Rq[i].PcDataType,  Rq[i].DataType, Rq[i].Data,  true, Rq[i].Result);
      Line := Line + Rq[i].Cnt;
    end;
    SetNormalCursor;
    ShowStatus;
    ShowErr;
  end;
end;

end.
