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