ads-client 2.0.0-beta.2 → 2.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -51,29 +51,39 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
51
51
  };
52
52
  Object.defineProperty(exports, "__esModule", { value: true });
53
53
  exports.Client = exports.ADS = void 0;
54
- const events_1 = __importDefault(require("events"));
55
54
  const net_1 = require("net");
55
+ const events_1 = __importDefault(require("events"));
56
56
  const debug_1 = __importDefault(require("debug"));
57
57
  const long_1 = __importDefault(require("long"));
58
58
  const ADS = __importStar(require("./ads-commons"));
59
59
  const client_error_1 = __importDefault(require("./client-error"));
60
+ /**
61
+ * Common ADS constants and helper functions
62
+ *
63
+ * @category Client
64
+ */
60
65
  exports.ADS = __importStar(require("./ads-commons"));
61
66
  /**
62
67
  * A class for handling TwinCAT ADS protocol communication.
63
68
  *
64
69
  * Settings are provided in constructor - see {@link Client.constructor} and {@link AdsClientSettings}.
65
70
  *
66
- * A client instance should be created for each target, however, a single client
67
- * can also be used to communicate with multiple endpoints.
71
+ * A client instance should be created for each target.
72
+ * However, a single client instance can also be used to communicate with
73
+ * multiple endpoints using the `targetOpts` parameter available in all methods.
68
74
  *
69
- * @example
75
+ * Client also emits different events, such as `client.on('connect', ...)`.
76
+ * See {@link AdsClientEvents} for all available events.
70
77
  *
78
+ * @example
71
79
  * ```js
72
80
  * const client = new Client({
73
81
  * targetAmsNetId: "192.168.4.1.1.1",
74
82
  * targetAdsPort: 851
75
83
  * });
76
84
  * ```
85
+ *
86
+ * @category Client
77
87
  */
78
88
  class Client extends events_1.default {
79
89
  /**
@@ -222,7 +232,8 @@ class Client extends events_1.default {
222
232
  connectionDownDelay: 5000,
223
233
  allowHalfOpen: false,
224
234
  rawClient: false,
225
- disableCaching: false
235
+ disableCaching: false,
236
+ deleteUnknownSubscriptions: true
226
237
  };
227
238
  /**
228
239
  * Active connection information.
@@ -247,6 +258,17 @@ class Client extends events_1.default {
247
258
  };
248
259
  }
249
260
  ;
261
+ /**
262
+ * Emits a warning, which results in a `warning` event, and a console message if `hideConsoleWarnings` is not set.
263
+ *
264
+ * @param message Warning message
265
+ */
266
+ warn(message) {
267
+ if (!this.settings.hideConsoleWarnings) {
268
+ console.log(`WARNING: ${message}`);
269
+ }
270
+ this.emit('warning', message);
271
+ }
250
272
  /**
251
273
  * Clears given timer if it's available and increases the ID.
252
274
  *
@@ -409,13 +431,13 @@ class Client extends events_1.default {
409
431
  }
410
432
  //allowHalfOpen allows this, but show some warnings..
411
433
  if (!this.metaData.tcSystemState) {
412
- !this.settings.hideConsoleWarnings && console.log(`WARNING: "allowHalfOpen" setting is active. Target is connected but no connection to TwinCAT system. If target is not PLC runtime, use setting "rawClient" instead of "allowHalfOpen".`);
434
+ this.warn(`"allowHalfOpen" setting is active. Target is connected but no connection to TwinCAT system. If target is not PLC runtime, use setting "rawClient" instead of "allowHalfOpen".`);
413
435
  }
414
436
  else if (this.metaData.tcSystemState.adsState !== ADS.ADS_STATE.Run) {
415
- !this.settings.hideConsoleWarnings && console.log(`WARNING: "allowHalfOpen" setting is active. Target is connected but TwinCAT system is in ${this.metaData.tcSystemState.adsStateStr} instead of run mode. No connection to PLC runtime.`);
437
+ this.warn(`"allowHalfOpen" setting is active. Target is connected but TwinCAT system is in ${this.metaData.tcSystemState.adsStateStr} instead of run mode. No connection to PLC runtime.`);
416
438
  }
417
439
  else {
418
- !this.settings.hideConsoleWarnings && console.log(`WARNING: "allowHalfOpen" setting is active. No connection to PLC runtime. Check "targetAdsPort" setting and PLC status`);
440
+ this.warn(`"allowHalfOpen" setting is active. No connection to PLC runtime. Check "targetAdsPort" setting and PLC status`);
419
441
  }
420
442
  }
421
443
  }
@@ -488,6 +510,7 @@ class Client extends events_1.default {
488
510
  connected: false
489
511
  };
490
512
  this.metaData = { ...this.defaultMetaData };
513
+ this.activeSubscriptions = {};
491
514
  this.socket?.removeAllListeners();
492
515
  this.socket?.destroy();
493
516
  this.socket = undefined;
@@ -508,6 +531,7 @@ class Client extends events_1.default {
508
531
  connected: false
509
532
  };
510
533
  this.metaData = { ...this.defaultMetaData };
534
+ this.activeSubscriptions = {};
511
535
  this.socket?.removeAllListeners();
512
536
  this.socket?.destroy();
513
537
  this.socket = undefined;
@@ -525,6 +549,7 @@ class Client extends events_1.default {
525
549
  connected: false
526
550
  };
527
551
  this.metaData = { ...this.defaultMetaData };
552
+ this.activeSubscriptions = {};
528
553
  this.debug(`disconnectFromTarget(): Connection closing failed, connection was forced to close`);
529
554
  this.emit("disconnect", isReconnecting);
530
555
  return reject(new client_error_1.default(`disconnect(): Disconnected with errors: ${disconnectError.message}`, err));
@@ -555,11 +580,11 @@ class Client extends events_1.default {
555
580
  //Trying to subscribe to previous subscriptions again
556
581
  const failures = await this.restoreSubscriptions();
557
582
  if (!failures.length) {
558
- isReconnecting && !this.settings.hideConsoleWarnings && console.log(`Reconnected and all subscriptions were restored!`);
583
+ isReconnecting && this.warn(`Reconnected and all subscriptions were restored!`);
559
584
  this.debug(`reconnectToTarget(): Reconnected and all subscriptions were restored!`);
560
585
  }
561
586
  else {
562
- !this.settings.hideConsoleWarnings && console.log(`WARNING: Reconnected but failed to restore following subscriptions:\n - ${failures.join('\n - ')}`);
587
+ this.warn(`Reconnected but failed to restore following subscriptions:\n - ${failures.join('\n - ')}`);
563
588
  this.debug(`reconnectToTarget(): Reconnected but failed to restore following subscriptions: ${failures.join(', ')}`);
564
589
  }
565
590
  this.emit('reconnect', !failures.length, failures);
@@ -906,7 +931,7 @@ class Client extends events_1.default {
906
931
  await this.restoreSubscriptions();
907
932
  }
908
933
  catch (err) {
909
- !this.settings.hideConsoleWarnings && console.log(`WARNING: Target PLC symbol version changed and all subscriptions were not restored (data might be lost from now on). Error info: ${JSON.stringify(err)}`);
934
+ this.warn(`Target PLC symbol version changed and all subscriptions were not restored (data might be lost from now on). Error info: ${JSON.stringify(err)}`);
910
935
  this.debug(`onPlcSymbolVersionChanged(): Failed to restore all subscriptions. Error: %o`, err);
911
936
  }
912
937
  }
@@ -920,7 +945,7 @@ class Client extends events_1.default {
920
945
  * See also {@link Client.socketErrorHandler} which is `onSocketError.bind(this)`
921
946
  */
922
947
  onSocketError(err) {
923
- !this.settings.hideConsoleWarnings && console.log(`WARNING: Socket connection to target closed to an an error, disconnecting: ${JSON.stringify(err)}`);
948
+ this.warn(`Socket connection to target closed to an an error, disconnecting: ${JSON.stringify(err)}`);
924
949
  this.onConnectionLost(true);
925
950
  }
926
951
  /**
@@ -936,12 +961,12 @@ class Client extends events_1.default {
936
961
  this.connection.connected = false;
937
962
  this.emit('connectionLost', socketFailure);
938
963
  if (this.settings.autoReconnect !== true) {
939
- !this.settings.hideConsoleWarnings && console.log("WARNING: Connection to target was lost and setting autoReconnect was false -> disconnecting");
964
+ this.warn("Connection to target was lost and setting autoReconnect was false -> disconnecting");
940
965
  await this.disconnectFromTarget(true).catch();
941
966
  return;
942
967
  }
943
968
  this.socketConnectionLostHandler && this.socket?.off('close', this.socketConnectionLostHandler);
944
- !this.settings.hideConsoleWarnings && console.log("WARNING: Connection to target was lost. Trying to reconnect automatically...");
969
+ this.warn("Connection to target was lost. Trying to reconnect automatically...");
945
970
  const tryToReconnect = async (firstRetryAttempt, timerId) => {
946
971
  //If the timer has changed, quit here (to prevent multiple timers)
947
972
  if (this.reconnectionTimer.id !== timerId) {
@@ -958,7 +983,7 @@ class Client extends events_1.default {
958
983
  //Reconnecting failed
959
984
  if (firstRetryAttempt) {
960
985
  this.debug(`onConnectionLost()/tryToReconnect(): Reconnecting failed, keeping trying in the background (${err.message}`);
961
- !this.settings.hideConsoleWarnings && console.log(`WARNING: Reconnecting failed. Keeping trying in the background every ${this.settings.reconnectInterval} ms...`);
986
+ this.warn(`Reconnecting failed. Keeping trying in the background every ${this.settings.reconnectInterval} ms...`);
962
987
  }
963
988
  //If this is still a valid timer, start over again
964
989
  if (this.reconnectionTimer.id === timerId) {
@@ -1434,12 +1459,24 @@ class Client extends events_1.default {
1434
1459
  })
1435
1460
  .catch(err => {
1436
1461
  this.debug(`onAdsCommandReceived(): Notification received but parsing Javascript object failed: %o`, err);
1437
- this.emit('client-error', new client_error_1.default(`onAdsCommandReceived(): Ntification received but parsing data to Javascript object failed. Subscription: ${JSON.stringify(subscription)}`, err));
1462
+ this.emit('client-error', new client_error_1.default(`An ADS notification received but parsing data to a Javascript object failed. Subscription: ${JSON.stringify(subscription)}`, err));
1463
+ });
1464
+ }
1465
+ else if (this.settings.deleteUnknownSubscriptions) {
1466
+ this.debug(`onAdsCommandReceived(): An ADS notification with an unknown handle ${sample.notificationHandle} was received from ${key}. Trying to delete it to save resources (deleteUnknownSubscriptions is set).`);
1467
+ this.deleteNotificationHandle(sample.notificationHandle, packet.ams.sourceAmsAddress)
1468
+ .then(() => {
1469
+ this.debug(`onAdsCommandReceived(): An ADS notification with an unknown handle ${sample.notificationHandle} was received from ${key} and automatically deleted`);
1470
+ this.warn(`An ADS notification with an unknown handle ${sample.notificationHandle} was received from ${key} and automatically deleted`);
1471
+ })
1472
+ .catch(err => {
1473
+ this.debug(`onAdsCommandReceived(): Failed to delete an unknown ADS notification handle ${sample.notificationHandle} (from ${key}): %o`, err);
1474
+ this.emit('client-error', new client_error_1.default(`Failed to delete an unknown ADS notification handle ${sample.notificationHandle} (from ${key})`, err));
1438
1475
  });
1439
1476
  }
1440
1477
  else {
1441
- this.debugD(`onAdsCommandReceived(): Notification received with unknown handle ${sample.notificationHandle} (${key}). Use unsubscribe() to save resources`);
1442
- this.emit('client-error', new client_error_1.default(`onAdsCommandReceived(): Notification received with unknown handle ${sample.notificationHandle} (${key}). Use unsubscribe() to save resources.`));
1478
+ this.debug(`onAdsCommandReceived(): Notification received with unknown handle ${sample.notificationHandle} (${key})`);
1479
+ this.warn(`An ADS notification with an unknown handle ${sample.notificationHandle} was received from ${key}. Use unsubscribe() or deleteUnknownSubscriptions setting to save resources.`);
1443
1480
  }
1444
1481
  }
1445
1482
  }
@@ -1454,7 +1491,7 @@ class Client extends events_1.default {
1454
1491
  }
1455
1492
  else {
1456
1493
  this.debugD(`onAdsCommandReceived(): Ads command received with unknown invokeId "${packet.ams.invokeId}"`);
1457
- this.emit('client-error', new client_error_1.default(`onAdsCommandReceived(): Ads command received with unknown invokeId "${packet.ams.invokeId}"`));
1494
+ this.emit('client-error', new client_error_1.default(`Ads command received with unknown invokeId "${packet.ams.invokeId}"`));
1458
1495
  }
1459
1496
  break;
1460
1497
  }
@@ -1486,7 +1523,7 @@ class Client extends events_1.default {
1486
1523
  this.clearTimer(this.tcSystemStatePollerTimer);
1487
1524
  this.debug("onRouterStateChanged(): Local loopback connection active, monitoring router state. Reconnecting when router is back running.");
1488
1525
  if (this.metaData.routerState.state === ADS.AMS_ROUTER_STATE.START) {
1489
- !this.settings.hideConsoleWarnings && console.log(`WARNING: Local AMS router state has changed to ${this.metaData.routerState.stateStr}. Reconnecting...`);
1526
+ this.warn(`Local AMS router state has changed to ${this.metaData.routerState.stateStr}. Reconnecting...`);
1490
1527
  this.onConnectionLost();
1491
1528
  }
1492
1529
  else {
@@ -1859,7 +1896,7 @@ class Client extends events_1.default {
1859
1896
  }
1860
1897
  //If extended flag RefactorInfo is set
1861
1898
  if ((symbol.extendedFlags & ADS.ADS_SYMBOL_FLAGS_2.RefactorInfo) === ADS.ADS_SYMBOL_FLAGS_2.RefactorInfo) {
1862
- !this.settings.hideConsoleWarnings && console.log(`WARNING: Symbol ${symbol.name} (${symbol.type}) has extended flag "RefactorInfo" which is not supported. Things might not work now. Please open an issue at Github`);
1899
+ this.warn(`Symbol ${symbol.name} (${symbol.type}) has extended flag "RefactorInfo" which is not supported. Things might not work now. Please open an issue at Github`);
1863
1900
  }
1864
1901
  //Reserved, if any
1865
1902
  symbol.reserved = data.subarray(pos);
@@ -2164,7 +2201,7 @@ class Client extends events_1.default {
2164
2201
  if ((dataType.flags & ADS.ADS_DATA_TYPE_FLAGS.RefactorInfo) === ADS.ADS_DATA_TYPE_FLAGS.RefactorInfo) {
2165
2202
  //TODO: this is not working now
2166
2203
  //Things probably break now
2167
- !this.settings.hideConsoleWarnings && console.log(`WARNING: Data type ${dataType.name} (${dataType.type}) has flag "RefactorInfo" which is not supported. Things might not work now. Please open an issue at Github`);
2204
+ this.warn(`Data type ${dataType.name} (${dataType.type}) has flag "RefactorInfo" which is not supported. Things might not work now. Please open an issue at Github`);
2168
2205
  }
2169
2206
  //If flag ExtendedFlags set
2170
2207
  if ((dataType.flags & ADS.ADS_DATA_TYPE_FLAGS.ExtendedFlags) === ADS.ADS_DATA_TYPE_FLAGS.ExtendedFlags) {
@@ -2181,13 +2218,13 @@ class Client extends events_1.default {
2181
2218
  if ((dataType.flags & ADS.ADS_DATA_TYPE_FLAGS.ExtendedEnumInfos) === ADS.ADS_DATA_TYPE_FLAGS.ExtendedEnumInfos) {
2182
2219
  //TODO: this is not working now
2183
2220
  //Things probably break now
2184
- !this.settings.hideConsoleWarnings && console.log(`WARNING: Data type ${dataType.name} (${dataType.type}) has flag "ExtendedEnumInfos" which is not supported. Things might not work now. Please open an issue at Github`);
2221
+ this.warn(`Data type ${dataType.name} (${dataType.type}) has flag "ExtendedEnumInfos" which is not supported. Things might not work now. Please open an issue at Github`);
2185
2222
  }
2186
2223
  //If flag SoftwareProtectionLevels set
2187
2224
  if ((dataType.flags & ADS.ADS_DATA_TYPE_FLAGS.SoftwareProtectionLevels) === ADS.ADS_DATA_TYPE_FLAGS.SoftwareProtectionLevels) {
2188
2225
  //TODO: this is not working now
2189
2226
  //Things probably break now
2190
- !this.settings.hideConsoleWarnings && console.log(`WARNING: Data type ${dataType.name} (${dataType.type}) has flag "SoftwareProtectionLevels" which is not supported. Things might not work now. Please open an issue at Github`);
2227
+ this.warn(`Data type ${dataType.name} (${dataType.type}) has flag "SoftwareProtectionLevels" which is not supported. Things might not work now. Please open an issue at Github`);
2191
2228
  }
2192
2229
  //Reserved, if any
2193
2230
  dataType.reserved = data.subarray(pos);
@@ -2901,14 +2938,44 @@ class Client extends events_1.default {
2901
2938
  * - {@link Client.unsubscribe}() - `DeleteNotification` command
2902
2939
  * - {@link Client.readWriteRaw}() - `ReadWrite` command
2903
2940
  *
2904
- * @template T ADS response type. If omitted, generic {@link AdsResponse} type is used
2905
- *
2906
- * @throws Throws an error if sending the command fails or if target responds with an error
2907
- *
2908
2941
  * @example
2909
2942
  * ```js
2910
- * TODO - DOCUMENTATION ONGOING
2943
+ * try {
2944
+ * //Creating readRaw(16448, 414816, 2) command manually and sending it using sendAdsCommand()
2945
+ *
2946
+ * const data = Buffer.alloc(12);
2947
+ * let pos = 0;
2948
+ *
2949
+ * //0..3 IndexGroup
2950
+ * data.writeUInt32LE(16448, pos);
2951
+ * pos += 4;
2952
+ *
2953
+ * //4..7 IndexOffset
2954
+ * data.writeUInt32LE(414816, pos);
2955
+ * pos += 4;
2956
+ *
2957
+ * //8..11 Read data length
2958
+ * data.writeUInt32LE(2, pos);
2959
+ * pos += 4;
2960
+ *
2961
+ * const res = await this.sendAdsCommand<AdsReadResponse>({
2962
+ * adsCommand: ADS.ADS_COMMAND.Read,
2963
+ * targetAmsNetId: targetOpts.amsNetId,
2964
+ * targetAdsPort: targetOpts.adsPort,
2965
+ * payload: data
2966
+ * });
2967
+ *
2968
+ * console.log(res.ads.payload); //<Buffer ff 7f>
2969
+ *
2970
+ * } catch (err) {
2971
+ * console.log("Error:", err);
2972
+ * }
2911
2973
  * ```
2974
+ *
2975
+ * @template T In Typescript, the type of the ADS response. If omitted, generic {@link AdsResponse} type is used.
2976
+ *
2977
+ * @throws Throws an error if sending the command fails or if target responds with an error
2978
+ *
2912
2979
  */
2913
2980
  async sendAdsCommand(command) {
2914
2981
  return new Promise(async (resolve, reject) => {
@@ -3221,7 +3288,7 @@ class Client extends events_1.default {
3221
3288
  this.debug(`setTcSystemToRun(): TwinCAT system at ${this.targetToString(targetOpts)} set to run mode`);
3222
3289
  if (reconnect) {
3223
3290
  this.debug(`setTcSystemToRun(): Reconnecting after TwinCAT system restart`);
3224
- !this.settings.hideConsoleWarnings && console.log("WARNING: Reconnecting after TwinCAT system restart");
3291
+ this.warn("Reconnecting after TwinCAT system restart");
3225
3292
  this.onConnectionLost();
3226
3293
  }
3227
3294
  }
@@ -3300,7 +3367,7 @@ class Client extends events_1.default {
3300
3367
  this.debug(`restartTcSystem(): TwinCAT system was restarted`);
3301
3368
  }
3302
3369
  /**
3303
- * Returns symbol for given variable path, such as `GVL_Test.ExampleStruct`.
3370
+ * Returns a symbol object for given variable path, such as `GVL_Test.ExampleStruct`.
3304
3371
  *
3305
3372
  * Returns previously cached value if available, otherwise reads it from the target
3306
3373
  * and caches it.
@@ -3671,7 +3738,7 @@ class Client extends events_1.default {
3671
3738
  }
3672
3739
  }
3673
3740
  /**
3674
- * Subscribes to raw value change notifications (ADS notifications) by raw ADS address (index group, index offset and data length).
3741
+ * Subscribes to raw value change notifications (ADS notifications) by a raw ADS address (index group, index offset and data length).
3675
3742
  *
3676
3743
  * Provided callback is called with the latest value when the value changes or when
3677
3744
  * enough time has passed (depending on settings).
@@ -3830,19 +3897,8 @@ class Client extends events_1.default {
3830
3897
  throw new client_error_1.default(`unsubscribe(): Client is not connected. Use connect() to connect to the target first.`);
3831
3898
  }
3832
3899
  this.debug(`unsubscribe(): Unsubscribing %o`, subscription);
3833
- //Allocating bytes for request
3834
- const data = Buffer.alloc(4);
3835
- let pos = 0;
3836
- //0..3 Notification handle
3837
- data.writeUInt32LE(subscription.notificationHandle, pos);
3838
- pos += 4;
3839
3900
  try {
3840
- const res = await this.sendAdsCommand({
3841
- adsCommand: ADS.ADS_COMMAND.DeleteNotification,
3842
- targetAmsNetId: subscription.remoteAddress.amsNetId,
3843
- targetAdsPort: subscription.remoteAddress.adsPort,
3844
- payload: data
3845
- });
3901
+ await this.deleteNotificationHandle(subscription.notificationHandle, subscription.remoteAddress);
3846
3902
  const address = ADS.amsAddressToString(subscription.remoteAddress);
3847
3903
  if (this.activeSubscriptions[address]) {
3848
3904
  delete this.activeSubscriptions[address][subscription.notificationHandle];
@@ -3854,6 +3910,33 @@ class Client extends events_1.default {
3854
3910
  throw new client_error_1.default(`unsubscribe(): Unsubscribing failed`, err);
3855
3911
  }
3856
3912
  }
3913
+ /**
3914
+ * Sends a delete ADS notification command to the target system.
3915
+ *
3916
+ * Doesn't delete subscriptions, just sends the ADS command.
3917
+ *
3918
+ * @param notificationHandle Notification handle to delete (number)
3919
+ * @param targetAmsAddress Target system address
3920
+ *
3921
+ * @throws NOTE: Throws error if failed
3922
+ */
3923
+ async deleteNotificationHandle(notificationHandle, targetAmsAddress) {
3924
+ this.debug(`deleteNotificationHandle(): Sending DeleteNotification command for handle ${notificationHandle} to ${ADS.amsAddressToString(targetAmsAddress)}`);
3925
+ //Allocating bytes for request
3926
+ const data = Buffer.alloc(4);
3927
+ let pos = 0;
3928
+ //0..3 Notification handle
3929
+ data.writeUInt32LE(notificationHandle, pos);
3930
+ pos += 4;
3931
+ const res = await this.sendAdsCommand({
3932
+ adsCommand: ADS.ADS_COMMAND.DeleteNotification,
3933
+ targetAmsNetId: targetAmsAddress.amsNetId,
3934
+ targetAdsPort: targetAmsAddress.adsPort,
3935
+ payload: data
3936
+ });
3937
+ this.debug(`deleteNotificationHandle(): Notification for handle ${notificationHandle} (${ADS.amsAddressToString(targetAmsAddress)}) deleted!`);
3938
+ return res.ads;
3939
+ }
3857
3940
  /**
3858
3941
  * Unsubscribes all active subscription (deletes all ADS notifications).
3859
3942
  *
@@ -4268,16 +4351,30 @@ class Client extends events_1.default {
4268
4351
  }
4269
4352
  }
4270
4353
  /**
4271
- * **TODO - DOCUMENTATION ONGOING**
4354
+ * Reads raw data from the target system by a raw ADS address (index group, index offset and data length).
4272
4355
  *
4273
- * Reads raw byte data from the target system by provided index group, index offset and data length (bytes)
4356
+ * This is the ADS protocol `Read` command.
4274
4357
  *
4275
- * This is the `ADS read` command in ADS protocol.
4358
+ * @example
4359
+ * ```js
4360
+ * try {
4361
+ * const data = await client.readRaw(16448, 414816, 2);
4362
+ * console.log(data); //<Buffer ff 7f>
4363
+ *
4364
+ * const converted = await client.convertFromRaw(data, 'INT');
4365
+ * console.log(converted); //32767
4366
+ *
4367
+ * } catch (err) {
4368
+ * console.log("Error:", err);
4369
+ * }
4370
+ * ```
4276
4371
  *
4277
4372
  * @param indexGroup Index group (address) of the data to read
4278
4373
  * @param indexOffset Index offset (address) of the data to read
4279
4374
  * @param size Data length to read (bytes)
4280
4375
  * @param targetOpts Optional target settings that override values in `settings`
4376
+ *
4377
+ * @throws Throws an error if sending the command fails or if the target responds with an error.
4281
4378
  */
4282
4379
  async readRaw(indexGroup, indexOffset, size, targetOpts = {}) {
4283
4380
  if (!this.connection.connected) {
@@ -4312,16 +4409,28 @@ class Client extends events_1.default {
4312
4409
  }
4313
4410
  }
4314
4411
  /**
4315
- * **TODO - DOCUMENTATION ONGOING**
4412
+ * Writes raw data to the target system by a raw ADS address (index group, index offset and data length).
4316
4413
  *
4317
- * Writes raw byte data to the target system by provided index group and index offset.
4414
+ * This is the ADS protocol `Write` command.
4318
4415
  *
4319
- * This is the `ADS write` command in ADS protocol.
4416
+ * @example
4417
+ * ```js
4418
+ * try {
4419
+ * const data = await client.convertToRaw(32767, 'INT');
4420
+ * console.log(data); //<Buffer ff 7f>
4421
+ *
4422
+ * await client.writeRaw(16448, 414816, data);
4423
+ * } catch (err) {
4424
+ * console.log("Error:", err);
4425
+ * }
4426
+ * ```
4320
4427
  *
4321
4428
  * @param indexGroup Index group (address) of the data to write to
4322
4429
  * @param indexOffset Index offset (address) of the data to write to
4323
4430
  * @param value Data to write
4324
4431
  * @param targetOpts Optional target settings that override values in `settings`
4432
+ *
4433
+ * @throws Throws an error if sending the command fails or if the target responds with an error.
4325
4434
  */
4326
4435
  async writeRaw(indexGroup, indexOffset, value, targetOpts = {}) {
4327
4436
  if (!this.connection.connected) {
@@ -4357,16 +4466,45 @@ class Client extends events_1.default {
4357
4466
  }
4358
4467
  }
4359
4468
  /**
4360
- * **TODO - DOCUMENTATION ONGOING**
4469
+ * Sends multiple `readRaw()` commands in one ADS packet.
4361
4470
  *
4362
- * Sends multiple readRaw() commands in one ADS packet
4471
+ * Reads raw data from the target system by a raw ADS addresses (index group, index offset and data length).
4472
+ * Results are returned for each command separately - see {@link ReadRawMultiResult} for details.
4363
4473
  *
4364
- * Reads raw byte data from the target system by provided index group, index offset and data length (bytes)
4474
+ * Uses ADS sum command under the hood (better and faster performance).
4475
+ * See [Beckhoff Information System](https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_adsdll2/9007199379576075.html&id=9180083787138954512) for more info.
4365
4476
  *
4366
- * Uses ADS sum command under the hood (better performance)
4477
+ * @example
4478
+ * ```js
4479
+ * try {
4480
+ * const results = await client.readRawMulti([
4481
+ * {
4482
+ * indexGroup: 16448,
4483
+ * indexOffset: 414816,
4484
+ * size: 2
4485
+ * },
4486
+ * {
4487
+ * indexGroup: 16448,
4488
+ * indexOffset: 414900,
4489
+ * size: 128
4490
+ * }
4491
+ * ]);
4492
+ *
4493
+ * if(results[0].success) {
4494
+ * console.log(`First result: ${results[0].value}`); //First result: <Buffer ff 7f>
4495
+ * } else {
4496
+ * console.log(`First read command failed: ${results[0].errorStr}`);
4497
+ * }
4498
+ *
4499
+ * } catch (err) {
4500
+ * console.log("Error:", err);
4501
+ * }
4502
+ * ```
4367
4503
  *
4368
4504
  * @param commands Array of read commands
4369
4505
  * @param targetOpts Optional target settings that override values in `settings`
4506
+ *
4507
+ * @throws Throws an error if sending the command fails or if the target responds with an error.
4370
4508
  */
4371
4509
  async readRawMulti(commands, targetOpts = {}) {
4372
4510
  if (!this.connection.connected) {
@@ -4442,16 +4580,50 @@ class Client extends events_1.default {
4442
4580
  }
4443
4581
  }
4444
4582
  /**
4445
- * **TODO - DOCUMENTATION ONGOING**
4583
+ * Sends multiple `writeRaw()` commands in one ADS packet.
4446
4584
  *
4447
- * Sends multiple writeRaw() commands in one ADS packet
4585
+ * Writes raw data to the target system by a raw ADS addresses (index group and index offset).
4586
+ * Results are returned for each command separately - see {@link WriteRawMultiResult} for details.
4448
4587
  *
4449
- * Writes raw byte data to the target system by provided index group and index offset.
4588
+ * Uses ADS sum command under the hood (better and faster performance).
4589
+ * See [Beckhoff Information System](https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_adsdll2/9007199379576075.html&id=9180083787138954512) for more info.
4450
4590
  *
4451
- * Uses ADS sum command under the hood (better performance)
4591
+ * @example
4592
+ * ```js
4593
+ * try {
4594
+ * const data1 = await client.convertToRaw(32767, 'INT');
4595
+ * console.log(data1); //<Buffer ff 7f>
4596
+ *
4597
+ * const data2 = Buffer.alloc(128); //example
4598
+ *
4599
+ * const results = await client.writeRawMulti([
4600
+ * {
4601
+ * indexGroup: 16448,
4602
+ * indexOffset: 414816,
4603
+ * value: data1
4604
+ * },
4605
+ * {
4606
+ * indexGroup: 16448,
4607
+ * indexOffset: 414900,
4608
+ * value: data2
4609
+ * }
4610
+ * ]);
4611
+ *
4612
+ * if(results[0].success) {
4613
+ * console.log(`First write command successful`);
4614
+ * } else {
4615
+ * console.log(`First write command failed: ${results[0].errorStr}`);
4616
+ * }
4617
+ *
4618
+ * } catch (err) {
4619
+ * console.log("Error:", err);
4620
+ * }
4621
+ * ```
4452
4622
  *
4453
4623
  * @param commands Array of write commands
4454
4624
  * @param targetOpts Optional target settings that override values in `settings`
4625
+ *
4626
+ * @throws Throws an error if sending the command fails or if the target responds with an error.
4455
4627
  */
4456
4628
  async writeRawMulti(commands, targetOpts = {}) {
4457
4629
  if (!this.connection.connected) {
@@ -4523,16 +4695,37 @@ class Client extends events_1.default {
4523
4695
  }
4524
4696
  }
4525
4697
  /**
4526
- * **TODO - DOCUMENTATION ONGOING**
4698
+ * Reads raw data from the target system by variable path (such as `GVL_Test.ExampleStruct`).
4699
+ *
4700
+ * Supports also reading `POINTER` and `REFERENCE` values (see example).
4701
+ *
4702
+ * This uses the ADS `READ_SYMVAL_BYNAME` under the hood, so only one
4703
+ * round-trip is needed.
4704
+ *
4705
+ * @example
4706
+ * ```js
4707
+ * try {
4708
+ * const data = await client.readRawByPath('GVL_Read.StandardTypes.INT_');
4709
+ * console.log(data); //<Buffer ff 7f>
4527
4710
  *
4528
- * Reads raw byte data from the target system by symbol path.
4711
+ * const converted = await client.convertFromRaw(data, 'INT');
4712
+ * console.log(converted); //32767
4529
4713
  *
4530
- * Supports also reading POINTER and REFERENCE values by using deference operator in path (`^`)
4714
+ * //Reading a POINTER value (Note the dereference operator ^)
4715
+ * const ptrValue = await client.readRawByPath('GVL_Read.ComplexTypes.POINTER_^');
4531
4716
  *
4532
- * This uses the ADS command `READ_SYMVAL_BYNAME` under the hood
4717
+ * //Reading a REFERENCE value
4718
+ * const refValue = await client.readRawByPath('GVL_Read.ComplexTypes.REFERENCE_');
4719
+ *
4720
+ * } catch (err) {
4721
+ * console.log("Error:", err);
4722
+ * }
4723
+ * ```
4533
4724
  *
4534
4725
  * @param path Variable path in the PLC to read (such as `GVL_Test.ExampleStruct`)
4535
4726
  * @param targetOpts Optional target settings that override values in `settings`
4727
+ *
4728
+ * @throws Throws an error if sending the command fails or if the target responds with an error.
4536
4729
  */
4537
4730
  async readRawByPath(path, targetOpts = {}) {
4538
4731
  if (!this.connection.connected) {
@@ -4574,17 +4767,39 @@ class Client extends events_1.default {
4574
4767
  }
4575
4768
  }
4576
4769
  /**
4577
- * **TODO - DOCUMENTATION ONGOING**
4770
+ * Writes raw data to the target system by variable path (such as `GVL_Test.ExampleStruct`).
4578
4771
  *
4579
- * Writes raw byte data to the target system by symbol path.
4772
+ * Supports also writing `POINTER` and `REFERENCE` values (see example).
4580
4773
  *
4581
- * Supports also reading POINTER and REFERENCE values by using deference operator in path (`^`)
4774
+ * NOTE: Unlike with {@link readRawByPath}(), this command uses multiple ADS requests for the operation.
4582
4775
  *
4583
- * Unlike `readRawByPath()`, this uses variable handles under the hood, the as there is no direct ADS command available for this.
4584
4776
  *
4585
- * @param path Variable path in the PLC to read (such as `GVL_Test.ExampleStruct`)
4777
+ * @example
4778
+ * ```js
4779
+ * try {
4780
+ * const data = await client.convertToRaw(32767, 'INT');
4781
+ * console.log(data); //<Buffer ff 7f>
4782
+ *
4783
+ * await client.writeRawByPath('GVL_Write.StandardTypes.INT_', data);
4784
+ *
4785
+ * //Writing a POINTER value (Note the dereference operator ^)
4786
+ * const ptrValue = ...
4787
+ * await client.writeRawByPath('GVL_Read.ComplexTypes.POINTER_^', ptrValue);
4788
+ *
4789
+ * //Writing a REFERENCE value
4790
+ * const refValue = ...
4791
+ * await client.readRawByPath('GVL_Read.ComplexTypes.REFERENCE_');
4792
+ *
4793
+ * } catch (err) {
4794
+ * console.log("Error:", err);
4795
+ * }
4796
+ * ```
4797
+ *
4798
+ * @param path Variable path in the PLC to write (such as `GVL_Test.ExampleStruct`)
4586
4799
  * @param value Data to write
4587
4800
  * @param targetOpts Optional target settings that override values in `settings`
4801
+ *
4802
+ * @throws Throws an error if sending the command fails or if the target responds with an error.
4588
4803
  */
4589
4804
  async writeRawByPath(path, value, targetOpts = {}) {
4590
4805
  if (!this.connection.connected) {
@@ -4594,12 +4809,12 @@ class Client extends events_1.default {
4594
4809
  try {
4595
4810
  let handle = null;
4596
4811
  try {
4597
- handle = await this.createVariableHandle(path);
4598
- await this.writeRawByHandle(handle, value);
4812
+ handle = await this.createVariableHandle(path, targetOpts);
4813
+ await this.writeRawByHandle(handle, value, targetOpts);
4599
4814
  }
4600
4815
  finally {
4601
4816
  if (handle) {
4602
- await this.deleteVariableHandle(handle);
4817
+ await this.deleteVariableHandle(handle, targetOpts);
4603
4818
  }
4604
4819
  }
4605
4820
  this.debug(`writeRawByPath(): Writing raw data to ${path} done (${value.byteLength} bytes)`);
@@ -4610,25 +4825,41 @@ class Client extends events_1.default {
4610
4825
  }
4611
4826
  }
4612
4827
  /**
4613
- * **TODO - DOCUMENTATION ONGOING**
4828
+ * Writes raw data to the target system by a raw ADS address (index group, index offset)
4829
+ * and reads the result as raw data.
4614
4830
  *
4615
- * Writes raw data to the target and reads the result as raw data
4831
+ * This is the ADS protocol `ReadWrite` command.
4616
4832
  *
4617
- * Uses `ADS ReadWrite` command
4833
+ * @example
4834
+ * ```js
4835
+ * const { ADS } = require('../dist/ads-client');
4836
+ *
4837
+ * try {
4838
+ * //Reading raw value by symbol path (= same as readRawByPath())
4839
+ * const path = ADS.encodeStringToPlcStringBuffer('GVL_Read.StandardTypes.INT_');
4840
+ * const data = await client.readWriteRaw(ADS.ADS_RESERVED_INDEX_GROUPS.SymbolValueByName, 0, 0xFFFFFFFF, path);
4841
+ * console.log(data); //<Buffer ff 7f>
4842
+ *
4843
+ * } catch (err) {
4844
+ * console.log("Error:", err);
4845
+ * }
4846
+ * ```
4618
4847
  *
4619
4848
  * @param indexGroup Address index group
4620
4849
  * @param indexOffset Address index offset
4621
- * @param size How many bytes to read
4622
- * @param writeData Data to write
4850
+ * @param size Data length to read (bytes)
4851
+ * @param value Value to write
4623
4852
  * @param targetOpts Optional target settings that override values in `settings`
4853
+ *
4854
+ * @throws Throws an error if sending the command fails or if the target responds with an error.
4624
4855
  */
4625
- async readWriteRaw(indexGroup, indexOffset, size, writeData, targetOpts = {}) {
4856
+ async readWriteRaw(indexGroup, indexOffset, size, value, targetOpts = {}) {
4626
4857
  if (!this.connection.connected) {
4627
4858
  throw new client_error_1.default(`readWriteRaw(): Client is not connected. Use connect() to connect to the target first.`);
4628
4859
  }
4629
- this.debug(`readWriteRaw(): Sending ReadWrite command (${JSON.stringify({ indexGroup, indexOffset, size })} with ${writeData.byteLength} bytes of data`);
4860
+ this.debug(`readWriteRaw(): Sending ReadWrite command (${JSON.stringify({ indexGroup, indexOffset, size })} with ${value.byteLength} bytes of data`);
4630
4861
  //Allocating bytes for request
4631
- const data = Buffer.alloc(16 + writeData.byteLength);
4862
+ const data = Buffer.alloc(16 + value.byteLength);
4632
4863
  let pos = 0;
4633
4864
  //0..3 IndexGroup
4634
4865
  data.writeUInt32LE(indexGroup, pos);
@@ -4640,11 +4871,11 @@ class Client extends events_1.default {
4640
4871
  data.writeUInt32LE(size, pos);
4641
4872
  pos += 4;
4642
4873
  //12..15 Write data length
4643
- data.writeUInt32LE(writeData.byteLength, pos);
4874
+ data.writeUInt32LE(value.byteLength, pos);
4644
4875
  pos += 4;
4645
4876
  //16..n Write data
4646
- writeData.copy(data, pos);
4647
- pos += writeData.byteLength;
4877
+ value.copy(data, pos);
4878
+ pos += value.byteLength;
4648
4879
  try {
4649
4880
  const res = await this.sendAdsCommand({
4650
4881
  adsCommand: ADS.ADS_COMMAND.ReadWrite,
@@ -4661,14 +4892,52 @@ class Client extends events_1.default {
4661
4892
  }
4662
4893
  }
4663
4894
  /**
4664
- * **TODO - DOCUMENTATION ONGOING**
4895
+ * Sends multiple `readWriteRaw()` commands in one ADS packet.
4665
4896
  *
4666
- * Sends multiple readWriteRaw() commands in one ADS packet
4897
+ * Writes raw data to the target system by a raw ADS address (index group, index offset)
4898
+ * and reads the result as raw data.
4667
4899
  *
4668
- * Uses ADS sum command under the hood (better performance)
4900
+ * Uses ADS sum command under the hood (better and faster performance).
4901
+ * See [Beckhoff Information System](https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_adsdll2/9007199379576075.html&id=9180083787138954512) for more info.
4669
4902
  *
4670
- * @param commands Array of read write commands
4903
+ * @example
4904
+ * ```js
4905
+ * try {
4906
+ * //Reading raw values by symbol paths (= same as readRawByPath())
4907
+ * const path = ADS.encodeStringToPlcStringBuffer('GVL_Read.StandardTypes.INT_');
4908
+ * const path2 = ADS.encodeStringToPlcStringBuffer('GVL_Read.StandardTypes.REAL_');
4909
+ *
4910
+ * const results = await client.readWriteRawMulti([
4911
+ * {
4912
+ * indexGroup: ADS.ADS_RESERVED_INDEX_GROUPS.SymbolValueByName,
4913
+ * indexOffset: 0,
4914
+ * size: 0xFFFF,
4915
+ * value: path
4916
+ * },
4917
+ * {
4918
+ * indexGroup: ADS.ADS_RESERVED_INDEX_GROUPS.SymbolValueByName,
4919
+ * indexOffset: 0,
4920
+ * size: 0xFFFF,
4921
+ * value: path2
4922
+ * }
4923
+ * ]);
4924
+ *
4925
+ * if(results[0].success) {
4926
+ * console.log(`First result: ${results[0].value}`); //First result: <Buffer ff 7f>
4927
+ * } else {
4928
+ * console.log(`First read/write command failed: ${results[0].errorStr}`);
4929
+ * }
4930
+ *
4931
+ * } catch (err) {
4932
+ * console.log("Error:", err);
4933
+ * }
4934
+ *
4935
+ * ```
4936
+ *
4937
+ * @param commands Array of read/write commands
4671
4938
  * @param targetOpts Optional target settings that override values in `settings`
4939
+ *
4940
+ * @throws Throws an error if sending the command fails or if the target responds with an error.
4672
4941
  */
4673
4942
  async readWriteRawMulti(commands, targetOpts = {}) {
4674
4943
  if (!this.connection.connected) {
@@ -4676,7 +4945,7 @@ class Client extends events_1.default {
4676
4945
  }
4677
4946
  this.debug(`readWriteRawMulti(): Sending ${commands.length} ReadWrite commands`);
4678
4947
  const totalSize = commands.reduce((total, command) => total + command.size, 0);
4679
- const totalWriteSize = commands.reduce((total, command) => total + command.writeData.byteLength, 0);
4948
+ const totalWriteSize = commands.reduce((total, command) => total + command.value.byteLength, 0);
4680
4949
  //Allocating bytes for request
4681
4950
  const data = Buffer.alloc(16 + commands.length * 16 + totalWriteSize);
4682
4951
  let pos = 0;
@@ -4704,13 +4973,13 @@ class Client extends events_1.default {
4704
4973
  data.writeUInt32LE(command.size, pos);
4705
4974
  pos += 4;
4706
4975
  //12..15 Write data length
4707
- data.writeUInt32LE(command.writeData.byteLength, pos);
4976
+ data.writeUInt32LE(command.value.byteLength, pos);
4708
4977
  pos += 4;
4709
4978
  });
4710
4979
  //data
4711
4980
  commands.forEach(command => {
4712
- command.writeData.copy(data, pos);
4713
- pos += command.writeData.byteLength;
4981
+ command.value.copy(data, pos);
4982
+ pos += command.value.byteLength;
4714
4983
  });
4715
4984
  try {
4716
4985
  const res = await this.sendAdsCommand({
@@ -4759,13 +5028,28 @@ class Client extends events_1.default {
4759
5028
  }
4760
5029
  }
4761
5030
  /**
4762
- * **TODO - DOCUMENTATION ONGOING**
5031
+ * Reads variable's value from the target system by a variable path (such as `GVL_Test.ExampleStruct`)
5032
+ * and returns the value as a Javascript object.
4763
5033
  *
4764
- * Reads a value by a variable path (such as `GVL_Test.ExampleStruct`) and converts the value to a Javascript object.
5034
+ * Returns variable's
5035
+ * - converted value
5036
+ * - raw value
5037
+ * - data type
5038
+ * - symbol
4765
5039
  *
4766
- * Returns the converted value, the raw value, the data type and the symbol.
5040
+ * **NOTE:** This requires that the target is a PLC runtime or has equivalent ADS protocol support.
4767
5041
  *
4768
- * @param path Variable path in the PLC to read (such as `GVL_Test.ExampleStruct`)
5042
+ * @example
5043
+ * ```js
5044
+ * try {
5045
+ * const res = await client.readValue('GVL_Test.ExampleStruct');
5046
+ * console.log(res.value);
5047
+ * } catch (err) {
5048
+ * console.log("Error:", err);
5049
+ * }
5050
+ * ```
5051
+ *
5052
+ * @param path Variable path in the PLC (such as `GVL_Test.ExampleStruct`)
4769
5053
  * @param targetOpts Optional target settings that override values in `settings`
4770
5054
  *
4771
5055
  * @template T In Typescript, the data type of the value, for example `readValue<number>(...)` or `readValue<ST_TypedStruct>(...)` (default: `any`)
@@ -4824,13 +5108,30 @@ class Client extends events_1.default {
4824
5108
  };
4825
5109
  }
4826
5110
  /**
4827
- * **TODO - DOCUMENTATION ONGOING**
5111
+ * Reads variable's value from the target system by a symbol object
5112
+ * and returns the value as a Javascript object.
4828
5113
  *
4829
- * Reads a value by a symbol and converts the value to a Javascript object.
5114
+ * Returns variable's
5115
+ * - converted value
5116
+ * - raw value
5117
+ * - data type
5118
+ * - symbol
4830
5119
  *
4831
- * Returns the converted value, the raw value, the data type and the symbol.
5120
+ * **NOTE:** This requires that the target is a PLC runtime or has equivalent ADS protocol support.
4832
5121
  *
4833
- * @param symbol Symbol (acquired using `getSymbol()`)
5122
+ * @example
5123
+ * ```js
5124
+ * try {
5125
+ * const symbol = await client.getSymbol('GVL_Test.ExampleStruct');
5126
+ *
5127
+ * const res = await client.readValueBySymbol(symbol);
5128
+ * console.log(res.value);
5129
+ * } catch (err) {
5130
+ * console.log("Error:", err);
5131
+ * }
5132
+ * ```
5133
+ *
5134
+ * @param symbol Symbol object (acquired using {@link getSymbol}())
4834
5135
  * @param targetOpts Optional target settings that override values in `settings`
4835
5136
  *
4836
5137
  * @template T In Typescript, the data type of the value, for example `readValueBySymbol<number>(...)` or `readValueBySymbol<ST_TypedStruct>(...)` (default: `any`)
@@ -4842,18 +5143,36 @@ class Client extends events_1.default {
4842
5143
  return this.readValue(symbol.name, targetOpts);
4843
5144
  }
4844
5145
  /**
4845
- * **TODO - DOCUMENTATION ONGOING**
5146
+ * Writes variable's value to the target system by a variable path (such as `GVL_Test.ExampleStruct`).
5147
+ * Converts the value from a Javascript object to a raw value.
4846
5148
  *
4847
- * Writes a value by a variable path (such as `GVL_Test.ExampleStruct`). Converts the value from a Javascript object to a raw value.
5149
+ * Returns variable's
5150
+ * - converted value
5151
+ * - raw value
5152
+ * - data type
5153
+ * - symbol
4848
5154
  *
4849
- * Returns the converted value, the raw value, the data type and the symbol.
5155
+ * **NOTE:** Do not use `autoFill` for `UNION` types, it doesn't work correctly.
4850
5156
  *
4851
- * **NOTE:** Do not use `autoFill` for `UNION` types, it works without errors but the result isn't probably the desired one
5157
+ * **NOTE:** This requires that the target is a PLC runtime or has equivalent ADS protocol support.
4852
5158
  *
4853
- * @param path Variable path in the PLC to read (such as `GVL_Test.ExampleStruct`)
5159
+ * @example
5160
+ * ```js
5161
+ * try {
5162
+ * const value = {
5163
+ * example: true
5164
+ * };
5165
+ *
5166
+ * const res = await client.writeValue('GVL_Test.ExampleStruct', value);
5167
+ * } catch (err) {
5168
+ * console.log("Error:", err);
5169
+ * }
5170
+ * ```
5171
+ *
5172
+ * @param path Variable path in the PLC (such as `GVL_Test.ExampleStruct`)
4854
5173
  * @param value Value to write
4855
5174
  * @param targetOpts Optional target settings that override values in `settings`
4856
- * @param autoFill If true and data type is a container (`STRUCT`, `FUNCTION_BLOCK` etc.), missing properties are automatically **set to default values** (usually `0` or `''`)
5175
+ * @param autoFill If set and the data type is a container (`STRUCT`, `FUNCTION_BLOCK` etc.), missing properties are automatically set to default values (usually `0` or `''`).
4857
5176
  *
4858
5177
  * @template T In Typescript, the data type of the value, for example `writeValue<number>(...)` or `writeValue<ST_TypedStruct>(...)`
4859
5178
  */