AmsTcpIpRouter Class

ADS Router class

Inheritance Hierarchy

System.Object
  TwinCAT.Ads.TcpRouter.AmsTcpIpRouter
Namespace:  TwinCAT.Ads.TcpRouter
Assembly:  TwinCAT.Ads.TcpRouter (in TwinCAT.Ads.TcpRouter.dll) Version: 6.0.328+39e3229

Syntax

C#

public class AmsTcpIpRouter : IAmsRouter

The AmsTcpIpRouter type exposes the following members.

Constructors

 

Name

Description

AmsTcpIpRouter Class 1:

AmsTcpIpRouter(AmsNetId)

Initializes a new instance of the AmsTcpIpRouter class.

AmsTcpIpRouter Class 2:

AmsTcpIpRouter(IConfiguration)

Initializes a new instance of the AmsTcpIpRouter class.

AmsTcpIpRouter Class 3:

AmsTcpIpRouter(AmsNetId, ILogger)

Initializes a new instance of the AmsTcpIpRouter class.

AmsTcpIpRouter Class 4:

AmsTcpIpRouter(ILogger, IConfiguration)

Initializes a new instance of the AmsTcpIpRouter class.

AmsTcpIpRouter Class 5:

AmsTcpIpRouter(AmsNetId, Int32, IPAddress, Int32, .IPAddress., ILogger)

Initializes a new instance of the AmsTcpIpRouter class.

AmsTcpIpRouter Class 6:

AmsTcpIpRouter(AmsNetId, Int32, IPAddress, Int32, IPNetwork, ILogger)

Initializes a new instance of the AmsTcpIpRouter class.

Properties

 

Name

Description

AmsTcpIpRouter Class 7:

AcceptedLoopbackIPs

Gets the allowed loopback sources.

AmsTcpIpRouter Class 8:

AcceptedLoopbackNetwork

Gets the Allowed loopback network.

AmsTcpIpRouter Class 9:

IsActive

Gets a value indicating whether the IAmsRouter is active (Running or in Starting / Stopping state).

AmsTcpIpRouter Class 10:

IsRunning

Gets a value indicating whether the IAmsRouter is running (Start phase completely finished).

AmsTcpIpRouter Class 11:

AmsTcpIpRouter Class 12:

LocalNetId

Gets the local AmsNetId

AmsTcpIpRouter Class 13:

Logger

Gets the logger interface

AmsTcpIpRouter Class 14:

Loopback

Gets the loopback alias

AmsTcpIpRouter Class 15:

LoopbackPort

Gets the loopback port for internal Loopback communnciation (default is 0xBF02)

AmsTcpIpRouter Class 16:

NetId

The Local AmsNetId of this router.

AmsTcpIpRouter Class 17:

RouterStatus

Gets the router status.

AmsTcpIpRouter Class 18:

Routes

Gets a read-only list of the routes

AmsTcpIpRouter Class 19:

TcpIpPort

Gets the used TCP IP Port for External communication.

Methods

 

Name

Description

AmsTcpIpRouter Class 20:

AddRoute

Adds a dynamic Route

AmsTcpIpRouter Class 21:

Equals

Determines whether the specified object is equal to the current object. (Inherited from Object.)

AmsTcpIpRouter Class 22:

Finalize

Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection. (Inherited from Object.)

AmsTcpIpRouter Class 23:

GetHashCode

Serves as the default hash function. (Inherited from Object.)

AmsTcpIpRouter Class 24:

GetType

Gets the Type of the current instance. (Inherited from Object.)

AmsTcpIpRouter Class 25:

IsRegisteredServer

Determines whether the Address specifies an locally registered AmsServer

AmsTcpIpRouter Class 26:

LoadRouteInfo

Loads the route information.

AmsTcpIpRouter Class 27:

MemberwiseClone

Creates a shallow copy of the current Object. (Inherited from Object.)

AmsTcpIpRouter Class 28:

RemoveRoute(AmsNetId)

Removes a dynamic Route

AmsTcpIpRouter Class 29:

RemoveRoute(String)

Removes a dynamic Route

AmsTcpIpRouter Class 30:

StartAsync

Starts the AmsTcpIpRouter asynchronously.

AmsTcpIpRouter Class 31:

Stop

Stops the AmsTcpIpRouter.

AmsTcpIpRouter Class 32:

ToString

Returns a string that represents the current object. (Inherited from Object.)

AmsTcpIpRouter Class 33:

TryAddRoute

Adds a dynamic Route

Events

 

Name

Description

AmsTcpIpRouter Class 34:

RouterStatusChanged

Occurs when the router status changes.

Fields

 

Name

Description

AmsTcpIpRouter Class 35:

AmsTcpIpRouter Class 36:

DEFAULT_TCP_PORT

The default TCP port (0xBF02, 48898)

AmsTcpIpRouter Class 37:

AmsTcpIpRouter Class 38:

TCP_TIMEOUT

The TCP timeout

Remarks

The AmsTcpIpRouter implements a simple ADS/AMS Router for systems, where no TwinCAT Router installation is available.

The Router opens two different type of communication channels

With this infrastructure, the AmsTcpIpRouter is able to process ADS/AMS communication in form of ADS Requests and Responses not only isolated on the local system, but also between the local system and remote systems as long they are properly configured.

For sophisticated scenarious, the default configurations can be changed to also support more than one router on one system and/or split Client/Server/Router applications in virtual environments like docker.

Property Name

Description

Default

Name

The name of the local system.

No default, must be set.

LocalNetId

The AmsNetId of the local system.

No default, must be set.

RemoteConnections

List of the registered remote Routes / Systems that can be reached remotely.

None/Empty

TcpIpPort

The TCP Port to be used for external ADS communication (**ADS External channel**)

0xBF02 (48898)

Loopback

The LoopbackIP of Device internal communication. This setting should only be changed if ADS Server and Router application should run on different (virtual) devices. On the AdsServer side an appropriate system configuration via RouterEndPoint is necessary if the LoopackIP is changed.

Loopback 127.0.0.1

LoopbackPort

The Loopback Port of Device internal ADS communication. This setting should only be changed when different TcpPorts are necessary to seperate internal and external router communcation (e.g. in WSL2 docker containers) where the LoopbackIP 127.0.0.1 isn't appropiate. On the AdsServer side an appropriate system configuration via RouterEndPoint is necessary if the loopback port is changed.

0xBF02 (48898)

AcceptedLoopbackIPs

The TCP Port to be used for external ADS communication (**ADS External channel**)

0xBF02 (48898)

AcceptedLoopbackNetwork

The TCP Port to be used for external ADS communication (**ADS External channel**)

0xBF02 (48898)

The router settings can be configured by the .NET Configuration Builder IConfigurationBuilder or simply by calling one of the AmsTcpIpRouter constructor overloads.

Xml Configuration (StaticRoutes.xml)

AddStaticRoutesXmlConfiguration(IConfigurationBuilder)

Json Configuration (appSettings.json)

Microsoft.Extensions.Configuration.JsonConfigurationExtensions.AddJsonFile(string)

Environment variables

Microsoft.Extensions.Configuration.EnvironmentVariablesExtensions.AddEnvironmentVariables()

ConsoleArguments

Microsoft.Extensions.Configuration.CommandLineConfigurationExtensions.AddCommandLine(string[])

Examples

The following sample shows how to use the AmsTcpIpRouter class within an own Console application. This console application can also be accessed as binary from the Nuget.org package repository. The ID of the package is 'Beckhoff.TwinCAT.Ads.AdsRouterConsole'.

Ads Router WorkerService

class Program
{
    /// <summary>
    /// Defines the entry point of the application.
    /// </summary>
    /// <param name="args">The arguments.</param>
    public static void Main(string[] args)
    {
    try
    {
        CreateHostBuilder(args).Build().Run();
    }
    catch (OperationCanceledException /*cex*/)
    {
        Console.WriteLine("Router cancelled!");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Router failed with '{ex.Message}'");
    }
    }

    /// <summary>
    /// Creates the host builder.
    /// </summary>
    /// <param name="args">The arguments.</param>
    /// <returns>IHostBuilder.</returns>
    public static IHostBuilder CreateHostBuilder(string[] args) 
    {
        var ret = Host.CreateDefaultBuilder(args);

        ret.ConfigureServices((hostContext, services) =>
        {
        services.AddHostedService<RouterService>();
        })
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
        // Add further AppConfigurationProvider here.
        //config.Sources.Clear(); // Clear all default config sources 
        config.AddEnvironmentVariables("ENV_"); // Use Environment variables
        //config.AddCommandLine(args); // Use Command Line
        //config.AddJsonFile("appSettings.Development.json"); // Use Appsettings
        //config.AddStaticRoutesXmlConfiguration(); // Overriding settings with StaticRoutes.Xml 
        })
        .ConfigureLogging(logging =>
        {
        //logging.ClearProviders();
        // Adding console logging here.
        //logging.AddConsole();
        });
        return ret;
    }
}

/// <summary>
/// The RouterService instance represents a long running (hosted) service that implements an <see cref="AmsTcpIpRouter"/>.
/// Implements the <see cref="BackgroundService" />
/// </summary>
/// <remarks>
/// Long running Background task that runs a <see cref="AmsTcpIpRouter."/>.
/// The service is stopped via the <see cref="CancellationToken"/> given to the <see cref="ExecuteAsync(CancellationToken)"/> method.
/// </remarks>
/// <seealso cref="BackgroundService" />
public class RouterService : BackgroundService
{
    /// <summary>
    /// Logger
    /// </summary>
    private readonly ILogger<RouterService> _logger;
    /// <summary>
    /// Configuration
    /// </summary>
    private readonly IConfiguration _configuration;

    /// <summary>
    /// Initializes a new instance of the <see cref="RouterService"/> class.
    /// </summary>
    /// <param name="logger">The logger.</param>
    /// <param name="configuration">The configuration.</param>
    public RouterService(ILogger<RouterService> logger, IConfiguration configuration)
    {
    _logger = logger;
    _configuration = configuration;
    string? value = _configuration.GetValue("ASPNETCORE_ENVIRONMENT", "Production");
    }

    /// <summary>
    /// Execute the Router asynchronously as <see cref="BackgroundService"/>.
    /// </summary>
    /// <param name="cancel">The cancellation token.</param>
    protected override async Task ExecuteAsync(CancellationToken cancel)
    {
    AmsTcpIpRouter router;

    using (_logger.BeginScope("Starting"))
    {
        StringBuilder appCommon = new StringBuilder();

        appCommon.AppendLine($"ApplicationPath: {Environment.GetCommandLineArgs()[0]}");
        appCommon.AppendLine($"BaseDirectory: {AppContext.BaseDirectory}");
        appCommon.AppendLine($"CurrentDirectory: {Directory.GetCurrentDirectory()}");
        //_logger.LogInformation(sB.ToString());

        StringBuilder config = new StringBuilder();
        string value = _configuration.GetValue("ASPNETCORE_ENVIRONMENT", "Production");
        config.AppendLine($"ASPNETCORE_ENVIRONMENT: {value}");

        Console.WriteLine("Application Directories");
        Console.WriteLine("=======================");
        Console.WriteLine(appCommon);
        Console.WriteLine("");
        Console.WriteLine("Configuration");
        Console.WriteLine("=============");
        Console.WriteLine(config);
        Console.WriteLine("");

        Console.WriteLine("Press Ctrl + C to shutdown!");

        router = new AmsTcpIpRouter(_logger, _configuration);
        router.RouterStatusChanged += Router_RouterStatusChanged;

        // Use this overload to instantiate a Router without support of IHost/IConfigurationProvider support and parametrize by code
        // AmsTcpIpRouter router = new AmsTcpIpRouter(new AmsNetId("1.2.3.4.5.6"), AmsTcpIpRouter.DEFAULT_TCP_PORT,IPAddress.Loopback,AmsTcpIpRouter.DEFAULT_TCP_PORT,_logger);
        // router.AddRoute(...);

        _logger.LogInformation(appCommon.ToString());
        _logger.LogInformation(config.ToString());
    }

    Task routerTask = router.StartAsync(cancel); // Start the router

    //#if ADSSERVER
    // AdsServer could be started here:
    SystemServiceServer systemService = new SystemServiceServer(router, _logger);
    AdsRouterServer adsRouterService = new AdsRouterServer(router, _logger);

    //TestAdsServer testServer = new TestAdsServer(_logger);
    //_logger.LogInformation($"Adding Test Server on port '{systemService.ServerAddress}'");
    Task systemServiceTask = systemService.ConnectServerAndWaitAsync(cancel);
    Task routerServerTask = adsRouterService.ConnectServerAndWaitAsync(cancel);

    await Task.WhenAll(routerTask, systemServiceTask, routerServerTask);

    //await routerTask;
    //#endif
    }

    /// <summary>
    /// Handles the RouterStatusChanged event of the <see cref="AmsTcpIpRouter"/>
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="RouterStatusChangedEventArgs"/> instance containing the event data.</param>
    private void Router_RouterStatusChanged(object? sender, RouterStatusChangedEventArgs e)
    {
    if (e.RouterStatus == RouterStatus.Started)
    {
        // From here on, the Router is available to receive Data.
    }
    }
}

Reference

TwinCAT.Ads.TcpRouter Namespace

RouteConfig

TwinCAT.Ams.AmsConfiguration