njs-modbus 1.3.5 → 1.4.0
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/README.md +63 -64
- package/dist/index.cjs +156 -145
- package/dist/index.d.ts +4 -3
- package/dist/index.mjs +156 -145
- package/dist/src/slave/slave.d.ts +4 -3
- package/dist/test/slave.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -66,6 +66,7 @@ npm install njs-modbus
|
|
|
66
66
|
### Modbus RTU Master
|
|
67
67
|
|
|
68
68
|
```typescript
|
|
69
|
+
import type { ModbusSlaveModel } from 'njs-modbus';
|
|
69
70
|
import { SerialPhysicalLayer, RtuApplicationLayer, ModbusMaster } from 'njs-modbus';
|
|
70
71
|
|
|
71
72
|
const physicalLayer = new SerialPhysicalLayer({ path: 'COM1', baudRate: 9600, dataBits: 8, parity: 'none', stopBits: 1 });
|
|
@@ -100,72 +101,70 @@ const MB_SERVER = {
|
|
|
100
101
|
|
|
101
102
|
const physicalLayer = new SerialPhysicalLayer({ path: 'COM1', baudRate: 9600, dataBits: 8, parity: 'none', stopBits: 1 });
|
|
102
103
|
const applicationLayer = new RtuApplicationLayer(physicalLayer);
|
|
104
|
+
const slave1: ModbusSlaveModel = {
|
|
105
|
+
readDiscreteInputs: (address, length) => {
|
|
106
|
+
return Array.from({ length }).map((_, i) => {
|
|
107
|
+
const discreteInput = MB_SERVER.discreteInputs.get(address + i);
|
|
108
|
+
if (typeof discreteInput === 'undefined') {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
return discreteInput;
|
|
112
|
+
});
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
readCoils: (address, length) => {
|
|
116
|
+
return Array.from({ length }).map((_, i) => {
|
|
117
|
+
const coil = MB_SERVER.coils.get(address + i);
|
|
118
|
+
if (typeof coil === 'undefined') {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
return coil;
|
|
122
|
+
});
|
|
123
|
+
},
|
|
124
|
+
writeSingleCoil: (address, value) => {
|
|
125
|
+
MB_SERVER.coils.set(address, value);
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
readInputRegisters: (address, length) => {
|
|
129
|
+
return Array.from({ length }).map((_, i) => {
|
|
130
|
+
const inputRegister = MB_SERVER.inputRegisters.get(address + i);
|
|
131
|
+
if (typeof inputRegister === 'undefined') {
|
|
132
|
+
return 0;
|
|
133
|
+
}
|
|
134
|
+
return inputRegister;
|
|
135
|
+
});
|
|
136
|
+
},
|
|
103
137
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
readCoils: (address, length) => {
|
|
117
|
-
return Array.from({ length }).map((_, i) => {
|
|
118
|
-
const coil = MB_SERVER.coils.get(address + i);
|
|
119
|
-
if (typeof coil === 'undefined') {
|
|
120
|
-
return false;
|
|
121
|
-
}
|
|
122
|
-
return coil;
|
|
123
|
-
});
|
|
124
|
-
},
|
|
125
|
-
writeSingleCoil: (address, value) => {
|
|
126
|
-
MB_SERVER.coils.set(address, value);
|
|
127
|
-
},
|
|
128
|
-
|
|
129
|
-
readInputRegisters: (address, length) => {
|
|
130
|
-
return Array.from({ length }).map((_, i) => {
|
|
131
|
-
const inputRegister = MB_SERVER.inputRegisters.get(address + i);
|
|
132
|
-
if (typeof inputRegister === 'undefined') {
|
|
133
|
-
return 0;
|
|
134
|
-
}
|
|
135
|
-
return inputRegister;
|
|
136
|
-
});
|
|
137
|
-
},
|
|
138
|
-
|
|
139
|
-
readHoldingRegisters: (address, length) => {
|
|
140
|
-
return Array.from({ length }).map((_, i) => {
|
|
141
|
-
const holdingRegister = MB_SERVER.holdingRegisters.get(address + i);
|
|
142
|
-
if (typeof holdingRegister === 'undefined') {
|
|
143
|
-
return 0;
|
|
144
|
-
}
|
|
145
|
-
return holdingRegister;
|
|
146
|
-
});
|
|
147
|
-
},
|
|
148
|
-
writeSingleRegister: (address, value) => {
|
|
149
|
-
MB_SERVER.holdingRegisters.set(address, value);
|
|
150
|
-
},
|
|
151
|
-
|
|
152
|
-
reportServerId: () => ({ additionalData: [1, 2, 3] }),
|
|
153
|
-
|
|
154
|
-
readDeviceIdentification: () => ({
|
|
155
|
-
0x00: 'Basic:VendorName',
|
|
156
|
-
0x01: 'Basic:ProductCode',
|
|
157
|
-
0x02: 'Basic:MajorMinorRevision',
|
|
158
|
-
0x03: 'Regular:VendorUrl',
|
|
159
|
-
0x04: 'Regular:ProductName',
|
|
160
|
-
0x05: 'Regular:ModelName',
|
|
161
|
-
0x06: 'Regular:UserApplicationName',
|
|
162
|
-
0x80: 'Extended:Extended',
|
|
163
|
-
0xff: 'Extended:Extended',
|
|
164
|
-
}),
|
|
138
|
+
readHoldingRegisters: (address, length) => {
|
|
139
|
+
return Array.from({ length }).map((_, i) => {
|
|
140
|
+
const holdingRegister = MB_SERVER.holdingRegisters.get(address + i);
|
|
141
|
+
if (typeof holdingRegister === 'undefined') {
|
|
142
|
+
return 0;
|
|
143
|
+
}
|
|
144
|
+
return holdingRegister;
|
|
145
|
+
});
|
|
146
|
+
},
|
|
147
|
+
writeSingleRegister: (address, value) => {
|
|
148
|
+
MB_SERVER.holdingRegisters.set(address, value);
|
|
165
149
|
},
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
150
|
+
|
|
151
|
+
reportServerId: () => ({ additionalData: [1, 2, 3] }),
|
|
152
|
+
|
|
153
|
+
readDeviceIdentification: () => ({
|
|
154
|
+
0x00: 'Basic:VendorName',
|
|
155
|
+
0x01: 'Basic:ProductCode',
|
|
156
|
+
0x02: 'Basic:MajorMinorRevision',
|
|
157
|
+
0x03: 'Regular:VendorUrl',
|
|
158
|
+
0x04: 'Regular:ProductName',
|
|
159
|
+
0x05: 'Regular:ModelName',
|
|
160
|
+
0x06: 'Regular:UserApplicationName',
|
|
161
|
+
0x80: 'Extended:Extended',
|
|
162
|
+
0xff: 'Extended:Extended',
|
|
163
|
+
}),
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const modbusSlave = new ModbusSlave(applicationLayer, physicalLayer);
|
|
167
|
+
modbusSlave.add(slave1);
|
|
169
168
|
|
|
170
169
|
modbusSlave
|
|
171
170
|
.open()
|
package/dist/index.cjs
CHANGED
|
@@ -1504,14 +1504,8 @@ class ModbusSlave extends EventEmitter {
|
|
|
1504
1504
|
get destroyed() {
|
|
1505
1505
|
return this.physicalLayer.destroyed;
|
|
1506
1506
|
}
|
|
1507
|
-
constructor(
|
|
1507
|
+
constructor(applicationLayer, physicalLayer) {
|
|
1508
1508
|
super();
|
|
1509
|
-
Object.defineProperty(this, "model", {
|
|
1510
|
-
enumerable: true,
|
|
1511
|
-
configurable: true,
|
|
1512
|
-
writable: true,
|
|
1513
|
-
value: model
|
|
1514
|
-
});
|
|
1515
1509
|
Object.defineProperty(this, "applicationLayer", {
|
|
1516
1510
|
enumerable: true,
|
|
1517
1511
|
configurable: true,
|
|
@@ -1524,17 +1518,14 @@ class ModbusSlave extends EventEmitter {
|
|
|
1524
1518
|
writable: true,
|
|
1525
1519
|
value: physicalLayer
|
|
1526
1520
|
});
|
|
1527
|
-
Object.defineProperty(this, "
|
|
1521
|
+
Object.defineProperty(this, "models", {
|
|
1528
1522
|
enumerable: true,
|
|
1529
1523
|
configurable: true,
|
|
1530
1524
|
writable: true,
|
|
1531
|
-
value:
|
|
1525
|
+
value: new Map()
|
|
1532
1526
|
});
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
}
|
|
1536
|
-
applicationLayer.on('framing', (frame, _response) => __awaiter(this, void 0, void 0, function* () {
|
|
1537
|
-
if (!(frame.unit === 0x00 || frame.unit === this.unit)) {
|
|
1527
|
+
applicationLayer.on('framing', (frame, _response) => {
|
|
1528
|
+
if (!(frame.unit === 0x00 || this.models.has(frame.unit))) {
|
|
1538
1529
|
return;
|
|
1539
1530
|
}
|
|
1540
1531
|
const response = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -1546,74 +1537,85 @@ class ModbusSlave extends EventEmitter {
|
|
|
1546
1537
|
}
|
|
1547
1538
|
catch (error) { }
|
|
1548
1539
|
});
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1540
|
+
const intercept = (model) => __awaiter(this, void 0, void 0, function* () {
|
|
1541
|
+
if (model.interceptor) {
|
|
1542
|
+
try {
|
|
1543
|
+
const data = yield model.interceptor(frame.fc, frame.data);
|
|
1544
|
+
if (data) {
|
|
1545
|
+
response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data })));
|
|
1546
|
+
return 'break';
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
catch (error) {
|
|
1550
|
+
this.responseError(frame, response, error);
|
|
1551
|
+
return 'break';
|
|
1555
1552
|
}
|
|
1556
1553
|
}
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1613
|
-
break;
|
|
1554
|
+
});
|
|
1555
|
+
const handleFC = (model) => {
|
|
1556
|
+
switch (frame.fc) {
|
|
1557
|
+
case 0x01: {
|
|
1558
|
+
this.handleFC1(model, frame, response);
|
|
1559
|
+
break;
|
|
1560
|
+
}
|
|
1561
|
+
case 0x02: {
|
|
1562
|
+
this.handleFC2(model, frame, response);
|
|
1563
|
+
break;
|
|
1564
|
+
}
|
|
1565
|
+
case 0x03: {
|
|
1566
|
+
this.handleFC3(model, frame, response);
|
|
1567
|
+
break;
|
|
1568
|
+
}
|
|
1569
|
+
case 0x04: {
|
|
1570
|
+
this.handleFC4(model, frame, response);
|
|
1571
|
+
break;
|
|
1572
|
+
}
|
|
1573
|
+
case 0x05: {
|
|
1574
|
+
this.handleFC5(model, frame, response);
|
|
1575
|
+
break;
|
|
1576
|
+
}
|
|
1577
|
+
case 0x06: {
|
|
1578
|
+
this.handleFC6(model, frame, response);
|
|
1579
|
+
break;
|
|
1580
|
+
}
|
|
1581
|
+
case 0x0f: {
|
|
1582
|
+
this.handleFC15(model, frame, response);
|
|
1583
|
+
break;
|
|
1584
|
+
}
|
|
1585
|
+
case 0x10: {
|
|
1586
|
+
this.handleFC16(model, frame, response);
|
|
1587
|
+
break;
|
|
1588
|
+
}
|
|
1589
|
+
case 0x11: {
|
|
1590
|
+
this.handleFC17(model, frame, response);
|
|
1591
|
+
break;
|
|
1592
|
+
}
|
|
1593
|
+
case 0x16: {
|
|
1594
|
+
this.handleFC22(model, frame, response);
|
|
1595
|
+
break;
|
|
1596
|
+
}
|
|
1597
|
+
case 0x17: {
|
|
1598
|
+
this.handleFC23(model, frame, response);
|
|
1599
|
+
break;
|
|
1600
|
+
}
|
|
1601
|
+
case 0x2b: {
|
|
1602
|
+
this.handleFC43_14(model, frame, response);
|
|
1603
|
+
break;
|
|
1604
|
+
}
|
|
1605
|
+
default: {
|
|
1606
|
+
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1607
|
+
break;
|
|
1608
|
+
}
|
|
1614
1609
|
}
|
|
1610
|
+
};
|
|
1611
|
+
for (const model of frame.unit === 0x00 ? this.models.values() : [this.models.get(frame.unit)]) {
|
|
1612
|
+
intercept(model).then((res) => {
|
|
1613
|
+
if (res !== 'break') {
|
|
1614
|
+
handleFC(model);
|
|
1615
|
+
}
|
|
1616
|
+
});
|
|
1615
1617
|
}
|
|
1616
|
-
})
|
|
1618
|
+
});
|
|
1617
1619
|
physicalLayer.on('error', (error) => {
|
|
1618
1620
|
this.emit('error', error);
|
|
1619
1621
|
});
|
|
@@ -1621,16 +1623,16 @@ class ModbusSlave extends EventEmitter {
|
|
|
1621
1623
|
this.emit('close');
|
|
1622
1624
|
});
|
|
1623
1625
|
}
|
|
1624
|
-
handleFC1(frame, response) {
|
|
1625
|
-
var _a
|
|
1626
|
+
handleFC1(model, frame, response) {
|
|
1627
|
+
var _a;
|
|
1626
1628
|
if (frame.data.length === 4) {
|
|
1627
|
-
if (
|
|
1629
|
+
if (model.readCoils) {
|
|
1628
1630
|
const bufferRx = Buffer.from(frame.data);
|
|
1629
1631
|
const address = bufferRx.readUInt16BE(0);
|
|
1630
1632
|
const length = bufferRx.readUInt16BE(2);
|
|
1631
1633
|
if (length >= 0x0001 && length <= 0x07d0) {
|
|
1632
|
-
if (checkRange([address, address + length], (
|
|
1633
|
-
Promise.resolve(
|
|
1634
|
+
if (checkRange([address, address + length], (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).coils)) {
|
|
1635
|
+
Promise.resolve(model.readCoils(address, length))
|
|
1634
1636
|
.then((coils) => {
|
|
1635
1637
|
const bufferTx = Buffer.alloc(Math.ceil(length / 8));
|
|
1636
1638
|
coils.forEach((coil, index) => {
|
|
@@ -1657,16 +1659,16 @@ class ModbusSlave extends EventEmitter {
|
|
|
1657
1659
|
}
|
|
1658
1660
|
}
|
|
1659
1661
|
}
|
|
1660
|
-
handleFC2(frame, response) {
|
|
1661
|
-
var _a
|
|
1662
|
+
handleFC2(model, frame, response) {
|
|
1663
|
+
var _a;
|
|
1662
1664
|
if (frame.data.length === 4) {
|
|
1663
|
-
if (
|
|
1665
|
+
if (model.readDiscreteInputs) {
|
|
1664
1666
|
const bufferRx = Buffer.from(frame.data);
|
|
1665
1667
|
const address = bufferRx.readUInt16BE(0);
|
|
1666
1668
|
const length = bufferRx.readUInt16BE(2);
|
|
1667
1669
|
if (length >= 0x0001 && length <= 0x07d0) {
|
|
1668
|
-
if (checkRange([address, address + length], (
|
|
1669
|
-
Promise.resolve(
|
|
1670
|
+
if (checkRange([address, address + length], (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).discreteInputs)) {
|
|
1671
|
+
Promise.resolve(model.readDiscreteInputs(address, length))
|
|
1670
1672
|
.then((discreteInputs) => {
|
|
1671
1673
|
const bufferTx = Buffer.alloc(Math.ceil(length / 8));
|
|
1672
1674
|
discreteInputs.forEach((discreteInput, index) => {
|
|
@@ -1693,16 +1695,16 @@ class ModbusSlave extends EventEmitter {
|
|
|
1693
1695
|
}
|
|
1694
1696
|
}
|
|
1695
1697
|
}
|
|
1696
|
-
handleFC3(frame, response) {
|
|
1697
|
-
var _a
|
|
1698
|
+
handleFC3(model, frame, response) {
|
|
1699
|
+
var _a;
|
|
1698
1700
|
if (frame.data.length === 4) {
|
|
1699
|
-
if (
|
|
1701
|
+
if (model.readHoldingRegisters) {
|
|
1700
1702
|
const bufferRx = Buffer.from(frame.data);
|
|
1701
1703
|
const address = bufferRx.readUInt16BE(0);
|
|
1702
1704
|
const length = bufferRx.readUInt16BE(2);
|
|
1703
1705
|
if (length >= 0x0001 && length <= 0x007d) {
|
|
1704
|
-
if (checkRange([address, address + length], (
|
|
1705
|
-
Promise.resolve(
|
|
1706
|
+
if (checkRange([address, address + length], (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).holdingRegisters)) {
|
|
1707
|
+
Promise.resolve(model.readHoldingRegisters(address, length))
|
|
1706
1708
|
.then((registers) => {
|
|
1707
1709
|
const bufferTx = Buffer.alloc(length * 2);
|
|
1708
1710
|
registers.forEach((register, index) => {
|
|
@@ -1727,16 +1729,16 @@ class ModbusSlave extends EventEmitter {
|
|
|
1727
1729
|
}
|
|
1728
1730
|
}
|
|
1729
1731
|
}
|
|
1730
|
-
handleFC4(frame, response) {
|
|
1731
|
-
var _a
|
|
1732
|
+
handleFC4(model, frame, response) {
|
|
1733
|
+
var _a;
|
|
1732
1734
|
if (frame.data.length === 4) {
|
|
1733
|
-
if (
|
|
1735
|
+
if (model.readInputRegisters) {
|
|
1734
1736
|
const bufferRx = Buffer.from(frame.data);
|
|
1735
1737
|
const address = bufferRx.readUInt16BE(0);
|
|
1736
1738
|
const length = bufferRx.readUInt16BE(2);
|
|
1737
1739
|
if (length >= 0x0001 && length <= 0x007d) {
|
|
1738
|
-
if (checkRange([address, address + length], (
|
|
1739
|
-
Promise.resolve(
|
|
1740
|
+
if (checkRange([address, address + length], (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).inputRegisters)) {
|
|
1741
|
+
Promise.resolve(model.readInputRegisters(address, length))
|
|
1740
1742
|
.then((registers) => {
|
|
1741
1743
|
const bufferTx = Buffer.alloc(length * 2);
|
|
1742
1744
|
registers.forEach((register, index) => {
|
|
@@ -1761,16 +1763,16 @@ class ModbusSlave extends EventEmitter {
|
|
|
1761
1763
|
}
|
|
1762
1764
|
}
|
|
1763
1765
|
}
|
|
1764
|
-
handleFC5(frame, response) {
|
|
1765
|
-
var _a
|
|
1766
|
+
handleFC5(model, frame, response) {
|
|
1767
|
+
var _a;
|
|
1766
1768
|
if (frame.data.length === 4) {
|
|
1767
|
-
if (
|
|
1769
|
+
if (model.writeSingleCoil) {
|
|
1768
1770
|
const bufferRx = Buffer.from(frame.data);
|
|
1769
1771
|
const address = bufferRx.readUInt16BE(0);
|
|
1770
1772
|
const value = bufferRx.readUInt16BE(2);
|
|
1771
1773
|
if (value === 0x0000 || value === 0xff00) {
|
|
1772
|
-
if (checkRange(address, (
|
|
1773
|
-
Promise.resolve(
|
|
1774
|
+
if (checkRange(address, (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).coils)) {
|
|
1775
|
+
Promise.resolve(model.writeSingleCoil(address, value === 0xff00))
|
|
1774
1776
|
.then(() => {
|
|
1775
1777
|
response(this.applicationLayer.encode(frame));
|
|
1776
1778
|
})
|
|
@@ -1791,16 +1793,16 @@ class ModbusSlave extends EventEmitter {
|
|
|
1791
1793
|
}
|
|
1792
1794
|
}
|
|
1793
1795
|
}
|
|
1794
|
-
handleFC6(frame, response) {
|
|
1795
|
-
var _a
|
|
1796
|
+
handleFC6(model, frame, response) {
|
|
1797
|
+
var _a;
|
|
1796
1798
|
if (frame.data.length === 4) {
|
|
1797
|
-
if (
|
|
1799
|
+
if (model.writeSingleRegister) {
|
|
1798
1800
|
const bufferRx = Buffer.from(frame.data);
|
|
1799
1801
|
const address = bufferRx.readUInt16BE(0);
|
|
1800
1802
|
const value = bufferRx.readUInt16BE(2);
|
|
1801
1803
|
if (value >= 0x0000 && value <= 0xffff) {
|
|
1802
|
-
if (checkRange(address, (
|
|
1803
|
-
Promise.resolve(
|
|
1804
|
+
if (checkRange(address, (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).holdingRegisters)) {
|
|
1805
|
+
Promise.resolve(model.writeSingleRegister(address, value))
|
|
1804
1806
|
.then(() => {
|
|
1805
1807
|
response(this.applicationLayer.encode(frame));
|
|
1806
1808
|
})
|
|
@@ -1821,20 +1823,20 @@ class ModbusSlave extends EventEmitter {
|
|
|
1821
1823
|
}
|
|
1822
1824
|
}
|
|
1823
1825
|
}
|
|
1824
|
-
handleFC15(frame, response) {
|
|
1825
|
-
var _a
|
|
1826
|
+
handleFC15(model, frame, response) {
|
|
1827
|
+
var _a;
|
|
1826
1828
|
if (frame.data.length > 5 && frame.data.length === 5 + frame.data[4]) {
|
|
1827
|
-
if (
|
|
1829
|
+
if (model.writeMultipleCoils || model.writeSingleCoil) {
|
|
1828
1830
|
const bufferRx = Buffer.from(frame.data);
|
|
1829
1831
|
const address = bufferRx.readUInt16BE(0);
|
|
1830
1832
|
const length = bufferRx.readUInt16BE(2);
|
|
1831
1833
|
const byteCount = bufferRx[4];
|
|
1832
1834
|
if (length >= 0x0001 && length <= 0x07b0 && byteCount === Math.ceil(length / 8)) {
|
|
1833
|
-
if (checkRange([address, address + length], (
|
|
1835
|
+
if (checkRange([address, address + length], (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).coils)) {
|
|
1834
1836
|
const value = Array.from({ length }).map((_, index) => (bufferRx[5 + ~~(index / 8)] & (1 << index % 8)) > 0);
|
|
1835
|
-
Promise.resolve(
|
|
1836
|
-
?
|
|
1837
|
-
: Promise.all(value.map((v, i) =>
|
|
1837
|
+
Promise.resolve(model.writeMultipleCoils
|
|
1838
|
+
? model.writeMultipleCoils(address, value)
|
|
1839
|
+
: Promise.all(value.map((v, i) => model.writeSingleCoil(address + i, v))))
|
|
1838
1840
|
.then(() => {
|
|
1839
1841
|
response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: Array.from(bufferRx).slice(0, 4) })));
|
|
1840
1842
|
})
|
|
@@ -1855,20 +1857,20 @@ class ModbusSlave extends EventEmitter {
|
|
|
1855
1857
|
}
|
|
1856
1858
|
}
|
|
1857
1859
|
}
|
|
1858
|
-
handleFC16(frame, response) {
|
|
1859
|
-
var _a
|
|
1860
|
+
handleFC16(model, frame, response) {
|
|
1861
|
+
var _a;
|
|
1860
1862
|
if (frame.data.length > 5 && frame.data.length === 5 + frame.data[4]) {
|
|
1861
|
-
if (
|
|
1863
|
+
if (model.writeMultipleRegisters || model.writeSingleRegister) {
|
|
1862
1864
|
const bufferRx = Buffer.from(frame.data);
|
|
1863
1865
|
const address = bufferRx.readUInt16BE(0);
|
|
1864
1866
|
const length = bufferRx.readUInt16BE(2);
|
|
1865
1867
|
const byteCount = bufferRx[4];
|
|
1866
1868
|
if (length >= 0x0001 && length <= 0x007b && byteCount === length * 2) {
|
|
1867
|
-
if (checkRange([address, address + length], (
|
|
1869
|
+
if (checkRange([address, address + length], (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).holdingRegisters)) {
|
|
1868
1870
|
const value = Array.from({ length }).map((_, index) => bufferRx.readUInt16BE(5 + index * 2));
|
|
1869
|
-
Promise.resolve(
|
|
1870
|
-
?
|
|
1871
|
-
: Promise.all(value.map((v, i) =>
|
|
1871
|
+
Promise.resolve(model.writeMultipleRegisters
|
|
1872
|
+
? model.writeMultipleRegisters(address, value)
|
|
1873
|
+
: Promise.all(value.map((v, i) => model.writeSingleRegister(address + i, v))))
|
|
1872
1874
|
.then(() => {
|
|
1873
1875
|
response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: Array.from(bufferRx).slice(0, 4) })));
|
|
1874
1876
|
})
|
|
@@ -1889,11 +1891,13 @@ class ModbusSlave extends EventEmitter {
|
|
|
1889
1891
|
}
|
|
1890
1892
|
}
|
|
1891
1893
|
}
|
|
1892
|
-
handleFC17(frame, response) {
|
|
1894
|
+
handleFC17(model, frame, response) {
|
|
1893
1895
|
if (frame.data.length === 0) {
|
|
1894
|
-
if (
|
|
1895
|
-
Promise.resolve(
|
|
1896
|
-
.then((
|
|
1896
|
+
if (model.reportServerId) {
|
|
1897
|
+
Promise.resolve(model.reportServerId())
|
|
1898
|
+
.then((_a) => {
|
|
1899
|
+
var _b;
|
|
1900
|
+
var { serverId = (_b = model.unit) !== null && _b !== void 0 ? _b : 1, runIndicatorStatus = true, additionalData = [] } = _a;
|
|
1897
1901
|
response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: [2 + additionalData.length, serverId, runIndicatorStatus ? 0xff : 0x00].concat(additionalData) })));
|
|
1898
1902
|
})
|
|
1899
1903
|
.catch((error) => {
|
|
@@ -1905,19 +1909,19 @@ class ModbusSlave extends EventEmitter {
|
|
|
1905
1909
|
}
|
|
1906
1910
|
}
|
|
1907
1911
|
}
|
|
1908
|
-
handleFC22(frame, response) {
|
|
1909
|
-
var _a
|
|
1912
|
+
handleFC22(model, frame, response) {
|
|
1913
|
+
var _a;
|
|
1910
1914
|
if (frame.data.length === 6) {
|
|
1911
|
-
if (
|
|
1915
|
+
if (model.maskWriteRegister || (model.readHoldingRegisters && model.writeSingleRegister)) {
|
|
1912
1916
|
const bufferRx = Buffer.from(frame.data);
|
|
1913
1917
|
const address = bufferRx.readUInt16BE(0);
|
|
1914
1918
|
const andMask = bufferRx.readUInt16BE(2);
|
|
1915
1919
|
const orMask = bufferRx.readUInt16BE(4);
|
|
1916
|
-
if (checkRange(address, (
|
|
1917
|
-
Promise.resolve(
|
|
1918
|
-
?
|
|
1919
|
-
: Promise.resolve(
|
|
1920
|
-
return Promise.resolve(
|
|
1920
|
+
if (checkRange(address, (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).holdingRegisters)) {
|
|
1921
|
+
Promise.resolve(model.maskWriteRegister
|
|
1922
|
+
? model.maskWriteRegister(address, andMask, orMask)
|
|
1923
|
+
: Promise.resolve(model.readHoldingRegisters(address, 1)).then(([value]) => {
|
|
1924
|
+
return Promise.resolve(model.writeSingleRegister(address, (value & andMask) | (orMask & (~andMask & 0xff))));
|
|
1921
1925
|
}))
|
|
1922
1926
|
.then(() => {
|
|
1923
1927
|
response(this.applicationLayer.encode(frame));
|
|
@@ -1935,10 +1939,10 @@ class ModbusSlave extends EventEmitter {
|
|
|
1935
1939
|
}
|
|
1936
1940
|
}
|
|
1937
1941
|
}
|
|
1938
|
-
handleFC23(frame, response) {
|
|
1939
|
-
var _a
|
|
1942
|
+
handleFC23(model, frame, response) {
|
|
1943
|
+
var _a;
|
|
1940
1944
|
if (frame.data.length > 9 && frame.data.length === 9 + frame.data[8]) {
|
|
1941
|
-
if (
|
|
1945
|
+
if (model.readHoldingRegisters && (model.writeMultipleRegisters || model.writeSingleRegister)) {
|
|
1942
1946
|
const bufferRx = Buffer.from(frame.data);
|
|
1943
1947
|
const address = {
|
|
1944
1948
|
read: bufferRx.readUInt16BE(0),
|
|
@@ -1954,12 +1958,12 @@ class ModbusSlave extends EventEmitter {
|
|
|
1954
1958
|
length.write >= 0x0001 &&
|
|
1955
1959
|
length.write <= 0x0079 &&
|
|
1956
1960
|
byteCount === length.write * 2) {
|
|
1957
|
-
if (checkRange([address.read, address.read + length.read, address.write, address.write + length.write], (
|
|
1961
|
+
if (checkRange([address.read, address.read + length.read, address.write, address.write + length.write], (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).holdingRegisters)) {
|
|
1958
1962
|
const value = Array.from({ length: length.write }).map((_, index) => bufferRx.readUInt16BE(9 + index * 2));
|
|
1959
|
-
Promise.resolve(
|
|
1960
|
-
?
|
|
1961
|
-
: Promise.all(value.map((v, i) =>
|
|
1962
|
-
.then(() => Promise.resolve(
|
|
1963
|
+
Promise.resolve(model.writeMultipleRegisters
|
|
1964
|
+
? model.writeMultipleRegisters(address.write, value)
|
|
1965
|
+
: Promise.all(value.map((v, i) => model.writeSingleRegister(address.write + i, v))))
|
|
1966
|
+
.then(() => Promise.resolve(model.readHoldingRegisters(address.read, length.read)))
|
|
1963
1967
|
.then((registers) => {
|
|
1964
1968
|
const bufferTx = Buffer.alloc(length.read * 2);
|
|
1965
1969
|
registers.forEach((register, index) => {
|
|
@@ -1984,9 +1988,9 @@ class ModbusSlave extends EventEmitter {
|
|
|
1984
1988
|
}
|
|
1985
1989
|
}
|
|
1986
1990
|
}
|
|
1987
|
-
handleFC43_14(frame, response) {
|
|
1991
|
+
handleFC43_14(model, frame, response) {
|
|
1988
1992
|
if (frame.data.length === 3) {
|
|
1989
|
-
if (frame.data[0] === 0x0e &&
|
|
1993
|
+
if (frame.data[0] === 0x0e && model.readDeviceIdentification) {
|
|
1990
1994
|
const readDeviceIDCode = frame.data[1];
|
|
1991
1995
|
let objectID = frame.data[2];
|
|
1992
1996
|
switch (readDeviceIDCode) {
|
|
@@ -2020,7 +2024,7 @@ class ModbusSlave extends EventEmitter {
|
|
|
2020
2024
|
return;
|
|
2021
2025
|
}
|
|
2022
2026
|
}
|
|
2023
|
-
Promise.resolve(
|
|
2027
|
+
Promise.resolve(model.readDeviceIdentification())
|
|
2024
2028
|
.then((identification) => {
|
|
2025
2029
|
const objects = new Map([
|
|
2026
2030
|
[0x00, 'null'],
|
|
@@ -2098,6 +2102,13 @@ class ModbusSlave extends EventEmitter {
|
|
|
2098
2102
|
responseError(frame, response, error) {
|
|
2099
2103
|
response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { fc: frame.fc | 0x80, data: [getCodeByError(error)] })));
|
|
2100
2104
|
}
|
|
2105
|
+
add(model) {
|
|
2106
|
+
var _a;
|
|
2107
|
+
this.models.set((_a = model.unit) !== null && _a !== void 0 ? _a : 1, model);
|
|
2108
|
+
}
|
|
2109
|
+
remove(unit) {
|
|
2110
|
+
this.models.delete(unit);
|
|
2111
|
+
}
|
|
2101
2112
|
open(...args) {
|
|
2102
2113
|
return this.physicalLayer.open(...args);
|
|
2103
2114
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -342,13 +342,12 @@ interface ModbusSlaveEvents {
|
|
|
342
342
|
close: [];
|
|
343
343
|
}
|
|
344
344
|
declare class ModbusSlave<A extends AbstractApplicationLayer, P extends AbstractPhysicalLayer> extends EventEmitter<ModbusSlaveEvents> {
|
|
345
|
-
private model;
|
|
346
345
|
private applicationLayer;
|
|
347
346
|
private physicalLayer;
|
|
348
|
-
|
|
347
|
+
models: Map<number, ModbusSlaveModel>;
|
|
349
348
|
get isOpen(): boolean;
|
|
350
349
|
get destroyed(): boolean;
|
|
351
|
-
constructor(
|
|
350
|
+
constructor(applicationLayer: A, physicalLayer: P);
|
|
352
351
|
private handleFC1;
|
|
353
352
|
private handleFC2;
|
|
354
353
|
private handleFC3;
|
|
@@ -362,6 +361,8 @@ declare class ModbusSlave<A extends AbstractApplicationLayer, P extends Abstract
|
|
|
362
361
|
private handleFC23;
|
|
363
362
|
private handleFC43_14;
|
|
364
363
|
private responseError;
|
|
364
|
+
add(model: ModbusSlaveModel): void;
|
|
365
|
+
remove(unit: number): void;
|
|
365
366
|
open(...args: Parameters<P['open']>): Promise<void>;
|
|
366
367
|
close(): Promise<void>;
|
|
367
368
|
destroy(): Promise<void>;
|
package/dist/index.mjs
CHANGED
|
@@ -1502,14 +1502,8 @@ class ModbusSlave extends EventEmitter {
|
|
|
1502
1502
|
get destroyed() {
|
|
1503
1503
|
return this.physicalLayer.destroyed;
|
|
1504
1504
|
}
|
|
1505
|
-
constructor(
|
|
1505
|
+
constructor(applicationLayer, physicalLayer) {
|
|
1506
1506
|
super();
|
|
1507
|
-
Object.defineProperty(this, "model", {
|
|
1508
|
-
enumerable: true,
|
|
1509
|
-
configurable: true,
|
|
1510
|
-
writable: true,
|
|
1511
|
-
value: model
|
|
1512
|
-
});
|
|
1513
1507
|
Object.defineProperty(this, "applicationLayer", {
|
|
1514
1508
|
enumerable: true,
|
|
1515
1509
|
configurable: true,
|
|
@@ -1522,17 +1516,14 @@ class ModbusSlave extends EventEmitter {
|
|
|
1522
1516
|
writable: true,
|
|
1523
1517
|
value: physicalLayer
|
|
1524
1518
|
});
|
|
1525
|
-
Object.defineProperty(this, "
|
|
1519
|
+
Object.defineProperty(this, "models", {
|
|
1526
1520
|
enumerable: true,
|
|
1527
1521
|
configurable: true,
|
|
1528
1522
|
writable: true,
|
|
1529
|
-
value:
|
|
1523
|
+
value: new Map()
|
|
1530
1524
|
});
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
}
|
|
1534
|
-
applicationLayer.on('framing', (frame, _response) => __awaiter(this, void 0, void 0, function* () {
|
|
1535
|
-
if (!(frame.unit === 0x00 || frame.unit === this.unit)) {
|
|
1525
|
+
applicationLayer.on('framing', (frame, _response) => {
|
|
1526
|
+
if (!(frame.unit === 0x00 || this.models.has(frame.unit))) {
|
|
1536
1527
|
return;
|
|
1537
1528
|
}
|
|
1538
1529
|
const response = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -1544,74 +1535,85 @@ class ModbusSlave extends EventEmitter {
|
|
|
1544
1535
|
}
|
|
1545
1536
|
catch (error) { }
|
|
1546
1537
|
});
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1538
|
+
const intercept = (model) => __awaiter(this, void 0, void 0, function* () {
|
|
1539
|
+
if (model.interceptor) {
|
|
1540
|
+
try {
|
|
1541
|
+
const data = yield model.interceptor(frame.fc, frame.data);
|
|
1542
|
+
if (data) {
|
|
1543
|
+
response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data })));
|
|
1544
|
+
return 'break';
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
catch (error) {
|
|
1548
|
+
this.responseError(frame, response, error);
|
|
1549
|
+
return 'break';
|
|
1553
1550
|
}
|
|
1554
1551
|
}
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1611
|
-
break;
|
|
1552
|
+
});
|
|
1553
|
+
const handleFC = (model) => {
|
|
1554
|
+
switch (frame.fc) {
|
|
1555
|
+
case 0x01: {
|
|
1556
|
+
this.handleFC1(model, frame, response);
|
|
1557
|
+
break;
|
|
1558
|
+
}
|
|
1559
|
+
case 0x02: {
|
|
1560
|
+
this.handleFC2(model, frame, response);
|
|
1561
|
+
break;
|
|
1562
|
+
}
|
|
1563
|
+
case 0x03: {
|
|
1564
|
+
this.handleFC3(model, frame, response);
|
|
1565
|
+
break;
|
|
1566
|
+
}
|
|
1567
|
+
case 0x04: {
|
|
1568
|
+
this.handleFC4(model, frame, response);
|
|
1569
|
+
break;
|
|
1570
|
+
}
|
|
1571
|
+
case 0x05: {
|
|
1572
|
+
this.handleFC5(model, frame, response);
|
|
1573
|
+
break;
|
|
1574
|
+
}
|
|
1575
|
+
case 0x06: {
|
|
1576
|
+
this.handleFC6(model, frame, response);
|
|
1577
|
+
break;
|
|
1578
|
+
}
|
|
1579
|
+
case 0x0f: {
|
|
1580
|
+
this.handleFC15(model, frame, response);
|
|
1581
|
+
break;
|
|
1582
|
+
}
|
|
1583
|
+
case 0x10: {
|
|
1584
|
+
this.handleFC16(model, frame, response);
|
|
1585
|
+
break;
|
|
1586
|
+
}
|
|
1587
|
+
case 0x11: {
|
|
1588
|
+
this.handleFC17(model, frame, response);
|
|
1589
|
+
break;
|
|
1590
|
+
}
|
|
1591
|
+
case 0x16: {
|
|
1592
|
+
this.handleFC22(model, frame, response);
|
|
1593
|
+
break;
|
|
1594
|
+
}
|
|
1595
|
+
case 0x17: {
|
|
1596
|
+
this.handleFC23(model, frame, response);
|
|
1597
|
+
break;
|
|
1598
|
+
}
|
|
1599
|
+
case 0x2b: {
|
|
1600
|
+
this.handleFC43_14(model, frame, response);
|
|
1601
|
+
break;
|
|
1602
|
+
}
|
|
1603
|
+
default: {
|
|
1604
|
+
this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1605
|
+
break;
|
|
1606
|
+
}
|
|
1612
1607
|
}
|
|
1608
|
+
};
|
|
1609
|
+
for (const model of frame.unit === 0x00 ? this.models.values() : [this.models.get(frame.unit)]) {
|
|
1610
|
+
intercept(model).then((res) => {
|
|
1611
|
+
if (res !== 'break') {
|
|
1612
|
+
handleFC(model);
|
|
1613
|
+
}
|
|
1614
|
+
});
|
|
1613
1615
|
}
|
|
1614
|
-
})
|
|
1616
|
+
});
|
|
1615
1617
|
physicalLayer.on('error', (error) => {
|
|
1616
1618
|
this.emit('error', error);
|
|
1617
1619
|
});
|
|
@@ -1619,16 +1621,16 @@ class ModbusSlave extends EventEmitter {
|
|
|
1619
1621
|
this.emit('close');
|
|
1620
1622
|
});
|
|
1621
1623
|
}
|
|
1622
|
-
handleFC1(frame, response) {
|
|
1623
|
-
var _a
|
|
1624
|
+
handleFC1(model, frame, response) {
|
|
1625
|
+
var _a;
|
|
1624
1626
|
if (frame.data.length === 4) {
|
|
1625
|
-
if (
|
|
1627
|
+
if (model.readCoils) {
|
|
1626
1628
|
const bufferRx = Buffer.from(frame.data);
|
|
1627
1629
|
const address = bufferRx.readUInt16BE(0);
|
|
1628
1630
|
const length = bufferRx.readUInt16BE(2);
|
|
1629
1631
|
if (length >= 0x0001 && length <= 0x07d0) {
|
|
1630
|
-
if (checkRange([address, address + length], (
|
|
1631
|
-
Promise.resolve(
|
|
1632
|
+
if (checkRange([address, address + length], (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).coils)) {
|
|
1633
|
+
Promise.resolve(model.readCoils(address, length))
|
|
1632
1634
|
.then((coils) => {
|
|
1633
1635
|
const bufferTx = Buffer.alloc(Math.ceil(length / 8));
|
|
1634
1636
|
coils.forEach((coil, index) => {
|
|
@@ -1655,16 +1657,16 @@ class ModbusSlave extends EventEmitter {
|
|
|
1655
1657
|
}
|
|
1656
1658
|
}
|
|
1657
1659
|
}
|
|
1658
|
-
handleFC2(frame, response) {
|
|
1659
|
-
var _a
|
|
1660
|
+
handleFC2(model, frame, response) {
|
|
1661
|
+
var _a;
|
|
1660
1662
|
if (frame.data.length === 4) {
|
|
1661
|
-
if (
|
|
1663
|
+
if (model.readDiscreteInputs) {
|
|
1662
1664
|
const bufferRx = Buffer.from(frame.data);
|
|
1663
1665
|
const address = bufferRx.readUInt16BE(0);
|
|
1664
1666
|
const length = bufferRx.readUInt16BE(2);
|
|
1665
1667
|
if (length >= 0x0001 && length <= 0x07d0) {
|
|
1666
|
-
if (checkRange([address, address + length], (
|
|
1667
|
-
Promise.resolve(
|
|
1668
|
+
if (checkRange([address, address + length], (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).discreteInputs)) {
|
|
1669
|
+
Promise.resolve(model.readDiscreteInputs(address, length))
|
|
1668
1670
|
.then((discreteInputs) => {
|
|
1669
1671
|
const bufferTx = Buffer.alloc(Math.ceil(length / 8));
|
|
1670
1672
|
discreteInputs.forEach((discreteInput, index) => {
|
|
@@ -1691,16 +1693,16 @@ class ModbusSlave extends EventEmitter {
|
|
|
1691
1693
|
}
|
|
1692
1694
|
}
|
|
1693
1695
|
}
|
|
1694
|
-
handleFC3(frame, response) {
|
|
1695
|
-
var _a
|
|
1696
|
+
handleFC3(model, frame, response) {
|
|
1697
|
+
var _a;
|
|
1696
1698
|
if (frame.data.length === 4) {
|
|
1697
|
-
if (
|
|
1699
|
+
if (model.readHoldingRegisters) {
|
|
1698
1700
|
const bufferRx = Buffer.from(frame.data);
|
|
1699
1701
|
const address = bufferRx.readUInt16BE(0);
|
|
1700
1702
|
const length = bufferRx.readUInt16BE(2);
|
|
1701
1703
|
if (length >= 0x0001 && length <= 0x007d) {
|
|
1702
|
-
if (checkRange([address, address + length], (
|
|
1703
|
-
Promise.resolve(
|
|
1704
|
+
if (checkRange([address, address + length], (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).holdingRegisters)) {
|
|
1705
|
+
Promise.resolve(model.readHoldingRegisters(address, length))
|
|
1704
1706
|
.then((registers) => {
|
|
1705
1707
|
const bufferTx = Buffer.alloc(length * 2);
|
|
1706
1708
|
registers.forEach((register, index) => {
|
|
@@ -1725,16 +1727,16 @@ class ModbusSlave extends EventEmitter {
|
|
|
1725
1727
|
}
|
|
1726
1728
|
}
|
|
1727
1729
|
}
|
|
1728
|
-
handleFC4(frame, response) {
|
|
1729
|
-
var _a
|
|
1730
|
+
handleFC4(model, frame, response) {
|
|
1731
|
+
var _a;
|
|
1730
1732
|
if (frame.data.length === 4) {
|
|
1731
|
-
if (
|
|
1733
|
+
if (model.readInputRegisters) {
|
|
1732
1734
|
const bufferRx = Buffer.from(frame.data);
|
|
1733
1735
|
const address = bufferRx.readUInt16BE(0);
|
|
1734
1736
|
const length = bufferRx.readUInt16BE(2);
|
|
1735
1737
|
if (length >= 0x0001 && length <= 0x007d) {
|
|
1736
|
-
if (checkRange([address, address + length], (
|
|
1737
|
-
Promise.resolve(
|
|
1738
|
+
if (checkRange([address, address + length], (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).inputRegisters)) {
|
|
1739
|
+
Promise.resolve(model.readInputRegisters(address, length))
|
|
1738
1740
|
.then((registers) => {
|
|
1739
1741
|
const bufferTx = Buffer.alloc(length * 2);
|
|
1740
1742
|
registers.forEach((register, index) => {
|
|
@@ -1759,16 +1761,16 @@ class ModbusSlave extends EventEmitter {
|
|
|
1759
1761
|
}
|
|
1760
1762
|
}
|
|
1761
1763
|
}
|
|
1762
|
-
handleFC5(frame, response) {
|
|
1763
|
-
var _a
|
|
1764
|
+
handleFC5(model, frame, response) {
|
|
1765
|
+
var _a;
|
|
1764
1766
|
if (frame.data.length === 4) {
|
|
1765
|
-
if (
|
|
1767
|
+
if (model.writeSingleCoil) {
|
|
1766
1768
|
const bufferRx = Buffer.from(frame.data);
|
|
1767
1769
|
const address = bufferRx.readUInt16BE(0);
|
|
1768
1770
|
const value = bufferRx.readUInt16BE(2);
|
|
1769
1771
|
if (value === 0x0000 || value === 0xff00) {
|
|
1770
|
-
if (checkRange(address, (
|
|
1771
|
-
Promise.resolve(
|
|
1772
|
+
if (checkRange(address, (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).coils)) {
|
|
1773
|
+
Promise.resolve(model.writeSingleCoil(address, value === 0xff00))
|
|
1772
1774
|
.then(() => {
|
|
1773
1775
|
response(this.applicationLayer.encode(frame));
|
|
1774
1776
|
})
|
|
@@ -1789,16 +1791,16 @@ class ModbusSlave extends EventEmitter {
|
|
|
1789
1791
|
}
|
|
1790
1792
|
}
|
|
1791
1793
|
}
|
|
1792
|
-
handleFC6(frame, response) {
|
|
1793
|
-
var _a
|
|
1794
|
+
handleFC6(model, frame, response) {
|
|
1795
|
+
var _a;
|
|
1794
1796
|
if (frame.data.length === 4) {
|
|
1795
|
-
if (
|
|
1797
|
+
if (model.writeSingleRegister) {
|
|
1796
1798
|
const bufferRx = Buffer.from(frame.data);
|
|
1797
1799
|
const address = bufferRx.readUInt16BE(0);
|
|
1798
1800
|
const value = bufferRx.readUInt16BE(2);
|
|
1799
1801
|
if (value >= 0x0000 && value <= 0xffff) {
|
|
1800
|
-
if (checkRange(address, (
|
|
1801
|
-
Promise.resolve(
|
|
1802
|
+
if (checkRange(address, (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).holdingRegisters)) {
|
|
1803
|
+
Promise.resolve(model.writeSingleRegister(address, value))
|
|
1802
1804
|
.then(() => {
|
|
1803
1805
|
response(this.applicationLayer.encode(frame));
|
|
1804
1806
|
})
|
|
@@ -1819,20 +1821,20 @@ class ModbusSlave extends EventEmitter {
|
|
|
1819
1821
|
}
|
|
1820
1822
|
}
|
|
1821
1823
|
}
|
|
1822
|
-
handleFC15(frame, response) {
|
|
1823
|
-
var _a
|
|
1824
|
+
handleFC15(model, frame, response) {
|
|
1825
|
+
var _a;
|
|
1824
1826
|
if (frame.data.length > 5 && frame.data.length === 5 + frame.data[4]) {
|
|
1825
|
-
if (
|
|
1827
|
+
if (model.writeMultipleCoils || model.writeSingleCoil) {
|
|
1826
1828
|
const bufferRx = Buffer.from(frame.data);
|
|
1827
1829
|
const address = bufferRx.readUInt16BE(0);
|
|
1828
1830
|
const length = bufferRx.readUInt16BE(2);
|
|
1829
1831
|
const byteCount = bufferRx[4];
|
|
1830
1832
|
if (length >= 0x0001 && length <= 0x07b0 && byteCount === Math.ceil(length / 8)) {
|
|
1831
|
-
if (checkRange([address, address + length], (
|
|
1833
|
+
if (checkRange([address, address + length], (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).coils)) {
|
|
1832
1834
|
const value = Array.from({ length }).map((_, index) => (bufferRx[5 + ~~(index / 8)] & (1 << index % 8)) > 0);
|
|
1833
|
-
Promise.resolve(
|
|
1834
|
-
?
|
|
1835
|
-
: Promise.all(value.map((v, i) =>
|
|
1835
|
+
Promise.resolve(model.writeMultipleCoils
|
|
1836
|
+
? model.writeMultipleCoils(address, value)
|
|
1837
|
+
: Promise.all(value.map((v, i) => model.writeSingleCoil(address + i, v))))
|
|
1836
1838
|
.then(() => {
|
|
1837
1839
|
response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: Array.from(bufferRx).slice(0, 4) })));
|
|
1838
1840
|
})
|
|
@@ -1853,20 +1855,20 @@ class ModbusSlave extends EventEmitter {
|
|
|
1853
1855
|
}
|
|
1854
1856
|
}
|
|
1855
1857
|
}
|
|
1856
|
-
handleFC16(frame, response) {
|
|
1857
|
-
var _a
|
|
1858
|
+
handleFC16(model, frame, response) {
|
|
1859
|
+
var _a;
|
|
1858
1860
|
if (frame.data.length > 5 && frame.data.length === 5 + frame.data[4]) {
|
|
1859
|
-
if (
|
|
1861
|
+
if (model.writeMultipleRegisters || model.writeSingleRegister) {
|
|
1860
1862
|
const bufferRx = Buffer.from(frame.data);
|
|
1861
1863
|
const address = bufferRx.readUInt16BE(0);
|
|
1862
1864
|
const length = bufferRx.readUInt16BE(2);
|
|
1863
1865
|
const byteCount = bufferRx[4];
|
|
1864
1866
|
if (length >= 0x0001 && length <= 0x007b && byteCount === length * 2) {
|
|
1865
|
-
if (checkRange([address, address + length], (
|
|
1867
|
+
if (checkRange([address, address + length], (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).holdingRegisters)) {
|
|
1866
1868
|
const value = Array.from({ length }).map((_, index) => bufferRx.readUInt16BE(5 + index * 2));
|
|
1867
|
-
Promise.resolve(
|
|
1868
|
-
?
|
|
1869
|
-
: Promise.all(value.map((v, i) =>
|
|
1869
|
+
Promise.resolve(model.writeMultipleRegisters
|
|
1870
|
+
? model.writeMultipleRegisters(address, value)
|
|
1871
|
+
: Promise.all(value.map((v, i) => model.writeSingleRegister(address + i, v))))
|
|
1870
1872
|
.then(() => {
|
|
1871
1873
|
response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: Array.from(bufferRx).slice(0, 4) })));
|
|
1872
1874
|
})
|
|
@@ -1887,11 +1889,13 @@ class ModbusSlave extends EventEmitter {
|
|
|
1887
1889
|
}
|
|
1888
1890
|
}
|
|
1889
1891
|
}
|
|
1890
|
-
handleFC17(frame, response) {
|
|
1892
|
+
handleFC17(model, frame, response) {
|
|
1891
1893
|
if (frame.data.length === 0) {
|
|
1892
|
-
if (
|
|
1893
|
-
Promise.resolve(
|
|
1894
|
-
.then((
|
|
1894
|
+
if (model.reportServerId) {
|
|
1895
|
+
Promise.resolve(model.reportServerId())
|
|
1896
|
+
.then((_a) => {
|
|
1897
|
+
var _b;
|
|
1898
|
+
var { serverId = (_b = model.unit) !== null && _b !== void 0 ? _b : 1, runIndicatorStatus = true, additionalData = [] } = _a;
|
|
1895
1899
|
response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: [2 + additionalData.length, serverId, runIndicatorStatus ? 0xff : 0x00].concat(additionalData) })));
|
|
1896
1900
|
})
|
|
1897
1901
|
.catch((error) => {
|
|
@@ -1903,19 +1907,19 @@ class ModbusSlave extends EventEmitter {
|
|
|
1903
1907
|
}
|
|
1904
1908
|
}
|
|
1905
1909
|
}
|
|
1906
|
-
handleFC22(frame, response) {
|
|
1907
|
-
var _a
|
|
1910
|
+
handleFC22(model, frame, response) {
|
|
1911
|
+
var _a;
|
|
1908
1912
|
if (frame.data.length === 6) {
|
|
1909
|
-
if (
|
|
1913
|
+
if (model.maskWriteRegister || (model.readHoldingRegisters && model.writeSingleRegister)) {
|
|
1910
1914
|
const bufferRx = Buffer.from(frame.data);
|
|
1911
1915
|
const address = bufferRx.readUInt16BE(0);
|
|
1912
1916
|
const andMask = bufferRx.readUInt16BE(2);
|
|
1913
1917
|
const orMask = bufferRx.readUInt16BE(4);
|
|
1914
|
-
if (checkRange(address, (
|
|
1915
|
-
Promise.resolve(
|
|
1916
|
-
?
|
|
1917
|
-
: Promise.resolve(
|
|
1918
|
-
return Promise.resolve(
|
|
1918
|
+
if (checkRange(address, (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).holdingRegisters)) {
|
|
1919
|
+
Promise.resolve(model.maskWriteRegister
|
|
1920
|
+
? model.maskWriteRegister(address, andMask, orMask)
|
|
1921
|
+
: Promise.resolve(model.readHoldingRegisters(address, 1)).then(([value]) => {
|
|
1922
|
+
return Promise.resolve(model.writeSingleRegister(address, (value & andMask) | (orMask & (~andMask & 0xff))));
|
|
1919
1923
|
}))
|
|
1920
1924
|
.then(() => {
|
|
1921
1925
|
response(this.applicationLayer.encode(frame));
|
|
@@ -1933,10 +1937,10 @@ class ModbusSlave extends EventEmitter {
|
|
|
1933
1937
|
}
|
|
1934
1938
|
}
|
|
1935
1939
|
}
|
|
1936
|
-
handleFC23(frame, response) {
|
|
1937
|
-
var _a
|
|
1940
|
+
handleFC23(model, frame, response) {
|
|
1941
|
+
var _a;
|
|
1938
1942
|
if (frame.data.length > 9 && frame.data.length === 9 + frame.data[8]) {
|
|
1939
|
-
if (
|
|
1943
|
+
if (model.readHoldingRegisters && (model.writeMultipleRegisters || model.writeSingleRegister)) {
|
|
1940
1944
|
const bufferRx = Buffer.from(frame.data);
|
|
1941
1945
|
const address = {
|
|
1942
1946
|
read: bufferRx.readUInt16BE(0),
|
|
@@ -1952,12 +1956,12 @@ class ModbusSlave extends EventEmitter {
|
|
|
1952
1956
|
length.write >= 0x0001 &&
|
|
1953
1957
|
length.write <= 0x0079 &&
|
|
1954
1958
|
byteCount === length.write * 2) {
|
|
1955
|
-
if (checkRange([address.read, address.read + length.read, address.write, address.write + length.write], (
|
|
1959
|
+
if (checkRange([address.read, address.read + length.read, address.write, address.write + length.write], (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).holdingRegisters)) {
|
|
1956
1960
|
const value = Array.from({ length: length.write }).map((_, index) => bufferRx.readUInt16BE(9 + index * 2));
|
|
1957
|
-
Promise.resolve(
|
|
1958
|
-
?
|
|
1959
|
-
: Promise.all(value.map((v, i) =>
|
|
1960
|
-
.then(() => Promise.resolve(
|
|
1961
|
+
Promise.resolve(model.writeMultipleRegisters
|
|
1962
|
+
? model.writeMultipleRegisters(address.write, value)
|
|
1963
|
+
: Promise.all(value.map((v, i) => model.writeSingleRegister(address.write + i, v))))
|
|
1964
|
+
.then(() => Promise.resolve(model.readHoldingRegisters(address.read, length.read)))
|
|
1961
1965
|
.then((registers) => {
|
|
1962
1966
|
const bufferTx = Buffer.alloc(length.read * 2);
|
|
1963
1967
|
registers.forEach((register, index) => {
|
|
@@ -1982,9 +1986,9 @@ class ModbusSlave extends EventEmitter {
|
|
|
1982
1986
|
}
|
|
1983
1987
|
}
|
|
1984
1988
|
}
|
|
1985
|
-
handleFC43_14(frame, response) {
|
|
1989
|
+
handleFC43_14(model, frame, response) {
|
|
1986
1990
|
if (frame.data.length === 3) {
|
|
1987
|
-
if (frame.data[0] === 0x0e &&
|
|
1991
|
+
if (frame.data[0] === 0x0e && model.readDeviceIdentification) {
|
|
1988
1992
|
const readDeviceIDCode = frame.data[1];
|
|
1989
1993
|
let objectID = frame.data[2];
|
|
1990
1994
|
switch (readDeviceIDCode) {
|
|
@@ -2018,7 +2022,7 @@ class ModbusSlave extends EventEmitter {
|
|
|
2018
2022
|
return;
|
|
2019
2023
|
}
|
|
2020
2024
|
}
|
|
2021
|
-
Promise.resolve(
|
|
2025
|
+
Promise.resolve(model.readDeviceIdentification())
|
|
2022
2026
|
.then((identification) => {
|
|
2023
2027
|
const objects = new Map([
|
|
2024
2028
|
[0x00, 'null'],
|
|
@@ -2096,6 +2100,13 @@ class ModbusSlave extends EventEmitter {
|
|
|
2096
2100
|
responseError(frame, response, error) {
|
|
2097
2101
|
response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { fc: frame.fc | 0x80, data: [getCodeByError(error)] })));
|
|
2098
2102
|
}
|
|
2103
|
+
add(model) {
|
|
2104
|
+
var _a;
|
|
2105
|
+
this.models.set((_a = model.unit) !== null && _a !== void 0 ? _a : 1, model);
|
|
2106
|
+
}
|
|
2107
|
+
remove(unit) {
|
|
2108
|
+
this.models.delete(unit);
|
|
2109
|
+
}
|
|
2099
2110
|
open(...args) {
|
|
2100
2111
|
return this.physicalLayer.open(...args);
|
|
2101
2112
|
}
|
|
@@ -45,13 +45,12 @@ interface ModbusSlaveEvents {
|
|
|
45
45
|
close: [];
|
|
46
46
|
}
|
|
47
47
|
export declare class ModbusSlave<A extends AbstractApplicationLayer, P extends AbstractPhysicalLayer> extends EventEmitter<ModbusSlaveEvents> {
|
|
48
|
-
private model;
|
|
49
48
|
private applicationLayer;
|
|
50
49
|
private physicalLayer;
|
|
51
|
-
|
|
50
|
+
models: Map<number, ModbusSlaveModel>;
|
|
52
51
|
get isOpen(): boolean;
|
|
53
52
|
get destroyed(): boolean;
|
|
54
|
-
constructor(
|
|
53
|
+
constructor(applicationLayer: A, physicalLayer: P);
|
|
55
54
|
private handleFC1;
|
|
56
55
|
private handleFC2;
|
|
57
56
|
private handleFC3;
|
|
@@ -65,6 +64,8 @@ export declare class ModbusSlave<A extends AbstractApplicationLayer, P extends A
|
|
|
65
64
|
private handleFC23;
|
|
66
65
|
private handleFC43_14;
|
|
67
66
|
private responseError;
|
|
67
|
+
add(model: ModbusSlaveModel): void;
|
|
68
|
+
remove(unit: number): void;
|
|
68
69
|
open(...args: Parameters<P['open']>): Promise<void>;
|
|
69
70
|
close(): Promise<void>;
|
|
70
71
|
destroy(): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|