njs-modbus 2.0.0 → 2.0.1

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/dist/index.cjs CHANGED
@@ -423,6 +423,9 @@ class SerialPhysicalLayer extends AbstractPhysicalLayer {
423
423
  });
424
424
  }
425
425
  destroy() {
426
+ if (this._destroyed) {
427
+ return Promise.resolve();
428
+ }
426
429
  this._destroyed = true;
427
430
  return this.close().then(() => {
428
431
  this.removeAllListeners();
@@ -562,6 +565,9 @@ class TcpClientPhysicalLayer extends AbstractPhysicalLayer {
562
565
  });
563
566
  }
564
567
  destroy() {
568
+ if (this._destroyed) {
569
+ return Promise.resolve();
570
+ }
565
571
  this._destroyed = true;
566
572
  return this.close().then(() => {
567
573
  this.removeAllListeners();
@@ -711,10 +717,18 @@ class TcpServerPhysicalLayer extends AbstractPhysicalLayer {
711
717
  for (const [socket] of this._connections) {
712
718
  socket.destroy();
713
719
  }
714
- server.close();
720
+ try {
721
+ server.close();
722
+ }
723
+ catch (_a) {
724
+ resolve();
725
+ }
715
726
  });
716
727
  }
717
728
  destroy() {
729
+ if (this._destroyed) {
730
+ return Promise.resolve();
731
+ }
718
732
  this._destroyed = true;
719
733
  return this.close().then(() => {
720
734
  this.removeAllListeners();
@@ -945,6 +959,9 @@ class UdpPhysicalLayer extends AbstractPhysicalLayer {
945
959
  });
946
960
  }
947
961
  destroy() {
962
+ if (this._destroyed) {
963
+ return Promise.resolve();
964
+ }
948
965
  this._destroyed = true;
949
966
  return this.close().then(() => {
950
967
  this.removeAllListeners();
@@ -1024,6 +1041,12 @@ class RtuApplicationLayer extends AbstractApplicationLayer {
1024
1041
  writable: true,
1025
1042
  value: void 0
1026
1043
  });
1044
+ Object.defineProperty(this, "_destroyed", {
1045
+ enumerable: true,
1046
+ configurable: true,
1047
+ writable: true,
1048
+ value: false
1049
+ });
1027
1050
  const { intervalBetweenFrames, interCharTimeout } = options;
1028
1051
  let threePointFiveT = 0;
1029
1052
  let onePointFiveT = 0;
@@ -1274,14 +1297,20 @@ class RtuApplicationLayer extends AbstractApplicationLayer {
1274
1297
  return buffer;
1275
1298
  }
1276
1299
  destroy() {
1300
+ if (this._destroyed) {
1301
+ return;
1302
+ }
1303
+ this._destroyed = true;
1277
1304
  this.removeAllListeners();
1278
1305
  for (const removeListener of this._removeAllListeners) {
1279
1306
  removeListener();
1280
1307
  }
1308
+ this._removeAllListeners.length = 0;
1281
1309
  for (const state of this._states.values()) {
1282
1310
  this.clearStateTimers(state);
1283
1311
  }
1284
1312
  this._states.clear();
1313
+ this._customFunctionCodes.clear();
1285
1314
  }
1286
1315
  }
1287
1316
 
@@ -1334,6 +1363,12 @@ class AsciiApplicationLayer extends AbstractApplicationLayer {
1334
1363
  writable: true,
1335
1364
  value: []
1336
1365
  });
1366
+ Object.defineProperty(this, "_destroyed", {
1367
+ enumerable: true,
1368
+ configurable: true,
1369
+ writable: true,
1370
+ value: false
1371
+ });
1337
1372
  this.lenientHex = (_a = options.lenientHex) !== null && _a !== void 0 ? _a : false;
1338
1373
  const lenientHex = this.lenientHex;
1339
1374
  const isHexChar = (value) => {
@@ -1471,10 +1506,15 @@ class AsciiApplicationLayer extends AbstractApplicationLayer {
1471
1506
  return out;
1472
1507
  }
1473
1508
  destroy() {
1509
+ if (this._destroyed) {
1510
+ return;
1511
+ }
1512
+ this._destroyed = true;
1474
1513
  this.removeAllListeners();
1475
1514
  for (const removeListener of this._removeAllListeners) {
1476
1515
  removeListener();
1477
1516
  }
1517
+ this._removeAllListeners.length = 0;
1478
1518
  this._states.clear();
1479
1519
  }
1480
1520
  }
@@ -1508,6 +1548,12 @@ class TcpApplicationLayer extends AbstractApplicationLayer {
1508
1548
  writable: true,
1509
1549
  value: []
1510
1550
  });
1551
+ Object.defineProperty(this, "_destroyed", {
1552
+ enumerable: true,
1553
+ configurable: true,
1554
+ writable: true,
1555
+ value: false
1556
+ });
1511
1557
  const handleData = (data, response, connection) => {
1512
1558
  var _a;
1513
1559
  let buffer = (_a = this._buffers.get(connection.id)) !== null && _a !== void 0 ? _a : EMPTY_BUFFER;
@@ -1590,10 +1636,15 @@ class TcpApplicationLayer extends AbstractApplicationLayer {
1590
1636
  return buffer;
1591
1637
  }
1592
1638
  destroy() {
1639
+ if (this._destroyed) {
1640
+ return;
1641
+ }
1642
+ this._destroyed = true;
1593
1643
  this.removeAllListeners();
1594
1644
  for (const removeListener of this._removeAllListeners) {
1595
1645
  removeListener();
1596
1646
  }
1647
+ this._removeAllListeners.length = 0;
1597
1648
  this._buffers.clear();
1598
1649
  }
1599
1650
  }
@@ -1704,7 +1755,7 @@ class ModbusMaster extends EventEmitter {
1704
1755
  return this.physicalLayer.isOpen;
1705
1756
  }
1706
1757
  get destroyed() {
1707
- return this.physicalLayer.destroyed;
1758
+ return this._cleanLevel === 'destroy' || this.physicalLayer.destroyed;
1708
1759
  }
1709
1760
  constructor(applicationLayer, physicalLayer, options = {}) {
1710
1761
  var _a, _b;
@@ -1751,6 +1802,12 @@ class ModbusMaster extends EventEmitter {
1751
1802
  writable: true,
1752
1803
  value: false
1753
1804
  });
1805
+ Object.defineProperty(this, "_cleanLevel", {
1806
+ enumerable: true,
1807
+ configurable: true,
1808
+ writable: true,
1809
+ value: 'none'
1810
+ });
1754
1811
  Object.defineProperty(this, "timeout", {
1755
1812
  enumerable: true,
1756
1813
  configurable: true,
@@ -2164,26 +2221,44 @@ class ModbusMaster extends EventEmitter {
2164
2221
  }
2165
2222
  });
2166
2223
  }
2224
+ _clean(level) {
2225
+ if (this._cleanLevel === 'destroy') {
2226
+ return;
2227
+ }
2228
+ if (this._cleanLevel === 'close' && level === 'close') {
2229
+ return;
2230
+ }
2231
+ const errorCode = level === 'destroy' ? ModbusErrorCode.MASTER_DESTROYED : ModbusErrorCode.MASTER_CLOSED;
2232
+ const message = level === 'destroy' ? 'Master destroyed' : 'Master closed';
2233
+ this._closed = true;
2234
+ const queued = this._queue.splice(0);
2235
+ for (const item of queued) {
2236
+ item.cancel(new ModbusError(errorCode, message));
2237
+ }
2238
+ this._masterSession.stopAll(new ModbusError(errorCode, message));
2239
+ this._cleanLevel = level;
2240
+ }
2167
2241
  open(...args) {
2242
+ if (this._cleanLevel === 'destroy') {
2243
+ return Promise.reject(new ModbusError(ModbusErrorCode.PORT_DESTROYED, 'Master is destroyed'));
2244
+ }
2245
+ this._cleanLevel = 'none';
2168
2246
  this._closed = false;
2247
+ this._nextTid = 1;
2169
2248
  return this.physicalLayer.open(...args);
2170
2249
  }
2171
2250
  close() {
2172
- this._closed = true;
2173
- const queued = this._queue.splice(0);
2174
- for (const item of queued) {
2175
- item.cancel(new ModbusError(ModbusErrorCode.MASTER_CLOSED, 'Master closed'));
2251
+ if (this._cleanLevel === 'destroy') {
2252
+ return Promise.resolve();
2176
2253
  }
2177
- this._masterSession.stopAll(new ModbusError(ModbusErrorCode.MASTER_CLOSED, 'Master closed'));
2254
+ this._clean('close');
2178
2255
  return this.physicalLayer.close();
2179
2256
  }
2180
2257
  destroy() {
2181
- this._closed = true;
2182
- const queued = this._queue.splice(0);
2183
- for (const item of queued) {
2184
- item.cancel(new ModbusError(ModbusErrorCode.MASTER_DESTROYED, 'Master destroyed'));
2258
+ if (this._cleanLevel === 'destroy') {
2259
+ return Promise.resolve();
2185
2260
  }
2186
- this._masterSession.stopAll(new ModbusError(ModbusErrorCode.MASTER_DESTROYED, 'Master destroyed'));
2261
+ this._clean('destroy');
2187
2262
  this.removeAllListeners();
2188
2263
  this.applicationLayer.destroy();
2189
2264
  return this.physicalLayer.destroy();
@@ -2195,7 +2270,7 @@ class ModbusSlave extends EventEmitter {
2195
2270
  return this.physicalLayer.isOpen;
2196
2271
  }
2197
2272
  get destroyed() {
2198
- return this.physicalLayer.destroyed;
2273
+ return this._cleanLevel === 'destroy' || this.physicalLayer.destroyed;
2199
2274
  }
2200
2275
  constructor(applicationLayer, physicalLayer, options = {}) {
2201
2276
  var _a;
@@ -2242,6 +2317,12 @@ class ModbusSlave extends EventEmitter {
2242
2317
  writable: true,
2243
2318
  value: new Map()
2244
2319
  });
2320
+ Object.defineProperty(this, "_cleanLevel", {
2321
+ enumerable: true,
2322
+ configurable: true,
2323
+ writable: true,
2324
+ value: 'none'
2325
+ });
2245
2326
  this.concurrent = (_a = options.concurrent) !== null && _a !== void 0 ? _a : false;
2246
2327
  if (this.concurrent && this.applicationLayer.PROTOCOL !== 'TCP') {
2247
2328
  throw new ModbusError(ModbusErrorCode.CONCURRENT_NOT_TCP, 'concurrent mode requires a Modbus TCP application layer');
@@ -2974,14 +3055,40 @@ class ModbusSlave extends EventEmitter {
2974
3055
  this._customFunctionCodes.delete(fc);
2975
3056
  this.applicationLayer.removeCustomFunctionCode(fc);
2976
3057
  }
3058
+ _clean(level) {
3059
+ if (this._cleanLevel === 'destroy') {
3060
+ return;
3061
+ }
3062
+ if (this._cleanLevel === 'close' && level === 'close') {
3063
+ return;
3064
+ }
3065
+ for (const q of this._queues.values()) {
3066
+ q.items.length = 0;
3067
+ }
3068
+ this._queues.clear();
3069
+ this._locks.clear();
3070
+ if (level === 'destroy') {
3071
+ this._customFunctionCodes.clear();
3072
+ this.models.clear();
3073
+ }
3074
+ this._cleanLevel = level;
3075
+ }
2977
3076
  open(...args) {
3077
+ this._cleanLevel = 'none';
2978
3078
  return this.physicalLayer.open(...args);
2979
3079
  }
2980
3080
  close() {
3081
+ if (this._cleanLevel === 'destroy') {
3082
+ return Promise.resolve();
3083
+ }
3084
+ this._clean('close');
2981
3085
  return this.physicalLayer.close();
2982
3086
  }
2983
3087
  destroy() {
2984
- this._locks.clear();
3088
+ if (this._cleanLevel === 'destroy') {
3089
+ return Promise.resolve();
3090
+ }
3091
+ this._clean('destroy');
2985
3092
  this.removeAllListeners();
2986
3093
  this.applicationLayer.destroy();
2987
3094
  return this.physicalLayer.destroy();
package/dist/index.d.ts CHANGED
@@ -313,6 +313,7 @@ declare class AsciiApplicationLayer extends AbstractApplicationLayer {
313
313
  readonly lenientHex: boolean;
314
314
  private _states;
315
315
  private _removeAllListeners;
316
+ private _destroyed;
316
317
  constructor(physicalLayer: SerialPhysicalLayer | TcpServerPhysicalLayer | TcpClientPhysicalLayer | UdpPhysicalLayer, options?: AsciiApplicationLayerOptions);
317
318
  private getState;
318
319
  flush(): void;
@@ -362,6 +363,7 @@ declare class RtuApplicationLayer extends AbstractApplicationLayer {
362
363
  private _removeAllListeners;
363
364
  private _threePointFiveT;
364
365
  private _onePointFiveT;
366
+ private _destroyed;
365
367
  constructor(physicalLayer: SerialPhysicalLayer | TcpServerPhysicalLayer | TcpClientPhysicalLayer | UdpPhysicalLayer, options?: RtuApplicationLayerOptions);
366
368
  private getState;
367
369
  private clearStateTimers;
@@ -383,6 +385,7 @@ declare class TcpApplicationLayer extends AbstractApplicationLayer {
383
385
  private _transactionId;
384
386
  private _buffers;
385
387
  private _removeAllListeners;
388
+ private _destroyed;
386
389
  constructor(physicalLayer: TcpServerPhysicalLayer | TcpClientPhysicalLayer | UdpPhysicalLayer);
387
390
  private tryExtract;
388
391
  private processFrame;
@@ -419,6 +422,7 @@ declare class ModbusMaster<A extends AbstractApplicationLayer, P extends Abstrac
419
422
  private _draining;
420
423
  private _nextTid;
421
424
  private _closed;
425
+ private _cleanLevel;
422
426
  timeout: number;
423
427
  readonly concurrent: boolean;
424
428
  get isOpen(): boolean;
@@ -484,6 +488,7 @@ declare class ModbusMaster<A extends AbstractApplicationLayer, P extends Abstrac
484
488
  removeCustomFunctionCode(fc: number): void;
485
489
  sendCustomFC(unit: 0, fc: number, data: Buffer | number[], timeout?: number): Promise<void>;
486
490
  sendCustomFC(unit: number, fc: number, data: Buffer | number[], timeout?: number): Promise<Buffer>;
491
+ private _clean;
487
492
  open(...args: Parameters<P['open']>): Promise<void>;
488
493
  close(): Promise<void>;
489
494
  destroy(): Promise<void>;
@@ -563,6 +568,7 @@ declare class ModbusSlave<A extends AbstractApplicationLayer, P extends Abstract
563
568
  private _queues;
564
569
  private _customFunctionCodes;
565
570
  private _locks;
571
+ private _cleanLevel;
566
572
  get isOpen(): boolean;
567
573
  get destroyed(): boolean;
568
574
  constructor(applicationLayer: A, physicalLayer: P, options?: ModbusSlaveOptions);
@@ -588,6 +594,7 @@ declare class ModbusSlave<A extends AbstractApplicationLayer, P extends Abstract
588
594
  remove(unit: number): void;
589
595
  addCustomFunctionCode(cfc: CustomFunctionCode): void;
590
596
  removeCustomFunctionCode(fc: number): void;
597
+ private _clean;
591
598
  open(...args: Parameters<P['open']>): Promise<void>;
592
599
  close(): Promise<void>;
593
600
  destroy(): Promise<void>;
package/dist/index.mjs CHANGED
@@ -421,6 +421,9 @@ class SerialPhysicalLayer extends AbstractPhysicalLayer {
421
421
  });
422
422
  }
423
423
  destroy() {
424
+ if (this._destroyed) {
425
+ return Promise.resolve();
426
+ }
424
427
  this._destroyed = true;
425
428
  return this.close().then(() => {
426
429
  this.removeAllListeners();
@@ -560,6 +563,9 @@ class TcpClientPhysicalLayer extends AbstractPhysicalLayer {
560
563
  });
561
564
  }
562
565
  destroy() {
566
+ if (this._destroyed) {
567
+ return Promise.resolve();
568
+ }
563
569
  this._destroyed = true;
564
570
  return this.close().then(() => {
565
571
  this.removeAllListeners();
@@ -709,10 +715,18 @@ class TcpServerPhysicalLayer extends AbstractPhysicalLayer {
709
715
  for (const [socket] of this._connections) {
710
716
  socket.destroy();
711
717
  }
712
- server.close();
718
+ try {
719
+ server.close();
720
+ }
721
+ catch (_a) {
722
+ resolve();
723
+ }
713
724
  });
714
725
  }
715
726
  destroy() {
727
+ if (this._destroyed) {
728
+ return Promise.resolve();
729
+ }
716
730
  this._destroyed = true;
717
731
  return this.close().then(() => {
718
732
  this.removeAllListeners();
@@ -943,6 +957,9 @@ class UdpPhysicalLayer extends AbstractPhysicalLayer {
943
957
  });
944
958
  }
945
959
  destroy() {
960
+ if (this._destroyed) {
961
+ return Promise.resolve();
962
+ }
946
963
  this._destroyed = true;
947
964
  return this.close().then(() => {
948
965
  this.removeAllListeners();
@@ -1022,6 +1039,12 @@ class RtuApplicationLayer extends AbstractApplicationLayer {
1022
1039
  writable: true,
1023
1040
  value: void 0
1024
1041
  });
1042
+ Object.defineProperty(this, "_destroyed", {
1043
+ enumerable: true,
1044
+ configurable: true,
1045
+ writable: true,
1046
+ value: false
1047
+ });
1025
1048
  const { intervalBetweenFrames, interCharTimeout } = options;
1026
1049
  let threePointFiveT = 0;
1027
1050
  let onePointFiveT = 0;
@@ -1272,14 +1295,20 @@ class RtuApplicationLayer extends AbstractApplicationLayer {
1272
1295
  return buffer;
1273
1296
  }
1274
1297
  destroy() {
1298
+ if (this._destroyed) {
1299
+ return;
1300
+ }
1301
+ this._destroyed = true;
1275
1302
  this.removeAllListeners();
1276
1303
  for (const removeListener of this._removeAllListeners) {
1277
1304
  removeListener();
1278
1305
  }
1306
+ this._removeAllListeners.length = 0;
1279
1307
  for (const state of this._states.values()) {
1280
1308
  this.clearStateTimers(state);
1281
1309
  }
1282
1310
  this._states.clear();
1311
+ this._customFunctionCodes.clear();
1283
1312
  }
1284
1313
  }
1285
1314
 
@@ -1332,6 +1361,12 @@ class AsciiApplicationLayer extends AbstractApplicationLayer {
1332
1361
  writable: true,
1333
1362
  value: []
1334
1363
  });
1364
+ Object.defineProperty(this, "_destroyed", {
1365
+ enumerable: true,
1366
+ configurable: true,
1367
+ writable: true,
1368
+ value: false
1369
+ });
1335
1370
  this.lenientHex = (_a = options.lenientHex) !== null && _a !== void 0 ? _a : false;
1336
1371
  const lenientHex = this.lenientHex;
1337
1372
  const isHexChar = (value) => {
@@ -1469,10 +1504,15 @@ class AsciiApplicationLayer extends AbstractApplicationLayer {
1469
1504
  return out;
1470
1505
  }
1471
1506
  destroy() {
1507
+ if (this._destroyed) {
1508
+ return;
1509
+ }
1510
+ this._destroyed = true;
1472
1511
  this.removeAllListeners();
1473
1512
  for (const removeListener of this._removeAllListeners) {
1474
1513
  removeListener();
1475
1514
  }
1515
+ this._removeAllListeners.length = 0;
1476
1516
  this._states.clear();
1477
1517
  }
1478
1518
  }
@@ -1506,6 +1546,12 @@ class TcpApplicationLayer extends AbstractApplicationLayer {
1506
1546
  writable: true,
1507
1547
  value: []
1508
1548
  });
1549
+ Object.defineProperty(this, "_destroyed", {
1550
+ enumerable: true,
1551
+ configurable: true,
1552
+ writable: true,
1553
+ value: false
1554
+ });
1509
1555
  const handleData = (data, response, connection) => {
1510
1556
  var _a;
1511
1557
  let buffer = (_a = this._buffers.get(connection.id)) !== null && _a !== void 0 ? _a : EMPTY_BUFFER;
@@ -1588,10 +1634,15 @@ class TcpApplicationLayer extends AbstractApplicationLayer {
1588
1634
  return buffer;
1589
1635
  }
1590
1636
  destroy() {
1637
+ if (this._destroyed) {
1638
+ return;
1639
+ }
1640
+ this._destroyed = true;
1591
1641
  this.removeAllListeners();
1592
1642
  for (const removeListener of this._removeAllListeners) {
1593
1643
  removeListener();
1594
1644
  }
1645
+ this._removeAllListeners.length = 0;
1595
1646
  this._buffers.clear();
1596
1647
  }
1597
1648
  }
@@ -1702,7 +1753,7 @@ class ModbusMaster extends EventEmitter {
1702
1753
  return this.physicalLayer.isOpen;
1703
1754
  }
1704
1755
  get destroyed() {
1705
- return this.physicalLayer.destroyed;
1756
+ return this._cleanLevel === 'destroy' || this.physicalLayer.destroyed;
1706
1757
  }
1707
1758
  constructor(applicationLayer, physicalLayer, options = {}) {
1708
1759
  var _a, _b;
@@ -1749,6 +1800,12 @@ class ModbusMaster extends EventEmitter {
1749
1800
  writable: true,
1750
1801
  value: false
1751
1802
  });
1803
+ Object.defineProperty(this, "_cleanLevel", {
1804
+ enumerable: true,
1805
+ configurable: true,
1806
+ writable: true,
1807
+ value: 'none'
1808
+ });
1752
1809
  Object.defineProperty(this, "timeout", {
1753
1810
  enumerable: true,
1754
1811
  configurable: true,
@@ -2162,26 +2219,44 @@ class ModbusMaster extends EventEmitter {
2162
2219
  }
2163
2220
  });
2164
2221
  }
2222
+ _clean(level) {
2223
+ if (this._cleanLevel === 'destroy') {
2224
+ return;
2225
+ }
2226
+ if (this._cleanLevel === 'close' && level === 'close') {
2227
+ return;
2228
+ }
2229
+ const errorCode = level === 'destroy' ? ModbusErrorCode.MASTER_DESTROYED : ModbusErrorCode.MASTER_CLOSED;
2230
+ const message = level === 'destroy' ? 'Master destroyed' : 'Master closed';
2231
+ this._closed = true;
2232
+ const queued = this._queue.splice(0);
2233
+ for (const item of queued) {
2234
+ item.cancel(new ModbusError(errorCode, message));
2235
+ }
2236
+ this._masterSession.stopAll(new ModbusError(errorCode, message));
2237
+ this._cleanLevel = level;
2238
+ }
2165
2239
  open(...args) {
2240
+ if (this._cleanLevel === 'destroy') {
2241
+ return Promise.reject(new ModbusError(ModbusErrorCode.PORT_DESTROYED, 'Master is destroyed'));
2242
+ }
2243
+ this._cleanLevel = 'none';
2166
2244
  this._closed = false;
2245
+ this._nextTid = 1;
2167
2246
  return this.physicalLayer.open(...args);
2168
2247
  }
2169
2248
  close() {
2170
- this._closed = true;
2171
- const queued = this._queue.splice(0);
2172
- for (const item of queued) {
2173
- item.cancel(new ModbusError(ModbusErrorCode.MASTER_CLOSED, 'Master closed'));
2249
+ if (this._cleanLevel === 'destroy') {
2250
+ return Promise.resolve();
2174
2251
  }
2175
- this._masterSession.stopAll(new ModbusError(ModbusErrorCode.MASTER_CLOSED, 'Master closed'));
2252
+ this._clean('close');
2176
2253
  return this.physicalLayer.close();
2177
2254
  }
2178
2255
  destroy() {
2179
- this._closed = true;
2180
- const queued = this._queue.splice(0);
2181
- for (const item of queued) {
2182
- item.cancel(new ModbusError(ModbusErrorCode.MASTER_DESTROYED, 'Master destroyed'));
2256
+ if (this._cleanLevel === 'destroy') {
2257
+ return Promise.resolve();
2183
2258
  }
2184
- this._masterSession.stopAll(new ModbusError(ModbusErrorCode.MASTER_DESTROYED, 'Master destroyed'));
2259
+ this._clean('destroy');
2185
2260
  this.removeAllListeners();
2186
2261
  this.applicationLayer.destroy();
2187
2262
  return this.physicalLayer.destroy();
@@ -2193,7 +2268,7 @@ class ModbusSlave extends EventEmitter {
2193
2268
  return this.physicalLayer.isOpen;
2194
2269
  }
2195
2270
  get destroyed() {
2196
- return this.physicalLayer.destroyed;
2271
+ return this._cleanLevel === 'destroy' || this.physicalLayer.destroyed;
2197
2272
  }
2198
2273
  constructor(applicationLayer, physicalLayer, options = {}) {
2199
2274
  var _a;
@@ -2240,6 +2315,12 @@ class ModbusSlave extends EventEmitter {
2240
2315
  writable: true,
2241
2316
  value: new Map()
2242
2317
  });
2318
+ Object.defineProperty(this, "_cleanLevel", {
2319
+ enumerable: true,
2320
+ configurable: true,
2321
+ writable: true,
2322
+ value: 'none'
2323
+ });
2243
2324
  this.concurrent = (_a = options.concurrent) !== null && _a !== void 0 ? _a : false;
2244
2325
  if (this.concurrent && this.applicationLayer.PROTOCOL !== 'TCP') {
2245
2326
  throw new ModbusError(ModbusErrorCode.CONCURRENT_NOT_TCP, 'concurrent mode requires a Modbus TCP application layer');
@@ -2972,14 +3053,40 @@ class ModbusSlave extends EventEmitter {
2972
3053
  this._customFunctionCodes.delete(fc);
2973
3054
  this.applicationLayer.removeCustomFunctionCode(fc);
2974
3055
  }
3056
+ _clean(level) {
3057
+ if (this._cleanLevel === 'destroy') {
3058
+ return;
3059
+ }
3060
+ if (this._cleanLevel === 'close' && level === 'close') {
3061
+ return;
3062
+ }
3063
+ for (const q of this._queues.values()) {
3064
+ q.items.length = 0;
3065
+ }
3066
+ this._queues.clear();
3067
+ this._locks.clear();
3068
+ if (level === 'destroy') {
3069
+ this._customFunctionCodes.clear();
3070
+ this.models.clear();
3071
+ }
3072
+ this._cleanLevel = level;
3073
+ }
2975
3074
  open(...args) {
3075
+ this._cleanLevel = 'none';
2976
3076
  return this.physicalLayer.open(...args);
2977
3077
  }
2978
3078
  close() {
3079
+ if (this._cleanLevel === 'destroy') {
3080
+ return Promise.resolve();
3081
+ }
3082
+ this._clean('close');
2979
3083
  return this.physicalLayer.close();
2980
3084
  }
2981
3085
  destroy() {
2982
- this._locks.clear();
3086
+ if (this._cleanLevel === 'destroy') {
3087
+ return Promise.resolve();
3088
+ }
3089
+ this._clean('destroy');
2983
3090
  this.removeAllListeners();
2984
3091
  this.applicationLayer.destroy();
2985
3092
  return this.physicalLayer.destroy();
@@ -15,6 +15,7 @@ export declare class AsciiApplicationLayer extends AbstractApplicationLayer {
15
15
  readonly lenientHex: boolean;
16
16
  private _states;
17
17
  private _removeAllListeners;
18
+ private _destroyed;
18
19
  constructor(physicalLayer: SerialPhysicalLayer | TcpServerPhysicalLayer | TcpClientPhysicalLayer | UdpPhysicalLayer, options?: AsciiApplicationLayerOptions);
19
20
  private getState;
20
21
  flush(): void;
@@ -43,6 +43,7 @@ export declare class RtuApplicationLayer extends AbstractApplicationLayer {
43
43
  private _removeAllListeners;
44
44
  private _threePointFiveT;
45
45
  private _onePointFiveT;
46
+ private _destroyed;
46
47
  constructor(physicalLayer: SerialPhysicalLayer | TcpServerPhysicalLayer | TcpClientPhysicalLayer | UdpPhysicalLayer, options?: RtuApplicationLayerOptions);
47
48
  private getState;
48
49
  private clearStateTimers;
@@ -6,6 +6,7 @@ export declare class TcpApplicationLayer extends AbstractApplicationLayer {
6
6
  private _transactionId;
7
7
  private _buffers;
8
8
  private _removeAllListeners;
9
+ private _destroyed;
9
10
  constructor(physicalLayer: TcpServerPhysicalLayer | TcpClientPhysicalLayer | UdpPhysicalLayer);
10
11
  private tryExtract;
11
12
  private processFrame;
@@ -31,6 +31,7 @@ export declare class ModbusMaster<A extends AbstractApplicationLayer, P extends
31
31
  private _draining;
32
32
  private _nextTid;
33
33
  private _closed;
34
+ private _cleanLevel;
34
35
  timeout: number;
35
36
  readonly concurrent: boolean;
36
37
  get isOpen(): boolean;
@@ -96,6 +97,7 @@ export declare class ModbusMaster<A extends AbstractApplicationLayer, P extends
96
97
  removeCustomFunctionCode(fc: number): void;
97
98
  sendCustomFC(unit: 0, fc: number, data: Buffer | number[], timeout?: number): Promise<void>;
98
99
  sendCustomFC(unit: number, fc: number, data: Buffer | number[], timeout?: number): Promise<Buffer>;
100
+ private _clean;
99
101
  open(...args: Parameters<P['open']>): Promise<void>;
100
102
  close(): Promise<void>;
101
103
  destroy(): Promise<void>;
@@ -60,6 +60,7 @@ export declare class ModbusSlave<A extends AbstractApplicationLayer, P extends A
60
60
  private _queues;
61
61
  private _customFunctionCodes;
62
62
  private _locks;
63
+ private _cleanLevel;
63
64
  get isOpen(): boolean;
64
65
  get destroyed(): boolean;
65
66
  constructor(applicationLayer: A, physicalLayer: P, options?: ModbusSlaveOptions);
@@ -85,6 +86,7 @@ export declare class ModbusSlave<A extends AbstractApplicationLayer, P extends A
85
86
  remove(unit: number): void;
86
87
  addCustomFunctionCode(cfc: CustomFunctionCode): void;
87
88
  removeCustomFunctionCode(fc: number): void;
89
+ private _clean;
88
90
  open(...args: Parameters<P['open']>): Promise<void>;
89
91
  close(): Promise<void>;
90
92
  destroy(): Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "njs-modbus",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "A pure JavaScript implemetation of Modbus for NodeJS.",
5
5
  "keywords": [
6
6
  "modbus",