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: 7.0.0+e56d35ccc4675faac24789a4aab60071fc61d470
Syntax
C#
public class AmsTcpIpRouter : IAmsRouterThe AmsTcpIpRouter type exposes the following members.
Properties
|
|
Name |
Description |
|---|---|---|
|
|
Gets the allowed loopback sources. | |
|
|
Gets the Allowed loopback network. | |
|
|
Gets the used channel type for loopback communication. | |
|
|
The ExternalMode indicates, that a different LoopbackIP/Port is used and not 127.0.0.1:0xBF02 | |
|
|
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. | |
|
|
Gets the UDP discovery port. | |
|
|
Gets the used Unix Domain socket path (UnixSocket | |
|
|
Gets a value indicating whether this router acts like a UserModeRuntime |
Methods
|
|
Name |
Description |
|---|---|---|
|
|
Adds a dynamic Route | |
|
|
Determines whether the used logger is enabled for the specified log level. | |
|
|
Determines whether the specified object is equal to the current object. | |
|
|
Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection. | |
|
|
Serves as the default hash function. | |
|
|
Gets the Type of the current instance. | |
|
|
Determines whether the Address specifies an locally registered AmsServer (uses Loopback connection) | |
|
|
Loads the route information. | |
|
|
Creates a shallow copy of the current Object. | |
|
|
Removes a dynamic Route | |
|
|
Removes a dynamic Route | |
|
|
Starts the AmsTcpIpRouter asynchronously. | |
|
|
Stops the AmsTcpIpRouter. | |
|
|
Returns a string that represents the current object. | |
|
|
Adds a dynamic Route |
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.
- 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 (RouterLoopbackPort)
- 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.
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 RouterLoopbackPort 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 RouterLoopbackPort 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) |
AddStaticRoutesXmlConfiguration(IConfigurationBuilder, ILoggerFactory) |
|
Json Configuration (appSettings.json) |
Microsoft.Extensions.Configuration.JsonConfigurationExtensions.AddJsonFile(string) |
|
Environment variables |
Microsoft.Extensions.Configuration.EnvironmentVariablesExtensions.AddEnvironmentVariables() |
|
ConsoleArguments |
Microsoft.Extensions.Configuration.CommandLineConfigurationExtensions.AddCommandLine(string[]) |
Example
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);
// Create a configuration for the custom logger
// var loggerConfig = new AdsLoggerConfiguration
// {
// LogLevel = Environment.GetEnvironmentVariable("Logging:LogLevel:Default");
// EventId = 0
// };
//var loggerConfig = AdsLoggerConfiguration.CreateFromEnvironment();
//var loggerConfig2 = AdsLoggerConfiguration.CreateFromConfiguration();
// // Create an ILoggerFactory and add the custom logger provider
// var loggerFactory = LoggerFactory.Create(builder =>
// {
// builder.SetMinimumLevel(LogLevel.Information)
// .AddProvider(new AdsLoggerProvider(() => loggerConfig));
// });
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.AddEnvironmentVariables(""); // Use Environment variables
//config.AddCommandLine(args); // Use Command Line
//config.AddJsonFile("appSettings.Development.json"); // Use Appsettings
//config.AddStaticRoutesXmlConfiguration(); // Overriding settings with StaticRoutes.Xml
})
.ConfigureLogging((context,logging) =>
{
logging.ClearProviders();
var loggerConfig = AdsLoggerConfiguration.CreateFromEnvironment();
logging.AddProvider(new AdsLoggerProvider(() => loggerConfig));
// Adding console logging here.
//var loggerConfig = AdsLoggerConfiguration.CreateFromConfiguration(context.Configuration);
//logging.AddProvider(new AdsLoggerProvider(() => loggerConfig));
// Too inefficient!
//logging.AddProvider(new AdsLoggerProvider(() => AdsLoggerConfiguration.CreateFromEnvironment()));
//logging.AddProvider(new AdsLoggerProvider(() => loggerConfig));
logging.SetMinimumLevel(LogLevel.Debug);
});
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
{
private readonly ILoggerFactory _loggerFactory;
/// <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="loggerFactory">The logger factory.</param>
/// <param name="configuration">The configuration.</param>
public RouterService(IConfiguration configuration, ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
_logger = loggerFactory.CreateLogger<RouterService>();
_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(_configuration, _loggerFactory);
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, _loggerFactory);
AdsRouterServer adsRouterService = new AdsRouterServer(router, _loggerFactory);
//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.
}
}
}See Also
Reference
TwinCAT.Ads.TcpRouter Namespace RouteConfig AmsConfiguration
Beckhoff Automation GmbH & Co. KG 2001-2026
- AmsTcpIpRouter.ChannelPortType Property
- AmsTcpIpRouter.ExternalMode Property
- AmsTcpIpRouter.UdpDiscoveryPort Property
- AmsTcpIpRouter.UnixDomainSocketPath Property
- ChannelPortType Enumeration
- AmsTcpIpRouter.UserModeRuntime Property
- AmsTcpIpRouter.CanLog Method
- AmsConfiguration.RouterLoopbackPort Property
- RouteConfig Class