AdsServer Class
Base implementation for an ADS Server.
Inheritance Hierarchy
System.Object
TwinCAT.Ads.Server.AdsServer
TwinCAT.Ads.Server.AdsSymbolicServer
Namespace: TwinCAT.Ads.Server
Assembly: TwinCAT.Ads.Server (in
TwinCAT.Ads.Server.dll) Version: 6.0.328+39e3229
Syntax
C#
public abstract class AdsServer : IDisposable
The AdsServer type exposes the following members.
Properties
|
Name |
Description |
---|---|---|
|
Gets the the internal AmsServer object. | |
|
Gets a value indicating whether AdsServer is connected. | |
|
Indicates, that the AdsServer is actually disconnecting. | |
|
Gets a value indicating whether this instance is disposed. | |
|
Gets a value indicating this AdsServer has a dynamic/unfixed port. | |
|
Gets the logger object. | |
|
The AMS address of this server. | |
|
Gets the name of the server. | |
|
Gets the server port. | |
|
Gets the Version of the Server. |
Methods
|
Name |
Description |
---|---|---|
|
Sends an ADS Add Device Notification request (synchronous). | |
|
Sends an ADS Add Device Notification request (async) | |
|
Sends an ADS Add Device Notification response. | |
|
Connect this ADS server to the local ADS router. | |
|
Registers the AdsServer at the router asynchronously. | |
|
Sends an ADS Delete Device Notification request (synchronous). | |
|
Sends an ADS Delete Device Notification request (async). | |
|
Sends an ADS Delete Device Notification response. | |
|
Sends an ADS Device Notification request asynchronously | |
|
Sends an ADS Device Notification request (sync) | |
|
Disconnects this ADS server from the local ADS router. | |
|
Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. | |
|
Releases unmanaged and - optionally - managed resources. | |
|
Determines whether the specified object is equal to the current object. (Inherited from Object.) | |
|
Finalizes an instance of the AdsServer class. (Overrides Object.Finalize..) | |
|
Serves as the default hash function. (Inherited from Object.) | |
|
Gets the name of the server. | |
|
Gets the Type of the current instance. (Inherited from Object.) | |
|
Creates a shallow copy of the current Object. (Inherited from Object.) | |
|
Called when an ADS Add Device Notification indication is received. | |
|
Called when an ADS Add Device Notification confirmation is received. | |
|
Handler function that is called, when the AdsServer is connected, but before calling OnConnected.. | |
|
Handler function that is called, when the AdsServer is connected. | |
|
Called when an ADS Delete Device Notification indication is received. | |
|
Called when an ADS Delete Device Notification confirmation is received. | |
|
Called when the AdsServer is about to be disconnected. | |
|
Called when an ADS Read indication is received. | |
|
Called when an ADS Read confirmation is received. | |
|
Called when an ADS Read Device Info confirmation is received. | |
|
Called when an ADS Read State indication is received. | |
|
Called when an ADS Read State confirmation is received. | |
|
Called when an ADS Read Write indication is received. | |
|
Called when an ADS Read Write confirmation is received. | |
|
Handler Function for a Router Notification. | |
|
Handles the ServerConnectionStateChanged event. | |
|
Called when an ADS Write indication is received. | |
|
Called when an ADS Write confirmation is received. | |
|
Called when an ADS Write Control indication is received. | |
|
Called when an ADS Write Control confirmation is received. | |
|
Sends an ADS Read Device Info request asynchronously | |
|
Sends an ADS Read Device Info request synchronously. | |
|
Sends an ADS Read Device Info response. | |
|
Sends an ADS Read State request (asynchronous) | |
|
Sends an ADS Read State request (synchronous) | |
|
Sends an ADS Read State response. | |
|
Sends an ADS Read Request. | |
|
Sends an ADS Read Request asynchronously. | |
|
Sends an ADS Read response. | |
|
Sends an ADS Read Write request. | |
|
Sends an ADS Read Write request synchronously | |
|
Sends an ADS Read Write Response. | |
|
Returns a string that represents the current object. (Inherited from Object.) | |
|
Sends an ADS Write Control request (synchronous) | |
|
Sends an ADS Write Control request (asynchronous). | |
|
Sends an ADS Write Control request (synchronous). | |
|
Sends an ADS Write Control response. | |
|
Sends an ADS Write request synchronously. | |
|
Sends an ADS Write request asynchronously. | |
|
Sends an ADS Write response. |
Remarks
Derived classes should overwrite the AMS indication methods to react on incoming requests. AMS The confirmation methods should be overwritten to receive replies on asynchronous requests sent by this ADS server.
Examples
The following sample shows how to derive from the AdsServer class and create your own Customized ADS Server.
C#
class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<ServerWorker>();
});
}
C#
public class ServerWorker : BackgroundService
{
private readonly ILogger<ServerWorker> _logger;
public ServerWorker(ILogger<ServerWorker> logger)
{
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken cancel)
{
// Instantiate the server
AdsSampleServer server = new AdsSampleServer(_logger);
// Connect the server and wait for cancel
await server.ConnectServerAndWaitAsync(cancel);
}
}
C#
/*
* Extend the AdsServer class to implement your own ADS server.
*/
public class AdsSampleServer : AdsServer
{
/// <summary>
/// Fixed ADS Port (to be changed ...)
/// </summary>
const ushort ADS_PORT = 42;
/// <summary>
/// Fixed Name for the ADS Port (change this ...)
/// </summary>
const string ADS_PORT_NAME = "AdsSampleServer_Port42";
/// <summary>
/// Some simple data / ProcessImage
/// </summary>
private byte[] _dataBuffer = {1, 2, 3, 4};
/// <summary>
/// Ads State
/// </summary>
private AdsState _adsState = AdsState.Config;
/// <summary>
/// Device State
/// </summary>
private ushort _deviceState = 0;
/// <summary>
/// Notification dictionary, thread safe
/// </summary>
private ConcurrentDictionary<uint, NotificationRequestEntry> _notificationTable = new ConcurrentDictionary<uint, NotificationRequestEntry>();
/// <summary>
/// Simple counter for different Notification handles here.
/// </summary>
private uint _currentNotificationHandle = 0;
/// <summary>
/// Logger
/// </summary>
private ILogger _logger;
/* Instantiate an ADS server with a fix ADS port assigned by the ADS router.
*/
public AdsSampleServer()
: this(null)
{
}
public AdsSampleServer(ILogger logger) : base(ADS_PORT, ADS_PORT_NAME)
{
base.serverVersion = new Version(0, 0, 1);
_logger = logger;
}
/* Overwrite the indication handlers of the AdsServer class for the services your ADS server
* provides. They are called upon incoming requests. Indications that are not overwritten in
* this class return the ADS DeviceServiceNotSupported error code to the requester.
*/
/* Handler function for Write Indication */
protected override Task<ResultWrite> OnWriteAsync(AmsAddress target, uint invokeId, uint indexGroup, uint indexOffset, ReadOnlyMemory<byte> writeData, CancellationToken cancel)
{
ResultWrite result;
switch (indexGroup) /* use index group (and offset) to distinguish between the services
of this server */
{
case 0x10000:
if (writeData.Length == 4)
{
writeData.CopyTo(_dataBuffer);
result = ResultWrite.CreateSuccess();
}
else
{
result = ResultWrite.CreateError(AdsErrorCode.DeviceInvalidSize);
}
break;
case 0x20000: /* used for the PLC Sample */
if (writeData.Length == 4)
{
uint value = BinaryPrimitives.ReadUInt32LittleEndian(writeData.Span);
result = ResultWrite.CreateSuccess();
}
else
{
result = ResultWrite.CreateError(AdsErrorCode.DeviceInvalidSize);
}
break;
default: /* other services are not supported */
result = ResultWrite.CreateError(AdsErrorCode.DeviceServiceNotSupported);
break;
}
return Task.FromResult(result);
}
/* Handler function for Read Indication */
protected override Task<ResultReadBytes> OnReadAsync(AmsAddress target, uint invokeId, uint indexGroup, uint indexOffset, int readLength, CancellationToken cancel)
{
ResultReadBytes result;
/* Distinguish between services like in OnWriteAsync */
result = ResultReadBytes.CreateSuccess(_dataBuffer.AsMemory());
// or Error with ErrorCode
// result = ResultReadBytes.CreateError(AdsErrorCode.DeviceNotSupported);
return Task.FromResult(result);
}
/* Handler function for ReadWrite Indication */
protected override Task<ResultReadWriteBytes> OnReadWriteAsync(AmsAddress target, uint invokeId, uint indexGroup, uint indexOffset, int readLength, ReadOnlyMemory<byte> writeData, CancellationToken cancel)
{
ResultReadWriteBytes result;
/* Distinguish between services like in AdsWriteInd */
if (readLength == 4 && writeData.Length == 4)
{
result = ResultReadWriteBytes.CreateSuccess(_dataBuffer.AsMemory(0, 4));
}
else
{
result = ResultReadWriteBytes.CreateError(AdsErrorCode.DeviceInvalidSize);
}
return Task.FromResult(result);
}
/* Handler function for ReadDeviceState Indication */
protected override Task<ResultReadDeviceState> OnReadDeviceStateAsync(AmsAddress target, uint invokeId, CancellationToken cancel)
{
StateInfo state = new StateInfo(_adsState, _deviceState);
ResultReadDeviceState result = ResultReadDeviceState.CreateSuccess(state);
return Task.FromResult(result);
}
/* Handler function for WriteControl Indication */
protected override Task<ResultAds> OnWriteControlAsync(AmsAddress target, uint invokeId, AdsState adsState, ushort deviceState, ReadOnlyMemory<byte> data, CancellationToken cancel)
{
// Set requested ADS and device status
_adsState = adsState;
_deviceState = deviceState;
ResultAds result = ResultAds.CreateSuccess();
return Task.FromResult(result);
}
/* Handler function for AddDeviceNotification Indication */
protected override Task<ResultHandle> OnAddDeviceNotificationAsync(AmsAddress target, uint invokeId, uint indexGroup, uint indexOffset, int dataLength, AmsAddress receiver, NotificationSettings settings, CancellationToken cancel)
{
/* Create a new notification entry an store it in the notification table */
NotificationRequestEntry notEntry = new NotificationRequestEntry(receiver, indexGroup, indexOffset, dataLength, settings);
_notificationTable.AddOrUpdate(_currentNotificationHandle, notEntry, (key, value) => notEntry);
ResultHandle result = ResultHandle.CreateSuccess(_currentNotificationHandle);
_currentNotificationHandle++;
return Task.FromResult(result);
}
/* Handler function for DeleteDeviceNotification Indication */
protected override Task<ResultAds> OnDeleteDeviceNotificationAsync(AmsAddress target, uint invokeId, uint hNotification, CancellationToken cancel)
{
ResultAds result;
/* check if the requested notification handle is still in the notification table */
if (_notificationTable.ContainsKey(hNotification))
{
NotificationRequestEntry entry = null;
_notificationTable.TryRemove(hNotification, out entry);
result = ResultAds.CreateSuccess();
}
else // notification handle is not in the notification table -> return an error code
// to the requester
{
result = ResultAds.CreateError(AdsErrorCode.DeviceNotifyHandleInvalid);
}
return Task.FromResult(result);
}
/* Handler function for DeviceNotification Indication */
protected override Task<ResultAds> OnDeviceNotificationAsync(AmsAddress sender, NotificationSamplesStamp[] stampHeaders, CancellationToken cancel)
{
/*
* Call notification handlers.
*/
return Task.FromResult(ResultAds.CreateSuccess());
}
}
/// <summary>
/// AdsSampleServer Notification request entry
/// </summary>
internal class NotificationRequestEntry
{
private AmsAddress _sender; // the AmsNetId of the requester
private uint _indexGroup; // the requested index group
private uint _indexOffset; // the requested index offset
private int _length; // the number of bytes to send
NotificationSettings _settings; // the notification settings
internal NotificationRequestEntry(AmsAddress sender,
uint indexGroup,
uint indexOffset,
int dataLength,
NotificationSettings settings)
{
_sender = sender;
_indexGroup = indexGroup;
_indexOffset = indexOffset;
_length = dataLength;
_settings = settings;
}
}