njs-modbus 1.3.5 → 1.5.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 +66 -67
- package/dist/index.cjs +583 -488
- package/dist/index.d.ts +10 -3
- package/dist/index.mjs +583 -488
- package/dist/src/slave/slave.d.ts +10 -3
- package/package.json +2 -1
- /package/dist/test/{master.d.ts → slave.test.d.ts} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -327,6 +327,7 @@ class TcpServerPhysicalLayer extends AbstractPhysicalLayer {
|
|
|
327
327
|
this._server.removeAllListeners();
|
|
328
328
|
for (const socket of this._sockets) {
|
|
329
329
|
socket.removeAllListeners();
|
|
330
|
+
socket.destroy();
|
|
330
331
|
}
|
|
331
332
|
this._server.close(() => {
|
|
332
333
|
resolve();
|
|
@@ -1111,31 +1112,47 @@ class ModbusMaster extends EventEmitter {
|
|
|
1111
1112
|
}
|
|
1112
1113
|
waitResponse(request, response, timeout) {
|
|
1113
1114
|
return new Promise((resolve, reject) => {
|
|
1115
|
+
let settled = false;
|
|
1116
|
+
const tid = setTimeout(() => {
|
|
1117
|
+
if (!settled) {
|
|
1118
|
+
settled = true;
|
|
1119
|
+
this.applicationLayer.stopWaitingResponse();
|
|
1120
|
+
reject(new Error('Timeout'));
|
|
1121
|
+
}
|
|
1122
|
+
}, timeout);
|
|
1114
1123
|
this.physicalLayer
|
|
1115
1124
|
.write(request.data)
|
|
1116
1125
|
.then(() => {
|
|
1117
|
-
if (
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
else {
|
|
1121
|
-
const tid = setTimeout(() => {
|
|
1122
|
-
this.applicationLayer.stopWaitingResponse();
|
|
1123
|
-
reject(new Error('Timeout'));
|
|
1124
|
-
}, timeout);
|
|
1125
|
-
this.applicationLayer.startWaitingResponse(response.preCheck, (error, frame) => {
|
|
1126
|
+
if (!settled) {
|
|
1127
|
+
if (request.broadcast) {
|
|
1128
|
+
settled = true;
|
|
1126
1129
|
clearTimeout(tid);
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1130
|
+
resolve();
|
|
1131
|
+
}
|
|
1132
|
+
else {
|
|
1133
|
+
this.applicationLayer.startWaitingResponse(response.preCheck, (error, frame) => {
|
|
1134
|
+
if (!settled) {
|
|
1135
|
+
settled = true;
|
|
1136
|
+
clearTimeout(tid);
|
|
1137
|
+
this.applicationLayer.stopWaitingResponse();
|
|
1138
|
+
if (error) {
|
|
1139
|
+
reject(error);
|
|
1140
|
+
}
|
|
1141
|
+
else {
|
|
1142
|
+
resolve(frame);
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
});
|
|
1146
|
+
}
|
|
1135
1147
|
}
|
|
1136
1148
|
})
|
|
1137
1149
|
.catch((error) => {
|
|
1138
|
-
|
|
1150
|
+
if (!settled) {
|
|
1151
|
+
settled = true;
|
|
1152
|
+
clearTimeout(tid);
|
|
1153
|
+
this.applicationLayer.stopWaitingResponse();
|
|
1154
|
+
reject(error);
|
|
1155
|
+
}
|
|
1139
1156
|
});
|
|
1140
1157
|
});
|
|
1141
1158
|
}
|
|
@@ -1504,14 +1521,8 @@ class ModbusSlave extends EventEmitter {
|
|
|
1504
1521
|
get destroyed() {
|
|
1505
1522
|
return this.physicalLayer.destroyed;
|
|
1506
1523
|
}
|
|
1507
|
-
constructor(
|
|
1524
|
+
constructor(applicationLayer, physicalLayer) {
|
|
1508
1525
|
super();
|
|
1509
|
-
Object.defineProperty(this, "model", {
|
|
1510
|
-
enumerable: true,
|
|
1511
|
-
configurable: true,
|
|
1512
|
-
writable: true,
|
|
1513
|
-
value: model
|
|
1514
|
-
});
|
|
1515
1526
|
Object.defineProperty(this, "applicationLayer", {
|
|
1516
1527
|
enumerable: true,
|
|
1517
1528
|
configurable: true,
|
|
@@ -1524,96 +1535,31 @@ class ModbusSlave extends EventEmitter {
|
|
|
1524
1535
|
writable: true,
|
|
1525
1536
|
value: physicalLayer
|
|
1526
1537
|
});
|
|
1527
|
-
Object.defineProperty(this, "
|
|
1538
|
+
Object.defineProperty(this, "models", {
|
|
1528
1539
|
enumerable: true,
|
|
1529
1540
|
configurable: true,
|
|
1530
1541
|
writable: true,
|
|
1531
|
-
value:
|
|
1542
|
+
value: new Map()
|
|
1532
1543
|
});
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1544
|
+
Object.defineProperty(this, "_processing", {
|
|
1545
|
+
enumerable: true,
|
|
1546
|
+
configurable: true,
|
|
1547
|
+
writable: true,
|
|
1548
|
+
value: false
|
|
1549
|
+
});
|
|
1550
|
+
Object.defineProperty(this, "_queue", {
|
|
1551
|
+
enumerable: true,
|
|
1552
|
+
configurable: true,
|
|
1553
|
+
writable: true,
|
|
1554
|
+
value: []
|
|
1555
|
+
});
|
|
1556
|
+
applicationLayer.on('framing', (frame, _response) => {
|
|
1557
|
+
if (!(frame.unit === 0x00 || this.models.has(frame.unit))) {
|
|
1538
1558
|
return;
|
|
1539
1559
|
}
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
}
|
|
1544
|
-
try {
|
|
1545
|
-
yield _response(data);
|
|
1546
|
-
}
|
|
1547
|
-
catch (error) { }
|
|
1548
|
-
});
|
|
1549
|
-
if (model.interceptor) {
|
|
1550
|
-
try {
|
|
1551
|
-
const data = yield model.interceptor(frame.fc, frame.data);
|
|
1552
|
-
if (data) {
|
|
1553
|
-
response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data })));
|
|
1554
|
-
return;
|
|
1555
|
-
}
|
|
1556
|
-
}
|
|
1557
|
-
catch (error) {
|
|
1558
|
-
this.responseError(frame, response, error);
|
|
1559
|
-
return;
|
|
1560
|
-
}
|
|
1561
|
-
}
|
|
1562
|
-
switch (frame.fc) {
|
|
1563
|
-
case 0x01: {
|
|
1564
|
-
this.handleFC1(frame, response);
|
|
1565
|
-
break;
|
|
1566
|
-
}
|
|
1567
|
-
case 0x02: {
|
|
1568
|
-
this.handleFC2(frame, response);
|
|
1569
|
-
break;
|
|
1570
|
-
}
|
|
1571
|
-
case 0x03: {
|
|
1572
|
-
this.handleFC3(frame, response);
|
|
1573
|
-
break;
|
|
1574
|
-
}
|
|
1575
|
-
case 0x04: {
|
|
1576
|
-
this.handleFC4(frame, response);
|
|
1577
|
-
break;
|
|
1578
|
-
}
|
|
1579
|
-
case 0x05: {
|
|
1580
|
-
this.handleFC5(frame, response);
|
|
1581
|
-
break;
|
|
1582
|
-
}
|
|
1583
|
-
case 0x06: {
|
|
1584
|
-
this.handleFC6(frame, response);
|
|
1585
|
-
break;
|
|
1586
|
-
}
|
|
1587
|
-
case 0x0f: {
|
|
1588
|
-
this.handleFC15(frame, response);
|
|
1589
|
-
break;
|
|
1590
|
-
}
|
|
1591
|
-
case 0x10: {
|
|
1592
|
-
this.handleFC16(frame, response);
|
|
1593
|
-
break;
|
|
1594
|
-
}
|
|
1595
|
-
case 0x11: {
|
|
1596
|
-
this.handleFC17(frame, response);
|
|
1597
|
-
break;
|
|
1598
|
-
}
|
|
1599
|
-
case 0x16: {
|
|
1600
|
-
this.handleFC22(frame, response);
|
|
1601
|
-
break;
|
|
1602
|
-
}
|
|
1603
|
-
case 0x17: {
|
|
1604
|
-
this.handleFC23(frame, response);
|
|
1605
|
-
break;
|
|
1606
|
-
}
|
|
1607
|
-
case 0x2b: {
|
|
1608
|
-
this.handleFC43_14(frame, response);
|
|
1609
|
-
break;
|
|
1610
|
-
}
|
|
1611
|
-
default: {
|
|
1612
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1613
|
-
break;
|
|
1614
|
-
}
|
|
1615
|
-
}
|
|
1616
|
-
}));
|
|
1560
|
+
this._queue.push({ frame, response: _response });
|
|
1561
|
+
this._drain();
|
|
1562
|
+
});
|
|
1617
1563
|
physicalLayer.on('error', (error) => {
|
|
1618
1564
|
this.emit('error', error);
|
|
1619
1565
|
});
|
|
@@ -1621,482 +1567,631 @@ class ModbusSlave extends EventEmitter {
|
|
|
1621
1567
|
this.emit('close');
|
|
1622
1568
|
});
|
|
1623
1569
|
}
|
|
1624
|
-
handleFC1(frame, response) {
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
if (
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
if (
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1570
|
+
handleFC1(model, frame, response) {
|
|
1571
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1572
|
+
var _a;
|
|
1573
|
+
if (frame.data.length === 4) {
|
|
1574
|
+
if (model.readCoils) {
|
|
1575
|
+
const bufferRx = Buffer.from(frame.data);
|
|
1576
|
+
const address = bufferRx.readUInt16BE(0);
|
|
1577
|
+
const length = bufferRx.readUInt16BE(2);
|
|
1578
|
+
if (length >= 0x0001 && length <= 0x07d0) {
|
|
1579
|
+
if (checkRange([address, address + length], (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).coils)) {
|
|
1580
|
+
try {
|
|
1581
|
+
const coils = yield Promise.resolve(model.readCoils(address, length));
|
|
1582
|
+
const bufferTx = Buffer.alloc(Math.ceil(length / 8));
|
|
1583
|
+
coils.forEach((coil, index) => {
|
|
1584
|
+
if (coil) {
|
|
1585
|
+
bufferTx[~~(index / 8)] |= 1 << index % 8;
|
|
1586
|
+
}
|
|
1587
|
+
});
|
|
1588
|
+
yield response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: [bufferTx.length].concat(Array.from(bufferTx)) })));
|
|
1589
|
+
}
|
|
1590
|
+
catch (error) {
|
|
1591
|
+
yield this.responseError(frame, response, error);
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
else {
|
|
1595
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_ADDRESS));
|
|
1596
|
+
}
|
|
1646
1597
|
}
|
|
1647
1598
|
else {
|
|
1648
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.
|
|
1599
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_VALUE));
|
|
1649
1600
|
}
|
|
1650
1601
|
}
|
|
1651
1602
|
else {
|
|
1652
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.
|
|
1603
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1653
1604
|
}
|
|
1654
1605
|
}
|
|
1655
|
-
|
|
1656
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1657
|
-
}
|
|
1658
|
-
}
|
|
1606
|
+
});
|
|
1659
1607
|
}
|
|
1660
|
-
handleFC2(frame, response) {
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
if (
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
if (
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1608
|
+
handleFC2(model, frame, response) {
|
|
1609
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1610
|
+
var _a;
|
|
1611
|
+
if (frame.data.length === 4) {
|
|
1612
|
+
if (model.readDiscreteInputs) {
|
|
1613
|
+
const bufferRx = Buffer.from(frame.data);
|
|
1614
|
+
const address = bufferRx.readUInt16BE(0);
|
|
1615
|
+
const length = bufferRx.readUInt16BE(2);
|
|
1616
|
+
if (length >= 0x0001 && length <= 0x07d0) {
|
|
1617
|
+
if (checkRange([address, address + length], (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).discreteInputs)) {
|
|
1618
|
+
try {
|
|
1619
|
+
const discreteInputs = yield Promise.resolve(model.readDiscreteInputs(address, length));
|
|
1620
|
+
const bufferTx = Buffer.alloc(Math.ceil(length / 8));
|
|
1621
|
+
discreteInputs.forEach((discreteInput, index) => {
|
|
1622
|
+
if (discreteInput) {
|
|
1623
|
+
bufferTx[~~(index / 8)] |= 1 << index % 8;
|
|
1624
|
+
}
|
|
1625
|
+
});
|
|
1626
|
+
yield response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: [bufferTx.length].concat(Array.from(bufferTx)) })));
|
|
1627
|
+
}
|
|
1628
|
+
catch (error) {
|
|
1629
|
+
yield this.responseError(frame, response, error);
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
else {
|
|
1633
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_ADDRESS));
|
|
1634
|
+
}
|
|
1682
1635
|
}
|
|
1683
1636
|
else {
|
|
1684
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.
|
|
1637
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_VALUE));
|
|
1685
1638
|
}
|
|
1686
1639
|
}
|
|
1687
1640
|
else {
|
|
1688
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.
|
|
1641
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1689
1642
|
}
|
|
1690
1643
|
}
|
|
1691
|
-
|
|
1692
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1693
|
-
}
|
|
1694
|
-
}
|
|
1644
|
+
});
|
|
1695
1645
|
}
|
|
1696
|
-
handleFC3(frame, response) {
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
if (
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
if (
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1646
|
+
handleFC3(model, frame, response) {
|
|
1647
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1648
|
+
var _a;
|
|
1649
|
+
if (frame.data.length === 4) {
|
|
1650
|
+
if (model.readHoldingRegisters) {
|
|
1651
|
+
const bufferRx = Buffer.from(frame.data);
|
|
1652
|
+
const address = bufferRx.readUInt16BE(0);
|
|
1653
|
+
const length = bufferRx.readUInt16BE(2);
|
|
1654
|
+
if (length >= 0x0001 && length <= 0x007d) {
|
|
1655
|
+
if (checkRange([address, address + length], (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).holdingRegisters)) {
|
|
1656
|
+
try {
|
|
1657
|
+
const registers = yield Promise.resolve(model.readHoldingRegisters(address, length));
|
|
1658
|
+
const bufferTx = Buffer.alloc(length * 2);
|
|
1659
|
+
registers.forEach((register, index) => {
|
|
1660
|
+
bufferTx.writeUInt16BE(register, index * 2);
|
|
1661
|
+
});
|
|
1662
|
+
yield response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: [bufferTx.length].concat(Array.from(bufferTx)) })));
|
|
1663
|
+
}
|
|
1664
|
+
catch (error) {
|
|
1665
|
+
yield this.responseError(frame, response, error);
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
else {
|
|
1669
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_ADDRESS));
|
|
1670
|
+
}
|
|
1716
1671
|
}
|
|
1717
1672
|
else {
|
|
1718
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.
|
|
1673
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_VALUE));
|
|
1719
1674
|
}
|
|
1720
1675
|
}
|
|
1721
1676
|
else {
|
|
1722
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.
|
|
1677
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1723
1678
|
}
|
|
1724
1679
|
}
|
|
1725
|
-
|
|
1726
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1727
|
-
}
|
|
1728
|
-
}
|
|
1680
|
+
});
|
|
1729
1681
|
}
|
|
1730
|
-
handleFC4(frame, response) {
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
if (
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
if (
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1682
|
+
handleFC4(model, frame, response) {
|
|
1683
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1684
|
+
var _a;
|
|
1685
|
+
if (frame.data.length === 4) {
|
|
1686
|
+
if (model.readInputRegisters) {
|
|
1687
|
+
const bufferRx = Buffer.from(frame.data);
|
|
1688
|
+
const address = bufferRx.readUInt16BE(0);
|
|
1689
|
+
const length = bufferRx.readUInt16BE(2);
|
|
1690
|
+
if (length >= 0x0001 && length <= 0x007d) {
|
|
1691
|
+
if (checkRange([address, address + length], (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).inputRegisters)) {
|
|
1692
|
+
try {
|
|
1693
|
+
const registers = yield Promise.resolve(model.readInputRegisters(address, length));
|
|
1694
|
+
const bufferTx = Buffer.alloc(length * 2);
|
|
1695
|
+
registers.forEach((register, index) => {
|
|
1696
|
+
bufferTx.writeUInt16BE(register, index * 2);
|
|
1697
|
+
});
|
|
1698
|
+
yield response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: [bufferTx.length].concat(Array.from(bufferTx)) })));
|
|
1699
|
+
}
|
|
1700
|
+
catch (error) {
|
|
1701
|
+
yield this.responseError(frame, response, error);
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
else {
|
|
1705
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_ADDRESS));
|
|
1706
|
+
}
|
|
1750
1707
|
}
|
|
1751
1708
|
else {
|
|
1752
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.
|
|
1709
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_VALUE));
|
|
1753
1710
|
}
|
|
1754
1711
|
}
|
|
1755
1712
|
else {
|
|
1756
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.
|
|
1713
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1757
1714
|
}
|
|
1758
1715
|
}
|
|
1759
|
-
|
|
1760
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1761
|
-
}
|
|
1762
|
-
}
|
|
1716
|
+
});
|
|
1763
1717
|
}
|
|
1764
|
-
handleFC5(frame, response) {
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
if (
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
if (
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1718
|
+
handleFC5(model, frame, response) {
|
|
1719
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1720
|
+
var _a;
|
|
1721
|
+
if (frame.data.length === 4) {
|
|
1722
|
+
if (model.writeSingleCoil) {
|
|
1723
|
+
const bufferRx = Buffer.from(frame.data);
|
|
1724
|
+
const address = bufferRx.readUInt16BE(0);
|
|
1725
|
+
const value = bufferRx.readUInt16BE(2);
|
|
1726
|
+
if (value === 0x0000 || value === 0xff00) {
|
|
1727
|
+
if (checkRange(address, (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).coils)) {
|
|
1728
|
+
try {
|
|
1729
|
+
yield Promise.resolve(model.writeSingleCoil(address, value === 0xff00));
|
|
1730
|
+
yield response(this.applicationLayer.encode(frame));
|
|
1731
|
+
}
|
|
1732
|
+
catch (error) {
|
|
1733
|
+
yield this.responseError(frame, response, error);
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
else {
|
|
1737
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_ADDRESS));
|
|
1738
|
+
}
|
|
1780
1739
|
}
|
|
1781
1740
|
else {
|
|
1782
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.
|
|
1741
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_VALUE));
|
|
1783
1742
|
}
|
|
1784
1743
|
}
|
|
1785
1744
|
else {
|
|
1786
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.
|
|
1745
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1787
1746
|
}
|
|
1788
1747
|
}
|
|
1789
|
-
|
|
1790
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1791
|
-
}
|
|
1792
|
-
}
|
|
1748
|
+
});
|
|
1793
1749
|
}
|
|
1794
|
-
handleFC6(frame, response) {
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
if (
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
if (
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1750
|
+
handleFC6(model, frame, response) {
|
|
1751
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1752
|
+
var _a;
|
|
1753
|
+
if (frame.data.length === 4) {
|
|
1754
|
+
if (model.writeSingleRegister) {
|
|
1755
|
+
const bufferRx = Buffer.from(frame.data);
|
|
1756
|
+
const address = bufferRx.readUInt16BE(0);
|
|
1757
|
+
const value = bufferRx.readUInt16BE(2);
|
|
1758
|
+
if (value >= 0x0000 && value <= 0xffff) {
|
|
1759
|
+
if (checkRange(address, (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).holdingRegisters)) {
|
|
1760
|
+
try {
|
|
1761
|
+
yield Promise.resolve(model.writeSingleRegister(address, value));
|
|
1762
|
+
yield response(this.applicationLayer.encode(frame));
|
|
1763
|
+
}
|
|
1764
|
+
catch (error) {
|
|
1765
|
+
yield this.responseError(frame, response, error);
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
else {
|
|
1769
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_ADDRESS));
|
|
1770
|
+
}
|
|
1810
1771
|
}
|
|
1811
1772
|
else {
|
|
1812
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.
|
|
1773
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_VALUE));
|
|
1813
1774
|
}
|
|
1814
1775
|
}
|
|
1815
1776
|
else {
|
|
1816
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.
|
|
1777
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1817
1778
|
}
|
|
1818
1779
|
}
|
|
1819
|
-
|
|
1820
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1821
|
-
}
|
|
1822
|
-
}
|
|
1780
|
+
});
|
|
1823
1781
|
}
|
|
1824
|
-
handleFC15(frame, response) {
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
if (
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
if (
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1782
|
+
handleFC15(model, frame, response) {
|
|
1783
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1784
|
+
var _a;
|
|
1785
|
+
if (frame.data.length > 5 && frame.data.length === 5 + frame.data[4]) {
|
|
1786
|
+
if (model.writeMultipleCoils || model.writeSingleCoil) {
|
|
1787
|
+
const bufferRx = Buffer.from(frame.data);
|
|
1788
|
+
const address = bufferRx.readUInt16BE(0);
|
|
1789
|
+
const length = bufferRx.readUInt16BE(2);
|
|
1790
|
+
const byteCount = bufferRx[4];
|
|
1791
|
+
if (length >= 0x0001 && length <= 0x07b0 && byteCount === Math.ceil(length / 8)) {
|
|
1792
|
+
if (checkRange([address, address + length], (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).coils)) {
|
|
1793
|
+
const value = Array.from({ length }).map((_, index) => (bufferRx[5 + ~~(index / 8)] & (1 << index % 8)) > 0);
|
|
1794
|
+
try {
|
|
1795
|
+
yield Promise.resolve(model.writeMultipleCoils
|
|
1796
|
+
? model.writeMultipleCoils(address, value)
|
|
1797
|
+
: Promise.all(value.map((v, i) => model.writeSingleCoil(address + i, v))));
|
|
1798
|
+
yield response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: Array.from(bufferRx).slice(0, 4) })));
|
|
1799
|
+
}
|
|
1800
|
+
catch (error) {
|
|
1801
|
+
yield this.responseError(frame, response, error);
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
else {
|
|
1805
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_ADDRESS));
|
|
1806
|
+
}
|
|
1844
1807
|
}
|
|
1845
1808
|
else {
|
|
1846
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.
|
|
1809
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_VALUE));
|
|
1847
1810
|
}
|
|
1848
1811
|
}
|
|
1849
1812
|
else {
|
|
1850
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.
|
|
1813
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1851
1814
|
}
|
|
1852
1815
|
}
|
|
1853
|
-
|
|
1854
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1855
|
-
}
|
|
1856
|
-
}
|
|
1816
|
+
});
|
|
1857
1817
|
}
|
|
1858
|
-
handleFC16(frame, response) {
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
if (
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
if (
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1818
|
+
handleFC16(model, frame, response) {
|
|
1819
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1820
|
+
var _a;
|
|
1821
|
+
if (frame.data.length > 5 && frame.data.length === 5 + frame.data[4]) {
|
|
1822
|
+
if (model.writeMultipleRegisters || model.writeSingleRegister) {
|
|
1823
|
+
const bufferRx = Buffer.from(frame.data);
|
|
1824
|
+
const address = bufferRx.readUInt16BE(0);
|
|
1825
|
+
const length = bufferRx.readUInt16BE(2);
|
|
1826
|
+
const byteCount = bufferRx[4];
|
|
1827
|
+
if (length >= 0x0001 && length <= 0x007b && byteCount === length * 2) {
|
|
1828
|
+
if (checkRange([address, address + length], (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).holdingRegisters)) {
|
|
1829
|
+
const value = Array.from({ length }).map((_, index) => bufferRx.readUInt16BE(5 + index * 2));
|
|
1830
|
+
try {
|
|
1831
|
+
yield Promise.resolve(model.writeMultipleRegisters
|
|
1832
|
+
? model.writeMultipleRegisters(address, value)
|
|
1833
|
+
: Promise.all(value.map((v, i) => model.writeSingleRegister(address + i, v))));
|
|
1834
|
+
yield response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: Array.from(bufferRx).slice(0, 4) })));
|
|
1835
|
+
}
|
|
1836
|
+
catch (error) {
|
|
1837
|
+
yield this.responseError(frame, response, error);
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
else {
|
|
1841
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_ADDRESS));
|
|
1842
|
+
}
|
|
1878
1843
|
}
|
|
1879
1844
|
else {
|
|
1880
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.
|
|
1845
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_VALUE));
|
|
1881
1846
|
}
|
|
1882
1847
|
}
|
|
1883
1848
|
else {
|
|
1884
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.
|
|
1849
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1885
1850
|
}
|
|
1886
1851
|
}
|
|
1887
|
-
|
|
1888
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1889
|
-
}
|
|
1890
|
-
}
|
|
1891
|
-
}
|
|
1892
|
-
handleFC17(frame, response) {
|
|
1893
|
-
if (frame.data.length === 0) {
|
|
1894
|
-
if (this.model.reportServerId) {
|
|
1895
|
-
Promise.resolve(this.model.reportServerId())
|
|
1896
|
-
.then(({ serverId = this.unit, runIndicatorStatus = true, additionalData = [] }) => {
|
|
1897
|
-
response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: [2 + additionalData.length, serverId, runIndicatorStatus ? 0xff : 0x00].concat(additionalData) })));
|
|
1898
|
-
})
|
|
1899
|
-
.catch((error) => {
|
|
1900
|
-
this.responseError(frame, response, error);
|
|
1901
|
-
});
|
|
1902
|
-
}
|
|
1903
|
-
else {
|
|
1904
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1905
|
-
}
|
|
1906
|
-
}
|
|
1852
|
+
});
|
|
1907
1853
|
}
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
if (
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
return Promise.resolve(this.model.writeSingleRegister(address, (value & andMask) | (orMask & (~andMask & 0xff))));
|
|
1921
|
-
}))
|
|
1922
|
-
.then(() => {
|
|
1923
|
-
response(this.applicationLayer.encode(frame));
|
|
1924
|
-
})
|
|
1925
|
-
.catch((error) => {
|
|
1926
|
-
this.responseError(frame, response, error);
|
|
1927
|
-
});
|
|
1854
|
+
handleFC17(model, frame, response) {
|
|
1855
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1856
|
+
var _a;
|
|
1857
|
+
if (frame.data.length === 0) {
|
|
1858
|
+
if (model.reportServerId) {
|
|
1859
|
+
try {
|
|
1860
|
+
const { serverId = (_a = model.unit) !== null && _a !== void 0 ? _a : 1, runIndicatorStatus = true, additionalData = [] } = yield Promise.resolve(model.reportServerId());
|
|
1861
|
+
yield response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: [2 + additionalData.length, serverId, runIndicatorStatus ? 0xff : 0x00].concat(additionalData) })));
|
|
1862
|
+
}
|
|
1863
|
+
catch (error) {
|
|
1864
|
+
yield this.responseError(frame, response, error);
|
|
1865
|
+
}
|
|
1928
1866
|
}
|
|
1929
1867
|
else {
|
|
1930
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.
|
|
1868
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1931
1869
|
}
|
|
1932
1870
|
}
|
|
1933
|
-
|
|
1934
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1935
|
-
}
|
|
1936
|
-
}
|
|
1871
|
+
});
|
|
1937
1872
|
}
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
if (
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
Promise.resolve(this.model.writeMultipleRegisters
|
|
1960
|
-
? this.model.writeMultipleRegisters(address.write, value)
|
|
1961
|
-
: Promise.all(value.map((v, i) => this.model.writeSingleRegister(address.write + i, v))))
|
|
1962
|
-
.then(() => Promise.resolve(this.model.readHoldingRegisters(address.read, length.read)))
|
|
1963
|
-
.then((registers) => {
|
|
1964
|
-
const bufferTx = Buffer.alloc(length.read * 2);
|
|
1965
|
-
registers.forEach((register, index) => {
|
|
1966
|
-
bufferTx.writeUInt16BE(register, index * 2);
|
|
1967
|
-
});
|
|
1968
|
-
response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: [bufferTx.length].concat(Array.from(bufferTx)) })));
|
|
1969
|
-
})
|
|
1970
|
-
.catch((error) => {
|
|
1971
|
-
this.responseError(frame, response, error);
|
|
1972
|
-
});
|
|
1873
|
+
handleFC22(model, frame, response) {
|
|
1874
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1875
|
+
var _a;
|
|
1876
|
+
if (frame.data.length === 6) {
|
|
1877
|
+
if (model.maskWriteRegister || (model.readHoldingRegisters && model.writeSingleRegister)) {
|
|
1878
|
+
const bufferRx = Buffer.from(frame.data);
|
|
1879
|
+
const address = bufferRx.readUInt16BE(0);
|
|
1880
|
+
const andMask = bufferRx.readUInt16BE(2);
|
|
1881
|
+
const orMask = bufferRx.readUInt16BE(4);
|
|
1882
|
+
if (checkRange(address, (_a = model.getAddressRange) === null || _a === void 0 ? void 0 : _a.call(model).holdingRegisters)) {
|
|
1883
|
+
try {
|
|
1884
|
+
yield Promise.resolve(model.maskWriteRegister
|
|
1885
|
+
? model.maskWriteRegister(address, andMask, orMask)
|
|
1886
|
+
: Promise.resolve(model.readHoldingRegisters(address, 1)).then(([value]) => {
|
|
1887
|
+
return Promise.resolve(model.writeSingleRegister(address, (value & andMask) | (orMask & (~andMask & 0xff))));
|
|
1888
|
+
}));
|
|
1889
|
+
yield response(this.applicationLayer.encode(frame));
|
|
1890
|
+
}
|
|
1891
|
+
catch (error) {
|
|
1892
|
+
yield this.responseError(frame, response, error);
|
|
1893
|
+
}
|
|
1973
1894
|
}
|
|
1974
1895
|
else {
|
|
1975
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_ADDRESS));
|
|
1896
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_ADDRESS));
|
|
1976
1897
|
}
|
|
1977
1898
|
}
|
|
1978
1899
|
else {
|
|
1979
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.
|
|
1900
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1980
1901
|
}
|
|
1981
1902
|
}
|
|
1982
|
-
|
|
1983
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1984
|
-
}
|
|
1985
|
-
}
|
|
1903
|
+
});
|
|
1986
1904
|
}
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
1905
|
+
handleFC23(model, frame, response) {
|
|
1906
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1907
|
+
var _a;
|
|
1908
|
+
if (frame.data.length > 9 && frame.data.length === 9 + frame.data[8]) {
|
|
1909
|
+
if (model.readHoldingRegisters && (model.writeMultipleRegisters || model.writeSingleRegister)) {
|
|
1910
|
+
const bufferRx = Buffer.from(frame.data);
|
|
1911
|
+
const address = {
|
|
1912
|
+
read: bufferRx.readUInt16BE(0),
|
|
1913
|
+
write: bufferRx.readUInt16BE(4),
|
|
1914
|
+
};
|
|
1915
|
+
const length = {
|
|
1916
|
+
read: bufferRx.readUInt16BE(2),
|
|
1917
|
+
write: bufferRx.readUInt16BE(6),
|
|
1918
|
+
};
|
|
1919
|
+
const byteCount = bufferRx[8];
|
|
1920
|
+
if (length.read >= 0x0001 &&
|
|
1921
|
+
length.read <= 0x007d &&
|
|
1922
|
+
length.write >= 0x0001 &&
|
|
1923
|
+
length.write <= 0x0079 &&
|
|
1924
|
+
byteCount === length.write * 2) {
|
|
1925
|
+
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)) {
|
|
1926
|
+
const value = Array.from({ length: length.write }).map((_, index) => bufferRx.readUInt16BE(9 + index * 2));
|
|
1927
|
+
try {
|
|
1928
|
+
yield Promise.resolve(model.writeMultipleRegisters
|
|
1929
|
+
? model.writeMultipleRegisters(address.write, value)
|
|
1930
|
+
: Promise.all(value.map((v, i) => model.writeSingleRegister(address.write + i, v))));
|
|
1931
|
+
const registers = yield Promise.resolve(model.readHoldingRegisters(address.read, length.read));
|
|
1932
|
+
const bufferTx = Buffer.alloc(length.read * 2);
|
|
1933
|
+
registers.forEach((register, index) => {
|
|
1934
|
+
bufferTx.writeUInt16BE(register, index * 2);
|
|
1935
|
+
});
|
|
1936
|
+
yield response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: [bufferTx.length].concat(Array.from(bufferTx)) })));
|
|
1937
|
+
}
|
|
1938
|
+
catch (error) {
|
|
1939
|
+
yield this.responseError(frame, response, error);
|
|
1940
|
+
}
|
|
2008
1941
|
}
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
case 0x04: {
|
|
2012
|
-
if (objectID > 0x06 && objectID < 0x80) {
|
|
2013
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_ADDRESS));
|
|
2014
|
-
return;
|
|
1942
|
+
else {
|
|
1943
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_ADDRESS));
|
|
2015
1944
|
}
|
|
2016
|
-
break;
|
|
2017
1945
|
}
|
|
2018
|
-
|
|
2019
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_VALUE));
|
|
2020
|
-
return;
|
|
1946
|
+
else {
|
|
1947
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_VALUE));
|
|
2021
1948
|
}
|
|
2022
1949
|
}
|
|
2023
|
-
|
|
2024
|
-
.
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
objectID = 0x00;
|
|
2042
|
-
}
|
|
2043
|
-
const ids = [];
|
|
2044
|
-
let totalLength = 10;
|
|
2045
|
-
let lastID = 0;
|
|
2046
|
-
let conformityLevel = 0x81;
|
|
2047
|
-
for (const [id, value] of objects.entries()) {
|
|
2048
|
-
if (id < 0x00 || (id >= 0x07 && id <= 0x7f) || id > 0xff) {
|
|
2049
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.SERVER_DEVICE_FAILURE));
|
|
2050
|
-
return;
|
|
1950
|
+
else {
|
|
1951
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
});
|
|
1955
|
+
}
|
|
1956
|
+
handleFC43_14(model, frame, response) {
|
|
1957
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1958
|
+
if (frame.data.length === 3) {
|
|
1959
|
+
if (frame.data[0] === 0x0e && model.readDeviceIdentification) {
|
|
1960
|
+
const readDeviceIDCode = frame.data[1];
|
|
1961
|
+
let objectID = frame.data[2];
|
|
1962
|
+
switch (readDeviceIDCode) {
|
|
1963
|
+
case 0x01: {
|
|
1964
|
+
if (objectID > 0x02 || (objectID > 0x06 && objectID < 0x80)) {
|
|
1965
|
+
objectID = 0x00;
|
|
1966
|
+
}
|
|
1967
|
+
break;
|
|
2051
1968
|
}
|
|
2052
|
-
|
|
2053
|
-
|
|
1969
|
+
case 0x02: {
|
|
1970
|
+
if (objectID >= 0x80 || (objectID > 0x06 && objectID < 0x80)) {
|
|
1971
|
+
objectID = 0x00;
|
|
1972
|
+
}
|
|
1973
|
+
break;
|
|
2054
1974
|
}
|
|
2055
|
-
|
|
2056
|
-
|
|
1975
|
+
case 0x03: {
|
|
1976
|
+
if (objectID > 0x06 && objectID < 0x80) {
|
|
1977
|
+
objectID = 0x00;
|
|
1978
|
+
}
|
|
1979
|
+
break;
|
|
2057
1980
|
}
|
|
2058
|
-
|
|
2059
|
-
|
|
1981
|
+
case 0x04: {
|
|
1982
|
+
if (objectID > 0x06 && objectID < 0x80) {
|
|
1983
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_ADDRESS));
|
|
1984
|
+
return;
|
|
1985
|
+
}
|
|
1986
|
+
break;
|
|
2060
1987
|
}
|
|
2061
|
-
|
|
2062
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.
|
|
1988
|
+
default: {
|
|
1989
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_VALUE));
|
|
2063
1990
|
return;
|
|
2064
1991
|
}
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
1992
|
+
}
|
|
1993
|
+
try {
|
|
1994
|
+
const identification = yield Promise.resolve(model.readDeviceIdentification());
|
|
1995
|
+
const objects = new Map([
|
|
1996
|
+
[0x00, 'null'],
|
|
1997
|
+
[0x01, 'null'],
|
|
1998
|
+
[0x02, 'null'],
|
|
1999
|
+
]);
|
|
2000
|
+
for (const [key, value] of Object.entries(identification)) {
|
|
2001
|
+
const id = parseInt(key);
|
|
2002
|
+
if (!isNaN(id) && id >= 0 && id <= 255) {
|
|
2003
|
+
objects.set(id, value);
|
|
2071
2004
|
}
|
|
2072
2005
|
}
|
|
2073
|
-
|
|
2074
|
-
totalLength += value.length + 2;
|
|
2075
|
-
ids.push(id);
|
|
2006
|
+
if (!objects.has(objectID)) {
|
|
2076
2007
|
if (readDeviceIDCode === 0x04) {
|
|
2077
|
-
|
|
2008
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_DATA_ADDRESS));
|
|
2009
|
+
return;
|
|
2078
2010
|
}
|
|
2011
|
+
objectID = 0x00;
|
|
2079
2012
|
}
|
|
2013
|
+
const ids = [];
|
|
2014
|
+
let totalLength = 10;
|
|
2015
|
+
let lastID = 0;
|
|
2016
|
+
let conformityLevel = 0x81;
|
|
2017
|
+
for (const [id, value] of objects.entries()) {
|
|
2018
|
+
if (id < 0x00 || (id >= 0x07 && id <= 0x7f) || id > 0xff) {
|
|
2019
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.SERVER_DEVICE_FAILURE));
|
|
2020
|
+
return;
|
|
2021
|
+
}
|
|
2022
|
+
if (id > 0x02) {
|
|
2023
|
+
conformityLevel = 0x82;
|
|
2024
|
+
}
|
|
2025
|
+
if (id > 0x80) {
|
|
2026
|
+
conformityLevel = 0x83;
|
|
2027
|
+
}
|
|
2028
|
+
if (objectID > id) {
|
|
2029
|
+
continue;
|
|
2030
|
+
}
|
|
2031
|
+
if (value.length > 245) {
|
|
2032
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.SERVER_DEVICE_FAILURE));
|
|
2033
|
+
return;
|
|
2034
|
+
}
|
|
2035
|
+
if (lastID !== 0) {
|
|
2036
|
+
continue;
|
|
2037
|
+
}
|
|
2038
|
+
if (value.length + 2 > 253 - totalLength) {
|
|
2039
|
+
if (lastID === 0) {
|
|
2040
|
+
lastID = id;
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
else {
|
|
2044
|
+
totalLength += value.length + 2;
|
|
2045
|
+
ids.push(id);
|
|
2046
|
+
if (readDeviceIDCode === 0x04) {
|
|
2047
|
+
break;
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
ids.sort((a, b) => a - b);
|
|
2052
|
+
yield response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: [0x0e, readDeviceIDCode, conformityLevel, lastID === 0 ? 0x00 : 0xff, lastID, ids.length].concat(ids
|
|
2053
|
+
.map((id) => {
|
|
2054
|
+
const value = objects.get(id);
|
|
2055
|
+
return [id, value.length].concat(Array.from(Buffer.from(value)));
|
|
2056
|
+
})
|
|
2057
|
+
.flat()) })));
|
|
2080
2058
|
}
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
})
|
|
2089
|
-
.catch((error) => {
|
|
2090
|
-
this.responseError(frame, response, error);
|
|
2091
|
-
});
|
|
2092
|
-
}
|
|
2093
|
-
else {
|
|
2094
|
-
this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
2059
|
+
catch (error) {
|
|
2060
|
+
yield this.responseError(frame, response, error);
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
else {
|
|
2064
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
2065
|
+
}
|
|
2095
2066
|
}
|
|
2096
|
-
}
|
|
2067
|
+
});
|
|
2097
2068
|
}
|
|
2098
2069
|
responseError(frame, response, error) {
|
|
2099
|
-
|
|
2070
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2071
|
+
yield response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { fc: frame.fc | 0x80, data: [getCodeByError(error)] })));
|
|
2072
|
+
});
|
|
2073
|
+
}
|
|
2074
|
+
_drain() {
|
|
2075
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2076
|
+
if (this._processing || this._queue.length === 0) {
|
|
2077
|
+
return;
|
|
2078
|
+
}
|
|
2079
|
+
this._processing = true;
|
|
2080
|
+
const { frame, response: _response } = this._queue.shift();
|
|
2081
|
+
try {
|
|
2082
|
+
yield this._processFrame(frame, _response);
|
|
2083
|
+
}
|
|
2084
|
+
catch (error) {
|
|
2085
|
+
this.emit('error', error);
|
|
2086
|
+
}
|
|
2087
|
+
finally {
|
|
2088
|
+
this._processing = false;
|
|
2089
|
+
if (this._queue.length > 0) {
|
|
2090
|
+
setImmediate(() => this._drain());
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
});
|
|
2094
|
+
}
|
|
2095
|
+
_processFrame(frame, _response) {
|
|
2096
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2097
|
+
const response = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
2098
|
+
if (frame.unit === 0x00) {
|
|
2099
|
+
return;
|
|
2100
|
+
}
|
|
2101
|
+
try {
|
|
2102
|
+
yield _response(data);
|
|
2103
|
+
}
|
|
2104
|
+
catch (error) { }
|
|
2105
|
+
});
|
|
2106
|
+
for (const model of frame.unit === 0x00 ? this.models.values() : [this.models.get(frame.unit)]) {
|
|
2107
|
+
const res = yield this._intercept(model, frame, response);
|
|
2108
|
+
if (res !== 'break') {
|
|
2109
|
+
yield this._handleFC(model, frame, response);
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
});
|
|
2113
|
+
}
|
|
2114
|
+
_intercept(model, frame, response) {
|
|
2115
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2116
|
+
if (model.interceptor) {
|
|
2117
|
+
try {
|
|
2118
|
+
const data = yield model.interceptor(frame.fc, frame.data);
|
|
2119
|
+
if (data) {
|
|
2120
|
+
yield response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data })));
|
|
2121
|
+
return 'break';
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
catch (error) {
|
|
2125
|
+
yield this.responseError(frame, response, error);
|
|
2126
|
+
return 'break';
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2129
|
+
});
|
|
2130
|
+
}
|
|
2131
|
+
_handleFC(model, frame, response) {
|
|
2132
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2133
|
+
switch (frame.fc) {
|
|
2134
|
+
case 0x01: {
|
|
2135
|
+
yield this.handleFC1(model, frame, response);
|
|
2136
|
+
break;
|
|
2137
|
+
}
|
|
2138
|
+
case 0x02: {
|
|
2139
|
+
yield this.handleFC2(model, frame, response);
|
|
2140
|
+
break;
|
|
2141
|
+
}
|
|
2142
|
+
case 0x03: {
|
|
2143
|
+
yield this.handleFC3(model, frame, response);
|
|
2144
|
+
break;
|
|
2145
|
+
}
|
|
2146
|
+
case 0x04: {
|
|
2147
|
+
yield this.handleFC4(model, frame, response);
|
|
2148
|
+
break;
|
|
2149
|
+
}
|
|
2150
|
+
case 0x05: {
|
|
2151
|
+
yield this.handleFC5(model, frame, response);
|
|
2152
|
+
break;
|
|
2153
|
+
}
|
|
2154
|
+
case 0x06: {
|
|
2155
|
+
yield this.handleFC6(model, frame, response);
|
|
2156
|
+
break;
|
|
2157
|
+
}
|
|
2158
|
+
case 0x0f: {
|
|
2159
|
+
yield this.handleFC15(model, frame, response);
|
|
2160
|
+
break;
|
|
2161
|
+
}
|
|
2162
|
+
case 0x10: {
|
|
2163
|
+
yield this.handleFC16(model, frame, response);
|
|
2164
|
+
break;
|
|
2165
|
+
}
|
|
2166
|
+
case 0x11: {
|
|
2167
|
+
yield this.handleFC17(model, frame, response);
|
|
2168
|
+
break;
|
|
2169
|
+
}
|
|
2170
|
+
case 0x16: {
|
|
2171
|
+
yield this.handleFC22(model, frame, response);
|
|
2172
|
+
break;
|
|
2173
|
+
}
|
|
2174
|
+
case 0x17: {
|
|
2175
|
+
yield this.handleFC23(model, frame, response);
|
|
2176
|
+
break;
|
|
2177
|
+
}
|
|
2178
|
+
case 0x2b: {
|
|
2179
|
+
yield this.handleFC43_14(model, frame, response);
|
|
2180
|
+
break;
|
|
2181
|
+
}
|
|
2182
|
+
default: {
|
|
2183
|
+
yield this.responseError(frame, response, getErrorByCode(exports.ErrorCode.ILLEGAL_FUNCTION));
|
|
2184
|
+
break;
|
|
2185
|
+
}
|
|
2186
|
+
}
|
|
2187
|
+
});
|
|
2188
|
+
}
|
|
2189
|
+
add(model) {
|
|
2190
|
+
var _a;
|
|
2191
|
+
this.models.set((_a = model.unit) !== null && _a !== void 0 ? _a : 1, model);
|
|
2192
|
+
}
|
|
2193
|
+
remove(unit) {
|
|
2194
|
+
this.models.delete(unit);
|
|
2100
2195
|
}
|
|
2101
2196
|
open(...args) {
|
|
2102
2197
|
return this.physicalLayer.open(...args);
|