Event driven reading

Requirements

Visual Studio 2010

TwinCAT ADS WCF 1.1.0.1

Description

Reading symbol data from the PLC by ADS notification callback on symbol change.
The TwinCAT.Ads DLL is used to read the data from the received byte array in an easy to handle way. 

Event driven reading 1:

WPF (C#) application

using System;
using System.Windows;
using TwinCAT.Ads;
using Sample02.TcAdsWcf;
using System.ServiceModel;
using System.Windows.Threading;
using System.Threading;

namespace Sample02
{
    // ConcurrencyMode.Multiple and UseSynchronizationContext = false prevent the GUI from Deadlocks,
    // while waiting for a WCF response on the callback channel.
    [CallbackBehavior (
    ConcurrencyMode = ConcurrencyMode.Multiple,
    UseSynchronizationContext = false )]
    public partial class MainWindow : Window, ITcAdsServiceDuplexCallback
    {
     // If the netid string is empty, the TwinCAT ADS WCF service will use the TwinCAT Runtime on its host machine.
    private const string NETID = "";
    private const int PORT = 801;

    private TcAdsServiceDuplexClient wcfClient;
    private int[] handles = new int [ 7 ];

    public MainWindow ( )
    {
        InitializeComponent ( );

        // Initialize duplex client with NetTcpBinding.
        wcfClient = new TcAdsServiceDuplexClient (
        new InstanceContext ( this ),
        new NetTcpBinding ( SecurityMode.None ),
        new EndpointAddress ( "net.tcp://localhost:4508/TwinCAT/Ads/Wcf/TcAdsService/UnsecNetTcp" ) );

        // Open connection to the WCF service.
        wcfClient.Open ( );
        
        // Subscribe to AdsNotification and AdsNotificationError events.
        wcfClient.SubscribeAdsNotificationEvent ( NETID, PORT );
        wcfClient.SubscribeAdsNotificationErrorEvent ( NETID, PORT );

        // Register device notifications.
        handles [ 0 ] = wcfClient.AddDeviceNotification1 (
        NETID, PORT, "MAIN.boolVal", 1, TcAdsWcf.AdsTransMode.OnChange, 100, 0, null );
        handles [ 1 ] = wcfClient.AddDeviceNotification1 (
        NETID, PORT, "MAIN.intVal", 2, TcAdsWcf.AdsTransMode.OnChange, 100, 0, null );
        handles [ 2 ] = wcfClient.AddDeviceNotification1 (
        NETID, PORT, "MAIN.dintVal", 4, TcAdsWcf.AdsTransMode.OnChange, 100, 0, null );
        handles [ 3 ] = wcfClient.AddDeviceNotification1 (
        NETID, PORT, "MAIN.sintVal", 1, TcAdsWcf.AdsTransMode.OnChange, 100, 0, null );
        handles [ 4 ] = wcfClient.AddDeviceNotification1 (
        NETID, PORT, "MAIN.lrealVal", 8, TcAdsWcf.AdsTransMode.OnChange, 100, 0, null );
        handles [ 5 ] = wcfClient.AddDeviceNotification1 (
        NETID, PORT, "MAIN.realVal", 4, TcAdsWcf.AdsTransMode.OnChange, 100, 0, null );
        handles [ 6 ] = wcfClient.AddDeviceNotification1 (
        NETID, PORT, "MAIN.stringVal", 50, TcAdsWcf.AdsTransMode.OnChange, 100, 0, null );
    }

    #region ITcAdsServiceDuplexCallback Members

    public void AdsNotification ( string netId, int port, byte [ ] buffer, int length, int notificationHandle, int offset, long timeStamp, object userData )
    {
        // Create AdsStream and AdsBinaryReader for buffer handling. 
        AdsStream adsStream = new AdsStream ( buffer );
        AdsBinaryReader binReader = new AdsBinaryReader ( adsStream );
        adsStream.Position = offset;

        // Choose action by notificationHandle value.
        // UI changes have to be invoked, 
        // because the callback methods are called from a background thread.
        if ( notificationHandle == handles [ 0 ] )
        {
        string value = binReader.ReadBoolean ( ).ToString ( );
        Dispatcher.BeginInvoke (
            DispatcherPriority.Input,
            new ThreadStart ( ( ) =>
            {
            tbBool.Text = value;
            } ) );
        }
        else if ( notificationHandle == handles [ 1 ] )
        {
        string value = binReader.ReadInt16 ( ).ToString ( );
        Dispatcher.BeginInvoke (
            DispatcherPriority.Input,
            new ThreadStart ( ( ) =>
            {
            tbInt.Text = value;
            } ) );
        }
        else if ( notificationHandle == handles [ 2 ] )
        {
        string value = binReader.ReadInt32 ( ).ToString ( );
        Dispatcher.BeginInvoke (
            DispatcherPriority.Input,
            new ThreadStart ( ( ) =>
            {
            tbDint.Text = value;
            } ) );
        }
        else if ( notificationHandle == handles [ 3 ] )
        {
        string value = binReader.ReadByte ( ).ToString ( );
        Dispatcher.BeginInvoke (
            DispatcherPriority.Input,
            new ThreadStart ( ( ) =>
            {
            tbSint.Text = value;
            } ) );
        }
        else if ( notificationHandle == handles [ 4 ] )
        {
        string value = binReader.ReadDouble ( ).ToString ( );
        Dispatcher.BeginInvoke (
            DispatcherPriority.Input,
            new ThreadStart ( ( ) =>
            {
            tbLreal.Text = value;
            } ) );
        }
        else if ( notificationHandle == handles [ 5 ] )
        {
        string value = binReader.ReadSingle ( ).ToString ( );
        Dispatcher.BeginInvoke (
            DispatcherPriority.Input,
            new ThreadStart ( ( ) =>
            {
            tbReal.Text = value;
            } ) );
        }
        else if ( notificationHandle == handles [ 6 ] )
        {
        string value = binReader.ReadPlcString ( length );
        Dispatcher.BeginInvoke (
            DispatcherPriority.Input,
            new ThreadStart ( ( ) =>
            {
            tbString.Text = value;
            } ) );
        }
    }

    public void AdsNotificationError ( string netId, int port, Exception error )
    {
        MessageBox.Show ( error.Message );
    }

    public void AdsStateChanged ( string netId, int port, TcAdsWcf.StateInfo state )
    {
        // Not needed
    }

    public void AdsSymbolVersionChanged ( string netId, int port )
    {
        // Not needed
    }

    public void AmsRouterNotification ( string netId, int port, TcAdsWcf.AmsRouterState state )
    {
        // Not needed
    }

    public void HeartBeat ( )
    {
        // Not needed
    }

    #endregion
    }
}

 

TcAdsWcf_Sample02.zip