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 |
---|---|---|
|
Initializes a new instance of the AmsTcpIpRouter class. | |
|
Initializes a new instance of the AmsTcpIpRouter class. | |
|
Initializes a new instance of the AmsTcpIpRouter class. | |
|
Initializes a new instance of the AmsTcpIpRouter class. | |
|
AmsTcpIpRouter(AmsNetId, Int32, IPAddress, Int32, .IPAddress., ILogger) |
Initializes a new instance of the AmsTcpIpRouter class. |
|
AmsTcpIpRouter(AmsNetId, Int32, IPAddress, Int32, IPNetwork, ILogger) |
Initializes a new instance of the AmsTcpIpRouter class. |
Properties
|
Name |
Description |
---|---|---|
|
Gets the allowed loopback sources. | |
|
Gets the Allowed loopback network. | |
|
Gets a value indicating whether the IAmsRouter is active (Running or in Starting / Stopping state). | |
|
Gets a value indicating whether the IAmsRouter is running (Start phase completely finished). | |
|
Gets the local AmsNetId | |
|
Gets the logger interface | |
|
Gets the loopback alias | |
|
Gets the loopback port for internal Loopback communnciation (default is 0xBF02) | |
|
The Local AmsNetId of this router. | |
|
Gets the router status. | |
|
Gets a read-only list of the routes | |
|
Gets the used TCP IP Port for External communication. |
Methods
|
Name |
Description |
---|---|---|
|
Adds a dynamic Route | |
|
Determines whether the specified object is equal to the current object. (Inherited from Object.) | |
|
Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection. (Inherited from Object.) | |
|
Serves as the default hash function. (Inherited from Object.) | |
|
Gets the Type of the current instance. (Inherited from Object.) | |
|
Determines whether the Address specifies an locally registered AmsServer | |
|
Loads the route information. | |
|
Creates a shallow copy of the current Object. (Inherited from Object.) | |
|
Removes a dynamic Route | |
|
Removes a dynamic Route | |
|
Starts the AmsTcpIpRouter asynchronously. | |
|
Stops the AmsTcpIpRouter. | |
|
Returns a string that represents the current object. (Inherited from Object.) | |
|
Adds a dynamic Route |
Fields
|
Name |
Description |
---|---|---|
|
The default TCP port (0xBF02, 48898) | |
|
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
- One for the machine internal communication between AdsClients and AdsServers. This is called the **ADS Loopback** port and has by default the IPAddress.Loopback (172.0.0.1) and Port 0xBF02 (DEFAULT_TCP_PORT)
- The other that routes the machine external communication to other TwinCAT ADS routers. This **ADS External Channel** is opened by default on every available IPAddress connected to a Network again on default Port 0xBF02. A **StaticRoutes** table (e.g. the StaticRoutes.xml of every TwinCAT System) is used to ensure security and maintain the list of remote target systems.
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. |
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 |
The TCP Port to be used for external ADS communication (**ADS External channel**) |
0xBF02 (48898) | |
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) |
The TCP Port to be used for external ADS communication (**ADS External channel**) |
0xBF02 (48898) | |
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) | |
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.
}
}
}