Consumer in C# to read and write PLC variables

This sample explains how to create an ADS-WebService-Consumer to read and write PLC-Variables via ADS-HTTP.

Creating a WebService-Consumers within the Microsoft VisualStudio.NET

In Visual Studio select "New Project" and create a new C# - Windows Application.

Consumer in C# to read and write PLC variables 1:

After creating the projects go to "Projects" "Add Web Reference...".

In the following dialog you may insert the URL of the WebService-WSDL-file or you can browse for it by clicking on "Web services on the local machine".

Consumer in C# to read and write PLC variables 2:

Name the reference and click the button "Add Reference" to complete .

Consumer in C# to read and write PLC variables 3:

To catch SOAP-Exceptions add the following line to the first lines of the source-code:

using System.Web.Services.Protocols;

To create a WebService-object insert the following line after "public class NameOfYourForm: System.Windows.Forms.Form":

TcAdsWebService.TcAdsWebService TcWebService = new TcAdsWebService.TcAdsWebService();

Add the following line in the constructor ("public NameOfYourForm") after "InitializeComponent();":

  
TcWebService.Url = "http://localhost/TcAdsWebService/TcAdsWebService.dll";

// Sample 1 : 
TcWebService.Url = "http://192.168.0.2/TcAdsWebService/TcAdsWebService.dll";

// Sample 2 :  
TcWebService.Url = "http://CX_xxxxxx/TcAdsWebService/TcAdsWebService.dll";

The address must be the URL of your TwinCAT ADS WebService-DLL-file.

Converting variables to byte-arrays

Variables must be converted to byte-arrays if they should be used with the ADS-WebService. Therefore it is necessary to be able to convert variables to byte-arrays and vice versa:

This could be realized with the BitConverter-class:

byte[] abDataBool = new byte[1];
abDataBool = BitConverter.GetBytes(bValueBool);

byte[] abDataInt = new byte[2];
abDataInt = BitConverter.GetBytes((Int16)iValueInt)

In this example a "bool"- and an "int"-variable were converted to byte-arrays.

To convert a byte-array back to a variable use the BitConverter-class as followed:

byte[] abDataBuffer = new byte[3];
bool bVarBool = BitConverter.ToBoolean(abDataBuffer,0);
int iVarInt = BitConverter.ToInt16(abDataBuffer,1);

Strings are converted with the the "ASCII-Encoder":

string szValueString;
byte[] abDataString = new byte[81];
System.Text.ASCIIEncoding encoder = new System.Text.ASCIIEncoding();
encoder.GetBytes(szValueString, 0, encoder.GetByteCount(szValueString), abDataString, 0);

 

To convert a byte-array back to a string use the following code:

byte[] abDataBuffer = new byte[81];
System.Text.ASCIIEncoding encoder = new System.Text.ASCIIEncoding();
string VarString = encoder.GetString(abDataBuffer, 3, 81);

You can get more detailed information about this methods and classes in literature for C#-Application-Developement.

Reading PLC-variables

To read a PLC-Variable use the "read"-method of the WebService-object:

WebService.Read(string netId, int nPort,
System.UInt32 indexGroup, System.UInt32 indexOffset, int cblen, out
System.Byte[] ppData);

Example:

try
{
    TcWebService.Read("192.168.0.2.1.1", 801, 0x4020, 0, 84, out abDataBuffer);
}
catch (SoapException ex)
{
    MessageBox.Show(ex.Message);
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

Writing PLC-variables

To write a PLC-Variable use the "write"-method of the WebService-object:

WebService.Write(string netId, int nPort,
System.UInt32 indexGroup, System.UInt32 indexOffset, System.Byte[]
pData);

Example:

byte[] Data = new byte[10];
try
{
    TcWebService.Write("192.168.0.2.1.1", 801, 0x4020, 0, Data);
}
catch (SoapException ex)
{
    MessageBox.Show(ex.Message);
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

Sample-Application:

PLC-program, IEC1131 declaration of the variables

PROGRAM MAIN
VAR
    PlcVarBool    AT %MX0.0  : BOOL := TRUE;
    PlcVarInt     AT %MW1    : INT := 1234;
    PlcVarString  AT %MD3    : STRING := 'Hello Automation';
END_VAR

C#-Application, the layout :

Consumer in C# to read and write PLC variables 4:

The source-code:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Web.Services.Protocols;    // Catches the SoapExceptions

namespace WebServiceTestConsumer
{
    public class frmWebServiceTestConsumer : System.Windows.Forms.Form
    {
        private System.ComponentModel.Container components = null;

        #region forms
        private System.Windows.Forms.Label lblBool;
        private System.Windows.Forms.Label lblInt;
        private System.Windows.Forms.Label lblString;
        private System.Windows.Forms.TextBox txtBool;
        private System.Windows.Forms.TextBox txtInt;
        private System.Windows.Forms.TextBox txtString;
        private System.Windows.Forms.Button btnRead;
        private System.Windows.Forms.Button btnWrite;
        #endregion

        #region variables and instances

        // Encodes byte-array to Strings and vice versa
        private System.Text.ASCIIEncoding           encoder         =       new     System.Text.ASCIIEncoding();

        // Instance of the TcAdsWebService
        private TcAdsWebService.TcAdsWebService TcWebService    =       new     TcAdsWebService.TcAdsWebService();

        private string  szWebServiceUrl     = "http://192.168.0.2/TcAdsWebService/TcAdsWebService.dll";
        public  string  szAmsNetId              =       "192.168.0.2.1.1";
        public  int         iPort           =       801;
        public  UInt32  iIndexGroup             =       0x4020;

        #endregion


        public frmWebServiceTestConsumer()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            // Links the WebService with its library
            TcWebService.Url = szWebServiceUrl;
        }

        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }


        #region Windows Form Designer generated code
        private void InitializeComponent()
        {
            this.lblBool = new System.Windows.Forms.Label();
            this.lblInt = new System.Windows.Forms.Label();
            this.lblString = new System.Windows.Forms.Label();
            this.txtBool = new System.Windows.Forms.TextBox();
            this.txtInt = new System.Windows.Forms.TextBox();
            this.txtString = new System.Windows.Forms.TextBox();
            this.btnRead = new System.Windows.Forms.Button();
            this.btnWrite = new System.Windows.Forms.Button();
            this.SuspendLayout();
            //
            // lblBool
            //
            this.lblBool.Location = new System.Drawing.Point(40, 24);
            this.lblBool.Name = "lblBool";
            this.lblBool.TabIndex = 0;
            this.lblBool.Text = "VarBool:";
            //
            // lblInt
            //
            this.lblInt.Location = new System.Drawing.Point(40, 80);
            this.lblInt.Name = "lblInt";
            this.lblInt.TabIndex = 1;
            this.lblInt.Text = "VarInt:";
            //
            // lblString
            //
            this.lblString.Location = new System.Drawing.Point(40, 136);
            this.lblString.Name = "lblString";
            this.lblString.TabIndex = 2;
            this.lblString.Text = "VarString:";
            //
            // txtBool
            //
            this.txtBool.Location = new System.Drawing.Point(152, 24);
            this.txtBool.Name = "txtBool";
            this.txtBool.TabIndex = 3;
            this.txtBool.Text = "";
            //
            // txtInt
            //
            this.txtInt.Location = new System.Drawing.Point(152, 80);
            this.txtInt.Name = "txtInt";
            this.txtInt.TabIndex = 4;
            this.txtInt.Text = "";
            //
            // txtString
            //
            this.txtString.Location = new System.Drawing.Point(152, 136);
            this.txtString.Name = "txtString";
            this.txtString.TabIndex = 5;
            this.txtString.Text = "";
            //
            // btnRead
            //
            this.btnRead.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.btnRead.Location = new System.Drawing.Point(48, 216);
            this.btnRead.Name = "btnRead";
            this.btnRead.TabIndex = 6;
            this.btnRead.Text = "&Read";
            this.btnRead.Click += new System.EventHandler(this.btnRead_Click);
            //
            // btnWrite
            //
            this.btnWrite.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.btnWrite.Location = new System.Drawing.Point(168, 216);
            this.btnWrite.Name = "btnWrite";
            this.btnWrite.TabIndex = 7;
            this.btnWrite.Text = "&Write";
            this.btnWrite.Click += new System.EventHandler(this.btnWrite_Click);
            //
            // frmWebServiceTestConsumer
            //
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(292, 266);
            this.Controls.Add(this.lblBool);
            this.Controls.Add(this.lblInt);
            this.Controls.Add(this.lblString);
            this.Controls.Add(this.txtBool);
            this.Controls.Add(this.txtInt);
            this.Controls.Add(this.txtString);
            this.Controls.Add(this.btnRead);
            this.Controls.Add(this.btnWrite);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.Name = "frmWebServiceTestConsumer";
            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            this.Text = "WebServiceTestConsumer";
            this.ResumeLayout(false);

        }
        #endregion

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.Run(new frmWebServiceTestConsumer());
        }



        #region Event-Methods

        private void btnRead_Click(object sender, System.EventArgs e)
        {
            Read();
        }


        private void btnWrite_Click(object sender, System.EventArgs e)
        {
            Write();
        }


        #endregion


        #region Worker-Methods

        private void Read()
        {
            // DataBuffer for the incoming data
            byte[] abDataBuffer = new byte[84]; //1 byte for "PlcVarBool", 2 bytes for "PlcVarInt" and 81 bytes for "PlcVarString" = 84 bytes

            try
            {
                TcWebService.Read(      szAmsNetId, iPort, iIndexGroup, 0, 84, out abDataBuffer);

                // Converts the first byte of the buffer to bool
                bool bVarBool       =       BitConverter.ToBoolean(abDataBuffer, 0);

                // Converts the second and third byte of the buffer to int
                int iVarInt             =       BitConverter.ToInt16(abDataBuffer, 1);

                // Converts the other bytes of the buffer to string
                string szVarString      =       encoder.GetString(abDataBuffer, 3, 81);
            
                // Writes values into the text-boxes
                txtBool.Text = bVarBool.ToString();
                txtInt.Text = iVarInt.ToString();
                txtString.Text = szVarString;
            }
            catch (SoapException ex)
            {
                MessageBox.Show(ex.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        
        private void Write()
        {
            try
            {
                // byte-arrays for the variables
                byte[]  abDataBool          =       new     byte[1];
                byte[]  abDataInt           =       new     byte[2];
                byte[]  abDataString    =       new     byte[81];


                // Gets values for the text-boxes
                bool    bValueBool          =       Convert.ToBoolean(txtBool.Text);
                int         iValueInt           =       Convert.ToInt16(txtInt.Text);
                string  szValueString   =       txtString.Text;


                // Converting variables to byte-arrays
                abDataBool      =       BitConverter.GetBytes(bValueBool);
                abDataInt       =       BitConverter.GetBytes((Int16)iValueInt);
                
                encoder.GetBytes(       szValueString,                          // Source
                                    0,                                          // Position of the first character to convert
                                    encoder.GetByteCount(szValueString),    // Gets the length of the source
                                    abDataString,                           // Byte-array to save the conversion to
                                    0);                                         // First byte in the array to save the conversion to



                // Writing values to PLC
                TcWebService.Write(szAmsNetId, iPort, iIndexGroup, 0, abDataBool);
                TcWebService.Write(szAmsNetId, iPort, iIndexGroup, 1, abDataInt);
                TcWebService.Write(szAmsNetId, iPort, iIndexGroup, 3, abDataString);
            }
            catch (SoapException ex)
            {
                MessageBox.Show(ex.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }


        #endregion
    }
}

Language / IDE

Extract the sample program

Visual C#

Sample01.exe