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.

Bestil prøveversion her:

Forberedelser

Du har allerede angivet din Web-IO Digital

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.

Download programeksempel

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.