ads-client 2.0.0-beta.3 → 2.0.0-beta.4
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.
- package/CHANGELOG.md +13 -0
- package/README.md +505 -258
- package/dist/ads-client.d.ts +280 -69
- package/dist/ads-client.js +332 -76
- package/dist/ads-client.js.map +1 -1
- package/package.json +3 -4
package/dist/ads-client.js
CHANGED
|
@@ -659,7 +659,7 @@ class Client extends events_1.default {
|
|
|
659
659
|
};
|
|
660
660
|
this.socket?.once('error', errorHandler);
|
|
661
661
|
try {
|
|
662
|
-
|
|
662
|
+
this.socketWrite(packet);
|
|
663
663
|
}
|
|
664
664
|
catch (err) {
|
|
665
665
|
this.socket?.off('error', errorHandler);
|
|
@@ -715,15 +715,45 @@ class Client extends events_1.default {
|
|
|
715
715
|
//Sometimes close event is not received, so resolve already here
|
|
716
716
|
this.socket.once('end', () => {
|
|
717
717
|
this.debugD(`unregisterAdsPort(): Socket connection ended, connection closed.`);
|
|
718
|
+
clearTimeout(this.portRegisterTimeoutTimer);
|
|
719
|
+
this.amsTcpCallback = undefined;
|
|
718
720
|
this.socket?.destroy();
|
|
719
721
|
resolve();
|
|
720
722
|
});
|
|
723
|
+
this.amsTcpCallback = (res) => {
|
|
724
|
+
this.amsTcpCallback = undefined;
|
|
725
|
+
clearTimeout(this.portRegisterTimeoutTimer);
|
|
726
|
+
if (res.amsTcp.command === ADS.AMS_HEADER_FLAG.AMS_TCP_PORT_CLOSE) {
|
|
727
|
+
this.debug(`unregisterAdsPort(): ADS port unregistered`);
|
|
728
|
+
this.socket?.destroy();
|
|
729
|
+
resolve();
|
|
730
|
+
}
|
|
731
|
+
};
|
|
732
|
+
//Timeout (if no answer from router)
|
|
733
|
+
this.portRegisterTimeoutTimer = setTimeout(() => {
|
|
734
|
+
//Callback is no longer needed, delete it
|
|
735
|
+
this.amsTcpCallback = undefined;
|
|
736
|
+
//Create a custom "ads error" so that the info is passed onwards
|
|
737
|
+
const adsError = {
|
|
738
|
+
ads: {
|
|
739
|
+
error: true,
|
|
740
|
+
errorCode: -1,
|
|
741
|
+
errorStr: `Timeout - no response in ${this.settings.timeoutDelay} ms`
|
|
742
|
+
}
|
|
743
|
+
};
|
|
744
|
+
this.debug(`unregisterAdsPort(): Failed to unregister ADS port: Timeout - no response in ${this.settings.timeoutDelay} ms`);
|
|
745
|
+
return reject(new client_error_1.default(`unregisterAdsPort(): Timeout - no response in ${this.settings.timeoutDelay} ms`, adsError));
|
|
746
|
+
}, this.settings.timeoutDelay);
|
|
721
747
|
try {
|
|
722
|
-
|
|
748
|
+
this.socketWrite(buffer);
|
|
723
749
|
}
|
|
724
750
|
catch (err) {
|
|
725
751
|
reject(err);
|
|
726
752
|
}
|
|
753
|
+
finally {
|
|
754
|
+
this.amsTcpCallback = undefined;
|
|
755
|
+
clearTimeout(this.portRegisterTimeoutTimer);
|
|
756
|
+
}
|
|
727
757
|
});
|
|
728
758
|
}
|
|
729
759
|
/**
|
|
@@ -1379,7 +1409,12 @@ class Client extends events_1.default {
|
|
|
1379
1409
|
//AMS port unregister
|
|
1380
1410
|
case ADS.AMS_HEADER_FLAG.AMS_TCP_PORT_CLOSE:
|
|
1381
1411
|
packet.amsTcp.commandStr = 'Port unregister';
|
|
1382
|
-
|
|
1412
|
+
if (this.amsTcpCallback) {
|
|
1413
|
+
this.amsTcpCallback(packet);
|
|
1414
|
+
}
|
|
1415
|
+
else {
|
|
1416
|
+
this.debug(`onAmsTcpPacketReceived(): Port unregister response received but no callback was assigned (${packet.amsTcp.commandStr})`);
|
|
1417
|
+
}
|
|
1383
1418
|
break;
|
|
1384
1419
|
//AMS port register
|
|
1385
1420
|
case ADS.AMS_HEADER_FLAG.AMS_TCP_PORT_CONNECT:
|
|
@@ -2325,6 +2360,7 @@ class Client extends events_1.default {
|
|
|
2325
2360
|
if (err.adsError && err.adsError?.errorCode === 1808) {
|
|
2326
2361
|
//Type wasn't found.
|
|
2327
2362
|
//Might be TwinCAT 2 system that doesn't provide pseudo or base data types by ADS --> check if we know the type ourselves
|
|
2363
|
+
const originalName = name;
|
|
2328
2364
|
if (ADS.BASE_DATA_TYPES.isPseudoType(name)) {
|
|
2329
2365
|
//This converts e.g. PVOID to a primitive type
|
|
2330
2366
|
if (knownSize === undefined) {
|
|
@@ -2358,6 +2394,11 @@ class Client extends events_1.default {
|
|
|
2358
2394
|
extendedFlags: 0,
|
|
2359
2395
|
reserved: Buffer.alloc(0)
|
|
2360
2396
|
};
|
|
2397
|
+
//Adding to cache, even though it's not read from the target
|
|
2398
|
+
//With TwinCAT 2, this prevents trying to read base types again and again from the target (as there aren't any)
|
|
2399
|
+
if (!this.settings.disableCaching && !targetOpts.adsPort && !targetOpts.amsNetId) {
|
|
2400
|
+
this.metaData.plcDataTypes[originalName.toLowerCase()] = dataType;
|
|
2401
|
+
}
|
|
2361
2402
|
}
|
|
2362
2403
|
else {
|
|
2363
2404
|
//Type is unknown - we can't do anything
|
|
@@ -2401,7 +2442,7 @@ class Client extends events_1.default {
|
|
|
2401
2442
|
}
|
|
2402
2443
|
}
|
|
2403
2444
|
else if ((((dataType.type === '' && !ADS.BASE_DATA_TYPES.isPseudoType(dataType.name)) || ADS.BASE_DATA_TYPES.isKnownType(dataType.name))
|
|
2404
|
-
&& dataType.flagsStr.includes('DataType')
|
|
2445
|
+
&& (dataType.flagsStr.includes('DataType') || ADS.BASE_DATA_TYPES.isKnownType(dataType.name)) //isKnownType() call is for TwinCAT 2 support, as base types (like INT16) do not have DataType flag (but it's the final base type)
|
|
2405
2446
|
&& !dataType.flagsStr.includes('EnumInfos')
|
|
2406
2447
|
&& dataType.arrayDimension === 0)) {
|
|
2407
2448
|
//This is final form (no need to go deeper)
|
|
@@ -2409,8 +2450,10 @@ class Client extends events_1.default {
|
|
|
2409
2450
|
}
|
|
2410
2451
|
else if (dataType.arrayDimension > 0) {
|
|
2411
2452
|
//Data type is an array - get array subtype
|
|
2453
|
+
//TwinCAT 2 support - calculate size if it's array of pointer etc.
|
|
2454
|
+
const size = dataType.size / dataType.arrayInfos.reduce((total, dimension) => total * dimension.length, 1);
|
|
2412
2455
|
builtType = {
|
|
2413
|
-
...(await this.buildDataType(dataType.type, targetOpts, false))
|
|
2456
|
+
...(await this.buildDataType(dataType.type, targetOpts, false, size))
|
|
2414
2457
|
};
|
|
2415
2458
|
builtType.arrayInfos = [...dataType.arrayInfos, ...builtType.arrayInfos];
|
|
2416
2459
|
}
|
|
@@ -3381,7 +3424,7 @@ class Client extends events_1.default {
|
|
|
3381
3424
|
* @example
|
|
3382
3425
|
* ```js
|
|
3383
3426
|
* try {
|
|
3384
|
-
* const symbol = await client.getSymbol('
|
|
3427
|
+
* const symbol = await client.getSymbol('GVL_Read.StandardTypes.INT_');
|
|
3385
3428
|
* } catch (err) {
|
|
3386
3429
|
* console.log("Error:", err);
|
|
3387
3430
|
* }
|
|
@@ -3677,7 +3720,7 @@ class Client extends events_1.default {
|
|
|
3677
3720
|
* //Checks if value has changed every 100ms
|
|
3678
3721
|
* //Callback is called only when the value has changed
|
|
3679
3722
|
* await client.subscribeValue(
|
|
3680
|
-
* '
|
|
3723
|
+
* 'GVL_Subscription.NumericValue_10ms',
|
|
3681
3724
|
* (data, subscription) => {
|
|
3682
3725
|
* console.log(`Value of ${subscription.symbol.name} has changed: ${data.value}`);
|
|
3683
3726
|
* },
|
|
@@ -3825,7 +3868,7 @@ class Client extends events_1.default {
|
|
|
3825
3868
|
* //Checks if value has changed every 100ms
|
|
3826
3869
|
* //Callback is called only when the value has changed
|
|
3827
3870
|
* await client.subscribe({
|
|
3828
|
-
* target: '
|
|
3871
|
+
* target: 'GVL_Subscription.NumericValue_10ms',
|
|
3829
3872
|
* callback: (data, subscription) => {
|
|
3830
3873
|
* console.log(`Value of ${subscription.symbol.name} has changed: ${data.value}`);
|
|
3831
3874
|
* },
|
|
@@ -4773,7 +4816,6 @@ class Client extends events_1.default {
|
|
|
4773
4816
|
*
|
|
4774
4817
|
* NOTE: Unlike with {@link readRawByPath}(), this command uses multiple ADS requests for the operation.
|
|
4775
4818
|
*
|
|
4776
|
-
*
|
|
4777
4819
|
* @example
|
|
4778
4820
|
* ```js
|
|
4779
4821
|
* try {
|
|
@@ -5042,7 +5084,7 @@ class Client extends events_1.default {
|
|
|
5042
5084
|
* @example
|
|
5043
5085
|
* ```js
|
|
5044
5086
|
* try {
|
|
5045
|
-
* const res = await client.readValue('
|
|
5087
|
+
* const res = await client.readValue('GVL_Read.StandardTypes.INT_');
|
|
5046
5088
|
* console.log(res.value);
|
|
5047
5089
|
* } catch (err) {
|
|
5048
5090
|
* console.log("Error:", err);
|
|
@@ -5053,6 +5095,7 @@ class Client extends events_1.default {
|
|
|
5053
5095
|
* @param targetOpts Optional target settings that override values in `settings`
|
|
5054
5096
|
*
|
|
5055
5097
|
* @template T In Typescript, the data type of the value, for example `readValue<number>(...)` or `readValue<ST_TypedStruct>(...)` (default: `any`)
|
|
5098
|
+
* @throws Throws an error if sending the command fails or if the target responds with an error.
|
|
5056
5099
|
*/
|
|
5057
5100
|
async readValue(path, targetOpts = {}) {
|
|
5058
5101
|
if (!this.connection.connected) {
|
|
@@ -5073,7 +5116,8 @@ class Client extends events_1.default {
|
|
|
5073
5116
|
let dataType;
|
|
5074
5117
|
try {
|
|
5075
5118
|
this.debugD(`readValue(): Getting data type for ${path}`);
|
|
5076
|
-
|
|
5119
|
+
//Also passing size for TC2 pointer/pseudo type support
|
|
5120
|
+
dataType = await this.buildDataType(symbol.type, targetOpts, true, symbol.size);
|
|
5077
5121
|
}
|
|
5078
5122
|
catch (err) {
|
|
5079
5123
|
this.debug(`readValue(): Getting data type for ${path} failed: %o`, err);
|
|
@@ -5108,7 +5152,7 @@ class Client extends events_1.default {
|
|
|
5108
5152
|
};
|
|
5109
5153
|
}
|
|
5110
5154
|
/**
|
|
5111
|
-
* Reads variable's value from the target system by a symbol object
|
|
5155
|
+
* Reads variable's value from the target system by a symbol object (acquired using `getSymbol()`)
|
|
5112
5156
|
* and returns the value as a Javascript object.
|
|
5113
5157
|
*
|
|
5114
5158
|
* Returns variable's
|
|
@@ -5122,7 +5166,7 @@ class Client extends events_1.default {
|
|
|
5122
5166
|
* @example
|
|
5123
5167
|
* ```js
|
|
5124
5168
|
* try {
|
|
5125
|
-
* const symbol = await client.getSymbol('
|
|
5169
|
+
* const symbol = await client.getSymbol('GVL_Read.StandardTypes.INT_');
|
|
5126
5170
|
*
|
|
5127
5171
|
* const res = await client.readValueBySymbol(symbol);
|
|
5128
5172
|
* console.log(res.value);
|
|
@@ -5131,10 +5175,11 @@ class Client extends events_1.default {
|
|
|
5131
5175
|
* }
|
|
5132
5176
|
* ```
|
|
5133
5177
|
*
|
|
5134
|
-
* @param symbol Symbol object
|
|
5178
|
+
* @param symbol Symbol object
|
|
5135
5179
|
* @param targetOpts Optional target settings that override values in `settings`
|
|
5136
5180
|
*
|
|
5137
5181
|
* @template T In Typescript, the data type of the value, for example `readValueBySymbol<number>(...)` or `readValueBySymbol<ST_TypedStruct>(...)` (default: `any`)
|
|
5182
|
+
* @throws Throws an error if sending the command fails or if the target responds with an error.
|
|
5138
5183
|
*/
|
|
5139
5184
|
async readValueBySymbol(symbol, targetOpts = {}) {
|
|
5140
5185
|
if (!this.connection.connected) {
|
|
@@ -5163,7 +5208,7 @@ class Client extends events_1.default {
|
|
|
5163
5208
|
* example: true
|
|
5164
5209
|
* };
|
|
5165
5210
|
*
|
|
5166
|
-
* const res = await client.writeValue('
|
|
5211
|
+
* const res = await client.writeValue('GVL_Read.StandardTypes.INT_', value);
|
|
5167
5212
|
* } catch (err) {
|
|
5168
5213
|
* console.log("Error:", err);
|
|
5169
5214
|
* }
|
|
@@ -5172,9 +5217,10 @@ class Client extends events_1.default {
|
|
|
5172
5217
|
* @param path Variable path in the PLC (such as `GVL_Test.ExampleStruct`)
|
|
5173
5218
|
* @param value Value to write
|
|
5174
5219
|
* @param targetOpts Optional target settings that override values in `settings`
|
|
5175
|
-
* @param autoFill If set and the data type is a container (`STRUCT`, `FUNCTION_BLOCK` etc.), missing properties are automatically set to
|
|
5220
|
+
* @param autoFill 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).
|
|
5176
5221
|
*
|
|
5177
5222
|
* @template T In Typescript, the data type of the value, for example `writeValue<number>(...)` or `writeValue<ST_TypedStruct>(...)`
|
|
5223
|
+
* @throws Throws an error if sending the command fails or if the target responds with an error.
|
|
5178
5224
|
*/
|
|
5179
5225
|
async writeValue(path, value, autoFill = false, targetOpts = {}) {
|
|
5180
5226
|
if (!this.connection.connected) {
|
|
@@ -5195,7 +5241,8 @@ class Client extends events_1.default {
|
|
|
5195
5241
|
let dataType;
|
|
5196
5242
|
try {
|
|
5197
5243
|
this.debugD(`writeValue(): Getting data type for ${path}`);
|
|
5198
|
-
|
|
5244
|
+
//Also passing size for TC2 pointer/pseudo type support
|
|
5245
|
+
dataType = await this.buildDataType(symbol.type, targetOpts, true, symbol.size);
|
|
5199
5246
|
}
|
|
5200
5247
|
catch (err) {
|
|
5201
5248
|
this.debug(`writeValue(): Getting data type for ${path} failed: %o`, err);
|
|
@@ -5253,20 +5300,37 @@ class Client extends events_1.default {
|
|
|
5253
5300
|
};
|
|
5254
5301
|
}
|
|
5255
5302
|
/**
|
|
5256
|
-
*
|
|
5303
|
+
* Writes variable's value to the target system by a symbol object (acquired using `getSymbol()`).
|
|
5304
|
+
* Converts the value from a Javascript object to a raw value.
|
|
5305
|
+
*
|
|
5306
|
+
* Returns variable's
|
|
5307
|
+
* - converted value
|
|
5308
|
+
* - raw value
|
|
5309
|
+
* - data type
|
|
5310
|
+
* - symbol
|
|
5311
|
+
*
|
|
5312
|
+
* **NOTE:** Do not use `autoFill` for `UNION` types, it doesn't work correctly.
|
|
5257
5313
|
*
|
|
5258
|
-
*
|
|
5314
|
+
* **NOTE:** This requires that the target is a PLC runtime or has equivalent ADS protocol support.
|
|
5259
5315
|
*
|
|
5260
|
-
*
|
|
5316
|
+
* @example
|
|
5317
|
+
* ```js
|
|
5318
|
+
* try {
|
|
5319
|
+
* const symbol = await client.getSymbol('GVL_Read.StandardTypes.INT_');
|
|
5261
5320
|
*
|
|
5262
|
-
*
|
|
5321
|
+
* const res = await client.writeValueBySymbol(symbol, 32767);
|
|
5322
|
+
* } catch (err) {
|
|
5323
|
+
* console.log("Error:", err);
|
|
5324
|
+
* }
|
|
5325
|
+
* ```
|
|
5263
5326
|
*
|
|
5264
|
-
* @param symbol Symbol
|
|
5327
|
+
* @param symbol Symbol object
|
|
5265
5328
|
* @param value Value to write
|
|
5266
5329
|
* @param targetOpts Optional target settings that override values in `settings`
|
|
5267
|
-
* @param autoFill If
|
|
5330
|
+
* @param autoFill 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).
|
|
5268
5331
|
*
|
|
5269
5332
|
* @template T In Typescript, the data type of the value, for example `writeValue<number>(...)` or `writeValue<ST_TypedStruct>(...)`
|
|
5333
|
+
* @throws Throws an error if sending the command fails or if the target responds with an error.
|
|
5270
5334
|
*/
|
|
5271
5335
|
async writeValueBySymbol(symbol, value, autoFill = false, targetOpts = {}) {
|
|
5272
5336
|
if (!this.connection.connected) {
|
|
@@ -5275,14 +5339,27 @@ class Client extends events_1.default {
|
|
|
5275
5339
|
return this.writeValue(symbol.name, value, autoFill, targetOpts);
|
|
5276
5340
|
}
|
|
5277
5341
|
/**
|
|
5278
|
-
* **TODO - DOCUMENTATION ONGOING**
|
|
5279
|
-
*
|
|
5280
5342
|
* Returns a default (empty) Javascript object representing provided PLC data type.
|
|
5281
5343
|
*
|
|
5282
|
-
* @
|
|
5344
|
+
* @example
|
|
5345
|
+
* ```js
|
|
5346
|
+
* try {
|
|
5347
|
+
* const res = await client.getDefaultPlcObject('INT');
|
|
5348
|
+
* console.log(res); //0
|
|
5349
|
+
|
|
5350
|
+
* const res2 = await client.getDefaultPlcObject('Tc2_Standard.TON');
|
|
5351
|
+
* console.log(res2); //{ IN: false, PT: 0, Q: false, ET: 0, M: false, StartTime: 0 }
|
|
5352
|
+
*
|
|
5353
|
+
* } catch (err) {
|
|
5354
|
+
* console.log("Error:", err);
|
|
5355
|
+
* }
|
|
5356
|
+
* ```
|
|
5357
|
+
*
|
|
5358
|
+
* @param dataType Data type name in the PLC as string (such as `ST_Struct`) or data type object (acquired using {@link getDataType}())
|
|
5283
5359
|
* @param targetOpts Optional target settings that override values in `settings`
|
|
5284
5360
|
*
|
|
5285
|
-
* @template T Typescript data type of the PLC data, for example `
|
|
5361
|
+
* @template T Typescript data type of the PLC data, for example `getDefaultPlcObject<number>(...)` or `getDefaultPlcObject<ST_TypedStruct>(...)`
|
|
5362
|
+
* @throws Throws an error if sending the command fails or if the target responds with an error.
|
|
5286
5363
|
*/
|
|
5287
5364
|
async getDefaultPlcObject(dataType, targetOpts = {}) {
|
|
5288
5365
|
if (!this.connection.connected) {
|
|
@@ -5306,15 +5383,28 @@ class Client extends events_1.default {
|
|
|
5306
5383
|
return value;
|
|
5307
5384
|
}
|
|
5308
5385
|
/**
|
|
5309
|
-
*
|
|
5386
|
+
* Converts raw data to a Javascript object by using the provided data type.
|
|
5310
5387
|
*
|
|
5311
|
-
*
|
|
5388
|
+
* @example
|
|
5389
|
+
* ```js
|
|
5390
|
+
* try {
|
|
5391
|
+
* const data = await client.readRaw(16448, 414816, 2);
|
|
5392
|
+
* console.log(data); //<Buffer ff 7f>
|
|
5312
5393
|
*
|
|
5313
|
-
*
|
|
5314
|
-
*
|
|
5394
|
+
* const converted = await client.convertFromRaw(data, 'INT');
|
|
5395
|
+
* console.log(converted); //32767
|
|
5396
|
+
*
|
|
5397
|
+
* } catch (err) {
|
|
5398
|
+
* console.log("Error:", err);
|
|
5399
|
+
* }
|
|
5400
|
+
* ```
|
|
5401
|
+
*
|
|
5402
|
+
* @param data Raw data (acquired for example using {@link readRaw}())
|
|
5403
|
+
* @param dataType Data type name in the PLC as string (such as `ST_Struct`) or data type object (acquired using {@link getDataType}())
|
|
5315
5404
|
* @param targetOpts Optional target settings that override values in `settings`
|
|
5316
5405
|
*
|
|
5317
5406
|
* @template T Typescript data type of the PLC data, for example `convertFromRaw<number>(...)` or `convertFromRaw<ST_TypedStruct>(...)`
|
|
5407
|
+
* @throws Throws an error if sending the command fails or if the target responds with an error.
|
|
5318
5408
|
*/
|
|
5319
5409
|
async convertFromRaw(data, dataType, targetOpts = {}) {
|
|
5320
5410
|
if (!this.connection.connected) {
|
|
@@ -5346,18 +5436,27 @@ class Client extends events_1.default {
|
|
|
5346
5436
|
return value;
|
|
5347
5437
|
}
|
|
5348
5438
|
/**
|
|
5349
|
-
*
|
|
5439
|
+
* Converts a Javascript object to raw data by using the provided data type.
|
|
5350
5440
|
*
|
|
5351
|
-
*
|
|
5441
|
+
* **NOTE:** Do not use `autoFill` for `UNION` types, it doesn't work correctly.
|
|
5442
|
+
|
|
5443
|
+
* @example
|
|
5444
|
+
* ```js
|
|
5445
|
+
* try {
|
|
5446
|
+
* const data = await client.convertToRaw(32767, 'INT');
|
|
5447
|
+
* console.log(data); //<Buffer ff 7f>
|
|
5352
5448
|
*
|
|
5353
|
-
*
|
|
5449
|
+
* } catch (err) {
|
|
5450
|
+
* console.log("Error:", err);
|
|
5451
|
+
* }
|
|
5452
|
+
* ```
|
|
5354
5453
|
*
|
|
5355
|
-
* @param value
|
|
5356
|
-
* @param dataType Data type name in the PLC as string (such as `ST_Struct`) or
|
|
5357
|
-
* @param autoFill If
|
|
5454
|
+
* @param value Value to convert
|
|
5455
|
+
* @param dataType Data type name in the PLC as string (such as `ST_Struct`) or data type object (acquired using {@link getDataType}())
|
|
5456
|
+
* @param autoFill 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).
|
|
5358
5457
|
* @param targetOpts Optional target settings that override values in `settings`
|
|
5359
5458
|
*
|
|
5360
|
-
* @
|
|
5459
|
+
* @throws Throws an error if sending the command fails or if the target responds with an error.
|
|
5361
5460
|
*/
|
|
5362
5461
|
async convertToRaw(value, dataType, autoFill = false, targetOpts = {}) {
|
|
5363
5462
|
if (!this.connection.connected) {
|
|
@@ -5413,14 +5512,39 @@ class Client extends events_1.default {
|
|
|
5413
5512
|
}
|
|
5414
5513
|
}
|
|
5415
5514
|
/**
|
|
5416
|
-
*
|
|
5515
|
+
* Creates a handle to a variable at the target system by variable path (such as `GVL_Test.ExampleStruct`).
|
|
5417
5516
|
*
|
|
5418
|
-
*
|
|
5517
|
+
* The handle can be then used for reading and writing the value.
|
|
5419
5518
|
*
|
|
5420
|
-
*
|
|
5519
|
+
* Reading and writing dereferenced `POINTER` and `REFERENCE` values is also possible.
|
|
5520
|
+
* See {@link readRawByHandle}() and {@link writeRawByHandle}().
|
|
5421
5521
|
*
|
|
5422
|
-
*
|
|
5423
|
-
*
|
|
5522
|
+
* NOTE: The handle should be deleted after it's no longer needed,
|
|
5523
|
+
* as there is a limited amount of handles available. See {@link deleteVariableHandle}().
|
|
5524
|
+
*
|
|
5525
|
+
* @example
|
|
5526
|
+
* ```js
|
|
5527
|
+
* try {
|
|
5528
|
+
* //POINTER value (Note the dereference operator ^)
|
|
5529
|
+
* const handle1 = await client.createVariableHandle('GVL_Read.ComplexTypes.POINTER_^');
|
|
5530
|
+
* const value = await client.readRawByHandle(handle1);
|
|
5531
|
+
* await client.deleteVariableHandle(handle1);
|
|
5532
|
+
*
|
|
5533
|
+
* const handle2 = await client.createVariableHandle('GVL_Read.StandardTypes.INT_');
|
|
5534
|
+
* const value2 = await client.readRawByHandle(handle2);
|
|
5535
|
+
* await client.deleteVariableHandle(handle2);
|
|
5536
|
+
*
|
|
5537
|
+
* //Now you use convertFromRaw() to get actual values
|
|
5538
|
+
*
|
|
5539
|
+
* } catch (err) {
|
|
5540
|
+
* console.log("Error:", err);
|
|
5541
|
+
* }
|
|
5542
|
+
* ```
|
|
5543
|
+
*
|
|
5544
|
+
* @param path Variable path in the PLC to read (such as `GVL_Test.ExampleStruct`)
|
|
5545
|
+
* @param targetOpts Optional target settings that override values in `settings`
|
|
5546
|
+
*
|
|
5547
|
+
* @throws Throws an error if sending the command fails or if the target responds with an error.
|
|
5424
5548
|
*/
|
|
5425
5549
|
async createVariableHandle(path, targetOpts = {}) {
|
|
5426
5550
|
if (!this.connection.connected) {
|
|
@@ -5478,18 +5602,44 @@ class Client extends events_1.default {
|
|
|
5478
5602
|
}
|
|
5479
5603
|
}
|
|
5480
5604
|
/**
|
|
5481
|
-
*
|
|
5605
|
+
* Sends multiple {@link createVariableHandle}() commands in one ADS packet.
|
|
5606
|
+
*
|
|
5607
|
+
* Creates a handle to a variable at the target system by variable path (such as `GVL_Test.ExampleStruct`).
|
|
5608
|
+
*
|
|
5609
|
+
* The handle can be then used for reading and writing the value.
|
|
5482
5610
|
*
|
|
5483
|
-
*
|
|
5611
|
+
* Reading and writing dereferenced `POINTER` and `REFERENCE` values is also possible.
|
|
5612
|
+
* See {@link readRawByHandle}() and {@link writeRawByHandle}().
|
|
5484
5613
|
*
|
|
5485
|
-
*
|
|
5614
|
+
* NOTE: The handle should be deleted after it's no longer needed,
|
|
5615
|
+
* as there is a limited amount of handles available. See {@link deleteVariableHandle}().
|
|
5486
5616
|
*
|
|
5487
|
-
*
|
|
5617
|
+
* Uses ADS sum command under the hood (better and faster performance).
|
|
5618
|
+
* See [Beckhoff Information System](https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_adsdll2/9007199379576075.html&id=9180083787138954512) for more info.
|
|
5619
|
+
*
|
|
5620
|
+
* @example
|
|
5621
|
+
* ```js
|
|
5622
|
+
* try {
|
|
5623
|
+
* const results = await client.createVariableHandleMulti([
|
|
5624
|
+
* 'GVL_Read.StandardTypes.INT_',
|
|
5625
|
+
* 'GVL_Read.StandardTypes.REAL_'
|
|
5626
|
+
* ]);
|
|
5488
5627
|
*
|
|
5489
|
-
*
|
|
5628
|
+
* if(results[0].success) {
|
|
5629
|
+
* console.log(`First handle: ${results[0].handle}`);
|
|
5630
|
+
* } else {
|
|
5631
|
+
* console.log(`Creating first handle failed: ${results[0].errorStr}`);
|
|
5632
|
+
* }
|
|
5490
5633
|
*
|
|
5491
|
-
*
|
|
5634
|
+
* } catch (err) {
|
|
5635
|
+
* console.log("Error:", err);
|
|
5636
|
+
* }
|
|
5637
|
+
* ```
|
|
5638
|
+
*
|
|
5639
|
+
* @param paths Array of variable paths in the PLC to read (such as `GVL_Test.ExampleStruct`)
|
|
5492
5640
|
* @param targetOpts Optional target settings that override values in `settings`
|
|
5641
|
+
*
|
|
5642
|
+
* @throws Throws an error if sending the command fails or if the target responds with an error.
|
|
5493
5643
|
*/
|
|
5494
5644
|
async createVariableHandleMulti(paths, targetOpts = {}) {
|
|
5495
5645
|
if (!this.connection.connected) {
|
|
@@ -5594,12 +5744,26 @@ class Client extends events_1.default {
|
|
|
5594
5744
|
}
|
|
5595
5745
|
}
|
|
5596
5746
|
/**
|
|
5597
|
-
*
|
|
5747
|
+
* Deletes a variable handle that was previously created
|
|
5748
|
+
* using {@link createVariableHandle}().
|
|
5749
|
+
*
|
|
5750
|
+
* @example
|
|
5751
|
+
* ```js
|
|
5752
|
+
* try {
|
|
5753
|
+
* const handle = createVariableHandle(...);
|
|
5598
5754
|
*
|
|
5599
|
-
*
|
|
5755
|
+
* //After use, deleting the handle
|
|
5756
|
+
* await client.deleteVariableHandle(handle);
|
|
5757
|
+
*
|
|
5758
|
+
* } catch (err) {
|
|
5759
|
+
* console.log("Error:", err);
|
|
5760
|
+
* }
|
|
5761
|
+
* ```
|
|
5600
5762
|
*
|
|
5601
5763
|
* @param handle Variable handle to delete
|
|
5602
|
-
* @param targetOpts Optional target settings that override values in `settings`
|
|
5764
|
+
* @param targetOpts Optional target settings that override values in `settings`
|
|
5765
|
+
*
|
|
5766
|
+
* @throws Throws an error if sending the command fails or if the target responds with an error.
|
|
5603
5767
|
*/
|
|
5604
5768
|
async deleteVariableHandle(handle, targetOpts = {}) {
|
|
5605
5769
|
if (!this.connection.connected) {
|
|
@@ -5637,16 +5801,38 @@ class Client extends events_1.default {
|
|
|
5637
5801
|
}
|
|
5638
5802
|
}
|
|
5639
5803
|
/**
|
|
5640
|
-
*
|
|
5804
|
+
* Sends multiple {@link deleteVariableHandle}() commands in one ADS packet.
|
|
5641
5805
|
*
|
|
5642
|
-
*
|
|
5806
|
+
* Deletes a variable handle that was previously created
|
|
5807
|
+
* using {@link createVariableHandle}().
|
|
5643
5808
|
*
|
|
5644
|
-
*
|
|
5809
|
+
* Uses ADS sum command under the hood (better and faster performance).
|
|
5810
|
+
* See [Beckhoff Information System](https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_adsdll2/9007199379576075.html&id=9180083787138954512) for more info.
|
|
5811
|
+
*
|
|
5812
|
+
* @example
|
|
5813
|
+
* ```js
|
|
5814
|
+
* try {
|
|
5815
|
+
* const handle1 = createVariableHandle(...);
|
|
5816
|
+
* const handle2 = createVariableHandle(...);
|
|
5817
|
+
*
|
|
5818
|
+
* //After use, deleting the handles
|
|
5819
|
+
* const results = await client.deleteVariableHandleMulti([handle1, handle2]);
|
|
5820
|
+
*
|
|
5821
|
+
* if(results[0].success) {
|
|
5822
|
+
* console.log(`First deleted`);
|
|
5823
|
+
* } else {
|
|
5824
|
+
* console.log(`Deleting first handle failed: ${results[0].errorStr}`);
|
|
5825
|
+
* }
|
|
5645
5826
|
*
|
|
5646
|
-
*
|
|
5827
|
+
* } catch (err) {
|
|
5828
|
+
* console.log("Error:", err);
|
|
5829
|
+
* }
|
|
5830
|
+
* ```
|
|
5647
5831
|
*
|
|
5648
5832
|
* @param handles Array of variable handles to delete
|
|
5649
5833
|
* @param targetOpts Optional target settings that override values in `settings`
|
|
5834
|
+
*
|
|
5835
|
+
* @throws Throws an error if sending the command fails or if the target responds with an error.
|
|
5650
5836
|
*/
|
|
5651
5837
|
async deleteVariableHandleMulti(handles, targetOpts = {}) {
|
|
5652
5838
|
if (!this.connection.connected) {
|
|
@@ -5718,13 +5904,24 @@ class Client extends events_1.default {
|
|
|
5718
5904
|
}
|
|
5719
5905
|
}
|
|
5720
5906
|
/**
|
|
5721
|
-
*
|
|
5907
|
+
* Reads raw data from the target system by a previously created variable handle (acquired using {@link createVariableHandle}())
|
|
5722
5908
|
*
|
|
5723
|
-
*
|
|
5909
|
+
* @example
|
|
5910
|
+
* ```js
|
|
5911
|
+
* try {
|
|
5912
|
+
* const handle = await client.createVariableHandle('GVL_Read.StandardTypes.INT_'');
|
|
5913
|
+
* const value = await client.readRawByHandle(handle);
|
|
5914
|
+
* await client.deleteVariableHandle(handle);
|
|
5724
5915
|
*
|
|
5916
|
+
* } catch (err) {
|
|
5917
|
+
* console.log("Error:", err);
|
|
5918
|
+
* }
|
|
5919
|
+
* ```
|
|
5725
5920
|
* @param handle Variable handle
|
|
5726
5921
|
* @param size Optional data length to read (bytes) - as default, size in handle is used if available. Uses 0xFFFFFFFF as fallback.
|
|
5727
|
-
* @param targetOpts Optional target settings that override values in `settings`
|
|
5922
|
+
* @param targetOpts Optional target settings that override values in `settings`
|
|
5923
|
+
*
|
|
5924
|
+
* @throws Throws an error if sending the command fails or if the target responds with an error.
|
|
5728
5925
|
*/
|
|
5729
5926
|
async readRawByHandle(handle, size, targetOpts = {}) {
|
|
5730
5927
|
if (!this.connection.connected) {
|
|
@@ -5748,13 +5945,28 @@ class Client extends events_1.default {
|
|
|
5748
5945
|
}
|
|
5749
5946
|
}
|
|
5750
5947
|
/**
|
|
5751
|
-
*
|
|
5948
|
+
* Writes raw data to the target system by a previously created variable handle (acquired using {@link createVariableHandle}())
|
|
5949
|
+
*
|
|
5950
|
+
* @example
|
|
5951
|
+
* ```js
|
|
5952
|
+
* try {
|
|
5953
|
+
* const value = await client.convertToRaw(32767, 'INT');
|
|
5954
|
+
* console.log(value); //<Buffer ff 7f>
|
|
5752
5955
|
*
|
|
5753
|
-
*
|
|
5956
|
+
* const handle = await client.createVariableHandle('GVL_Read.StandardTypes.INT_');
|
|
5957
|
+
* await client.writeRawByHandle(handle, value);
|
|
5958
|
+
* await client.deleteVariableHandle(handle);
|
|
5959
|
+
*
|
|
5960
|
+
* } catch (err) {
|
|
5961
|
+
* console.log("Error:", err);
|
|
5962
|
+
* }
|
|
5963
|
+
* ```
|
|
5754
5964
|
*
|
|
5755
5965
|
* @param handle Variable handle
|
|
5756
5966
|
* @param value Data to write
|
|
5757
|
-
* @param targetOpts Optional target settings that override values in `settings`
|
|
5967
|
+
* @param targetOpts Optional target settings that override values in `settings`
|
|
5968
|
+
*
|
|
5969
|
+
* @throws Throws an error if sending the command fails or if the target responds with an error.
|
|
5758
5970
|
*/
|
|
5759
5971
|
async writeRawByHandle(handle, value, targetOpts = {}) {
|
|
5760
5972
|
if (!this.connection.connected) {
|
|
@@ -5772,12 +5984,23 @@ class Client extends events_1.default {
|
|
|
5772
5984
|
}
|
|
5773
5985
|
}
|
|
5774
5986
|
/**
|
|
5775
|
-
*
|
|
5987
|
+
* Reads raw data from the target system by a symbol object (acquired using `getSymbol()`)
|
|
5776
5988
|
*
|
|
5777
|
-
*
|
|
5989
|
+
* @example
|
|
5990
|
+
* ```js
|
|
5991
|
+
* try {
|
|
5992
|
+
* const symbol = await client.getSymbol('GVL_Read.StandardTypes.INT_');
|
|
5993
|
+
* const value = await client.readRawBySymbol(symbol);
|
|
5778
5994
|
*
|
|
5779
|
-
*
|
|
5780
|
-
*
|
|
5995
|
+
* } catch (err) {
|
|
5996
|
+
* console.log("Error:", err);
|
|
5997
|
+
* }
|
|
5998
|
+
* ```
|
|
5999
|
+
*
|
|
6000
|
+
* @param symbol Symbol
|
|
6001
|
+
* @param targetOpts Optional target settings that override values in `settings`
|
|
6002
|
+
*
|
|
6003
|
+
* @throws Throws an error if sending the command fails or if the target responds with an error.
|
|
5781
6004
|
*/
|
|
5782
6005
|
async readRawBySymbol(symbol, targetOpts = {}) {
|
|
5783
6006
|
if (!this.connection.connected) {
|
|
@@ -5795,13 +6018,27 @@ class Client extends events_1.default {
|
|
|
5795
6018
|
}
|
|
5796
6019
|
}
|
|
5797
6020
|
/**
|
|
5798
|
-
*
|
|
6021
|
+
* Writes raw data to the target system by a symbol object (acquired using `getSymbol()`)
|
|
6022
|
+
*
|
|
6023
|
+
* @example
|
|
6024
|
+
* ```js
|
|
6025
|
+
* try {
|
|
6026
|
+
* const value = await client.convertToRaw(32767, 'INT');
|
|
6027
|
+
* console.log(value); //<Buffer ff 7f>
|
|
5799
6028
|
*
|
|
5800
|
-
*
|
|
6029
|
+
* const symbol = await client.getSymbol('GVL_Read.StandardTypes.INT_');
|
|
6030
|
+
* await client.writeRawBySymbol(symbol, value);
|
|
5801
6031
|
*
|
|
5802
|
-
*
|
|
6032
|
+
* } catch (err) {
|
|
6033
|
+
* console.log("Error:", err);
|
|
6034
|
+
* }
|
|
6035
|
+
* ```
|
|
6036
|
+
*
|
|
6037
|
+
* @param symbol Symbol
|
|
5803
6038
|
* @param value Data to write
|
|
5804
6039
|
* @param targetOpts Optional target settings that override values in `settings`
|
|
6040
|
+
*
|
|
6041
|
+
* @throws Throws an error if sending the command fails or if the target responds with an error.
|
|
5805
6042
|
*/
|
|
5806
6043
|
async writeRawBySymbol(symbol, value, targetOpts = {}) {
|
|
5807
6044
|
if (!this.connection.connected) {
|
|
@@ -5818,21 +6055,40 @@ class Client extends events_1.default {
|
|
|
5818
6055
|
}
|
|
5819
6056
|
}
|
|
5820
6057
|
/**
|
|
5821
|
-
*
|
|
6058
|
+
* Invokes a function block RPC method on the target system.
|
|
5822
6059
|
*
|
|
5823
|
-
*
|
|
6060
|
+
* Returns the return value of the method and outputs (if any).
|
|
5824
6061
|
*
|
|
5825
|
-
*
|
|
6062
|
+
* NOTE: In the PLC, `{attribute 'TcRpcEnable'}` is required above the `METHOD` definition.
|
|
5826
6063
|
*
|
|
5827
|
-
*
|
|
6064
|
+
* @example
|
|
6065
|
+
* ```js
|
|
6066
|
+
* try {
|
|
6067
|
+
* const res = await client.invokeRpcMethod('GVL_RPC.RpcBlock', 'Calculator', {
|
|
6068
|
+
* Value1: 1,
|
|
6069
|
+
* Value2: 123
|
|
6070
|
+
* });
|
|
6071
|
+
*
|
|
6072
|
+
* console.log(res);
|
|
6073
|
+
* //{
|
|
6074
|
+
* // returnValue: true,
|
|
6075
|
+
* // outputs: { Sum: 124, Product: 123, Division: 0.008130080997943878 }
|
|
6076
|
+
* //}
|
|
5828
6077
|
*
|
|
5829
|
-
*
|
|
5830
|
-
*
|
|
5831
|
-
*
|
|
6078
|
+
* } catch (err) {
|
|
6079
|
+
* console.log("Error:", err);
|
|
6080
|
+
* }
|
|
6081
|
+
* ```
|
|
6082
|
+
*
|
|
6083
|
+
* @param path Variable path in the PLC of the function block instance (such as `GVL_Test.ExampleBlock`)
|
|
6084
|
+
* @param method Function block method name
|
|
6085
|
+
* @param parameters Method parameters (inputs) (if any)
|
|
5832
6086
|
* @param targetOpts Optional target settings that override values in `settings`
|
|
5833
6087
|
*
|
|
5834
6088
|
* @template T Typescript data type of the method return value, for example `invokeRpcMethod<number>(...)` or `invokeRpcMethod<ST_TypedStruct>(...)`
|
|
5835
6089
|
* @template U Typescript data type of the method outputs object, for example `invokeRpcMethod<number, ST_TypedStruct>(...)`
|
|
6090
|
+
*
|
|
6091
|
+
* @throws Throws an error if sending the command fails or if the target responds with an error.
|
|
5836
6092
|
*/
|
|
5837
6093
|
async invokeRpcMethod(path, method, parameters = {}, targetOpts = {}) {
|
|
5838
6094
|
if (!this.connection.connected) {
|