A class for handling TwinCAT ADS protocol communication.

Settings are provided in constructor - see Client.constructor and AdsClientSettings.

A client instance should be created for each target. However, a single client instance can also be used to communicate with multiple endpoints using the targetOpts parameter available in all methods.

Client also emits different events, such as client.on('connect', ...). See AdsClientEvents for all available events.

const client = new Client({
targetAmsNetId: "192.168.4.1.1.1",
targetAdsPort: 851
});

Hierarchy

Constructors

  • Creates a new ADS client instance.

    Settings are provided in settings parameter - see AdsClientSettings.

    Parameters

    Returns Client

    const client = new Client({
    targetAmsNetId: "192.168.4.1.1.1",
    targetAdsPort: 851
    });

Properties

connection: AdsClientConnection = ...

Active connection information.

See AdsClientConnection

metaData: ConnectionMetaData = ...

Active connection metadata.

Metadata includes target device information, symbols, data types and so on.

Some properties might not be available in all connection setups and setting combinations.

settings: Required<AdsClientSettings> = ...

Active client settings.

You can change some settings directly from this object on the fly, mainly some non-communication related ones.

If the client is not yet connected, it's OK to change all settings from here.

However, the most correct way is to use the Client.constructor.

client.settings.convertDatesToJavascript = false; //OK
client.settings.targetAdsPort = 852; //Not OK if already connected (some things might break)

Accessors

  • get debugLevel(): Readonly<DebugLevel>
  • Active debug level (read-only).

    Use Client.setDebugLevel for setting debug level.

    Debug levels:

    • 0: no debugging (default)
    • 1: basic debugging ($env:DEBUG='ads-client')
    • 2: detailed debugging ($env:DEBUG='ads-client,ads-client:details')
    • 3: detailed debugging with raw I/O data ($env:DEBUG='ads-client,ads-client:details,ads-client:raw-data')

    Debug data is available in the console (See Debug library for mode).

    Returns Readonly<DebugLevel>

Methods

  • Caches all data types from the target PLC runtime.

    Can be used to pre-cache all data types to speed up communication. Caching is only available for the original target configured in the settings.

    If caching is disabled using settings.disableCaching nothing is done.

    Calling getDataTypes() without targetOpts has the same effect.

    NOTE: This requires that the target is a PLC runtime or has equivalent ADS protocol support.

    Returns Promise<void>

    try {
    await client.cacheDataTypes();
    //client.metaData.plcDataTypes now has all PLC runtime data types
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Caches all symbols from the target PLC runtime.

    Can be used to pre-cache all symbols to speed up communication. Caching is only available for the original target configured in the settings.

    If caching is disabled using settings.disableCaching nothing is done.

    Calling getSymbols() without targetOpts has the same effect.

    NOTE: This requires that the target is a PLC runtime or has equivalent ADS protocol support.

    Returns Promise<void>

    try {
    await client.cacheSymbols();
    //client.metaData.plcSymbols now has all PLC runtime symbols
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Connects to the target that is configured in Client.settings (set in Client.constructor).

    If success, returns the connection information (see AdsClientConnection)

    Returns Promise<Required<AdsClientConnection>>

    Throws an error if connecting fails

    try {
    const res = await client.connect();

    console.log(`Connected to the ${res.targetAmsNetId}`);
    console.log(`Router assigned us AmsNetId ${res.localAmsNetId} and port ${res.localAdsPort}`);
    } catch (err) {
    console.log("Connecting failed:", err);
    }
  • Converts raw data to a Javascript object by using the provided data type.

    Type Parameters

    • T = any

      Typescript data type of the PLC data, for example convertFromRaw<number>(...) or convertFromRaw<ST_TypedStruct>(...)

    Parameters

    • data: Buffer

      Raw data (acquired for example using readRaw())

    • dataType: string | AdsDataType

      Data type name in the PLC as string (such as ST_Struct) or data type object (acquired using getDataType())

    • Optionalattributes: AdsAttributeEntry[]

      Additional attributes of the symbol or data type used for conversion

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<T>

    try {
    const data = await client.readRaw(16448, 414816, 2);
    console.log(data); //<Buffer ff 7f>

    const converted = await client.convertFromRaw(data, 'INT');
    console.log(converted); //32767

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Converts a Javascript object to raw data by using the provided data type.

    NOTE: Do not use autoFill for UNION types, it doesn't work correctly.

    Parameters

    • value: any

      Value to convert

    • dataType: string | AdsDataType

      Data type name in the PLC as string (such as ST_Struct) or data type object (acquired using getDataType())

    • autoFill: boolean = false

      autoFill If set and the data type is a container (STRUCT, FUNCTION_BLOCK etc.), missing properties are automatically set to default values (0 or empty string).

    • Optionalattributes: AdsAttributeEntry[]

      Additional attributes of the symbol or data type used for conversion

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<Buffer>

    try {
    const data = await client.convertToRaw(32767, 'INT');
    console.log(data); //<Buffer ff 7f>

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Creates a handle to a variable at the target system by variable path (such as GVL_Test.ExampleStruct).

    The handle can be then used for reading and writing the value.

    Reading and writing dereferenced POINTER and REFERENCE values is also possible. See readRawByHandle() and writeRawByHandle().

    NOTE: The handle should be deleted after it's no longer needed, as there is a limited amount of handles available. See deleteVariableHandle().

    Parameters

    • path: string

      Variable path in the PLC to read (such as GVL_Test.ExampleStruct)

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<VariableHandle>

    try {
    //POINTER value (Note the dereference operator ^)
    const handle1 = await client.createVariableHandle('GVL_Read.ComplexTypes.POINTER_^');
    const value = await client.readRawByHandle(handle1);
    await client.deleteVariableHandle(handle1);

    const handle2 = await client.createVariableHandle('GVL_Read.StandardTypes.INT_');
    const value2 = await client.readRawByHandle(handle2);
    await client.deleteVariableHandle(handle2);

    //Now you use convertFromRaw() to get actual values

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Sends multiple createVariableHandle() commands in one ADS packet.

    Creates a handle to a variable at the target system by variable path (such as GVL_Test.ExampleStruct).

    The handle can be then used for reading and writing the value.

    Reading and writing dereferenced POINTER and REFERENCE values is also possible. See readRawByHandle() and writeRawByHandle().

    NOTE: The handle should be deleted after it's no longer needed, as there is a limited amount of handles available. See deleteVariableHandle().

    Uses ADS sum command under the hood (better and faster performance). See Beckhoff Information System for more info.

    Parameters

    • paths: string[]

      Array of variable paths in the PLC to read (such as GVL_Test.ExampleStruct)

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<CreateVariableHandleMultiResult[]>

    try {
    const results = await client.createVariableHandleMulti([
    'GVL_Read.StandardTypes.INT_',
    'GVL_Read.StandardTypes.REAL_'
    ]);

    if(results[0].success) {
    console.log(`First handle: ${results[0].handle}`);
    } else {
    console.log(`Creating first handle failed: ${results[0].errorStr}`);
    }

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Deletes a variable handle that was previously created using createVariableHandle().

    Parameters

    • handle: number | VariableHandle

      Variable handle to delete

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<void>

    try {
    const handle = createVariableHandle(...);

    //After use, deleting the handle
    await client.deleteVariableHandle(handle);

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Sends multiple deleteVariableHandle() commands in one ADS packet.

    Deletes a variable handle that was previously created using createVariableHandle().

    Uses ADS sum command under the hood (better and faster performance). See Beckhoff Information System for more info.

    Parameters

    • handles: (number | VariableHandle)[]

      Array of variable handles to delete

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<DeleteVariableHandleMultiResult[]>

    try {
    const handle1 = createVariableHandle(...);
    const handle2 = createVariableHandle(...);

    //After use, deleting the handles
    const results = await client.deleteVariableHandleMulti([handle1, handle2]);

    if(results[0].success) {
    console.log(`First deleted`);
    } else {
    console.log(`Deleting first handle failed: ${results[0].errorStr}`);
    }

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Disconnects from the target and closes active connection.

    Subscriptions are deleted in a handled manner and ADS port is unregisterd.

    WARNING: If force is used, active subscriptions are not deleted! This affects PLCs performance in the long run.

    Parameters

    • force: boolean = false

      If true, the connection is dropped immediately (uncontrolled) - use only in special "emergency" cases (default: false)

    Returns Promise<void>

    Throws an error if disconnecting fails. However the connection stil ended.

    try {
    const res = await client.disconnect();
    console.log("Disconnected");
    } catch (err) {
    console.log("Disconnected with error:", err);
    }
  • Returns full data type declaration for requested data type (such as ST_Struct) with all children (and their children and so on).

    If available, previously cached data is used for building the full data type. Otherwise data is read from the target and cached.

    If caching is disabled using settings.disableCaching, data is always read from the target.

    If targetOpts is used to override target, caching is always disabled.

    NOTE: This requires that the target is a PLC runtime or has equivalent ADS protocol support.

    Parameters

    • name: string

      Data type name at the target (such as ST_Struct)

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings. If used, caching is disabled -> possible performance impact.

    Returns Promise<AdsDataType>

    try {
    const dataType = await client.getDataType('ST_Struct');
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Returns all target PLC runtime data types.

    If targetOpts is not used to override target and settings.disableCaching is not set, the results are cached.

    WARNING: The returned object might be VERY large!

    As default, the results do not have subitems constructred, unlike when calling getDataType(). To get all data types with full constructions (children and their children and so on), set parameter fullTypes to true. WARNING: This heavily increases the result size and CPU usage.

    Parameters

    • OptionalbuildFullTypes: boolean

      If true, all data types are built to include all subitems (and their subitems and so on)

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<AdsDataTypeContainer>

    try {
    const dataTypes = await client.getDataTypes();
    //with built data types
    const fullDataTypes = await client.getDataTypes(true);
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Returns a default (empty) Javascript object representing provided PLC data type.

    Type Parameters

    • T = any

      Typescript data type of the PLC data, for example getDefaultPlcObject<number>(...) or getDefaultPlcObject<ST_TypedStruct>(...)

    Parameters

    • dataType: string | AdsDataType

      Data type name in the PLC as string (such as ST_Struct) or data type object (acquired using getDataType())

    • Optionalattributes: AdsAttributeEntry[]

      Additional attributes of the symbol or data type used for conversion

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<T>

    try {
    const res = await client.getDefaultPlcObject('INT');
    console.log(res); //0

    const res2 = await client.getDefaultPlcObject('Tc2_Standard.TON');
    console.log(res2); //{ IN: false, PT: 0, Q: false, ET: 0, M: false, StartTime: 0 }

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Returns a symbol object for given variable path, such as GVL_Test.ExampleStruct.

    Returns previously cached value if available, otherwise reads it from the target and caches it.

    If caching is disabled using settings.disableCaching, data is always read from the target.

    If targetOpts is used to override target, caching is always disabled.

    NOTE: This requires that the target is a PLC runtime or has equivalent ADS protocol support.

    Parameters

    • path: string

      Symbol variable path at the target (such as GVL_Test.ExampleStruct)

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings. If used, caching is disabled -> possible performance impact.

    Returns Promise<AdsSymbol>

    try {
    const symbol = await client.getSymbol('GVL_Read.StandardTypes.INT_');
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Returns all symbols from the target PLC runtime.

    NOTE: This requires that the target is a PLC runtime or has equivalent ADS protocol support.

    WARNING: The returned object might be VERY large!

    If targetOpts is not used to override target, the upload info is also saved to the metaData.symbols.

    Parameters

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<AdsSymbolContainer>

    try {
    const symbols = await client.getSymbols();
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Invokes a function block RPC method on the target system.

    Returns the return value of the method and outputs (if any).

    NOTE: In the PLC, {attribute 'TcRpcEnable'} is required above the METHOD definition.

    Type Parameters

    • T = any

      Typescript data type of the method return value, for example invokeRpcMethod<number>(...) or invokeRpcMethod<ST_TypedStruct>(...)

    • U = Record<string, any>

      Typescript data type of the method outputs object, for example invokeRpcMethod<number, ST_TypedStruct>(...)

    Parameters

    • path: string

      Variable path in the PLC of the function block instance (such as GVL_Test.ExampleBlock)

    • method: string

      Function block method name

    • parameters: Record<string, any> = {}

      Method parameters (inputs) (if any)

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<RpcMethodCallResult<T, U>>

    try {
    const res = await client.invokeRpcMethod('GVL_RPC.RpcBlock', 'Calculator', {
    Value1: 1,
    Value2: 123
    });

    console.log(res);
    //{
    // returnValue: true,
    // outputs: { Sum: 124, Product: 123, Division: 0.008130080997943878 }
    //}

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Reads target device information.

    This is the ADS protocol ReadDeviceInfo command.

    If targetOpts is not used to override target, the state is also saved to the metaData.deviceInfo.

    Parameters

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<AdsDeviceInfo>

    try {
    const deviceInfo = await client.readDeviceInfo();
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Reads target PLC runtime state (usually Run, Stop etc. - see ADS.ADS_STATE)

    If targetOpts is not used to override target, the state is also saved to the metaData.plcRuntimeState.

    This is the same as readState(), except that the result is saved to the metaData.plcRuntimeState.

    NOTE: This requires that the target is a PLC runtime or has equivalent ADS protocol support.

    Parameters

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<AdsState>

    try {
    const plcState = await client.readPlcRuntimeState();
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Reads target PLC runtime symbol version.

    Symbol version usually changes when the PLC software is updated with download.

    NOTE: This requires that the target is a PLC runtime or has equivalent ADS protocol support.

    Note that if settings.rawClient is not used, the symbol version should already be up-to-date in metaData.plcSymbolVersion, as the client subscribes to its changes during connecting.

    If targetOpts is not used to override target, the state is also saved to the metaData.plcSymbolVersion.

    Parameters

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<number>

    try {
    const symbolVersion = await client.readPlcSymbolVersion();
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Reads target PLC runtime upload information.

    Upload information includes information about target PLC runtime data types and symbols (count and total data length).

    NOTE: This requires that the target is a PLC runtime or has equivalent ADS protocol support.

    If targetOpts is not used to override target, the upload info is also saved to the metaData.plcUploadInfo.

    Parameters

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<AdsUploadInfo>

    try {
    const uploadInfo = await client.readPlcUploadInfo();
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Reads raw data from the target system by a raw ADS address (index group, index offset and data length).

    This is the ADS protocol Read command.

    Parameters

    • indexGroup: number

      Index group (address) of the data to read

    • indexOffset: number

      Index offset (address) of the data to read

    • size: number

      Data length to read (bytes)

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<Buffer>

    try {
    const data = await client.readRaw(16448, 414816, 2);
    console.log(data); //<Buffer ff 7f>

    const converted = await client.convertFromRaw(data, 'INT');
    console.log(converted); //32767

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Reads raw data from the target system by a previously created variable handle (acquired using createVariableHandle())

    Parameters

    • handle: number | VariableHandle

      Variable handle

    • Optionalsize: number

      Optional data length to read (bytes) - as default, size in handle is used if available. Uses 0xFFFFFFFF as fallback.

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<Buffer>

    try {
    const handle = await client.createVariableHandle('GVL_Read.StandardTypes.INT_'');
    const value = await client.readRawByHandle(handle);
    await client.deleteVariableHandle(handle);

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Reads raw data from the target system by variable path (such as GVL_Test.ExampleStruct).

    Supports also reading POINTER and REFERENCE values (see example).

    This uses the ADS READ_SYMVAL_BYNAME under the hood, so only one round-trip is needed.

    Parameters

    • path: string

      Variable path in the PLC to read (such as GVL_Test.ExampleStruct)

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<Buffer>

    try {
    const data = await client.readRawByPath('GVL_Read.StandardTypes.INT_');
    console.log(data); //<Buffer ff 7f>

    const converted = await client.convertFromRaw(data, 'INT');
    console.log(converted); //32767

    //Reading a POINTER value (Note the dereference operator ^)
    const ptrValue = await client.readRawByPath('GVL_Read.ComplexTypes.POINTER_^');

    //Reading a REFERENCE value
    const refValue = await client.readRawByPath('GVL_Read.ComplexTypes.REFERENCE_');

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Reads raw data from the target system by a symbol object (acquired using getSymbol())

    Parameters

    • symbol: AdsSymbol

      Symbol

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<Buffer>

    try {
    const symbol = await client.getSymbol('GVL_Read.StandardTypes.INT_');
    const value = await client.readRawBySymbol(symbol);

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Sends multiple readRaw() commands in one ADS packet.

    Reads raw data from the target system by a raw ADS addresses (index group, index offset and data length). Results are returned for each command separately - see ReadRawMultiResult for details.

    Uses ADS sum command under the hood (better and faster performance). See Beckhoff Information System for more info.

    Parameters

    • commands: ReadRawMultiCommand[]

      Array of read commands

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<ReadRawMultiResult[]>

    try {
    const results = await client.readRawMulti([
    {
    indexGroup: 16448,
    indexOffset: 414816,
    size: 2
    },
    {
    indexGroup: 16448,
    indexOffset: 414900,
    size: 128
    }
    ]);

    if(results[0].success) {
    console.log(`First result: ${results[0].value}`); //First result: <Buffer ff 7f>
    } else {
    console.log(`First read command failed: ${results[0].errorStr}`);
    }

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Reads target ADS state - see ADS.ADS_STATE).

    This is the ADS protocol ReadState command.

    See also readPlcRuntimeState() and readTcSystemState().

    Parameters

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<AdsState>

    try {
    const state = await client.readState();
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Reads target TwinCAT system state from ADS port 10000 (usually Run or Config).

    If targetOpts is not used to override target, the state is also saved to the metaData.tcSystemState.

    This is the same as readState(), except that the result is saved to the metaData.tcSystemState.

    Parameters

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<AdsState>

    try {
    const tcSystemState = await client.readTcSystemState();
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Reads variable's value from the target system by a variable path (such as GVL_Test.ExampleStruct) and returns the value as a Javascript object.

    Returns variable's

    • converted value
    • raw value
    • data type
    • symbol

    NOTE: This requires that the target is a PLC runtime or has equivalent ADS protocol support.

    Type Parameters

    • T = any

      In Typescript, the data type of the value, for example readValue<number>(...) or readValue<ST_TypedStruct>(...) (default: any)

    Parameters

    • path: string

      Variable path in the PLC (such as GVL_Test.ExampleStruct)

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<ReadValueResult<T>>

    try {
    const res = await client.readValue('GVL_Read.StandardTypes.INT_');
    console.log(res.value);
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Reads variable's value from the target system by a symbol object (acquired using getSymbol()) and returns the value as a Javascript object.

    Returns variable's

    • converted value
    • raw value
    • data type
    • symbol

    NOTE: This requires that the target is a PLC runtime or has equivalent ADS protocol support.

    Type Parameters

    • T = any

      In Typescript, the data type of the value, for example readValueBySymbol<number>(...) or readValueBySymbol<ST_TypedStruct>(...) (default: any)

    Parameters

    • symbol: AdsSymbol

      Symbol object

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<ReadValueResult<T>>

    try {
    const symbol = await client.getSymbol('GVL_Read.StandardTypes.INT_');

    const res = await client.readValueBySymbol(symbol);
    console.log(res.value);
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Writes raw data to the target system by a raw ADS address (index group, index offset) and reads the result as raw data.

    This is the ADS protocol ReadWrite command.

    Parameters

    • indexGroup: number

      Address index group

    • indexOffset: number

      Address index offset

    • size: number

      Data length to read (bytes)

    • value: Buffer

      Value to write

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<Buffer>

    const { ADS } = require('../dist/ads-client');

    try {
    //Reading raw value by symbol path (= same as readRawByPath())
    const path = ADS.encodeStringToPlcStringBuffer('GVL_Read.StandardTypes.INT_');
    const data = await client.readWriteRaw(ADS.ADS_RESERVED_INDEX_GROUPS.SymbolValueByName, 0, 0xFFFFFFFF, path);
    console.log(data); //<Buffer ff 7f>

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Sends multiple readWriteRaw() commands in one ADS packet.

    Writes raw data to the target system by a raw ADS address (index group, index offset) and reads the result as raw data.

    Uses ADS sum command under the hood (better and faster performance). See Beckhoff Information System for more info.

    Parameters

    Returns Promise<ReadWriteRawMultiResult[]>

    try {
    //Reading raw values by symbol paths (= same as readRawByPath())
    const path = ADS.encodeStringToPlcStringBuffer('GVL_Read.StandardTypes.INT_');
    const path2 = ADS.encodeStringToPlcStringBuffer('GVL_Read.StandardTypes.REAL_');

    const results = await client.readWriteRawMulti([
    {
    indexGroup: ADS.ADS_RESERVED_INDEX_GROUPS.SymbolValueByName,
    indexOffset: 0,
    size: 0xFFFF,
    value: path
    },
    {
    indexGroup: ADS.ADS_RESERVED_INDEX_GROUPS.SymbolValueByName,
    indexOffset: 0,
    size: 0xFFFF,
    value: path2
    }
    ]);

    if(results[0].success) {
    console.log(`First result: ${results[0].value}`); //First result: <Buffer ff 7f>
    } else {
    console.log(`First read/write command failed: ${results[0].errorStr}`);
    }

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Reconnects to the target (disconnects and then connects again).

    Active subscriptions are saved and restored automatically after reconnecting.

    WARNING: If forceDisconnect is used, active subscriptions are not deleted! This affects PLCs performance in the long run.

    Parameters

    • forceDisconnect: boolean = false

      If true, the connection is dropped immediately (uncontrolled - as force in ()) - use only in special "emergency" cases (default: false)

    Returns Promise<Required<AdsClientConnection>>

    Throws an error if connecting fails

  • Resets the target PLC runtime. Same as reset cold in TwinCAT XAE.

    Parameters

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<void>

    Throws an error if sending the command fails or if the target responds with an error.

    try {
    await client.resetPlc();
    } catch (err) {
    console.log("Error:", err);
    }
  • Restarts the PLC runtime. Same as calling first resetPlc() and then startPlc()`

    NOTE: This requires that the target is a PLC runtime or has equivalent ADS protocol support.

    @example

    try {
    await client.restartPlc();
    } catch (err) {
    console.log("Error:", err);
    }

    @param targetOpts Optional target settings that override values in settings

    Parameters

    Returns Promise<void>

    Throws an error if sending the command fails or if the target responds with an error.

  • Restarts the target TwinCAT system.

    Just a wrapper for setTcSystemToRun() - the operation is the same.

    NOTE: As default, also reconnects the client afterwards to restore subscriptions.

    Parameters

    • reconnect: boolean = true

      If true, connection is reconnected afterwards to restore subscriptions etc. (default: true)

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<void>

    try {
    //Reconnect the client
    await client.restartTcSystem();

    //Don't reconnect the client
    await client.restartTcSystem(false);
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Sends a raw ADS command to the target.

    This can be useful in some special cases or custom system. See ADS.ADS_COMMAND for common commands.

    NOTE: Client already includes all the most common commands:

    Type Parameters

    Parameters

    Returns Promise<AmsTcpPacket<T>>

    try {
    //Creating readRaw(16448, 414816, 2) command manually and sending it using sendAdsCommand()

    const data = Buffer.alloc(12);
    let pos = 0;

    //0..3 IndexGroup
    data.writeUInt32LE(16448, pos);
    pos += 4;

    //4..7 IndexOffset
    data.writeUInt32LE(414816, pos);
    pos += 4;

    //8..11 Read data length
    data.writeUInt32LE(2, pos);
    pos += 4;

    const res = await this.sendAdsCommand<AdsReadResponse>({
    adsCommand: ADS.ADS_COMMAND.Read,
    targetAmsNetId: targetOpts.amsNetId,
    targetAdsPort: targetOpts.adsPort,
    payload: data
    });

    console.log(res.ads.payload); //<Buffer ff 7f>

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if target responds with an error

  • Sends a raw ADS command to the target with fallback. A wrapper for Client.sendAdsCommand().

    Calls sendAdsCommand(command) and if it fails with ADS error 1793 or 1808 then calls the sendAdsCommand(fallback).

    See Client.readPlcUploadInfo() for use case.

    The ideas is copied from TwinCAT.Ads.dll (TwinCAT.Ads.AdsClientExtensions.ReadWithFallbackAsync()).

    Type Parameters

    Parameters

    Returns Promise<SendAdsCommandWithFallbackResult<T>>

    try {
    const data = Buffer.alloc(12);
    //...code omitted...

    const command = {
    adsCommand: ADS.ADS_COMMAND.Read,
    targetAmsNetId: targetOpts.amsNetId,
    targetAdsPort: targetOpts.adsPort,
    payload: data
    };

    const fbData = Buffer.alloc(12);
    //...code omitted...

    const fallback = {
    adsCommand: ADS.ADS_COMMAND.Read,
    targetAmsNetId: targetOpts.amsNetId,
    targetAdsPort: targetOpts.adsPort,
    payload: fbData
    };

    const { response: res, fallbackUsed } = await this.sendAdsCommandWithFallback<AdsReadResponse>(command, fallback);

    //If we are here, one of those commands was succcesful
    if(fallbackUsed) {
    console.log("Fallback was used. Result:", res.ads.payload);
    } else {
    console.log("Fallback was not used. Result:", res.ads.payload);
    }

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if target responds with an error

  • Sets active debug level.

    Debug levels:

    • 0: no debugging (default)
    • 1: basic debugging ($env:DEBUG='ads-client')
    • 2: detailed debugging ($env:DEBUG='ads-client,ads-client:details')
    • 3: detailed debugging with raw I/O data ($env:DEBUG='ads-client,ads-client:details,ads-client:raw-data')

    Debug data is available in the console (See Debug library for mode).

    Parameters

    Returns void

  • Sets the target TwinCAT system to config mode. Same as Restart TwinCAT (Config mode) in TwinCAT XAE.

    NOTE: If the target is a PLC runtime, the connection might be lost.

    Parameters

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<void>

    try {
    await client.setTcSystemToConfig();
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Sets the target TwinCAT system to run mode. Same as Restart TwinCAT system in TwinCAT XAE.

    NOTE: As default, also reconnects the client afterwards to restore subscriptions.

    Parameters

    • reconnect: boolean = true

      If true, connection is reconnected afterwards to restore subscriptions etc. (default: true)

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<void>

    try {
    //Reconnect the client
    await client.setTcSystemToRun();

    //Don't reconnect the client
    await client.setTcSystemToRun(false);
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Starts the target PLC runtime. Same as pressing the green play button in TwinCAT XAE.

    NOTE: This requires that the target is a PLC runtime or has equivalent ADS protocol support.

    Parameters

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<void>

    Throws an error if sending the command fails or if target responds with an error

    try {
    await client.startPlc();
    } catch (err) {
    console.log("Error:", err);
    }
  • Stops the target PLC runtime. Same as pressing the red stop button in TwinCAT XAE.

    Parameters

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<void>

    Throws an error if sending the command fails or if the target responds with an error.

    try {
    await client.stopPlc();
    } catch (err) {
    console.log("Error:", err);
    }
  • Subscribes to value change notifications (ADS notifications) by variable path (such as GVL_Test.ExampleStruct) or raw ADS address (index group, index offset and data length).

    Provided callback is called with the latest value when the value changes or when enough time has passed (depending on settings).

    NOTE: This requires that the target is a PLC runtime or has equivalent ADS protocol support.

    Type Parameters

    • T = any

      In Typescript, the data type of the value, for example subscribe<number>(...) or subscribe<ST_TypedStruct>(...). If the target is a raw address, use subscribe<Buffer>. (default: any)

    Parameters

    • options: SubscriptionSettings<T>

      Subscription options

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings. If used, caching is disabled -> possible performance impact.

    Returns Promise<ActiveSubscription<T>>

    //Checks if value has changed every 100ms
    //Callback is called only when the value has changed
    await client.subscribe({
    target: 'GVL_Subscription.NumericValue_10ms',
    callback: (data, subscription) => {
    console.log(`Value of ${subscription.symbol.name} has changed: ${data.value}`);
    },
    cycleTime: 100
    });
    //Checks if value has changed every 100ms
    //Callback is called only when the value has changed
    await client.subscribe({
    target: {
    indexGroup: 16448,
    indexOffset: 414816,
    size: 2
    },
    callback: (data, subscription) => {
    console.log(`Value has changed: ${data.value}`);
    },
    cycleTime: 100
    });

    Throws an error if sending the command fails or if the target responds with an error.

  • Subscribes to raw value change notifications (ADS notifications) by a raw ADS address (index group, index offset and data length).

    Provided callback is called with the latest value when the value changes or when enough time has passed (depending on settings).

    Check also subscribe() instead, this is just a wrapper for it.

    NOTE: This requires that the target is a PLC runtime or has equivalent ADS protocol support.

    Parameters

    • indexGroup: number

      Index group (address) of the data to subscribe to

    • indexOffset: number

      Index offset (address) of the data to subscribe to

    • size: number

      Data length (bytes)

    • callback: SubscriptionCallback<Buffer>

      Callback function to call when a new value is received ((data, subscription) => {})

    • OptionalcycleTime: number

      Cycle time for subscription (default: 200 ms)

      • If sendOnChange is true (default), PLC checks if value has changed with cycleTime interval. If the value has changed, the PLC sends the value and the callback is called.
      • If sendOnChange is false, PLC constantly sends the value with cycleTime interval and the callback is called.
    • OptionalsendOnChange: boolean

      Send a new value only when the value has changed (default: true)

      • If true (default), the PLC checks the value for changes every cycleTime milliseconds. If the value has changed, PLC sends the new value and the callback is called.
      • If false, the PLC sends the value cyclically every cycleTime milliseconds (and the callback is called)

      NOTE: When subscribing, the value is always sent once.

    • OptionalmaxDelay: number

      How long the PLC waits before sending the value at maximum? (default: 0 ms --> maximum delay is off)

      If the value is not changing, the first notification with the active value after subscribing is sent after maxDelay.

      If the value is changing, the PLC sends one or more notifications every maxDelay.

      So if cycleTime is 100 ms, maxDelay is 1000 ms and value changes every 100 ms, the PLC sends 10 notifications every 1000 ms. This can be useful for throttling.

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings. If used, caching is disabled -> possible performance impact.

    Returns Promise<ActiveSubscription<Buffer>>

    //Checks if value has changed every 100ms
    //Callback is called only when the value has changed
    await client.subscribeRaw(16448, 414816, 2, (data, subscription) => {
    console.log(`Value has changed: ${data.value.toString('hex')}`);
    }, 100);

    Throws an error if sending the command fails or if the target responds with an error.

  • Subscribes to value change notifications (ADS notifications) by a variable path, such as GVL_Test.ExampleStruct.

    Provided callback is called with the latest value of the symbol when the value changes or when enough time has passed (depending on settings).

    Check also subscribe() instead, this is just a wrapper for it.

    NOTE: This requires that the target is a PLC runtime or has equivalent ADS protocol support.

    Type Parameters

    • T = any

      In Typescript, the data type of the value, for example subscribeValue<number>(...) or subscribeValue<ST_TypedStruct>(...). (default: any)

    Parameters

    • path: string

      Variable path in the PLC (such as GVL_Test.ExampleStruct)

    • callback: SubscriptionCallback<T>

      Callback function to call when a new value is received ((data, subscription) => {})

    • OptionalcycleTime: number

      Cycle time for subscription (default: 200 ms)

      • If sendOnChange is true (default), PLC checks if value has changed with cycleTime interval. If the value has changed, the PLC sends the value and the callback is called.
      • If sendOnChange is false, PLC constantly sends the value with cycleTime interval and the callback is called.
    • OptionalsendOnChange: boolean

      Send a new value only when the value has changed (default: true)

      • If true (default), the PLC checks the value for changes every cycleTime milliseconds. If the value has changed, PLC sends the new value and the callback is called.
      • If false, the PLC sends the value cyclically every cycleTime milliseconds (and the callback is called)

      NOTE: When subscribing, the value is always sent once.

    • OptionalmaxDelay: number

      How long the PLC waits before sending the value at maximum? (default: 0 ms --> maximum delay is off)

      If the value is not changing, the first notification with the active value after subscribing is sent after maxDelay.

      If the value is changing, the PLC sends one or more notifications every maxDelay.

      So if cycleTime is 100 ms, maxDelay is 1000 ms and value changes every 100 ms, the PLC sends 10 notifications every 1000 ms. This can be useful for throttling.

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings. If used, caching is disabled -> possible performance impact.

    Returns Promise<ActiveSubscription<T>>

    //Checks if value has changed every 100ms
    //Callback is called only when the value has changed
    await client.subscribeValue(
    'GVL_Subscription.NumericValue_10ms',
    (data, subscription) => {
    console.log(`Value of ${subscription.symbol.name} has changed: ${data.value}`);
    },
    100
    );

    Throws an error if sending the command fails or if the target responds with an error.

  • Unsubscribes the subscription (deletes ADS notification).

    PLC stops checking the value for changes (if configured so) and no longer sends new values.

    Parameters

    • subscription: ActiveSubscription<any>

      Subscription to unsubscribe (created previously by subscribing for example using subscribe())

    Returns Promise<void>

    const sub = await client.subscribe(...);

    //later
    try {
    await client.unsubscribe(sub);
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Unsubscribes all active subscription (deletes all ADS notifications).

    PLC stops checking the values for changes (if configured so) and no longer sends new values.

    Returns Promise<void>

    const sub = await client.subscribe(...);
    const sub2 = await client.subscribe(...);

    //later
    try {
    await client.unsubscribeAll();
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Sends an ADS WriteControl command to the target.

    More info: Beckhoff documentation

    Parameters

    • adsState:
          | number
          | "toString"
          | "Invalid"
          | "Idle"
          | "Reset"
          | "Initialize"
          | "Start"
          | "Run"
          | "Stop"
          | "SaveConfig"
          | "LoadConfig"
          | "PowerFailure"
          | "PowerGood"
          | "Error"
          | "Shutdown"
          | "Suspend"
          | "Resume"
          | "Config"
          | "Reconfig"
          | "Stopping"
          | "Incompatible"
          | "Exception"

      Requested ADS state - see ADS.ADS_STATE. Can be a number or a valid string, such as Config

    • deviceState: number = 0

      Requested device state (default: 0)

    • data: Buffer = ...

      Additional data to send (if any)

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<void>

    Throws an error if sending the command fails or if the target responds with an error.

    try {
    //Set target (PLC) to run
    await client.writeControl("Run");
    } catch (err) {
    console.log("Error:", err);
    }
  • Writes raw data to the target system by a raw ADS address (index group, index offset and data length).

    This is the ADS protocol Write command.

    Parameters

    • indexGroup: number

      Index group (address) of the data to write to

    • indexOffset: number

      Index offset (address) of the data to write to

    • value: Buffer

      Data to write

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<void>

    try {
    const data = await client.convertToRaw(32767, 'INT');
    console.log(data); //<Buffer ff 7f>

    await client.writeRaw(16448, 414816, data);
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Writes raw data to the target system by a previously created variable handle (acquired using createVariableHandle())

    Parameters

    • handle: number | VariableHandle

      Variable handle

    • value: Buffer

      Data to write

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<void>

    try {
    const value = await client.convertToRaw(32767, 'INT');
    console.log(value); //<Buffer ff 7f>

    const handle = await client.createVariableHandle('GVL_Read.StandardTypes.INT_');
    await client.writeRawByHandle(handle, value);
    await client.deleteVariableHandle(handle);

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Writes raw data to the target system by variable path (such as GVL_Test.ExampleStruct).

    Supports also writing POINTER and REFERENCE values (see example).

    NOTE: Unlike with readRawByPath(), this command uses multiple ADS requests for the operation.

    Parameters

    • path: string

      Variable path in the PLC to write (such as GVL_Test.ExampleStruct)

    • value: Buffer

      Data to write

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<void>

    try {
    const data = await client.convertToRaw(32767, 'INT');
    console.log(data); //<Buffer ff 7f>

    await client.writeRawByPath('GVL_Write.StandardTypes.INT_', data);

    //Writing a POINTER value (Note the dereference operator ^)
    const ptrValue = ...
    await client.writeRawByPath('GVL_Write.ComplexTypes.POINTER_^', ptrValue);

    //Writing a REFERENCE value
    const refValue = ...
    await client.writeRawByPath('GVL_Write.ComplexTypes.REFERENCE_');

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Writes raw data to the target system by a symbol object (acquired using getSymbol())

    Parameters

    • symbol: AdsSymbol

      Symbol

    • value: Buffer

      Data to write

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<void>

    try {
    const value = await client.convertToRaw(32767, 'INT');
    console.log(value); //<Buffer ff 7f>

    const symbol = await client.getSymbol('GVL_Read.StandardTypes.INT_');
    await client.writeRawBySymbol(symbol, value);

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Sends multiple writeRaw() commands in one ADS packet.

    Writes raw data to the target system by a raw ADS addresses (index group and index offset). Results are returned for each command separately - see WriteRawMultiResult for details.

    Uses ADS sum command under the hood (better and faster performance). See Beckhoff Information System for more info.

    Parameters

    • commands: WriteRawMultiCommand[]

      Array of write commands

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<WriteRawMultiResult[]>

    try {
    const data1 = await client.convertToRaw(32767, 'INT');
    console.log(data1); //<Buffer ff 7f>

    const data2 = Buffer.alloc(128); //example

    const results = await client.writeRawMulti([
    {
    indexGroup: 16448,
    indexOffset: 414816,
    value: data1
    },
    {
    indexGroup: 16448,
    indexOffset: 414900,
    value: data2
    }
    ]);

    if(results[0].success) {
    console.log(`First write command successful`);
    } else {
    console.log(`First write command failed: ${results[0].errorStr}`);
    }

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Writes variable's value to the target system by a variable path (such as GVL_Test.ExampleStruct). Converts the value from a Javascript object to a raw value.

    Returns variable's

    • converted value
    • raw value
    • data type
    • symbol

    NOTE: Do not use autoFill for UNION types, it doesn't work correctly.

    NOTE: This requires that the target is a PLC runtime or has equivalent ADS protocol support.

    Type Parameters

    • T = any

      In Typescript, the data type of the value, for example writeValue<number>(...) or writeValue<ST_TypedStruct>(...)

    Parameters

    • path: string

      Variable path in the PLC (such as GVL_Test.ExampleStruct)

    • value: T

      Value to write

    • autoFill: boolean = false

      If set and the data type is a container (STRUCT, FUNCTION_BLOCK etc.), missing properties are automatically set to active values read from target (kept as-is).

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<WriteValueResult<T>>

    try {
    const res = await client.writeValue('GVL_Write.StandardTypes.INT_', 32767);
    console.log('Value written:', res.value);

    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.

  • Writes variable's value to the target system by a symbol object (acquired using getSymbol()). Converts the value from a Javascript object to a raw value.

    Returns variable's

    • converted value
    • raw value
    • data type
    • symbol

    NOTE: Do not use autoFill for UNION types, it doesn't work correctly.

    NOTE: This requires that the target is a PLC runtime or has equivalent ADS protocol support.

    Type Parameters

    • T = any

      In Typescript, the data type of the value, for example writeValue<number>(...) or writeValue<ST_TypedStruct>(...)

    Parameters

    • symbol: AdsSymbol

      Symbol object

    • value: T

      Value to write

    • autoFill: boolean = false

      If set and the data type is a container (STRUCT, FUNCTION_BLOCK etc.), missing properties are automatically set to active values read from target (kept as-is).

    • targetOpts: Partial<AmsAddress> = {}

      Optional target settings that override values in settings

    Returns Promise<WriteValueResult<T>>

    try {
    const symbol = await client.getSymbol('GVL_Read.StandardTypes.INT_');

    const res = await client.writeValueBySymbol(symbol, 32767);
    } catch (err) {
    console.log("Error:", err);
    }

    Throws an error if sending the command fails or if the target responds with an error.