Wiesemann & Theis GmbH

Tecnologia di rete, dei sensori e delle interfacce per industria, ufficio e informatizzazione

Tutorial al Web-IO digitale:

Attivare Web-IO digitale con Delphi mediante
socket binari


Come linguaggio di alto livello di facile apprendimento, Delphi offre tutto ciò che è necessario per la programmazione di applicazioni TCP/IP. Pertanto Delphi è un apprezzato ausilio per realizzare applicazioni che comunicano con il Web-IO digitale attraverso socket binari. Ulteriori driver o DLL non saranno necessari.

Controllo di Web-IO con C Sharp

Con il seguente esempio di programma Delphi, l’utente può attivare il Web-IO digitale con i suoi input e output in un’applicazione Windows attraverso la modalità socket binario.


Preparativi


Elementi di comando Delphi

Nella denominazione dei singoli oggetti è utile utilizzare nomi che ne riprendono il significato. In questo esempio la prima parte del nome descrive il tipo dell’oggetto e la seconda parte la funzione.

Per l’attuazione della comunicazione TCP viene usata la componente TIdTCPClient di Indy che appartiene ai componenti Delphi.

Le strutture binarie

Per l’accesso binario è necessario definire le necessarie strutture binarie, con cui si deve comunicare con il Web-IO. Una descrizione dettagliata di queste strutture è disponibile nella breve panoramica binary o nel manuale di programmazione sul Web-IO.

La struttura EADriver

Con le sue quattro variabili a 16 bit è EADriver la struttura di base che è anche un elemento di tutte le altre strutture binarie.

							
Type
  READriver=packed record
    Start_1:word;
    Start_2:word;
    StructType:word;
    StructLength:word;
  end;

  RWriteRegister=packed record
    EADriver : READriver;
    Amount:word;
    Value:word;
  end;

  RSetBits=packed record
    EADriver : READriver;
    Mask:word;
    Value:word;
  end ;

  RRegisterState=packed record
    EADriver : READriver;
    DriverID : word;
    InputValue : word;
    OutputValue : word;
  end;

  RReadCounter=packed record
    EADriver : READriver;
    CounterIndex : word;
  end;

  RCounter=packed record
    EADriver : READriver;
    CounterIndex: word;
    CounterValue: longword;
  end;

  RAllCounter=packed record
    EADriver : READriver;
    CounterNoOf: word;
    CounterValue: array [0..11]of longword;
  end;

  ROptions=packed record
    EADriver : READriver;
    Version : longword;
    Options : longword;
  end;
							
						

Nelle strutture è importante che le singole variabili vengano archiviate ininterrotte nella memoria. Delphi non lo realizza automaticamente, in particolare se in una struttura vengono riunite variabili di dimensioni diverse. Per garantire tuttavia un’occupazione ininterrotta della memoria, si =packed record definisce che tra le singole variabili non ci sono punti di memoria inutilizzati.

Avvio del programma

Inizializzazione degli elementi di comando

Per trattare eventi che si verificano in modo asincrono come la ricezione dati, viene definito in preparazione un rispettivo thread, creato e lanciato all’avvio del programma.

Il gruppo con gli elementi di comando per il Web-IO viene innanzitutto bloccato per l’uso. Non appena viene realizzato un collegamento, vengono abilitati tutti gli elementi per i quali ha senso l’abilitazione.

							

  .....
  .....
  private
    { Private-Deklarationen }
  public
    procedure ClientSocketThreadRun(Sender: TIdThreadComponent);
    { Public-Deklarationen }
  end;
var
  webio_binary_client: Twebio_binary_client;
  ClientSocketThread : TIdThreadComponent;

implementation

{$R *.DFM}

procedure Twebio_binary_client.FormCreate(Sender: TObject);
begin
  ClientSocketThread := TIdThreadComponent.Create();
  ClientSocketThread.onRun := ClientSocketThreadRun;
  StatusBar1.SimpleText := ’No Connection’;
  bt_disconnect.Enabled := False;
  gb_io.Enabled := False;
end;
							
						

Controllo del collegamento

Inizializzazione del collegamento

Immettendo l’indirizzo IP del Web-IO nel campo di testo ed_ip e facendo clic sul pulsante bt_connect viene avviata la creazione del collegamento

							
procedure Twebio_binary_client.bt_connectClick(Sender: TObject);
begin
  if ed_ip.Text <> ’’ then
  begin
    ClientSocket.Host := ed_ip.Text;
    ClientSocket.Port := strtoint(ed_port.Text);
    ClientSocket.Connect;
  end;
end;
							
						

Collegamento realizzato

Non appena il Web-IO accetta il collegamento, l’elemento di controllo ClientSocket esegue la corrispondente procedura. Nella riga di stato viene visualizzata la realizzazione del collegamento, gli elementi di comando vengono abilitati per l’utilizzo e il pulsante Disconnect risulta utilizzabile.

Inviando la struttura Options Al Web-IO questo viene istruito, fissando un output a trasmettere lo stato di attivazione modificato attraverso la struttura RegisterState.

							
procedure Twebio_binary_client.bt_disconnectClick(Sender: TObject);
begin
  ClientSocket.Disconnect;
end;

procedure Twebio_binary_client.ClientSocketConnected(Sender: TObject);
var
  Options : structOptions;
  SendBuffer : TIdBytes;
begin
  ClientSocketThread.Active := true;
  StatusBar1.SimpleText := ’Connected to ’ + ed_ip.Text;
  bt_connect.Enabled := False;
  bt_disconnect.Enabled := True;
  gb_io.Enabled := True;
  Options.EADriver.Start_1 := 0;
  Options.EADriver.Start_2 := 0;
  Options.EADriver.StructType := $1F0;
  Options.EADriver.StructLength := $10;
  Options.Version := 1;
  Options.Options := 1;
  SendBuffer := RawToBytes(Options, Options.EADriver.StructLength);
  ClientSocket.IOHandler.Write(SendBuffer);
end;
							
						

Trasmettitore delle strutture binarie

L’elemento di controllo TIdTCPClient Indy non può inviare direttamente strutture. Per questo ogni struttura deve essere convertita prima dell’invio innanzitutto mediante RawToBytes Un byte array.

Disinserzione del collegamento

Il collegamento rimane fino a quando non viene terminato dall’utente facendo clic sul pulsante Disconnect oppure il Web-IO termina il collegamento.

							
procedure Twebio_ascii_client.bt_disconnectClick(Sender: TObject);
begin
  ClientSocket.Disconnect;
end;
              
						

Anche in questo caso l’elemento di controllo ClientSocket richiama la corrispondente procedura.

							
procedure Twebio_ascii_client.ClientSocketDisconnected(Sender: TObject);
begin
  ClientSocketThread.Active := false;
  ClientSocket.Disconnect;
  StatusBar1.SimpleText := ’No Connection’;
  bt_connect.Enabled := True;
  bt_disconnect.Enabled := False;
  gb_io.Enabled := False;
end;
              
						

Utilizzo e comunicazione della parte client

Non appena si è stabilita una connessione con il Web-IO, l’utente può inviare strutture binarie al Web-IO utilizzando i rispettivi elementi del programma.

Impostazione degli output

L’impostazione degli output è resa possibile all’utente da due caselle di spunta cb_outputx. Il programma utilizza a tale scopo l’evento MouseUP di questo oggetto. Se viene registrato un MouseUp, ossia un rilascio della casella di spunta output, il programma esegue la corrispondente procedura e inoltra al Web-IO, in base all’eventuale presenza o meno del segno di spunta, la struttura SetBit compilata con i valori adatti.

							
procedure Twebio_binary_client.cb_outputMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  SetBits : structSetBits;
  SendBuffer : TIdBytes;
begin
  SetBits.EADriver.Start_1 := 0;
  SetBits.EADriver.Start_2 := 0;
  SetBits.EADriver.StructType := $09;
  SetBits.EADriver.StructLength := $0C;
  if sender = cb_output0 then
  begin
    SetBits.Mask := 1;
    if cb_output0.Checked then
      SetBits.Value := 1
    else
      SetBits.Value := 0;
  end;
  if sender = cb_output1 then
  begin
    SetBits.Mask := 2;
    if cb_output1.Checked then
      SetBits.Value := 2
    else
      SetBits.Value := 0;
  end;
  SendBuffer := RawToBytes(SetBits, SetBits.EADriver.StructLength);
  ClientSocket.IOHandler.Write(SendBuffer);
end;
							
						

Interrogazione dello stato degli output/input

L’utente può richiedere lo stato degli output e degli input facendo clic sul relativo pulsante.

							
procedure Twebio_binary_client.bt_outputs_readClick(Sender: TObject);
var
  EADriver : structEADriver;
  SendBuffer : TIdBytes;
begin
  EADriver.Start_1 := 0;
  EADriver.Start_2 := 0;
  EADriver.StructType := $21;
  EADriver.StructLength := $08;
  SendBuffer := RawToBytes(EADriver, EADriver.StructLength);
  ClientSocket.IOHandler.Write(SendBuffer);
end;
							
						

Inviando la struttura RegisterRequest Vengono richiesti gli stati di attivazione di input e output. Il Web-IO risponde a questa richiesta con la struttura RegisterState.

Se fossero interrogati solo gli input, ciò viene avviao attraverso clic sul tasto bt_inputs. A tal scopo viene inviata la struttura ReadRegister a cui il Web-IO risponde con la struttura WriteRegister.

							
procedure Twebio_binary_client.bt_inputs_readClick(Sender: TObject);
var
  EADriver : structEADriver;
  SendBuffer : TIdBytes;
begin
  EADriver.Start_1 := 0;
  EADriver.Start_2 := 0;
  EADriver.StructType := $01;
  EADriver.StructLength := $08;
  SendBuffer := RawToBytes(EADriver, EADriver.StructLength);
  ClientSocket.IOHandler.Write(SendBuffer);
end;
							
						

Interrogazione/cancellazione dei counter

È possibile interrogare o cancellare anche gli stati dei counter degli input. A tal scopo viene inviata la struttura ReadCounter o ReadClearCounter, laddove con CounterIndex viene trasmesso il numero del counter. Il Web-IO risponde con la struttura Counter.

							
procedure Twebio_binary_client.bt_counter_readClick(Sender: TObject);
var
  ReadCounter : structReadCounter;
  SendBuffer : TIdBytes;
begin
  ReadCounter.EADriver.Start_1 := 0;
  ReadCounter.EADriver.Start_2 := 0;
  ReadCounter.EADriver.StructType := $B0;
  ReadCounter.EADriver.StructLength := $0A;
  if sender = bt_counter_read0 then ReadCounter.CounterIndex := 0;
  if sender = bt_counter_read1 then ReadCounter.CounterIndex := 1;
  SendBuffer := RawToBytes(ReadCounter, ReadCounter.EADriver.StructLength);
  ClientSocket.IOHandler.Write(SendBuffer);
end;

procedure Twebio_binary_client.bt_counter_clearClick(Sender: TObject);
var
  ReadCounter : structReadCounter;
  SendBuffer : TIdBytes;
begin
  ReadCounter.EADriver.Start_1 := 0;
  ReadCounter.EADriver.Start_2 := 0;
  ReadCounter.EADriver.StructType := $C0;
  ReadCounter.EADriver.StructLength := $0A;
  if sender = bt_counter_clear0 then ReadCounter.CounterIndex := 0;
  if sender = bt_counter_clear1 then ReadCounter.CounterIndex := 1;
  SendBuffer := RawToBytes(ReadCounter, ReadCounter.EADriver.StructLength);
  ClientSocket.IOHandler.Write(SendBuffer);
end;
							
						

Sulla struttura ReadAllCounter o ReadClearAllCounter è possibile leggere o cancellare contemporaneamente anche tutti i counter. Il Web-IO risponde con la struttura AllCounter.

							
procedure Twebio_binary_client.bt_counter_readallClick(Sender: TObject);
var
  EADriver : structEADriver;
  SendBuffer : TIdBytes;
begin
  EADriver.Start_1 := 0;
  EADriver.Start_2 := 0;
  EADriver.StructType := $B1;
  EADriver.StructLength := $08;
  SendBuffer := RawToBytes(EADriver, EADriver.StructLength);
  ClientSocket.IOHandler.Write(SendBuffer);
end;

procedure Twebio_binary_client.bt_counter_clearallClick(Sender: TObject);
var
  EADriver : structEADriver;
  SendBuffer : TIdBytes;
begin
  EADriver.Start_1 := 0;
  EADriver.Start_2 := 0;
  EADriver.StructType := $C1;
  EADriver.StructLength := $08;
  SendBuffer := RawToBytes(EADriver, EADriver.StructLength);
  ClientSocket.IOHandler.Write(SendBuffer);
end;
							
						

Ricezione dei dati dal Web-IO

Analisi e visualizzazione dei dati ricevuti

Il Web-IO invia a seconda della richiesta o dell’evento da scatenare la struttura giusta. Alla ricezione dei dati viene aperta la corrispondente procedura di callback. Per la valutazione riempiono i primi 8 byte del byte-array ricevuto attraverso BytesToRaw Innanzitutto una struttura EADriver. L’applicazione riconosce di che tipo di struttura si tratta attraverso la variabile EADriver.StructType.

  • EADriver.StructType = 8
    Struttura WriteRegister per lo stato degli input

  • EADriver.StructType = 31 (hex.)
    Struttura RegisterState per lo stato degli input e output

  • EADriver.StructType = B4 (hex.)
    Struttura Counter per il valore di singoli counter

  • EADriver.StructType = B5 (hex.)
    Struttura AllCounter per il valore di tutti i counter

Per la valutazione riempie la byte array ricevuta attraverso BytesToRaw la struttura adatta.

I valori così trasmessi vengono poi valutati e visualizzati. Per gli input e output viene trasmesso attraverso WriteRegister.Value, RegisterStae.InputValue e RegisterStae.outputValue lo schema di bit di tutti gli input e output.

							
procedure Twebio_binary_client.ClientSocketThreadRun(Sender: TIdThreadComponent);
var
  ReceiveBuffer : TIdBytes;
  EADriver : structEADriver;
  WriteRegister : structWriteRegister;
  RegisterState : structRegisterState;
  Counter : structCounter;
  AllCounter : structAllCounter;
begin
  while not ClientSocket.IOHandler.InputBufferIsEmpty do
  begin
    SetLength(ReceiveBuffer, length(ReceiveBuffer)+1);
    ReceiveBuffer[length(ReceiveBuffer)-1] := ClientSocket.IOHandler.ReadByte;
  end;
  if length(ReceiveBuffer) > 7 then
    BytesToRaw(ReceiveBuffer, EADriver, 8);
    case EADriver.StructType of

    $08 : begin
            if length(ReceiveBuffer) >= EADriver.StructLength then
            begin
              BytesToRaw(ReceiveBuffer, WriteRegister, EADriver.StructLength);
              if WriteRegister.Value and 1 = 1 then
                cb_input0.Checked := True
              else
                cb_input0.Checked := False;
              if WriteRegister.Value and 2 = 2 then
                cb_input1.Checked := True
              else
                cb_input1.Checked := False;
            end;
          end;
    $31 : begin
            if length(ReceiveBuffer) >= EADriver.StructLength then
            begin
              BytesToRaw(ReceiveBuffer, RegisterState, EADriver.StructLength);
              if RegisterState.InputValue and 1 = 1 then
                cb_input0.Checked := True
              else
                cb_input0.Checked := False;
              if RegisterState.InputValue and 2 = 2 then
                cb_input1.Checked := True
              else
                cb_input1.Checked := False;
              if RegisterState.OutputValue and 1 = 1 then
                cb_output0.Checked := True
              else
                cb_output0.Checked := False;
              if RegisterState.OutputValue and 2 = 2 then
                cb_output1.Checked := True
              else
                cb_output1.Checked := False;
            end;
          end;
    $B4 : begin
            if length(ReceiveBuffer) >= EADriver.StructLength then
            begin
              BytesToRaw(ReceiveBuffer, Counter, EADriver.StructLength);
              if Counter.CounterIndex = 0 then
                ed_counter0.Text := IntToStr(Counter.CounterValue);
              if Counter.CounterIndex = 1 then
                ed_counter1.Text := IntToStr(Counter.CounterValue);
            end;
          end;
    $B5 : begin
            if length(ReceiveBuffer) >= EADriver.StructLength then
            begin
              BytesToRaw(ReceiveBuffer, AllCounter, EADriver.StructLength);
              ed_counter0.Text := IntToStr(AllCounter.CounterValue[0]);
              ed_counter1.Text := IntToStr(AllCounter.CounterValue[1]);
            end;
          end;
    end;
end;
							
						

Polling

Interrogazione ciclica di determinati valori

Per permettere anche un aggiornamento automatico della visualizzazione, viene utilizzato un timer.

In base alle caselle di spunta per il polling degli output, degli input e dei counter le corrispondenti informazioni vengono interrogate dal Web-IO nell’intervallo impostato.

							
procedure Twebio_binary_client.timer_pollingTimer(Sender: TObject);
begin
  if ClientSocket.Connected and cb_output_polling.Checked then
    bt_outputs_readClick(self);
  if ClientSocket.Connected and cb_input_polling.Checked then
    bt_inputs_readClick(self);
  if ClientSocket.Connected and cb_counter_polling.Checked then
    bt_counter_readallClick(self);
end;
							
						

L’intervallo desiderato può essere immesso nel corrispondente campo di testo. In caso di una modifica l’intervallo del timer viene adattato automaticamente.

							
procedure Twebio_binary_client.ed_intervalChange(Sender: TObject);
begin
  timer_polling.Interval := strtoint(ed_interval.Text);
end;
							
						

Il programma esempio supporta tutte le comuni funzioni del Web-IO nella modalità socket binario ottimizzata per il Web-IO 2x input digitale, 2x output digitale. Per gli altri modelli di Web-IO devono eventualmente essere eseguiti adattamenti al programma. Una descrizione dettagliata delle strutture binarie è disponibile nella breve panoramica binary o nel manuale di programmazione sul Web-IO.

Download esempio di programma


Prodotti



^