Tutorial al Web-IO digitale:
Attivare il Web-IO digitale con C# mediante
socket binari
Per la creazione di applicazioni Windows, Visual C++ è stata una delle piattaforme di sviluppo più utilizzate fino a poco tempo fa. Nel frattempo sempre più programmatori lavorano con il framework .Net e creano le loro applicazioni in C# (C Sharp).
Con il seguente esempio di programma C# l’utente può attivare il Web-IO digitale con i suoi input e output in un’applicazione Windows attraverso la modalità socket binario.
Preparativi
- Mettere sotto tensione il Web-IO e collegare gli IO
- Collegare il Web-IO alla rete
- Assegnazione di indirizzi IP
Nel Web-IO nell’area Vie di comunicazione >> API socket Attivare i socket BINARY1, spuntare gli Input-Trigger e autorizzare gli output per l’attivazione
Collocazione dei diversi elementi di comando e oggetti di visualizzazione nel modulo VB.net
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.
Importazione di risorse e dichiarazione di variabili locali
Come prima cosa vengono importate tutte le classi necessarie per il collegamento di rete e la GUI (Graphical User Interface).
using System;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Runtime.InteropServices;
Successivamente i componenti dell’applicazione e le variabili importanti per un collegamento TCP vengono dichiarati variabili locali della classe e con ciò resi accessibili ai metodi della classe.
public class mainWindow : System.Windows.Forms.Form
{ // All elements of the application
private CheckBox cb_Output0;
private CheckBox cb_Output1;
private CheckBox cb_Input0;
private CheckBox cb_Input1;
private CheckBox cb_Polling_Counter;
private CheckBox cb_Polling_Outputs;
private CheckBox cb_Polling_Inputs;
private Button bt_Readall_Outputs;
private Button bt_Readall_Inputs;
private Button bt_Clear_Counter0;
private Button bt_Clear_Counter1;
private Button bt_Clearall_Counter;
private Button bt_Read_Counter0;
private Button bt_Read_Counter1;
private Button bt_Readall_Counter;
private Label lb_Counter0;
private Label lb_Counter1;
private Label lb_Intervall;
private TextBox tb_Counter0;
private TextBox tb_Counter1;
private TextBox tb_Intervall;
private Button bt_Connect;
private Button bt_Disconnect;
private TextBox tb_Password;
private TextBox tb_Port;
private TextBox tb_IP;
private GroupBox gb_ioControlBox;
private GroupBox gb_conControlBox;
private StatusBar statusBar;
private Label label2;
private Label label1;
private Label label3;
private System.Windows.Forms.Timer counter;
private System.Windows.Forms.Timer outputs;
private System.Windows.Forms.Timer inputs;
private Socket client;
private int intervall;
private byte[] receivebuffer = new byte[256];
private structIOState IOState;
delegate void delegateSub();
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 IOStateLa struttura IOState non rientra nelle strutture binarie e non viene impiegata direttamente per la comunicazione tra applicazione e Web-IO. Serve per lo scambio degli stati IO tra thread ricevente e le parti di programma, deputate all’aggiornamento degli elementi di visualizzazione.
La struttura EADriverCon le sue quattro variabili a 16 bit è EADriver la struttura di base che è anche un elemento di tutte le altre strutture binarie.
public struct structIOState
{
public UInt16 InputState;
public UInt16 OutputState;
public UInt32 CounterValue0;
public UInt32 CounterValue1;
}
public struct structEADriver
{
public UInt16 Start_1;
public UInt16 Start_2;
public UInt16 StructType;
public UInt16 StructLength;
}
public struct structOptions
{
public structEADriver EADriver;
public UInt32 Version;
public UInt32 Options;
}
public struct structWriteRegister
{
public structEADriver EADriver;
public UInt16 Amount;
public UInt16 Value;
}
public struct structSetBit
{
public structEADriver EADriver;
public UInt16 Mask;
public UInt16 Value;
}
public struct structRegisterState
{
public structEADriver EADriver;
public UInt16 DriverID;
public UInt16 InputValue;
public UInt16 OutputValue;
}
public struct structReadCounter
{
public structEADriver EADriver;
public UInt16 CounterIndex;
}
[StructLayout(LayoutKind.Explicit)]
public struct structCounter
{
[FieldOffset(0)]public structEADriver EADriver;
[FieldOffset(8)] public UInt16 CounterIndex;
[FieldOffset(10)] public UInt32 CounterValue;
}
[StructLayout(LayoutKind.Explicit)]
public struct structAllCounter
{
[FieldOffset(0)] public structEADriver EADriver;
[FieldOffset(8)] public UInt16 CounterNoOf;
[FieldOffset(10)] public UInt32 CounterValue0;
[FieldOffset(14)] public UInt32 CounterValue1;
}
Nelle strutture è importante che le singole variabili vengano archiviate ininterrotte nella memoria. C# non realizza ciò automaticamente, in particolare se in una struttura vengono riunite variabili di dimensioni diverse. Per garantire tuttavia un’occupazione ininterrotta della memoria, si [StructLayout(LayoutKind.Explicit)]
definisce che ogni singola variabile [FieldOffset(14)]
viene assegnata mediante un offset fisso alla prima posizione della memoria della struttura.
Avvio del programma
Inizializzazione degli elementi di comandoIl 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.
Il nome del relativo elemento di comando può essere derivato in base al contesto dall’elemento stesso. I primi due caratteri del nome indicano il tipo dell’elemento (cb -> checkbox, bt -> button, gb -> groupbox e tb -> textbox).
public mainWindow()
{
InitializeComponent();
gb_ioControlBox.Enabled = false;
bt_Disconnect.Enabled = false;
cb_Input0.Enabled = false;
cb_Input1.Enabled = false;
tb_Counter0.Enabled = false;
tb_Counter1.Enabled = false;
IOState.InputState = 0;
IOState.OutputState = 0;
IOState.CounterValue0 = 0;
IOState.CounterValue1 = 0;
}
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.
private void bt_Connect_Click(object sender, System.EventArgs e)
{
try
{
if ((tb_IP.Text != "") && (tb_Port.Text != ""))
{
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(tb_IP.Text), int.Parse(tb_Port.Text));
client.BeginConnect(ipep, new AsyncCallback(connectCallback), client);
}
else
statusBar.Text = "IP and Port needed!";
}
catch (SocketException)
{
statusBar.Text = "Connection not possible!";
}
}
Creazione del collegamento
Per lo svolgimento della gestione TCP/IP viene innanzitutto definito un IPEndPoint dall’indirizzo IP e dalla porta TCP e con ciò viene inizializzato il socket TCP_client. Durante la richiesta di collegamento viene creato un rimando a una procedura di callback.
Collegamento realizzatoNon appena il Web-IO accetta il collegamento, viene eseguita la procedura di callback. Inoltre viene creato un rimando a una routine di callback per la ricezione dei dati.
Inviando la struttura Options Al Web-IO questo viene istruito, fissando un output a trasmettere lo stato di attivazione modificato attraverso la struttura RegisterState.
private void connectCallback(IAsyncResult ar)
{
try
{
client = (Socket)ar.AsyncState;
client.EndConnect(ar);
connectupdatedisplay();
intervall = 1000;
client.BeginReceive(receivebuffer, 0, 255, SocketFlags.None, new AsyncCallback(receiveCallback), client);
}
catch (Exception)
{
disconnect();
}
if (client.Connected)
{
IntPtr BufPtr;
structOptions Options;
Options.EADriver.Start_1 = 0;
Options.EADriver.Start_2 = 0;
Options.EADriver.StructType = 0x1F0;
Options.EADriver.StructLength = 16;
Options.Version = 0;
Options.Options = 1;
BufPtr = Marshal.AllocHGlobal(Marshal.SizeOf(Options));
Marshal.StructureToPtr(Options, BufPtr, true);
sendstructure(BufPtr, (short)Options.EADriver.StructLength);
}
}
Inoltre avviando la procedura connectupdatedisplay()
vengono autorizzati tutti gli elementi di comando necessari dell’applicazione e viene disattivato il Connect Button.
private void connectupdatedisplay()
{
if (InvokeRequired)
{
BeginInvoke(new delegateSub(connectupdatedisplay), new object[] { });
return;
}
statusBar.Text = "Connected!";
gb_ioControlBox.Enabled = true;
bt_Disconnect.Enabled = true;
bt_Connect.Enabled = false;
}
Nella versione attuale di C# non è più consentito accedere da un thread (qui la funzione Callback) a elementi grafici di un altro thread (forma).
Qui offre una soluzione l’uso di delegate e invoke.
Disinserzione del collegamentoIl collegamento sussiste finché viene interrotto dall’utente mediante clic sul tasto Disconnect o finché il Web-IO interrompe il collegamento.
private void bt_Disconnect_Click(object sender, System.EventArgs e)
{
try
{
client.Shutdown(SocketShutdown.Both);
client.Close();
disconnectupdatedisplay();
}
catch (Exception)
{
statusBar.Text = "Not able to disconnect!";
}
}
In questo caso viene richiamata una corrispondente procedura.
private void disconnect()
{
try
{
client.Shutdown(SocketShutdown.Both);
client.Close();
disconnectupdatedisplay();
}
catch (Exception)
{
statusBar.Text = "Not able to disconnect!";
}
}
Per un accesso sicuro in termini di thread il ripristino degli elementi del modulo è stato trasferito alla procedura disconnectupdatedisplay()
.
private void disconnectupdatedisplay()
{
if (InvokeRequired)
{
BeginInvoke(new delegateSub(disconnectupdatedisplay), new object[] { });
return;
}
statusBar.Text = "Disconnected!";
gb_ioControlBox.Enabled = false;
bt_Disconnect.Enabled = false;
bt_Connect.Enabled = true;
}
Errore di collegamento
Tutte le azioni che riguardano la comunicazione TCP/IP vengono eseguite nell’ambito dell’istruzione Try. Se si verificano degli errori, viene utilizzato il disconnect();
metodo dell’ oggetto client.
Utilizzo e comunicazione della parte client
Invio di strutture binarieNon appena viene realizzato un collegamento con il Web-IO, l’utente può inviare strutture binarie al Web-IO controllando i corrispondenti elementi del programma.
private void sendstructure(IntPtr BufPtr, Int16 BufSize)
{
byte[] senddata;
senddata = new byte[BufSize];
Marshal.Copy(BufPtr, senddata, 0, BufSize);
client.BeginSend(senddata, 0, senddata.Length, 0, new AsyncCallback(sendCallback), client);
}
private void sendCallback(IAsyncResult ar)
{
try
{
Socket tmp_client = (Socket) ar.AsyncState;
int bytessend = tmp_client.EndSend(ar);
}
catch(Exception)
{
statusBar.Text = "Error by sending";
}
}
C# non prevede alcun metodo per l’invio diretto di strutture binarie. I dati binari possono essere inviati solo come byte array. Per questo all’apertura della funzione sendstructure viene trasmesso un pointer (indicatore). Il suddetto pointer rimanda al punto della memoria da cui è ritrovabile il contenuto della struttura da inviare. Qui è chiaro perché le variabili strutturali devono essere salvate nella memoria in byte ininterrotti. Come secondo parametro viene trasmessa la lunghezza della struttura.
Mediante Marshal.Copy(BufPtr, senddata, 0, Bufsize)
i dati strutturali vengono poi copiati in una serie di byte (byte array). Questa serie di byte viene poi inviata al Web-IO.
L’impostazione degli output è resa possibile all’utente da due caselle di spunta cb_outputx. Il programma utilizza a tal scopo l’evento MouseUP di questo oggetto. Se si registra un MouseUP, quindi rilasciando il checkbox output, il programma esegue la rispettiva procedura e trasmette, a seconda che il checkbox sia stato impostato o meno, la struttura SetBit opportunamente compilata al Web-IO.
private void cb_Output0_MouseUp(object sender, MouseEventArgs e)
{
IntPtr BufPtr;
structSetBit SetBit;
SetBit.EADriver.Start_1 = 0;
SetBit.EADriver.Start_2 = 0;
SetBit.EADriver.StructType = 0x9;
SetBit.EADriver.StructLength = 0xC;
SetBit.Mask = 1;
if (cb_Output0.Checked)
SetBit.Value = 1;
else
SetBit.Value = 0;
BufPtr = Marshal.AllocHGlobal(Marshal.SizeOf(SetBit));
Marshal.StructureToPtr(SetBit, BufPtr, true);
sendstructure(BufPtr, (short)SetBit.EADriver.StructLength);
}
private void cb_Output1_MouseUp(object sender, MouseEventArgs e)
{
IntPtr BufPtr;
structSetBit SetBit;
SetBit.EADriver.Start_1 = 0;
SetBit.EADriver.Start_2 = 0;
SetBit.EADriver.StructType = 0x9;
SetBit.EADriver.StructLength = 0xC;
SetBit.Mask = 2;
if (cb_Output1.Checked)
SetBit.Value = 2;
else
SetBit.Value = 0;
BufPtr = Marshal.AllocHGlobal(Marshal.SizeOf(SetBit));
Marshal.StructureToPtr(SetBit, BufPtr, true);
sendstructure(BufPtr, (short)SetBit.EADriver.StructLength);
}
Interrogazione dello stato degli output/input
L’utente può richiedere lo stato degli output e degli input facendo clic sul relativo pulsante.
private void bt_Readall_Outputs_Click(object sender, System.EventArgs e)
{
IntPtr BufPtr;
structEADriver RegisterRequest;
RegisterRequest.Start_1 = 0;
RegisterRequest.Start_2 = 0;
RegisterRequest.StructType = 0x21;
RegisterRequest.StructLength = 8;
BufPtr = Marshal.AllocHGlobal(Marshal.SizeOf(RegisterRequest));
Marshal.StructureToPtr(RegisterRequest, BufPtr, true);
sendstructure(BufPtr, (short)RegisterRequest.StructLength);
}
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 avviato attraverso clic sul tasto bt_inputs. A tal scopo viene inviata la struttura ReadRegister a cui il Web-IO risponde con la struttura WriteRegister.
private void bt_Readall_Inputs_Click(object sender, System.EventArgs e)
{
IntPtr BufPtr;
structEADriver ReadRegister;
ReadRegister.Start_1 = 0;
ReadRegister.Start_2 = 0;
ReadRegister.StructType = 1;
ReadRegister.StructLength = 8;
BufPtr = Marshal.AllocHGlobal(Marshal.SizeOf(ReadRegister));
Marshal.StructureToPtr(ReadRegister, BufPtr, true);
sendstructure(BufPtr, (short)ReadRegister.StructLength);
}
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.
private void bt_Read_Counter0_Click(object sender, System.EventArgs e)
{
IntPtr BufPtr;
structReadCounter ReadCounter;
ReadCounter.EADriver.Start_1 = 0;
ReadCounter.EADriver.Start_2 = 0;
ReadCounter.EADriver.StructType = 0xB0;
ReadCounter.EADriver.StructLength = 0xA;
ReadCounter.CounterIndex = 0;
BufPtr = Marshal.AllocHGlobal(Marshal.SizeOf(ReadCounter));
Marshal.StructureToPtr(ReadCounter, BufPtr, true);
sendstructure(BufPtr, (short)ReadCounter.EADriver.StructLength);
}
private void bt_Read_Counter1_Click(object sender, System.EventArgs e)
{
IntPtr BufPtr;
structReadCounter ReadCounter;
ReadCounter.EADriver.Start_1 = 0;
ReadCounter.EADriver.Start_2 = 0;
ReadCounter.EADriver.StructType = 0xB0;
ReadCounter.EADriver.StructLength = 0xA;
ReadCounter.CounterIndex = 1;
BufPtr = Marshal.AllocHGlobal(Marshal.SizeOf(ReadCounter));
Marshal.StructureToPtr(ReadCounter, BufPtr, true);
sendstructure(BufPtr, (short)ReadCounter.EADriver.StructLength);
}
private void bt_Clear_Counter0_Click(object sender, System.EventArgs e)
{
IntPtr BufPtr;
structReadCounter ReadCounter;
ReadCounter.EADriver.Start_1 = 0;
ReadCounter.EADriver.Start_2 = 0;
ReadCounter.EADriver.StructType = 0xC0;
ReadCounter.EADriver.StructLength = 0xA;
ReadCounter.CounterIndex = 0;
BufPtr = Marshal.AllocHGlobal(Marshal.SizeOf(ReadCounter));
Marshal.StructureToPtr(ReadCounter, BufPtr, true);
sendstructure(BufPtr, (short)ReadCounter.EADriver.StructLength);
}
private void bt_Clear_Counter1_Click(object sender, System.EventArgs e)
{
IntPtr BufPtr;
structReadCounter ReadCounter;
ReadCounter.EADriver.Start_1 = 0;
ReadCounter.EADriver.Start_2 = 0;
ReadCounter.EADriver.StructType = 0xC0;
ReadCounter.EADriver.StructLength = 0xA;
ReadCounter.CounterIndex = 1;
BufPtr = Marshal.AllocHGlobal(Marshal.SizeOf(ReadCounter));
Marshal.StructureToPtr(ReadCounter, BufPtr, true);
sendstructure(BufPtr, (short)ReadCounter.EADriver.StructLength);
}
Sulla struttura ReadAllCounter o ReadClearAllCounter è possibile leggere o cancellare contemporaneamente anche tutti i counter. Il Web-IO risponde con la struttura AllCounter.
private void bt_Readall_Counter_Click(object sender, System.EventArgs e)
{
IntPtr BufPtr;
structEADriver ReadAllCounter;
ReadAllCounter.Start_1 = 0;
ReadAllCounter.Start_2 = 0;
ReadAllCounter.StructType = 0xB1;
ReadAllCounter.StructLength = 8;
BufPtr = Marshal.AllocHGlobal(Marshal.SizeOf(ReadAllCounter));
Marshal.StructureToPtr(ReadAllCounter, BufPtr, true);
sendstructure(BufPtr, (short)ReadAllCounter.StructLength);
}
private void bt_Clearall_Counter_Click(object sender, System.EventArgs e)
{
IntPtr BufPtr;
structEADriver ReadClearAllCounter;
ReadClearAllCounter.Start_1 = 0;
ReadClearAllCounter.Start_2 = 0;
ReadClearAllCounter.StructType = 0xC1;
ReadClearAllCounter.StructLength = 8;
BufPtr = Marshal.AllocHGlobal(Marshal.SizeOf(ReadClearAllCounter));
Marshal.StructureToPtr(ReadClearAllCounter, BufPtr, true);
sendstructure(BufPtr, (short)ReadClearAllCounter.StructLength);
}
Ricezione dei dati dal Web-IO
Analisi e visualizzazione dei dati ricevutiIl 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 i primi 8 byte del byte-array ricevuto riempiono attraverso un’operazione del puntatore 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 il byte array ricevuto riempie ora la struttura adatta attraverso un’operazione del puntatore.
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.
private void receiveCallback(IAsyncResult ar)
{
int BytesRead;
string rcv = string.Empty;
try
{
BytesRead = client.EndReceive(ar);
client.BeginReceive(receivebuffer, 0, 255, SocketFlags.None, new AsyncCallback(receiveCallback), client);
}
catch (Exception)
{
BytesRead = 0;
}
if (BytesRead == 0)
{
if (client.Connected) { disconnect(); }
}
else
{
GCHandle MyGC = GCHandle.Alloc(receivebuffer, GCHandleType.Pinned);
structEADriver EADriver = (structEADriver)Marshal.PtrToStructure(MyGC.AddrOfPinnedObject(), typeof(structEADriver));
switch (EADriver.StructType)
{
case 8:
structWriteRegister WriteRegister = (structWriteRegister)Marshal.PtrToStructure(MyGC.AddrOfPinnedObject(), typeof(structWriteRegister));
IOState.InputState = WriteRegister.Value;
break;
case 0x31:
structRegisterState RegisterState = (structRegisterState)Marshal.PtrToStructure(MyGC.AddrOfPinnedObject(), typeof(structRegisterState));
IOState.InputState = RegisterState.InputValue;
IOState.OutputState = RegisterState.OutputValue;
break;
case 0xB4:
structCounter Counter = (structCounter)Marshal.PtrToStructure(MyGC.AddrOfPinnedObject(), typeof(structCounter));
if (Counter.CounterIndex == 0) { IOState.CounterValue0 = Counter.CounterValue; }
if (Counter.CounterIndex == 1) { IOState.CounterValue1 = Counter.CounterValue; }
break;
case 0xB5:
structAllCounter AllCounter = (structAllCounter)Marshal.PtrToStructure(MyGC.AddrOfPinnedObject(), typeof(structAllCounter));
IOState.CounterValue0 = AllCounter.CounterValue0;
IOState.CounterValue1 = AllCounter.CounterValue1;
break;
}
IOupdatedisplay();
MyGC.Free();
}
}
Per un aggiornamento della visualizzazione sicuro in termini di thread la copia del processo degli IO viene trasmesso attraverso la struttura IOState alla procedura IOupdatedisplay. Attraverso Invoke e formazione di Delegate gli elementi di visualizzazione interessati vengono adattati allo stato IO.
private void IOupdatedisplay()
{
if (InvokeRequired)
{
BeginInvoke(new delegateSub(IOupdatedisplay), new object[] { });
return;
}
if ((IOState.OutputState & 1) == 1)
cb_Output0.Checked = true;
else
cb_Output0.Checked = false;
if ((IOState.OutputState & 2) == 2)
cb_Output1.Checked = true;
else
cb_Output1.Checked = false;
if ((IOState.InputState & 1) == 1)
cb_Input0.Checked = true;
else
cb_Input0.Checked = false;
if ((IOState.InputState & 2) == 2)
cb_Input1.Checked = true;
else
cb_Input1.Checked = false;
tb_Counter0.Text = IOState.CounterValue0.ToString();
tb_Counter1.Text = IOState.CounterValue1.ToString();
}
Polling
Interrogazione ciclica di determinati valoriPer 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.
private void timer_handler(object sender, System.EventArgs e)
{
if (sender == counter) bt_Readall_Counter_Click(sender, e);
if (sender == outputs) bt_Readall_Outputs_Click(sender, e);
if (sender == inputs) bt_Readall_Inputs_Click(sender, e);
}
private void cb_Polling_Counter_CheckedChanged(object sender, System.EventArgs e)
{
if(cb_Polling_Counter.Checked)
{
counter = new System.Windows.Forms.Timer();
counter.Interval = intervall;
counter.Start();
counter.Tick += new EventHandler(timer_handler);
}
else
counter.Stop();
}
private void cb_Polling_Outputs_CheckedChanged(object sender, System.EventArgs e)
{
if(cb_Polling_Outputs.Checked)
{
outputs = new System.Windows.Forms.Timer();
outputs.Interval = intervall;
outputs.Start();
outputs.Tick += new EventHandler(timer_handler);
}
else
outputs.Stop();
}
private void cb_Polling_Inputs_CheckedChanged(object sender, System.EventArgs e)
{
if(cb_Polling_Inputs.Checked)
{
inputs = new System.Windows.Forms.Timer();
inputs.Interval = intervall;
inputs.Start();
inputs.Tick += new EventHandler(timer_handler);
}
else
inputs.Stop();
}
L’intervallo desiderato può essere immesso nel corrispondente campo di testo. In caso di una modifica l’intervallo del timer viene adattato automaticamente.
private void tb_Intervall_TextChanged(object sender, System.EventArgs e)
{
try
{
if(Convert.ToInt32(tb_Intervall.Text) > 0)
{
intervall = Convert.ToInt32(tb_Intervall.Text);
statusBar.Text = "New range: " + intervall.ToString() + " ms!";
}
else
statusBar.Text = "Only positiv Integer allowed!";
}
catch(Exception)
{
statusBar.Text = "Only positiv Integer allowed!";
}
}
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.