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