Blog
Kom i gang med at programmere Web-IO-enheder!
Ved hjælp af det følgende C#-programeksempel kan du repræsentere din Web-IO Digital med dens indgange og udgange i en Windows-applikation. Du kan også skifte mellem Web-IO-udgangene.
Kom i gang - bestil en prøveversion i 30 dage.
Prøv vores produkter fra Wiesemann & Theis gratis i 30 dage ved at skrive det i ordrebekræftelsen: Ønsker at teste produktet.
Hvis du ikke ønsker at gøre brug af din returret inden for 30 dage, skal du blot betale den medfølgende faktura. Gratis forsendelse i Danmark.
Forberedelser
- med magt,
- konfigurerede ind- og udgange,
- tilsluttet den til dit netværk,
- tildelt den en IP-adresse – hvilket med WuTility ikke er noget problem.
1. Kombiner de forskellige betjeningselementer og visningsobjekter i formen

2. Importer ressourcer og erklæringer fra medlemsvariabler
For det første importeres alle de klasser, der er nødvendige for netværksforbindelsen og GUI’en.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Net;
using System.Net.Sockets;
using System.Text;Derefter erklæres applikationskomponenterne og de vigtige variabler for en TCP-forbindelse som medlemsvariabler, hvilket gør dem tilgængelige for klassens metoder.
private System.Windows.Forms.CheckBox
cb_Output0;
private System.Windows.Forms.CheckBox
cb_Output1;
private System.Windows.Forms.CheckBox
cb_Input0;
private System.Windows.Forms.CheckBox
cb_Input1;
private System.Windows.Forms.CheckBox
cb_Polling_Counter;
private System.Windows.Forms.CheckBox
cb_Polling_Outputs;
private System.Windows.Forms.CheckBox
cb_Polling_Inputs;
private System.Windows.Forms.Button
bt_Readall_Outputs;
private System.Windows.Forms.Button
bt_Readall_Inputs;
private System.Windows.Forms.Button
bt_Clear_Counter0;
private System.Windows.Forms.Button
bt_Clear_Counter1;
private System.Windows.Forms.Button
bt_Clearall_Counter;
private System.Windows.Forms.Button
bt_Read_Counter0;
private System.Windows.Forms.Button
bt_Read_Counter1;
private System.Windows.Forms.Button
bt_Readall_Counter;
private System.Windows.Forms.Label
lb_Counter0;
private System.Windows.Forms.Label
lb_Counter1;
private System.Windows.Forms.Label
lb_Intervall;
private System.Windows.Forms.TextBox
tb_Counter0;
private System.Windows.Forms.TextBox
tb_Counter1;
private System.Windows.Forms.TextBox
tb_Intervall;
private System.Windows.Forms.Button
bt_Connect;
private System.Windows.Forms.Button
bt_Disconnect;
private System.Windows.Forms.TextBox
tb_Password;
private System.Windows.Forms.TextBox
tb_Port;
private System.Windows.Forms.TextBox
tb_IP;
private System.Windows.Forms.GroupBox
gb_ioControlBox;
private System.Windows.Forms.GroupBox
gb_conControlBox;
private System.Windows.Forms.StatusBar
statusBar;
private System.ComponentModel.Container
components = null;
private System.Windows.Forms.Timer
counter;
private System.Windows.Forms.Timer
outputs;
private System.Windows.Forms.Timer
inputs;
private Socket client;
private string rcv;
private int intervall;
private byte[] buffer = new byte[256];3. Start af programmet
Opsætning af betjeningselementerne
Gruppen med betjeningselementerne til Web-IO er først blokeret fra drift. Så snart en forbindelse er etableret, aktiveres alle elementer, der har et meningsfuldt format.
Navnet på det respektive betjeningselement er afledt af selve elementet afhængigt af konteksten. De første to tegn i navnet står for elementtypen (cb -> Checkbox, bt -> Button, gb -> Groupbox og 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;
}4. Kontrol af tilslutning
Etablering af forbindelsen
Når du har indtastet IP-adressen for Web-IO i tekstfeltet tb_IP og Port 80 i tekstfeltet tb_port, kan du åbne en forbindelse ved at klikke på knappen bt_connect. Hvis der ikke er indtastet en IP-adresse eller port, vises en meddelelse i statuslinjen
Åbning af forbindelsen
For at kunne åbne en TCP-forbindelse initialiseres den allerede deklarerede socket-variabel. Den får en stream og forbindelsestypen. Derudover genereres en variabel, som gemmer port og IP-adresse. For at programmet kan køre asynkront, venter det ikke på hændelser, men bruger i stedet callback-rutiner. Callback-metoder initialiseres, når en proces startes, og påkaldes, når den tilsvarende hændelse indtræffer, dvs. f.eks. når en forbindelse åbnes for at sende eller modtage.
private void bt_Connect_Click(object sender, System.EventArgs e)
{
try
{
if((tb_IP.Text != "") && (tb_Port.Text == "80"))
{
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!";
}
}I det følgende vises den callback-rutine, der påkaldes, når forbindelsen er etableret. Når forbindelsen er oprettet, aktiveres alle nyttige betjeningselementer for applikationen, og Connect-knappen deaktiveres. Derudover begynder programmet straks at gå i modtageklar tilstand. Til dette initialiseres callback-rutinen “receiveCallback”, som forklares mere detaljeret nedenfor.
private void connectCallback(IAsyncResult ar)
{
try
{
client = (Socket) ar.AsyncState;
client.EndConnect(ar);
statusBar.Text = "Connected!";
gb_ioControlBox.Enabled = true;
bt_Disconnect.Enabled = true;
bt_Connect.Enabled = false;
intervall = 1000;
client.BeginReceive(buffer, 0, 255, SocketFlags.None, new AsyncCallback(receiveCallback), client);
}
catch(Exception)
{
disconnect(); statusBar.Text = "Error while connecting!";
}
}Frakobling
Forbindelsen forbliver åben, indtil brugeren klikker på knappen Afbryd forbindelsen, eller indtil den afsluttes af Web-IO’en. Når du har klikket på knappen, vises en meddelelse om, at forbindelsen er blevet afbrudt.
private void bt_Disconnect_Click(object
sender, System.EventArgs e)
{
disconnect();
}Når forbindelsen afsluttes, skal alle elementer returneres til deres oprindelige tilstand. Det bør derefter ikke længere være muligt at trykke på afbryderknappen.
private void disconnect()
{
try
{
client.Shutdown(SocketShutdown.Both);
client.Close();
statusBar.Text = "Disconnected!";
gb_ioControlBox.Enabled = false;
bt_Disconnect.Enabled = false;
bt_Connect.Enabled = true;
}
catch(Exception)
{
statusBar.Text = "Not able to disconnect!";
}
}Nu lukkes forbindelsen igen, og applikationen nulstilles til sin oprindelige tilstand.
5. Betjening og kommunikation fra klientsiden
Så snart der er oprettet forbindelse til Web-IO, kan brugeren bruge de tilsvarende programelementer til at sende kommandoer til Web-IO.
Når man sender en besked til Web-IO, påkaldes en callback-rutine, ligesom når man modtager.
private void sendCallback(IAsyncResult ar)
{
try
{
Socket tmp_client = (Socket) ar.AsyncState;
int bytessend = tmp_client.EndSend(ar);
}
catch(Exception)
{
statusBar.Text = "Error while sending";
}
}Indstilling af udgange
Udgangene på Web-IO kan skiftes ved hjælp af de to afkrydsningsfelter IDC_OUTPUT0 og IDC_OUTPUT1. Afkrydsningsfeltet registrerer, hvornår der blev klikket på det, og udløser derefter en handling. Afhængigt af om afkrydsningsfeltet allerede er sat, sættes udgangen enten til ON eller OFF.
private void cb_Output0_CheckedChanged(object sender, System.EventArgs e)
{
if(cb_Output0.Checked)
send("GET /outputaccess0?PW=" + tb_Password.Text + "&State=ON&");
else
send("GET /outputaccess0?PW=" + tb_Password.Text + "&State=OFF&");
}private void cb_Output1_CheckedChanged(object sender, System.EventArgs e)
{
if(cb_Output1.Checked)
send("GET /outputaccess1?PW=" + tb_Password.Text + "&State=ON&");
else
send("GET /outputaccess1?PW=" + tb_Password.Text + "&State=OFF&");
}Forespørgsel på output/input-status
private void bt_Readall_Outputs_Click(object sender, System.EventArgs e)
{
send("GET /output?PW=" + tb_Password.Text + "&");
}private void bt_Readall_Inputs_Click(object sender, System.EventArgs e)
{
send("GET /input?PW=" + tb_Password.Text + "&");
}Forespørgselstællere
Den følgende metode sender en forespørgsel til en bestemt tæller og beder om et svar, der indeholder tællerens aktuelle tilstand.
private void bt_Read_Counter0_Click(object sender, System.EventArgs e)
{
send("GET /counter0?PW=" + tb_Password.Text + "&");
}private void bt_Read_Counter1_Click(object sender, System.EventArgs e)
{
send("GET /counter1?PW=" + tb_Password.Text + "&");
}Naturligvis kan alle tællertilstande også polles med en enkelt kommando.
private void bt_Readall_Counter_Click(object sender, System.EventArgs e)
{
send("GET /counter?PW=" + tb_Password.Text + "&");
}Nulstil tællere
private void bt_Clear_Counter0_Click(object sender, System.EventArgs e)
{
send("GET /counterclear0?PW=" + tb_Password.Text + "&");
}private void bt_Clear_Counter1_Click(object sender, System.EventArgs e)
{
send("GET /counterclear1?PW=" + tb_Password.Text + "&");
}Naturligvis kan alle tællere nulstilles sammen med en enkelt kommando.
private void bt_Clearall_Counter_Click(object sender, System.EventArgs e)
{
send("GET /counterclear?PW=" + tb_Password.Text + "&");
}Da alle tællertilstande kan aflæses eller nulstilles ved hjælp af én kommando, skal der implementeres en metode, som behandler svarstrengen fra Web-IO og tildeler hver tæller i applikationen dens specifikke tilstand.
private void readAndClearCounter(string data)
{
int j = 0;
string[] counter = new string[12];
for(int i = 0; i < data.Length-1; i++)
{
if((data[i].CompareTo(';')) == 0)
j++;
else
counter[j] += data[i].ToString();
}
tb_Counter0.Text = counter[0];
tb_Counter1.Text = counter[1];
}6. Modtagelse af data fra Web-IO
Behandle og vise de modtagne data
- Alle kommandoer og anmodninger til Web-IO kvitteres med en svarstreng. Svarene har en bestemt struktur afhængigt af typen:
- For udgangene: output;<binær værdi af udgangsstatus i hexadecimalt format>
- For en særlig udgang: outputx;<ON eller OFF>
- For indgangene: input;<binær værdi af indgangsstatus i hexadecimalt format>
- For et særligt input inputx;<ON eller OFF>
- Så er der svarstrengen til en tæller, som ser ud som følger.
- Tæller: counterx;<decimal tællerstatus>
- eller counter;<decimal counter state 0 >; <decimal counter state 0 >; … hvis du vil læse alle tællerne på én gang.
- Alle svarstrenge afsluttes med en 0-byte.
I vores program påkaldes metoden receiveCallback() for at modtage en sådan besked. I denne metode læses og behandles svarstrengen fra Web-IO’en. Det unikke her er den event-drevne invoking, som finder sted, så snart Web-IO’en sender data til applikationen.
private void receiveCallback(IAsyncResult ar)
{
int bytesRead;
try
{
bytesRead = client.EndReceive(ar);
rcv = string.Empty;
rcv = Encoding.ASCII.GetString(buffer);
client.BeginReceive(buffer, 0, 255, SocketFlags.None, new AsyncCallback(receiveCallback), client);
}
catch(Exception)
{
bytesRead = 0;
}
if(bytesRead == 0 && client.Connected)
disconnect();
else if(rcv != null)
{
if(rcv[0] == 'o')
{
int i = Int32.Parse(rcv.Substring(7), System.Globalization.NumberStyles.HexNumber);
if((i & 1) == 1)
cb_Output0.Checked = true;
else
cb_Output0.Checked = false;
if((i & 2) == 2)
cb_Output1.Checked = true;
else
cb_Output1.Checked = false;
}
if(rcv[0] == 'i')
{
int i = Int32.Parse(rcv.Substring(6), System.Globalization.NumberStyles.HexNumber);
if((i & 1) == 1)
cb_Input0.Checked = true;
else
cb_Input0.Checked = false;
if((i & 2) == 2)
cb_Input1.Checked = true;
else
cb_Input1.Checked = false;
}
if(rcv[0] == 'c')
{
if(rcv[7] == '0')
tb_Counter0.Text = rcv.Substring(9);
if(rcv[7] == '1')
tb_Counter1.Text = rcv.Substring(9);
if(rcv[7] == ';')
readAndClearCounter(rcv.Substring(8));
}
}
}7. Afstemning
Cyklisk afstemning af bestemte værdier
Det er ønskeligt, at status for en individuel komponent opdateres af komponenten selv, så applikationen altid viser den aktuelle status. Til det formål bruger programmet en timer, som sender cykliske forespørgsler til Web-IO med et brugerdefineret tidsinterval.
Tidsintervallet kan angives i feltet IDC_POLLINGTEXT.
Dette fanger selvfølgelig også tilfælde, hvor brugeren indtaster en nonsensværdi, såsom en negativ tidsværdi.
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 positive Integer allowed!";
}
catch(Exception)
{
statusBar.Text = "Only positive Integer allowed!";
}
}For at udføre cyklisk polling af Web-IO-tilstande kan du vælge mellem polling af udgangene, indgangene eller tællerne.
Hver polling-variant har sin egen initialiserede timer.
Hvis du aktiverer afkrydsningsfeltet cb_Polling_Outputs, vil polling blive anvendt på udgangene. Den tilsvarende timer initialiseres.
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();
}Det samme gælder for indgange og tællere
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();
}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();
}I denne metode opfanges den respektive hændelse i den timer, der lige har rapporteret, og tildeles en bestemt handling.
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);
}programmet eksemplet understøtter alle almindelige funktioner i Web-IO i kommandostrengstilstand, optimeret til Web-IO 2x Digital Input, 2x Digital Output. For de andre Web-IO-modeller kan det være nødvendigt at tilpasse programmet. Yderligere programeksempler til socket-programmering kan findes på værktøjssiderne for Web-IO. En detaljeret beskrivelse af socket-grænsefladen til Web-IO Digital-modellerne findes i referencemanualen.
Wiesemann & Theis GmbH blev grundlagt i 1979 af Reinhard Wiesemann og Rüdiger Theis. Med 50 ansatte producerer virksomheden mikrocomputer- og netværksteknologi i Wuppertal. I 2001 introducerede Wiesemann & Theis den første industrielle temperatursensor med et netværksinterface, Web-Thermometer, og har næsten 20 års erfaring inden for områderne Industri 4.0 og Internet of Things.
Active Communication har været distributør for W&T siden 1992 i Danmark og siden 2002 også i Sverige, Norge og Island. W&T’s produkter er ekstremt brugervenlige og pålidelige til en konkurrencedygtig pris.