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