njs-modbus 1.3.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
@@ -552,6 +552,12 @@ class RtuApplicationLayer extends AbstractApplicationLayer {
552
552
  */
553
553
  intervalBetweenFrames) {
554
554
  super();
555
+ Object.defineProperty(this, "_waitingResponse", {
556
+ enumerable: true,
557
+ configurable: true,
558
+ writable: true,
559
+ value: void 0
560
+ });
555
561
  Object.defineProperty(this, "_timerThreePointFive", {
556
562
  enumerable: true,
557
563
  configurable: true,
@@ -583,19 +589,31 @@ class RtuApplicationLayer extends AbstractApplicationLayer {
583
589
  }
584
590
  const handleData = (data, response) => {
585
591
  this._bufferRx = Buffer.concat([this._bufferRx, data]);
586
- clearTimeout(this._timerThreePointFive);
587
- const handleData = () => {
588
- const frame = this.framing(this._bufferRx);
589
- if (frame) {
590
- this.emit('framing', frame, response);
591
- }
592
- this._bufferRx = Buffer.alloc(0);
593
- };
594
- if (threePointFiveT) {
595
- 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
+ });
596
600
  }
597
601
  else {
598
- 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
+ }
599
617
  }
600
618
  };
601
619
  physicalLayer.on('data', handleData);
@@ -611,18 +629,56 @@ class RtuApplicationLayer extends AbstractApplicationLayer {
611
629
  physicalLayer.removeListener('close', handleClose);
612
630
  });
613
631
  }
614
- framing(buffer) {
632
+ framing(buffer, callback) {
615
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
+ }
616
663
  const crcPassed = buffer.readUInt16LE(buffer.length - 2) === crc(buffer.subarray(0, buffer.length - 2));
617
664
  if (crcPassed) {
618
- return {
619
- unit: buffer[0],
620
- fc: buffer[1],
621
- data: Array.from(buffer.subarray(2, buffer.length - 2)),
622
- buffer,
623
- };
665
+ callback(null, frame);
666
+ }
667
+ else {
668
+ callback(new Error('CRC check failed'));
624
669
  }
625
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;
626
682
  }
627
683
  encode(data) {
628
684
  const buffer = Buffer.alloc(data.data.length + 4);
@@ -651,6 +707,12 @@ const CHAR_CODE = {
651
707
  class AsciiApplicationLayer extends AbstractApplicationLayer {
652
708
  constructor(physicalLayer) {
653
709
  super();
710
+ Object.defineProperty(this, "_waitingResponse", {
711
+ enumerable: true,
712
+ configurable: true,
713
+ writable: true,
714
+ value: void 0
715
+ });
654
716
  Object.defineProperty(this, "_status", {
655
717
  enumerable: true,
656
718
  configurable: true,
@@ -699,10 +761,14 @@ class AsciiApplicationLayer extends AbstractApplicationLayer {
699
761
  else {
700
762
  this._status = 'idle';
701
763
  if (value === CHAR_CODE.LF) {
702
- const frame = this.framing(Buffer.from(this._frame));
703
- if (frame) {
704
- this.emit('framing', frame, response);
705
- }
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
+ });
706
772
  }
707
773
  }
708
774
  break;
@@ -715,7 +781,7 @@ class AsciiApplicationLayer extends AbstractApplicationLayer {
715
781
  physicalLayer.removeListener('data', handleData);
716
782
  });
717
783
  const handleClose = () => {
718
- this._status = 'reception';
784
+ this._status = 'idle';
719
785
  this._frame = [];
720
786
  };
721
787
  physicalLayer.on('close', handleClose);
@@ -723,28 +789,71 @@ class AsciiApplicationLayer extends AbstractApplicationLayer {
723
789
  physicalLayer.removeListener('close', handleClose);
724
790
  });
725
791
  }
726
- framing(_buffer) {
727
- if (_buffer.length >= 6 && _buffer.length % 2 === 0) {
728
- const frame = [];
729
- let num = '';
730
- for (const value of _buffer) {
731
- num += String.fromCharCode(value);
732
- if (num.length === 2) {
733
- frame.push(Number('0x' + num));
734
- 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
+ }
735
803
  }
736
- }
737
- const buffer = Buffer.from(frame);
738
- const lrcPassed = buffer[buffer.length - 1] === lrc(buffer.subarray(0, buffer.length - 1));
739
- if (lrcPassed) {
740
- return {
804
+ const buffer = Buffer.from(ascii);
805
+ const frame = {
741
806
  unit: buffer[0],
742
807
  fc: buffer[1],
743
808
  data: Array.from(buffer.subarray(2, buffer.length - 1)),
744
809
  buffer: _buffer,
745
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
+ }
841
+ }
842
+ else {
843
+ callback(new Error('Invalid data'));
746
844
  }
747
845
  }
846
+ else {
847
+ callback(new Error('Insufficient data length'));
848
+ }
849
+ }
850
+ startWaitingResponse(preCheck, callback) {
851
+ this._waitingResponse = { preCheck, callback };
852
+ this._status = 'idle';
853
+ this._frame = [];
854
+ }
855
+ stopWaitingResponse() {
856
+ this._waitingResponse = undefined;
748
857
  }
749
858
  encode(data) {
750
859
  const buffer = Buffer.alloc(data.data.length + 3);
@@ -772,6 +881,12 @@ class AsciiApplicationLayer extends AbstractApplicationLayer {
772
881
  class TcpApplicationLayer extends AbstractApplicationLayer {
773
882
  constructor(physicalLayer) {
774
883
  super();
884
+ Object.defineProperty(this, "_waitingResponse", {
885
+ enumerable: true,
886
+ configurable: true,
887
+ writable: true,
888
+ value: void 0
889
+ });
775
890
  Object.defineProperty(this, "_transactionId", {
776
891
  enumerable: true,
777
892
  configurable: true,
@@ -785,28 +900,68 @@ class TcpApplicationLayer extends AbstractApplicationLayer {
785
900
  value: []
786
901
  });
787
902
  const handleData = (data, response) => {
788
- const frame = this.framing(data);
789
- if (frame) {
790
- this.emit('framing', frame, response);
791
- }
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
+ });
792
911
  };
793
912
  physicalLayer.on('data', handleData);
794
913
  this._removeAllListeners.push(() => {
795
914
  physicalLayer.removeListener('data', handleData);
796
915
  });
797
916
  }
798
- framing(buffer) {
917
+ framing(buffer, callback) {
799
918
  if (buffer.length >= 8) {
800
919
  if (buffer[2] === 0 && buffer[3] === 0 && buffer.readUInt16BE(4) === buffer.length - 6) {
801
- return {
920
+ const frame = {
802
921
  transaction: buffer.readUInt16BE(0),
803
922
  unit: buffer[6],
804
923
  fc: buffer[7],
805
924
  data: Array.from(buffer.subarray(8)),
806
925
  buffer,
807
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'));
808
954
  }
809
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;
810
965
  }
811
966
  encode(data) {
812
967
  var _a;
@@ -830,38 +985,6 @@ class TcpApplicationLayer extends AbstractApplicationLayer {
830
985
  }
831
986
  }
832
987
 
833
- /******************************************************************************
834
- Copyright (c) Microsoft Corporation.
835
-
836
- Permission to use, copy, modify, and/or distribute this software for any
837
- purpose with or without fee is hereby granted.
838
-
839
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
840
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
841
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
842
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
843
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
844
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
845
- PERFORMANCE OF THIS SOFTWARE.
846
- ***************************************************************************** */
847
- /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
848
-
849
-
850
- function __awaiter(thisArg, _arguments, P, generator) {
851
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
852
- return new (P || (P = Promise))(function (resolve, reject) {
853
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
854
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
855
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
856
- step((generator = generator.apply(thisArg, _arguments || [])).next());
857
- });
858
- }
859
-
860
- typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
861
- var e = new Error(message);
862
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
863
- };
864
-
865
988
  class ModbusMaster extends EventEmitter {
866
989
  get isOpen() {
867
990
  return this.physicalLayer.isOpen;
@@ -889,12 +1012,6 @@ class ModbusMaster extends EventEmitter {
889
1012
  writable: true,
890
1013
  value: timeout
891
1014
  });
892
- Object.defineProperty(this, "_responses", {
893
- enumerable: true,
894
- configurable: true,
895
- writable: true,
896
- value: new Set()
897
- });
898
1015
  Object.defineProperty(this, "writeFC1", {
899
1016
  enumerable: true,
900
1017
  configurable: true,
@@ -979,11 +1096,6 @@ class ModbusMaster extends EventEmitter {
979
1096
  this.handleFC22 = this.maskWriteRegister;
980
1097
  this.handleFC23 = this.readAndWriteMultipleRegisters;
981
1098
  this.handleFC43_14 = this.readDeviceIdentification;
982
- applicationLayer.on('framing', (frame) => __awaiter(this, void 0, void 0, function* () {
983
- for (const response of this._responses) {
984
- response(frame);
985
- }
986
- }));
987
1099
  physicalLayer.on('error', (error) => {
988
1100
  this.emit('error', error);
989
1101
  });
@@ -991,46 +1103,55 @@ class ModbusMaster extends EventEmitter {
991
1103
  this.emit('close');
992
1104
  });
993
1105
  }
994
- waitResponse(timeout, cb) {
1106
+ waitResponse(request, response, timeout) {
995
1107
  return new Promise((resolve, reject) => {
996
- const tid = setTimeout(() => {
997
- this._responses.delete(response);
998
- reject('Timeout');
999
- }, timeout);
1000
- const response = (frame) => {
1001
- const data = cb(frame);
1002
- if (typeof data !== 'undefined') {
1003
- clearTimeout(tid);
1004
- this._responses.delete(response);
1005
- resolve({
1006
- transaction: frame.transaction,
1007
- unit: frame.unit,
1008
- fc: frame.fc,
1009
- data,
1010
- 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
+ }
1011
1128
  });
1012
1129
  }
1013
- };
1014
- this._responses.add(response);
1130
+ })
1131
+ .catch((error) => {
1132
+ reject(error);
1133
+ });
1015
1134
  });
1016
1135
  }
1017
1136
  writeFC1Or2(unit, fc, address, length, timeout) {
1137
+ const byteCount = Math.ceil(length / 8);
1018
1138
  const bufferTx = Buffer.alloc(4);
1019
1139
  bufferTx.writeUInt16BE(address, 0);
1020
1140
  bufferTx.writeUInt16BE(length, 2);
1021
- this.physicalLayer.write(this.applicationLayer.encode({
1022
- unit,
1023
- fc,
1024
- data: Array.from(bufferTx),
1025
- }));
1026
- if (unit !== 0) {
1027
- return this.waitResponse(timeout, (frame) => {
1028
- const byteCount = Math.ceil(length / 8);
1029
- if (frame.unit === unit && frame.fc === fc && frame.data.length === 1 + byteCount && frame.data[0] === byteCount) {
1030
- return Array.from({ length }).map((_, index) => (frame.data[1 + ~~(index / 8)] & (1 << index % 8)) > 0);
1031
- }
1032
- });
1033
- }
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
+ });
1034
1155
  }
1035
1156
  readCoils(unit, address, length, timeout = this.timeout) {
1036
1157
  return this.writeFC1Or2(unit, 0x01, address, length, timeout);
@@ -1039,23 +1160,25 @@ class ModbusMaster extends EventEmitter {
1039
1160
  return this.writeFC1Or2(unit, 0x02, address, length, timeout);
1040
1161
  }
1041
1162
  writeFC3Or4(unit, fc, address, length, timeout) {
1163
+ const byteCount = length * 2;
1042
1164
  const bufferTx = Buffer.alloc(4);
1043
1165
  bufferTx.writeUInt16BE(address, 0);
1044
1166
  bufferTx.writeUInt16BE(length, 2);
1045
- this.physicalLayer.write(this.applicationLayer.encode({
1046
- unit,
1047
- fc,
1048
- data: Array.from(bufferTx),
1049
- }));
1050
- if (unit !== 0) {
1051
- return this.waitResponse(timeout, (frame) => {
1052
- const byteCount = length * 2;
1053
- if (frame.unit === unit && frame.fc === fc && frame.data.length === 1 + byteCount && frame.data[0] === byteCount) {
1054
- const bufferRx = Buffer.from(frame.data.slice(1));
1055
- return Array.from({ length }).map((_, index) => bufferRx.readUInt16BE(index * 2));
1056
- }
1057
- });
1058
- }
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
+ });
1059
1182
  }
1060
1183
  readHoldingRegisters(unit, address, length, timeout = this.timeout) {
1061
1184
  return this.writeFC3Or4(unit, 0x03, address, length, timeout);
@@ -1068,42 +1191,48 @@ class ModbusMaster extends EventEmitter {
1068
1191
  const bufferTx = Buffer.alloc(4);
1069
1192
  bufferTx.writeUInt16BE(address, 0);
1070
1193
  bufferTx.writeUInt16BE(value ? 0xff00 : 0x0000, 2);
1071
- this.physicalLayer.write(this.applicationLayer.encode({
1072
- unit,
1073
- fc,
1074
- data: Array.from(bufferTx),
1075
- }));
1076
- if (unit !== 0) {
1077
- return this.waitResponse(timeout, (frame) => {
1078
- if (frame.unit === unit &&
1079
- frame.fc === fc &&
1080
- frame.data.length === bufferTx.length &&
1081
- frame.data.every((v, i) => v === bufferTx[i])) {
1082
- return value;
1083
- }
1084
- });
1085
- }
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
+ });
1086
1212
  }
1087
1213
  writeSingleRegister(unit, address, value, timeout = this.timeout) {
1088
1214
  const fc = 0x06;
1089
1215
  const bufferTx = Buffer.alloc(4);
1090
1216
  bufferTx.writeUInt16BE(address, 0);
1091
1217
  bufferTx.writeUInt16BE(value, 2);
1092
- this.physicalLayer.write(this.applicationLayer.encode({
1093
- unit,
1094
- fc,
1095
- data: Array.from(bufferTx),
1096
- }));
1097
- if (unit !== 0) {
1098
- return this.waitResponse(timeout, (frame) => {
1099
- if (frame.unit === unit &&
1100
- frame.fc === fc &&
1101
- frame.data.length === bufferTx.length &&
1102
- frame.data.every((v, i) => v === bufferTx[i])) {
1103
- return value;
1104
- }
1105
- });
1106
- }
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
+ });
1107
1236
  }
1108
1237
  writeMultipleCoils(unit, address, value, timeout = this.timeout) {
1109
1238
  const fc = 0x0f;
@@ -1117,18 +1246,20 @@ class ModbusMaster extends EventEmitter {
1117
1246
  bufferTx[5 + ~~(i / 8)] |= 1 << i % 8;
1118
1247
  }
1119
1248
  });
1120
- this.physicalLayer.write(this.applicationLayer.encode({
1121
- unit,
1122
- fc,
1123
- data: Array.from(bufferTx),
1124
- }));
1125
- if (unit !== 0) {
1126
- return this.waitResponse(timeout, (frame) => {
1127
- if (frame.unit === unit && frame.fc === fc && frame.data.length === 4 && frame.data.every((v, i) => v === bufferTx[i])) {
1128
- return value;
1129
- }
1130
- });
1131
- }
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
+ });
1132
1263
  }
1133
1264
  writeMultipleRegisters(unit, address, value, timeout = this.timeout) {
1134
1265
  const fc = 0x10;
@@ -1140,40 +1271,48 @@ class ModbusMaster extends EventEmitter {
1140
1271
  value.forEach((v, i) => {
1141
1272
  bufferTx.writeUInt16BE(v, 5 + i * 2);
1142
1273
  });
1143
- this.physicalLayer.write(this.applicationLayer.encode({
1144
- unit,
1145
- fc,
1146
- data: Array.from(bufferTx),
1147
- }));
1148
- if (unit !== 0) {
1149
- return this.waitResponse(timeout, (frame) => {
1150
- if (frame.unit === unit && frame.fc === fc && frame.data.length === 4 && frame.data.every((v, i) => v === bufferTx[i])) {
1151
- return value;
1152
- }
1153
- });
1154
- }
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
+ });
1155
1288
  }
1156
1289
  reportServerId(unit, timeout = this.timeout) {
1157
1290
  const fc = 0x11;
1158
- this.physicalLayer.write(this.applicationLayer.encode({
1159
- unit,
1160
- fc,
1161
- data: [],
1162
- }));
1163
- if (unit !== 0) {
1164
- return this.waitResponse(timeout, (frame) => {
1165
- if (frame.unit === unit && frame.fc === fc && frame.data.length >= 3) {
1166
- const byteCount = frame.data[0];
1167
- if (frame.data.length - 1 === byteCount) {
1168
- return {
1169
- serverId: frame.data[1],
1170
- runIndicatorStatus: frame.data[2] === 0xff,
1171
- additionalData: frame.data.slice(3),
1172
- };
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];
1173
1304
  }
1174
- }
1175
- });
1176
- }
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
+ });
1177
1316
  }
1178
1317
  maskWriteRegister(unit, address, andMask, orMask, timeout = this.timeout) {
1179
1318
  const fc = 0x16;
@@ -1181,18 +1320,20 @@ class ModbusMaster extends EventEmitter {
1181
1320
  bufferTx.writeUInt16BE(address, 0);
1182
1321
  bufferTx.writeUInt16BE(andMask, 2);
1183
1322
  bufferTx.writeUInt16BE(orMask, 4);
1184
- this.physicalLayer.write(this.applicationLayer.encode({
1185
- unit,
1186
- fc,
1187
- data: Array.from(bufferTx),
1188
- }));
1189
- if (unit !== 0) {
1190
- return this.waitResponse(timeout, (frame) => {
1191
- if (frame.unit === unit && frame.fc === fc && frame.data.length === 6 && frame.data.every((v, i) => v === bufferTx[i])) {
1192
- return { andMask, orMask };
1193
- }
1194
- });
1195
- }
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
+ });
1196
1337
  }
1197
1338
  readAndWriteMultipleRegisters(unit, read, write, timeout = this.timeout) {
1198
1339
  const fc = 0x17;
@@ -1206,73 +1347,104 @@ class ModbusMaster extends EventEmitter {
1206
1347
  write.value.forEach((v, i) => {
1207
1348
  bufferTx.writeUInt16BE(v, 9 + i * 2);
1208
1349
  });
1209
- this.physicalLayer.write(this.applicationLayer.encode({
1210
- unit,
1211
- fc,
1212
- data: Array.from(bufferTx),
1213
- }));
1214
- if (unit !== 0) {
1215
- return this.waitResponse(timeout, (frame) => {
1216
- if (frame.unit === unit && frame.fc === fc && frame.data.length === 1 + byteCount && frame.data[0] === byteCount) {
1217
- const bufferRx = Buffer.from(frame.data.slice(1));
1218
- return Array.from({ length: read.length }).map((_, index) => bufferRx.readUInt16BE(index * 2));
1219
- }
1220
- });
1221
- }
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
+ });
1222
1365
  }
1223
1366
  readDeviceIdentification(unit, readDeviceIDCode, objectId, timeout = this.timeout) {
1224
1367
  const fc = 0x2b;
1225
- this.physicalLayer.write(this.applicationLayer.encode({
1226
- unit,
1227
- fc,
1228
- data: [0x0e, readDeviceIDCode, objectId],
1229
- }));
1230
- if (unit !== 0) {
1231
- return this.waitResponse(timeout, (frame) => {
1232
- if (frame.unit === unit &&
1233
- frame.fc === fc &&
1234
- frame.data.length >= 6 &&
1235
- frame.data[0] === 0x0e &&
1236
- frame.data[1] === readDeviceIDCode) {
1237
- const conformityLevel = frame.data[2];
1238
- const moreFollows = frame.data[3] === 0xff;
1239
- const nextObjectId = frame.data[4];
1240
- const objectLength = frame.data[5];
1241
- const objects = [];
1242
- let object = [];
1243
- for (const v of frame.data.slice(6)) {
1244
- switch (object.length) {
1245
- case 0:
1246
- case 1: {
1247
- object.push(v);
1248
- break;
1249
- }
1250
- case 2: {
1251
- object.push([v]);
1252
- 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
+ }
1253
1403
  }
1254
- case 3: {
1255
- object[2].push(v);
1256
- break;
1404
+ if (objects.length === frame.data[5]) {
1405
+ return 6 + objects.reduce((previous, current) => previous + current, 0);
1257
1406
  }
1258
1407
  }
1259
- if (object.length === 3 && object[1] === object[2].length) {
1260
- objects.push({ id: object[0], value: Buffer.from(object[2]).toString() });
1261
- object = [];
1408
+ else {
1409
+ return false;
1262
1410
  }
1263
1411
  }
1264
- if (objects.length === objectLength) {
1265
- return {
1266
- readDeviceIDCode,
1267
- conformityLevel,
1268
- moreFollows,
1269
- nextObjectId,
1270
- objects,
1271
- };
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
+ }
1272
1437
  }
1273
1438
  }
1274
- });
1275
- }
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
+ });
1276
1448
  }
1277
1449
  open(...args) {
1278
1450
  return this.physicalLayer.open(...args);
@@ -1287,6 +1459,38 @@ class ModbusMaster extends EventEmitter {
1287
1459
  }
1288
1460
  }
1289
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
+
1290
1494
  class ModbusSlave extends EventEmitter {
1291
1495
  get isOpen() {
1292
1496
  return this.physicalLayer.isOpen;
@@ -1327,7 +1531,15 @@ class ModbusSlave extends EventEmitter {
1327
1531
  if (!(frame.unit === 0x00 || frame.unit === this.unit)) {
1328
1532
  return;
1329
1533
  }
1330
- 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
+ });
1331
1543
  if (model.interceptor) {
1332
1544
  try {
1333
1545
  const data = yield model.interceptor(frame.fc, frame.data);