njs-modbus 1.2.0 → 1.3.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.mjs CHANGED
@@ -544,8 +544,20 @@ function lrc(data) {
544
544
  }
545
545
 
546
546
  class RtuApplicationLayer extends AbstractApplicationLayer {
547
- constructor(physicalLayer, bitsBetweenFrames) {
547
+ constructor(physicalLayer,
548
+ /**
549
+ * The time interval between two frames, support two formats:
550
+ * - bit: `48bit` as default
551
+ * - millisecond: `20ms`
552
+ */
553
+ intervalBetweenFrames) {
548
554
  super();
555
+ Object.defineProperty(this, "_waitingResponse", {
556
+ enumerable: true,
557
+ configurable: true,
558
+ writable: true,
559
+ value: void 0
560
+ });
549
561
  Object.defineProperty(this, "_timerThreePointFive", {
550
562
  enumerable: true,
551
563
  configurable: true,
@@ -566,25 +578,42 @@ class RtuApplicationLayer extends AbstractApplicationLayer {
566
578
  });
567
579
  let threePointFiveT = 0;
568
580
  if (physicalLayer.TYPE === 'SERIAL') {
569
- threePointFiveT = Math.ceil(physicalLayer.baudRate > 19200
570
- ? 1.8
571
- : getThreePointFiveT(physicalLayer.baudRate, bitsBetweenFrames));
581
+ if (intervalBetweenFrames && intervalBetweenFrames.endsWith('ms')) {
582
+ threePointFiveT = Number(intervalBetweenFrames.slice(0, -2));
583
+ }
584
+ else {
585
+ threePointFiveT = Math.ceil(physicalLayer.baudRate > 19200
586
+ ? 1.8
587
+ : getThreePointFiveT(physicalLayer.baudRate, intervalBetweenFrames ? Number(intervalBetweenFrames.slice(0, -3)) : 48));
588
+ }
572
589
  }
573
590
  const handleData = (data, response) => {
574
591
  this._bufferRx = Buffer.concat([this._bufferRx, data]);
575
- clearTimeout(this._timerThreePointFive);
576
- const handleData = () => {
577
- const frame = this.framing(this._bufferRx);
578
- if (frame) {
579
- this.emit('framing', frame, response);
580
- }
581
- this._bufferRx = Buffer.alloc(0);
582
- };
583
- if (threePointFiveT) {
584
- this._timerThreePointFive = setTimeout(handleData, threePointFiveT);
592
+ if (this._waitingResponse) {
593
+ this.framing(this._bufferRx, (error, frame) => {
594
+ if (error && error.message === 'Insufficient data length') {
595
+ return;
596
+ }
597
+ this._waitingResponse.callback(error, frame);
598
+ this._bufferRx = Buffer.alloc(0);
599
+ });
585
600
  }
586
601
  else {
587
- handleData();
602
+ clearTimeout(this._timerThreePointFive);
603
+ const handleData = () => {
604
+ this.framing(this._bufferRx, (error, frame) => {
605
+ if (!error) {
606
+ this.emit('framing', frame, response);
607
+ }
608
+ this._bufferRx = Buffer.alloc(0);
609
+ });
610
+ };
611
+ if (threePointFiveT) {
612
+ this._timerThreePointFive = setTimeout(handleData, threePointFiveT);
613
+ }
614
+ else {
615
+ handleData();
616
+ }
588
617
  }
589
618
  };
590
619
  physicalLayer.on('data', handleData);
@@ -600,18 +629,56 @@ class RtuApplicationLayer extends AbstractApplicationLayer {
600
629
  physicalLayer.removeListener('close', handleClose);
601
630
  });
602
631
  }
603
- framing(buffer) {
632
+ framing(buffer, callback) {
604
633
  if (buffer.length >= 4) {
634
+ const frame = {
635
+ unit: buffer[0],
636
+ fc: buffer[1],
637
+ data: Array.from(buffer.subarray(2, buffer.length - 2)),
638
+ buffer,
639
+ };
640
+ if (this._waitingResponse) {
641
+ for (const check of this._waitingResponse.preCheck) {
642
+ const res = check(frame);
643
+ if (typeof res === 'undefined') {
644
+ callback(new Error('Insufficient data length'));
645
+ return;
646
+ }
647
+ if (typeof res === 'number') {
648
+ if (res < frame.data.length) {
649
+ callback(new Error('Insufficient data length'));
650
+ return;
651
+ }
652
+ if (res !== frame.data.length) {
653
+ callback(new Error('Invalid response'));
654
+ return;
655
+ }
656
+ }
657
+ if (!res) {
658
+ callback(new Error('Invalid response'));
659
+ return;
660
+ }
661
+ }
662
+ }
605
663
  const crcPassed = buffer.readUInt16LE(buffer.length - 2) === crc(buffer.subarray(0, buffer.length - 2));
606
664
  if (crcPassed) {
607
- return {
608
- unit: buffer[0],
609
- fc: buffer[1],
610
- data: Array.from(buffer.subarray(2, buffer.length - 2)),
611
- buffer,
612
- };
665
+ callback(null, frame);
666
+ }
667
+ else {
668
+ callback(new Error('CRC check failed'));
613
669
  }
614
670
  }
671
+ else {
672
+ callback(new Error('Insufficient data length'));
673
+ }
674
+ }
675
+ startWaitingResponse(preCheck, callback) {
676
+ this._waitingResponse = { preCheck, callback };
677
+ clearTimeout(this._timerThreePointFive);
678
+ this._bufferRx = Buffer.alloc(0);
679
+ }
680
+ stopWaitingResponse() {
681
+ this._waitingResponse = undefined;
615
682
  }
616
683
  encode(data) {
617
684
  const buffer = Buffer.alloc(data.data.length + 4);
@@ -640,6 +707,12 @@ const CHAR_CODE = {
640
707
  class AsciiApplicationLayer extends AbstractApplicationLayer {
641
708
  constructor(physicalLayer) {
642
709
  super();
710
+ Object.defineProperty(this, "_waitingResponse", {
711
+ enumerable: true,
712
+ configurable: true,
713
+ writable: true,
714
+ value: void 0
715
+ });
643
716
  Object.defineProperty(this, "_status", {
644
717
  enumerable: true,
645
718
  configurable: true,
@@ -688,10 +761,14 @@ class AsciiApplicationLayer extends AbstractApplicationLayer {
688
761
  else {
689
762
  this._status = 'idle';
690
763
  if (value === CHAR_CODE.LF) {
691
- const frame = this.framing(Buffer.from(this._frame));
692
- if (frame) {
693
- this.emit('framing', frame, response);
694
- }
764
+ this.framing(Buffer.from(this._frame), (error, frame) => {
765
+ if (this._waitingResponse) {
766
+ this._waitingResponse.callback(error, frame);
767
+ }
768
+ else if (!error) {
769
+ this.emit('framing', frame, response);
770
+ }
771
+ });
695
772
  }
696
773
  }
697
774
  break;
@@ -704,7 +781,7 @@ class AsciiApplicationLayer extends AbstractApplicationLayer {
704
781
  physicalLayer.removeListener('data', handleData);
705
782
  });
706
783
  const handleClose = () => {
707
- this._status = 'reception';
784
+ this._status = 'idle';
708
785
  this._frame = [];
709
786
  };
710
787
  physicalLayer.on('close', handleClose);
@@ -712,29 +789,72 @@ class AsciiApplicationLayer extends AbstractApplicationLayer {
712
789
  physicalLayer.removeListener('close', handleClose);
713
790
  });
714
791
  }
715
- framing(_buffer) {
716
- if (_buffer.length >= 6 && _buffer.length % 2 === 0) {
717
- const frame = [];
718
- let num = '';
719
- for (const value of _buffer) {
720
- num += String.fromCharCode(value);
721
- if (num.length === 2) {
722
- frame.push(Number('0x' + num));
723
- num = '';
792
+ framing(_buffer, callback) {
793
+ if (_buffer.length >= 6) {
794
+ if (_buffer.length % 2 === 0) {
795
+ const ascii = [];
796
+ let num = '';
797
+ for (const value of _buffer) {
798
+ num += String.fromCharCode(value);
799
+ if (num.length === 2) {
800
+ ascii.push(Number('0x' + num));
801
+ num = '';
802
+ }
724
803
  }
725
- }
726
- const buffer = Buffer.from(frame);
727
- const lrcPassed = buffer[buffer.length - 1] === lrc(buffer.subarray(0, buffer.length - 1));
728
- if (lrcPassed) {
729
- return {
804
+ const buffer = Buffer.from(ascii);
805
+ const frame = {
730
806
  unit: buffer[0],
731
807
  fc: buffer[1],
732
808
  data: Array.from(buffer.subarray(2, buffer.length - 1)),
733
809
  buffer: _buffer,
734
810
  };
811
+ if (this._waitingResponse) {
812
+ for (const check of this._waitingResponse.preCheck) {
813
+ const res = check(frame);
814
+ if (typeof res === 'undefined') {
815
+ callback(new Error('Insufficient data length'));
816
+ return;
817
+ }
818
+ if (typeof res === 'number') {
819
+ if (res < frame.data.length) {
820
+ callback(new Error('Insufficient data length'));
821
+ return;
822
+ }
823
+ if (res !== frame.data.length) {
824
+ callback(new Error('Invalid response'));
825
+ return;
826
+ }
827
+ }
828
+ if (!res) {
829
+ callback(new Error('Invalid response'));
830
+ return;
831
+ }
832
+ }
833
+ }
834
+ const lrcPassed = buffer[buffer.length - 1] === lrc(buffer.subarray(0, buffer.length - 1));
835
+ if (lrcPassed) {
836
+ callback(null, frame);
837
+ }
838
+ else {
839
+ callback(new Error('LRC check failed'));
840
+ }
735
841
  }
842
+ else {
843
+ callback(new Error('Invalid data'));
844
+ }
845
+ }
846
+ else {
847
+ callback(new Error('Insufficient data length'));
736
848
  }
737
849
  }
850
+ startWaitingResponse(preCheck, callback) {
851
+ this._waitingResponse = { preCheck, callback };
852
+ this._status = 'idle';
853
+ this._frame = [];
854
+ }
855
+ stopWaitingResponse() {
856
+ this._waitingResponse = undefined;
857
+ }
738
858
  encode(data) {
739
859
  const buffer = Buffer.alloc(data.data.length + 3);
740
860
  buffer.writeUInt8(data.unit, 0);
@@ -761,6 +881,12 @@ class AsciiApplicationLayer extends AbstractApplicationLayer {
761
881
  class TcpApplicationLayer extends AbstractApplicationLayer {
762
882
  constructor(physicalLayer) {
763
883
  super();
884
+ Object.defineProperty(this, "_waitingResponse", {
885
+ enumerable: true,
886
+ configurable: true,
887
+ writable: true,
888
+ value: void 0
889
+ });
764
890
  Object.defineProperty(this, "_transactionId", {
765
891
  enumerable: true,
766
892
  configurable: true,
@@ -774,28 +900,68 @@ class TcpApplicationLayer extends AbstractApplicationLayer {
774
900
  value: []
775
901
  });
776
902
  const handleData = (data, response) => {
777
- const frame = this.framing(data);
778
- if (frame) {
779
- this.emit('framing', frame, response);
780
- }
903
+ this.framing(data, (error, frame) => {
904
+ if (this._waitingResponse) {
905
+ this._waitingResponse.callback(error, frame);
906
+ }
907
+ else if (!error) {
908
+ this.emit('framing', frame, response);
909
+ }
910
+ });
781
911
  };
782
912
  physicalLayer.on('data', handleData);
783
913
  this._removeAllListeners.push(() => {
784
914
  physicalLayer.removeListener('data', handleData);
785
915
  });
786
916
  }
787
- framing(buffer) {
917
+ framing(buffer, callback) {
788
918
  if (buffer.length >= 8) {
789
919
  if (buffer[2] === 0 && buffer[3] === 0 && buffer.readUInt16BE(4) === buffer.length - 6) {
790
- return {
920
+ const frame = {
791
921
  transaction: buffer.readUInt16BE(0),
792
922
  unit: buffer[6],
793
923
  fc: buffer[7],
794
924
  data: Array.from(buffer.subarray(8)),
795
925
  buffer,
796
926
  };
927
+ if (this._waitingResponse) {
928
+ for (const check of this._waitingResponse.preCheck) {
929
+ const res = check(frame);
930
+ if (typeof res === 'undefined') {
931
+ callback(new Error('Insufficient data length'));
932
+ return;
933
+ }
934
+ if (typeof res === 'number') {
935
+ if (res < frame.data.length) {
936
+ callback(new Error('Insufficient data length'));
937
+ return;
938
+ }
939
+ if (res !== frame.data.length) {
940
+ callback(new Error('Invalid response'));
941
+ return;
942
+ }
943
+ }
944
+ if (!res) {
945
+ callback(new Error('Invalid response'));
946
+ return;
947
+ }
948
+ }
949
+ }
950
+ callback(null, frame);
951
+ }
952
+ else {
953
+ callback(new Error('Invalid data'));
797
954
  }
798
955
  }
956
+ else {
957
+ callback(new Error('Insufficient data length'));
958
+ }
959
+ }
960
+ startWaitingResponse(preCheck, callback) {
961
+ this._waitingResponse = { preCheck, callback };
962
+ }
963
+ stopWaitingResponse() {
964
+ this._waitingResponse = undefined;
799
965
  }
800
966
  encode(data) {
801
967
  var _a;
@@ -819,38 +985,6 @@ class TcpApplicationLayer extends AbstractApplicationLayer {
819
985
  }
820
986
  }
821
987
 
822
- /******************************************************************************
823
- Copyright (c) Microsoft Corporation.
824
-
825
- Permission to use, copy, modify, and/or distribute this software for any
826
- purpose with or without fee is hereby granted.
827
-
828
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
829
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
830
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
831
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
832
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
833
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
834
- PERFORMANCE OF THIS SOFTWARE.
835
- ***************************************************************************** */
836
- /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
837
-
838
-
839
- function __awaiter(thisArg, _arguments, P, generator) {
840
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
841
- return new (P || (P = Promise))(function (resolve, reject) {
842
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
843
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
844
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
845
- step((generator = generator.apply(thisArg, _arguments || [])).next());
846
- });
847
- }
848
-
849
- typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
850
- var e = new Error(message);
851
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
852
- };
853
-
854
988
  class ModbusMaster extends EventEmitter {
855
989
  get isOpen() {
856
990
  return this.physicalLayer.isOpen;
@@ -878,12 +1012,6 @@ class ModbusMaster extends EventEmitter {
878
1012
  writable: true,
879
1013
  value: timeout
880
1014
  });
881
- Object.defineProperty(this, "_responses", {
882
- enumerable: true,
883
- configurable: true,
884
- writable: true,
885
- value: new Set()
886
- });
887
1015
  Object.defineProperty(this, "writeFC1", {
888
1016
  enumerable: true,
889
1017
  configurable: true,
@@ -968,11 +1096,6 @@ class ModbusMaster extends EventEmitter {
968
1096
  this.handleFC22 = this.maskWriteRegister;
969
1097
  this.handleFC23 = this.readAndWriteMultipleRegisters;
970
1098
  this.handleFC43_14 = this.readDeviceIdentification;
971
- applicationLayer.on('framing', (frame) => __awaiter(this, void 0, void 0, function* () {
972
- for (const response of this._responses) {
973
- response(frame);
974
- }
975
- }));
976
1099
  physicalLayer.on('error', (error) => {
977
1100
  this.emit('error', error);
978
1101
  });
@@ -980,46 +1103,55 @@ class ModbusMaster extends EventEmitter {
980
1103
  this.emit('close');
981
1104
  });
982
1105
  }
983
- waitResponse(timeout, cb) {
1106
+ waitResponse(request, response, timeout) {
984
1107
  return new Promise((resolve, reject) => {
985
- const tid = setTimeout(() => {
986
- this._responses.delete(response);
987
- reject('Timeout');
988
- }, timeout);
989
- const response = (frame) => {
990
- const data = cb(frame);
991
- if (typeof data !== 'undefined') {
992
- clearTimeout(tid);
993
- this._responses.delete(response);
994
- resolve({
995
- transaction: frame.transaction,
996
- unit: frame.unit,
997
- fc: frame.fc,
998
- data,
999
- buffer: frame.buffer,
1108
+ this.physicalLayer
1109
+ .write(request.data)
1110
+ .then(() => {
1111
+ if (request.broadcast) {
1112
+ resolve();
1113
+ }
1114
+ else {
1115
+ const tid = setTimeout(() => {
1116
+ this.applicationLayer.stopWaitingResponse();
1117
+ reject(new Error('Timeout'));
1118
+ }, timeout);
1119
+ this.applicationLayer.startWaitingResponse(response.preCheck, (error, frame) => {
1120
+ clearTimeout(tid);
1121
+ this.applicationLayer.stopWaitingResponse();
1122
+ if (error) {
1123
+ reject(error);
1124
+ }
1125
+ else {
1126
+ resolve(frame);
1127
+ }
1000
1128
  });
1001
1129
  }
1002
- };
1003
- this._responses.add(response);
1130
+ })
1131
+ .catch((error) => {
1132
+ reject(error);
1133
+ });
1004
1134
  });
1005
1135
  }
1006
1136
  writeFC1Or2(unit, fc, address, length, timeout) {
1137
+ const byteCount = Math.ceil(length / 8);
1007
1138
  const bufferTx = Buffer.alloc(4);
1008
1139
  bufferTx.writeUInt16BE(address, 0);
1009
1140
  bufferTx.writeUInt16BE(length, 2);
1010
- this.physicalLayer.write(this.applicationLayer.encode({
1011
- unit,
1012
- fc,
1013
- data: Array.from(bufferTx),
1014
- }));
1015
- if (unit !== 0) {
1016
- return this.waitResponse(timeout, (frame) => {
1017
- const byteCount = Math.ceil(length / 8);
1018
- if (frame.unit === unit && frame.fc === fc && frame.data.length === 1 + byteCount && frame.data[0] === byteCount) {
1019
- return Array.from({ length }).map((_, index) => (frame.data[1 + ~~(index / 8)] & (1 << index % 8)) > 0);
1020
- }
1021
- });
1022
- }
1141
+ return this.waitResponse({
1142
+ data: this.applicationLayer.encode({
1143
+ unit,
1144
+ fc,
1145
+ data: Array.from(bufferTx),
1146
+ }),
1147
+ broadcast: unit === 0,
1148
+ }, {
1149
+ preCheck: [(frame) => frame.unit === unit && frame.fc === fc, () => 1 + byteCount, (frame) => frame.data[0] === byteCount],
1150
+ }, timeout).then((frame) => {
1151
+ if (frame) {
1152
+ return Object.assign(Object.assign({}, frame), { data: Array.from({ length }).map((_, index) => (frame.data[1 + ~~(index / 8)] & (1 << index % 8)) > 0) });
1153
+ }
1154
+ });
1023
1155
  }
1024
1156
  readCoils(unit, address, length, timeout = this.timeout) {
1025
1157
  return this.writeFC1Or2(unit, 0x01, address, length, timeout);
@@ -1028,23 +1160,25 @@ class ModbusMaster extends EventEmitter {
1028
1160
  return this.writeFC1Or2(unit, 0x02, address, length, timeout);
1029
1161
  }
1030
1162
  writeFC3Or4(unit, fc, address, length, timeout) {
1163
+ const byteCount = length * 2;
1031
1164
  const bufferTx = Buffer.alloc(4);
1032
1165
  bufferTx.writeUInt16BE(address, 0);
1033
1166
  bufferTx.writeUInt16BE(length, 2);
1034
- this.physicalLayer.write(this.applicationLayer.encode({
1035
- unit,
1036
- fc,
1037
- data: Array.from(bufferTx),
1038
- }));
1039
- if (unit !== 0) {
1040
- return this.waitResponse(timeout, (frame) => {
1041
- const byteCount = length * 2;
1042
- if (frame.unit === unit && frame.fc === fc && frame.data.length === 1 + byteCount && frame.data[0] === byteCount) {
1043
- const bufferRx = Buffer.from(frame.data.slice(1));
1044
- return Array.from({ length }).map((_, index) => bufferRx.readUInt16BE(index * 2));
1045
- }
1046
- });
1047
- }
1167
+ return this.waitResponse({
1168
+ data: this.applicationLayer.encode({
1169
+ unit,
1170
+ fc,
1171
+ data: Array.from(bufferTx),
1172
+ }),
1173
+ broadcast: unit === 0,
1174
+ }, {
1175
+ preCheck: [(frame) => frame.unit === unit && frame.fc === fc, () => 1 + byteCount, (frame) => frame.data[0] === byteCount],
1176
+ }, timeout).then((frame) => {
1177
+ if (frame) {
1178
+ const bufferRx = Buffer.from(frame.data.slice(1));
1179
+ return Object.assign(Object.assign({}, frame), { data: Array.from({ length }).map((_, index) => bufferRx.readUInt16BE(index * 2)) });
1180
+ }
1181
+ });
1048
1182
  }
1049
1183
  readHoldingRegisters(unit, address, length, timeout = this.timeout) {
1050
1184
  return this.writeFC3Or4(unit, 0x03, address, length, timeout);
@@ -1057,42 +1191,48 @@ class ModbusMaster extends EventEmitter {
1057
1191
  const bufferTx = Buffer.alloc(4);
1058
1192
  bufferTx.writeUInt16BE(address, 0);
1059
1193
  bufferTx.writeUInt16BE(value ? 0xff00 : 0x0000, 2);
1060
- this.physicalLayer.write(this.applicationLayer.encode({
1061
- unit,
1062
- fc,
1063
- data: Array.from(bufferTx),
1064
- }));
1065
- if (unit !== 0) {
1066
- return this.waitResponse(timeout, (frame) => {
1067
- if (frame.unit === unit &&
1068
- frame.fc === fc &&
1069
- frame.data.length === bufferTx.length &&
1070
- frame.data.every((v, i) => v === bufferTx[i])) {
1071
- return value;
1072
- }
1073
- });
1074
- }
1194
+ return this.waitResponse({
1195
+ data: this.applicationLayer.encode({
1196
+ unit,
1197
+ fc,
1198
+ data: Array.from(bufferTx),
1199
+ }),
1200
+ broadcast: unit === 0,
1201
+ }, {
1202
+ preCheck: [
1203
+ (frame) => frame.unit === unit && frame.fc === fc,
1204
+ () => bufferTx.length,
1205
+ (frame) => frame.data.every((v, i) => v === bufferTx[i]),
1206
+ ],
1207
+ }, timeout).then((frame) => {
1208
+ if (frame) {
1209
+ return Object.assign(Object.assign({}, frame), { data: value });
1210
+ }
1211
+ });
1075
1212
  }
1076
1213
  writeSingleRegister(unit, address, value, timeout = this.timeout) {
1077
1214
  const fc = 0x06;
1078
1215
  const bufferTx = Buffer.alloc(4);
1079
1216
  bufferTx.writeUInt16BE(address, 0);
1080
1217
  bufferTx.writeUInt16BE(value, 2);
1081
- this.physicalLayer.write(this.applicationLayer.encode({
1082
- unit,
1083
- fc,
1084
- data: Array.from(bufferTx),
1085
- }));
1086
- if (unit !== 0) {
1087
- return this.waitResponse(timeout, (frame) => {
1088
- if (frame.unit === unit &&
1089
- frame.fc === fc &&
1090
- frame.data.length === bufferTx.length &&
1091
- frame.data.every((v, i) => v === bufferTx[i])) {
1092
- return value;
1093
- }
1094
- });
1095
- }
1218
+ return this.waitResponse({
1219
+ data: this.applicationLayer.encode({
1220
+ unit,
1221
+ fc,
1222
+ data: Array.from(bufferTx),
1223
+ }),
1224
+ broadcast: unit === 0,
1225
+ }, {
1226
+ preCheck: [
1227
+ (frame) => frame.unit === unit && frame.fc === fc,
1228
+ () => bufferTx.length,
1229
+ (frame) => frame.data.every((v, i) => v === bufferTx[i]),
1230
+ ],
1231
+ }, timeout).then((frame) => {
1232
+ if (frame) {
1233
+ return Object.assign(Object.assign({}, frame), { data: value });
1234
+ }
1235
+ });
1096
1236
  }
1097
1237
  writeMultipleCoils(unit, address, value, timeout = this.timeout) {
1098
1238
  const fc = 0x0f;
@@ -1106,18 +1246,20 @@ class ModbusMaster extends EventEmitter {
1106
1246
  bufferTx[5 + ~~(i / 8)] |= 1 << i % 8;
1107
1247
  }
1108
1248
  });
1109
- this.physicalLayer.write(this.applicationLayer.encode({
1110
- unit,
1111
- fc,
1112
- data: Array.from(bufferTx),
1113
- }));
1114
- if (unit !== 0) {
1115
- return this.waitResponse(timeout, (frame) => {
1116
- if (frame.unit === unit && frame.fc === fc && frame.data.length === 4 && frame.data.every((v, i) => v === bufferTx[i])) {
1117
- return value;
1118
- }
1119
- });
1120
- }
1249
+ return this.waitResponse({
1250
+ data: this.applicationLayer.encode({
1251
+ unit,
1252
+ fc,
1253
+ data: Array.from(bufferTx),
1254
+ }),
1255
+ broadcast: unit === 0,
1256
+ }, {
1257
+ preCheck: [(frame) => frame.unit === unit && frame.fc === fc, () => 4, (frame) => frame.data.every((v, i) => v === bufferTx[i])],
1258
+ }, timeout).then((frame) => {
1259
+ if (frame) {
1260
+ return Object.assign(Object.assign({}, frame), { data: value });
1261
+ }
1262
+ });
1121
1263
  }
1122
1264
  writeMultipleRegisters(unit, address, value, timeout = this.timeout) {
1123
1265
  const fc = 0x10;
@@ -1129,40 +1271,48 @@ class ModbusMaster extends EventEmitter {
1129
1271
  value.forEach((v, i) => {
1130
1272
  bufferTx.writeUInt16BE(v, 5 + i * 2);
1131
1273
  });
1132
- this.physicalLayer.write(this.applicationLayer.encode({
1133
- unit,
1134
- fc,
1135
- data: Array.from(bufferTx),
1136
- }));
1137
- if (unit !== 0) {
1138
- return this.waitResponse(timeout, (frame) => {
1139
- if (frame.unit === unit && frame.fc === fc && frame.data.length === 4 && frame.data.every((v, i) => v === bufferTx[i])) {
1140
- return value;
1141
- }
1142
- });
1143
- }
1274
+ return this.waitResponse({
1275
+ data: this.applicationLayer.encode({
1276
+ unit,
1277
+ fc,
1278
+ data: Array.from(bufferTx),
1279
+ }),
1280
+ broadcast: unit === 0,
1281
+ }, {
1282
+ preCheck: [(frame) => frame.unit === unit && frame.fc === fc, () => 4, (frame) => frame.data.every((v, i) => v === bufferTx[i])],
1283
+ }, timeout).then((frame) => {
1284
+ if (frame) {
1285
+ return Object.assign(Object.assign({}, frame), { data: value });
1286
+ }
1287
+ });
1144
1288
  }
1145
1289
  reportServerId(unit, timeout = this.timeout) {
1146
1290
  const fc = 0x11;
1147
- this.physicalLayer.write(this.applicationLayer.encode({
1148
- unit,
1149
- fc,
1150
- data: [],
1151
- }));
1152
- if (unit !== 0) {
1153
- return this.waitResponse(timeout, (frame) => {
1154
- if (frame.unit === unit && frame.fc === fc && frame.data.length >= 3) {
1155
- const byteCount = frame.data[0];
1156
- if (frame.data.length - 1 === byteCount) {
1157
- return {
1158
- serverId: frame.data[1],
1159
- runIndicatorStatus: frame.data[2] === 0xff,
1160
- additionalData: frame.data.slice(3),
1161
- };
1291
+ return this.waitResponse({
1292
+ data: this.applicationLayer.encode({
1293
+ unit,
1294
+ fc,
1295
+ data: [],
1296
+ }),
1297
+ broadcast: unit === 0,
1298
+ }, {
1299
+ preCheck: [
1300
+ (frame) => frame.unit === unit && frame.fc === fc,
1301
+ (frame) => {
1302
+ if (frame.data.length >= 3) {
1303
+ return 1 + frame.data[0];
1162
1304
  }
1163
- }
1164
- });
1165
- }
1305
+ },
1306
+ ],
1307
+ }, timeout).then((frame) => {
1308
+ if (frame) {
1309
+ return Object.assign(Object.assign({}, frame), { data: {
1310
+ serverId: frame.data[1],
1311
+ runIndicatorStatus: frame.data[2] === 0xff,
1312
+ additionalData: frame.data.slice(3),
1313
+ } });
1314
+ }
1315
+ });
1166
1316
  }
1167
1317
  maskWriteRegister(unit, address, andMask, orMask, timeout = this.timeout) {
1168
1318
  const fc = 0x16;
@@ -1170,18 +1320,20 @@ class ModbusMaster extends EventEmitter {
1170
1320
  bufferTx.writeUInt16BE(address, 0);
1171
1321
  bufferTx.writeUInt16BE(andMask, 2);
1172
1322
  bufferTx.writeUInt16BE(orMask, 4);
1173
- this.physicalLayer.write(this.applicationLayer.encode({
1174
- unit,
1175
- fc,
1176
- data: Array.from(bufferTx),
1177
- }));
1178
- if (unit !== 0) {
1179
- return this.waitResponse(timeout, (frame) => {
1180
- if (frame.unit === unit && frame.fc === fc && frame.data.length === 6 && frame.data.every((v, i) => v === bufferTx[i])) {
1181
- return { andMask, orMask };
1182
- }
1183
- });
1184
- }
1323
+ return this.waitResponse({
1324
+ data: this.applicationLayer.encode({
1325
+ unit,
1326
+ fc,
1327
+ data: Array.from(bufferTx),
1328
+ }),
1329
+ broadcast: unit === 0,
1330
+ }, {
1331
+ preCheck: [(frame) => frame.unit === unit && frame.fc === fc, () => 6, (frame) => frame.data.every((v, i) => v === bufferTx[i])],
1332
+ }, timeout).then((frame) => {
1333
+ if (frame) {
1334
+ return Object.assign(Object.assign({}, frame), { data: { andMask, orMask } });
1335
+ }
1336
+ });
1185
1337
  }
1186
1338
  readAndWriteMultipleRegisters(unit, read, write, timeout = this.timeout) {
1187
1339
  const fc = 0x17;
@@ -1195,73 +1347,104 @@ class ModbusMaster extends EventEmitter {
1195
1347
  write.value.forEach((v, i) => {
1196
1348
  bufferTx.writeUInt16BE(v, 9 + i * 2);
1197
1349
  });
1198
- this.physicalLayer.write(this.applicationLayer.encode({
1199
- unit,
1200
- fc,
1201
- data: Array.from(bufferTx),
1202
- }));
1203
- if (unit !== 0) {
1204
- return this.waitResponse(timeout, (frame) => {
1205
- if (frame.unit === unit && frame.fc === fc && frame.data.length === 1 + byteCount && frame.data[0] === byteCount) {
1206
- const bufferRx = Buffer.from(frame.data.slice(1));
1207
- return Array.from({ length: read.length }).map((_, index) => bufferRx.readUInt16BE(index * 2));
1208
- }
1209
- });
1210
- }
1350
+ return this.waitResponse({
1351
+ data: this.applicationLayer.encode({
1352
+ unit,
1353
+ fc,
1354
+ data: Array.from(bufferTx),
1355
+ }),
1356
+ broadcast: unit === 0,
1357
+ }, {
1358
+ preCheck: [(frame) => frame.unit === unit && frame.fc === fc, () => 1 + byteCount, (frame) => frame.data[0] === byteCount],
1359
+ }, timeout).then((frame) => {
1360
+ if (frame) {
1361
+ const bufferRx = Buffer.from(frame.data.slice(1));
1362
+ return Object.assign(Object.assign({}, frame), { data: Array.from({ length: read.length }).map((_, index) => bufferRx.readUInt16BE(index * 2)) });
1363
+ }
1364
+ });
1211
1365
  }
1212
1366
  readDeviceIdentification(unit, readDeviceIDCode, objectId, timeout = this.timeout) {
1213
1367
  const fc = 0x2b;
1214
- this.physicalLayer.write(this.applicationLayer.encode({
1215
- unit,
1216
- fc,
1217
- data: [0x0e, readDeviceIDCode, objectId],
1218
- }));
1219
- if (unit !== 0) {
1220
- return this.waitResponse(timeout, (frame) => {
1221
- if (frame.unit === unit &&
1222
- frame.fc === fc &&
1223
- frame.data.length >= 6 &&
1224
- frame.data[0] === 0x0e &&
1225
- frame.data[1] === readDeviceIDCode) {
1226
- const conformityLevel = frame.data[2];
1227
- const moreFollows = frame.data[3] === 0xff;
1228
- const nextObjectId = frame.data[4];
1229
- const objectLength = frame.data[5];
1230
- const objects = [];
1231
- let object = [];
1232
- for (const v of frame.data.slice(6)) {
1233
- switch (object.length) {
1234
- case 0:
1235
- case 1: {
1236
- object.push(v);
1237
- break;
1368
+ return this.waitResponse({
1369
+ data: this.applicationLayer.encode({
1370
+ unit,
1371
+ fc,
1372
+ data: [0x0e, readDeviceIDCode, objectId],
1373
+ }),
1374
+ broadcast: unit === 0,
1375
+ }, {
1376
+ preCheck: [
1377
+ (frame) => frame.unit === unit && frame.fc === fc,
1378
+ (frame) => {
1379
+ if (frame.data.length >= 6) {
1380
+ if (frame.data[0] === 0x0e && frame.data[1] === readDeviceIDCode) {
1381
+ const objects = [];
1382
+ let object = [];
1383
+ for (const v of frame.data.slice(6)) {
1384
+ switch (object.length) {
1385
+ case 0:
1386
+ case 1: {
1387
+ object.push(v);
1388
+ break;
1389
+ }
1390
+ case 2: {
1391
+ object.push([v]);
1392
+ break;
1393
+ }
1394
+ case 3: {
1395
+ object[2].push(v);
1396
+ if (object[1] === object[2].length) {
1397
+ objects.push(2 + object[1]);
1398
+ object = [];
1399
+ }
1400
+ break;
1401
+ }
1402
+ }
1238
1403
  }
1239
- case 2: {
1240
- object.push([v]);
1241
- break;
1242
- }
1243
- case 3: {
1244
- object[2].push(v);
1245
- break;
1404
+ if (objects.length === frame.data[5]) {
1405
+ return 6 + objects.reduce((previous, current) => previous + current, 0);
1246
1406
  }
1247
1407
  }
1248
- if (object.length === 3 && object[1] === object[2].length) {
1249
- objects.push({ id: object[0], value: Buffer.from(object[2]).toString() });
1250
- object = [];
1408
+ else {
1409
+ return false;
1251
1410
  }
1252
1411
  }
1253
- if (objects.length === objectLength) {
1254
- return {
1255
- readDeviceIDCode,
1256
- conformityLevel,
1257
- moreFollows,
1258
- nextObjectId,
1259
- objects,
1260
- };
1412
+ },
1413
+ ],
1414
+ }, timeout).then((frame) => {
1415
+ if (frame) {
1416
+ const objects = [];
1417
+ let object = [];
1418
+ for (const v of frame.data.slice(6)) {
1419
+ switch (object.length) {
1420
+ case 0:
1421
+ case 1: {
1422
+ object.push(v);
1423
+ break;
1424
+ }
1425
+ case 2: {
1426
+ object.push([v]);
1427
+ break;
1428
+ }
1429
+ case 3: {
1430
+ object[2].push(v);
1431
+ if (object[1] === object[2].length) {
1432
+ objects.push({ id: object[0], value: Buffer.from(object[2]).toString() });
1433
+ object = [];
1434
+ }
1435
+ break;
1436
+ }
1261
1437
  }
1262
1438
  }
1263
- });
1264
- }
1439
+ return Object.assign(Object.assign({}, frame), { data: {
1440
+ readDeviceIDCode,
1441
+ conformityLevel: frame.data[2],
1442
+ moreFollows: frame.data[3] === 0xff,
1443
+ nextObjectId: frame.data[4],
1444
+ objects,
1445
+ } });
1446
+ }
1447
+ });
1265
1448
  }
1266
1449
  open(...args) {
1267
1450
  return this.physicalLayer.open(...args);
@@ -1276,6 +1459,38 @@ class ModbusMaster extends EventEmitter {
1276
1459
  }
1277
1460
  }
1278
1461
 
1462
+ /******************************************************************************
1463
+ Copyright (c) Microsoft Corporation.
1464
+
1465
+ Permission to use, copy, modify, and/or distribute this software for any
1466
+ purpose with or without fee is hereby granted.
1467
+
1468
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
1469
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1470
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
1471
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1472
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
1473
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1474
+ PERFORMANCE OF THIS SOFTWARE.
1475
+ ***************************************************************************** */
1476
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
1477
+
1478
+
1479
+ function __awaiter(thisArg, _arguments, P, generator) {
1480
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
1481
+ return new (P || (P = Promise))(function (resolve, reject) {
1482
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
1483
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
1484
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
1485
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
1486
+ });
1487
+ }
1488
+
1489
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
1490
+ var e = new Error(message);
1491
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
1492
+ };
1493
+
1279
1494
  class ModbusSlave extends EventEmitter {
1280
1495
  get isOpen() {
1281
1496
  return this.physicalLayer.isOpen;
@@ -1316,7 +1531,15 @@ class ModbusSlave extends EventEmitter {
1316
1531
  if (!(frame.unit === 0x00 || frame.unit === this.unit)) {
1317
1532
  return;
1318
1533
  }
1319
- const response = frame.unit === 0x00 ? () => Promise.resolve() : _response;
1534
+ const response = (data) => __awaiter(this, void 0, void 0, function* () {
1535
+ if (frame.unit === 0x00) {
1536
+ return;
1537
+ }
1538
+ try {
1539
+ yield _response(data);
1540
+ }
1541
+ catch (error) { }
1542
+ });
1320
1543
  if (model.interceptor) {
1321
1544
  try {
1322
1545
  const data = yield model.interceptor(frame.fc, frame.data);