Applicazione relativa al Web-IO digitale:
Web-IO digitali controllo e monitoraggio con Lazarus/Free Pascal
Lazarus è un ambiente di sviluppo open source che emula Delphi e che utilizza Free Pascal. L’aspetto interessante di Lazarus è che questo ambiente di sviluppo è disponibile per Windows, Linux e alcuni sistemi MAC e può essere utilizzato attraverso vari progetti. All’indirizzo https://www.lazarus.freepascal.org/ Lazarus può essere scaricato gratuitamente.
Come linguaggio di alto livello di facile apprendimento Lazarus offre tutto ciò che è necessario per la programmazione di applicazioni Web-IO®. Per lo svolgimento della comunicazione TCP/IP deve tuttavia essere installato l’ elemento di controllo LNET supplementare come pacchetto di componenti.
Con il seguente esempio di programma potete riprodurre il vostro Web-IO digitale con i suoi input e output in un’applicazione Windows. Inoltre potete collegare gli output del Web-IO.
Preparativi
Avete già alimentato con corrente- il vostro Web-IO digitale,
- collegato gli ingressi e le uscite,
- effettuato il collegamento alla vostra rete
- e assegnato un indirizzo IP: con WuTility è facile!
1. Collocazione dei diversi elementi di comando e oggetti di visualizzazione nel modulo Lazarus
Nella denominazione dei singoli oggetti è utile utilizzare nomi che ne riprendono il significato. In questo esempio la prima parte del nome descrive il tipo di oggetto e la seconda parte la funzione.
2. Controllo del collegamento
Inizializzazione del collegamentoImmettendo 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 TForm1.bt_connectClick(Sender: TObject);
begin
if ed_ip.Text <> ’’ then
begin
bt_connect.Enabled := false;
LTCPComponent1.Connect(ed_ip.Text, strtoint(ed_port.Text));
end;
end;
Collegamento realizzato Non appena il Web-IO accetta il collegamento, l’elemento di controllo ClintSocket 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.
procedure TForm1.LTCPComponent1Connect(aSocket:TLSocket);
begin
StatusBar1.SimpleText :=’Connected to ’ + ed_ip.Text;
bt_connect.Enabled := False;
bt_disconnect.Enabled := True;
gb_io.Enabled := True;
end;
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 TForm1.bt_disconnectClick(Sender:TObject);
begin
StatusBar1.SimpleText :=’No Connection’;
bt_connect.Enabled := True;
bt_disconnect.Enabled := False;
gb_io.Enabled := False;
LTCPComponent1.Disconnect;
end;
Anche in questo caso l’elemento di controllo ClientSocket richiama la corrispondente procedura
procedure TForm1.LTCPComponent1Disconnect(aSocket:TLSocket);
begin
StatusBar1.SimpleText :=’No Connection’;
bt_connect.Enabled := True;
bt_disconnect.Enabled := False;
gb_io.Enabled := False;
LTCPComponent1.Disconnect;
end;
Errore di collegamento Anche nel caso di un errore di collegamento l’elemento di controllo ClientSocket esegue una corrispondente procedura che corrisponde a grandi linee alla procedura di disconnessione. Nella riga di stato viene inoltre visualizzato il numero di errore Winsock e l’ErrorCode viene alla fine impostato su 0, affinché non si arrivi ad un errore di run-time.
procedure TForm1.LTCPComponent1Error(const msg: string; aSocket: TLSocket);
begin
StatusBar1.SimpleText :=’Error: ’+ msg;
bt_connect.Enabled := True;
bt_disconnect.Enabled := False;
gb_io.Enabled := False;
LTCPComponent1.Disconnect;
end;
3. Utilizzo e comunicazione del lato client
Non appena viene realizzato un collegamento con il Web-IO, l’utente può inviare comandi al Web-IO utilizzando i corrispondenti elementi del programma.
Impostazione degli outputL’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 abbandono della casella di spunta degli output, il programma esegue la corrispondente procedura e inoltra al Web-IO, in base all’eventuale impostazione della casella di spunta, il comando adatto.
procedure TForm1.cb_output0MouseUp(Sender:TOBject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if cb_output0.Checked then
LTCPComponent1.SendMessage(’GET/outputaccess0?PW=’ + ed_password.Text+ ’&State=ON&’,nil)
else
LTCPComponent1.SendMessage(’GET/outputaccess0?PW=’ + ed_password.Text + ’&State=OFF&’,nil)
end;
procedure TForm1.cb_output1MouseUp(Sender:TOBject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if cb_output1.Checked then
LTCPComponent1.SendMessage(’GET/outputaccess1?PW=’ + ed_password.Text + ’&State=ON&’,nil)
else
LTCPComponent1.SendMessage(’GET/outputaccess1?PW=’ + ed_password.Text + ’&State=OFF&’,nil)
end;
Interrogazione dello stato degli output/input L’utente può richiedere lo stato degli output e degli input facendo clic sul relativo pulsante.
procedure TForm1.bt_outputs_readClick(Sender:TObject);
begin
LTCPComponent1.SendMessage(’GET/output?PW=’ + ed_password.Text + ’&’,nil);
end;
procedure TForm1.bt_inputs_readClick(Sender:TObject);
begin
LTCPComponent1.SendMessage(’GET/input?PW=’ + ed_password.Text + ’&’,nil);
end;
Interrogazione/cancellazione dei counter È possibile interrogare o cancellare anche gli stati dei counter degli input.
procedure TForm1.bt_counter_read0Click(Sender:TObject);
begin
LTCPComponent1.SendMessage(’GET/counter0?PW=’ + ed_password.Text + ’&’,nil);
end;
procedure TForm1.bt_counter_read1Click(Sender:TObject);
begin
LTCPComponent1.SendMessage(’GET/counter1?PW=’ + ed_password.Text + ’&’,nil);
end;
procedure TForm1.bt_counter_clear0Click(Sender: TObject);
begin
LTCPComponent1.SendMessage(’GET/counterclear0?PW=’ + ed_password.Text + ’&’,nil);
end;
procedure TForm1.bt_counter_clear1Click(Sender:TObject);
begin
LTCPComponent1.SendMessage(’GET/counterclear1?PW=’ + ed_password.Text + ’&’,nil);
end;
Naturalmente è possibile leggere o cancellare contemporaneamente anche tutti i counter.
procedure TForm1.bt_counter_readallClick(Sender:TObject);
begin
LTCPComponent1.SendMessage(’GET/counter?PW=’ + ed_password.Text + ’&’,nil);
end;
procedure TForm1.bt_counter_clearallClick(Sender:TObject);
begin
LTCPComponent1.SendMessage(’GET/counterclear?PW=’ + ed_password.Text + ’&’,nil);
end;
4. Ricezione dei dati dal Web-IO
Analisi e visualizzazione dei dati ricevuti- Tutti i comandi e le richieste al Web-IO vengono confermati con una stringa di risposta. Le risposte hanno una struttura specifica in base al tipo.
- Per gli output: output;<valore binario dello stato degli output in formato esadecimale>
- Per gli input: input;<valore binario dello stato degli input in formato esadecimale>
- Per i counter: counterx;<stato del conteggio decimale>
- oppure counter;<stato del conteggio decimale 0 >; <stato del conteggio decimale 0 >; ... se tutti i counter devono essere letti in un’unica volta.
- Tutte le stringe di risposta terminano con 0 byte.
- Se l’elemento di controllo ClientSocket riceve dati, esso richiama la corrispondente procedura
procedure TForm1.LTCPComponent1Receive(aSocket:TLSocket);
var ReceiveString : String;
SemiPosition : integer;
OutputValue : word;
InputValue : word;
begin
aSocket.GetMessage(ReceiveString);
if Receivestring[1] = ’o’ then
begin
OutputValue := HextoInt(copy(ReceiveString, pos(’;’,ReceiveString)+1,length(ReceiveString)-pos(’;’,ReceiveString)-1));
if OutputValue and 1 = 1 then
cb_output0.Checked := True
else
cb_output0.Checked := False;
if OutputValue and 2 = 2 then
cb_output1.Checked := True
else
cb_output1.Checked := False;
end;
if Receivestring[1] = ’i’ then
begin
InputValue := HextoInt(copy(ReceiveString, pos(’;’,ReceiveString)+1, length(ReceiveString)-pos(’;’,ReceiveString)-1));
if InputValue and 1 = 1 then
cb_input0.Checked := True
else
cb_input0.Checked := False;
if InputValue and 2 = 2 then
cb_input1.Checked := True
else
cb_input1.Checked := False;
end;
if Receivestring[1] = ’c’ then
begin
if copy(ReceiveString, 8, 1) = ’0’ then
ed_counter0.Text := copy(ReceiveString, 10,length(ReceiveString)-10);
if copy(ReceiveString, 8, 1) = ’1’ then
ed_counter1.Text := copy(ReceiveString, 10,length(ReceiveString)-10);
if copy(ReceiveString, 8, 1) = ’;’ then
begin
ReceiveString[8] := ’ ’;
ed_counter0.Text := copy(ReceiveString, 9, pos(’;’,ReceiveString)-9);
ed_counter1.Text := copy(ReceiveString, pos(’;’,ReceiveString)+1, length(ReceiveString)-pos(’;’,ReceiveString)-1);
end;
end;
end;
La procedura di ricezione controlla, sulla base del primo carattere dei dati ricevuti, se si tratta di messaggi degli input, degli output o dei counter. In base a ciò viene ad es. stabilito quale stato ha quale output. Poiché lo stato degli output viene fornito in formato esadecimale, è innanzitutto necessaria una trasformazione in un valore intero per calcolare ulteriori fasi. Per la trasformazione è stata integrata nel programma una corrispondente funzione. Nei counter è possibile sia interrogare i valori dei singoli contatori che leggere tutti i counter contemporaneamente. Gli stati dei singoli contatori vengono visualizzati in una stringa in decimali separati mediante punto e virgola
function HexToInt(HexString :String) : longWord;
var CharCount : integer;
HexCharValue : longWord;
HexValue : longWord;
begin
HexValue := 0;
HexString := UpperCase(HexString);
for CharCount := 1 to length(HexString)
do
begin
HexCharValue := ord(HexString[CharCount]);
if HexCharValue > 57 then
HexCharValue := HexCharValue - 55
else
HexCharValue := HexCharValue - 48;
HexCharValue := HexCharValue
shl ((length(HexString) - CharCount) * 4);
HexValue := HexValue or HexCharValue;
end;
HexToInt := HexValue;
end;
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 richiamate dal Web-IO nell’intervallo impostato.
5. Polling
L’intervallo desiderato può essere immesso nel corrispondente campo di testo.
procedure TForm1.timer_pollingTimer(Sender:TObject);
begin
if LTCPComponent1.Connected and cb_output_polling.Checked then
LTCPComponent1.SendMessage(’GET/output?PW=’ + ed_password.Text + ’&’,nil);
if LTCPComponent1.Connected and cb_input_polling.Checked then
LTCPComponent1.SendMessage(’GET/input?PW=’ + ed_password.Text + ’&’,nil);
if LTCPComponent1.Connected and cb_counter_polling.Checked then
LTCPComponent1.SendMessage(’GET/counter?PW=’ + ed_password.Text + ’&’,nil);
end;
In caso di modifica l’intervallo del timer viene adattato automaticamente.
procedure TForm1.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à stringa di comando, ottimizzata per il Web-IO 2x input digitale, 2x output digitale Per gli altri modelli di Web-IO devono essere eventualmente apportati adattamenti al programma. Ulteriori esempi di programma per la programmazione socket sono riportati nelle pagine dei tool relative al Web-IO. Una descrizione dettagliata relativa all’interfaccia socket dei modelli Web-IO digitali è riportata nel manuale di riferimento.
Nessun problema: vi mettiamo a disposizione gratuitamente per 30 giorni il Web-IO digitale 2x input, 2x output. Non dovete far altro che compilare l’ordinazione del campione e vi forniremo il Web-IO in prova in conto aperto. Se ci restituite l’apparecchio entro 30 giorni, vi accreditiamo completamente la fattura.
All’ordinazione del campione