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.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
|
}
|
|
@@ -1502,14 +1519,8 @@ class ModbusSlave extends EventEmitter {
|
|
|
1502
1519
|
get destroyed() {
|
|
1503
1520
|
return this.physicalLayer.destroyed;
|
|
1504
1521
|
}
|
|
1505
|
-
constructor(
|
|
1522
|
+
constructor(applicationLayer, physicalLayer) {
|
|
1506
1523
|
super();
|
|
1507
|
-
Object.defineProperty(this, "model", {
|
|
1508
|
-
enumerable: true,
|
|
1509
|
-
configurable: true,
|
|
1510
|
-
writable: true,
|
|
1511
|
-
value: model
|
|
1512
|
-
});
|
|
1513
1524
|
Object.defineProperty(this, "applicationLayer", {
|
|
1514
1525
|
enumerable: true,
|
|
1515
1526
|
configurable: true,
|
|
@@ -1522,96 +1533,31 @@ class ModbusSlave extends EventEmitter {
|
|
|
1522
1533
|
writable: true,
|
|
1523
1534
|
value: physicalLayer
|
|
1524
1535
|
});
|
|
1525
|
-
Object.defineProperty(this, "
|
|
1536
|
+
Object.defineProperty(this, "models", {
|
|
1526
1537
|
enumerable: true,
|
|
1527
1538
|
configurable: true,
|
|
1528
1539
|
writable: true,
|
|
1529
|
-
value:
|
|
1540
|
+
value: new Map()
|
|
1530
1541
|
});
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
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
|
+
});
|
|
1554
|
+
applicationLayer.on('framing', (frame, _response) => {
|
|
1555
|
+
if (!(frame.unit === 0x00 || this.models.has(frame.unit))) {
|
|
1536
1556
|
return;
|
|
1537
1557
|
}
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
}
|
|
1542
|
-
try {
|
|
1543
|
-
yield _response(data);
|
|
1544
|
-
}
|
|
1545
|
-
catch (error) { }
|
|
1546
|
-
});
|
|
1547
|
-
if (model.interceptor) {
|
|
1548
|
-
try {
|
|
1549
|
-
const data = yield model.interceptor(frame.fc, frame.data);
|
|
1550
|
-
if (data) {
|
|
1551
|
-
response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data })));
|
|
1552
|
-
return;
|
|
1553
|
-
}
|
|
1554
|
-
}
|
|
1555
|
-
catch (error) {
|
|
1556
|
-
this.responseError(frame, response, error);
|
|
1557
|
-
return;
|
|
1558
|
-
}
|
|
1559
|
-
}
|
|
1560
|
-
switch (frame.fc) {
|
|
1561
|
-
case 0x01: {
|
|
1562
|
-
this.handleFC1(frame, response);
|
|
1563
|
-
break;
|
|
1564
|
-
}
|
|
1565
|
-
case 0x02: {
|
|
1566
|
-
this.handleFC2(frame, response);
|
|
1567
|
-
break;
|
|
1568
|
-
}
|
|
1569
|
-
case 0x03: {
|
|
1570
|
-
this.handleFC3(frame, response);
|
|
1571
|
-
break;
|
|
1572
|
-
}
|
|
1573
|
-
case 0x04: {
|
|
1574
|
-
this.handleFC4(frame, response);
|
|
1575
|
-
break;
|
|
1576
|
-
}
|
|
1577
|
-
case 0x05: {
|
|
1578
|
-
this.handleFC5(frame, response);
|
|
1579
|
-
break;
|
|
1580
|
-
}
|
|
1581
|
-
case 0x06: {
|
|
1582
|
-
this.handleFC6(frame, response);
|
|
1583
|
-
break;
|
|
1584
|
-
}
|
|
1585
|
-
case 0x0f: {
|
|
1586
|
-
this.handleFC15(frame, response);
|
|
1587
|
-
break;
|
|
1588
|
-
}
|
|
1589
|
-
case 0x10: {
|
|
1590
|
-
this.handleFC16(frame, response);
|
|
1591
|
-
break;
|
|
1592
|
-
}
|
|
1593
|
-
case 0x11: {
|
|
1594
|
-
this.handleFC17(frame, response);
|
|
1595
|
-
break;
|
|
1596
|
-
}
|
|
1597
|
-
case 0x16: {
|
|
1598
|
-
this.handleFC22(frame, response);
|
|
1599
|
-
break;
|
|
1600
|
-
}
|
|
1601
|
-
case 0x17: {
|
|
1602
|
-
this.handleFC23(frame, response);
|
|
1603
|
-
break;
|
|
1604
|
-
}
|
|
1605
|
-
case 0x2b: {
|
|
1606
|
-
this.handleFC43_14(frame, response);
|
|
1607
|
-
break;
|
|
1608
|
-
}
|
|
1609
|
-
default: {
|
|
1610
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1611
|
-
break;
|
|
1612
|
-
}
|
|
1613
|
-
}
|
|
1614
|
-
}));
|
|
1558
|
+
this._queue.push({ frame, response: _response });
|
|
1559
|
+
this._drain();
|
|
1560
|
+
});
|
|
1615
1561
|
physicalLayer.on('error', (error) => {
|
|
1616
1562
|
this.emit('error', error);
|
|
1617
1563
|
});
|
|
@@ -1619,482 +1565,631 @@ class ModbusSlave extends EventEmitter {
|
|
|
1619
1565
|
this.emit('close');
|
|
1620
1566
|
});
|
|
1621
1567
|
}
|
|
1622
|
-
handleFC1(frame, response) {
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
if (
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
if (
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1568
|
+
handleFC1(model, frame, response) {
|
|
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
|
+
}
|
|
1644
1595
|
}
|
|
1645
1596
|
else {
|
|
1646
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.
|
|
1597
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
|
|
1647
1598
|
}
|
|
1648
1599
|
}
|
|
1649
1600
|
else {
|
|
1650
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.
|
|
1601
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1651
1602
|
}
|
|
1652
1603
|
}
|
|
1653
|
-
|
|
1654
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1655
|
-
}
|
|
1656
|
-
}
|
|
1604
|
+
});
|
|
1657
1605
|
}
|
|
1658
|
-
handleFC2(frame, response) {
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
if (
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
if (
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1606
|
+
handleFC2(model, frame, response) {
|
|
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
|
+
}
|
|
1680
1633
|
}
|
|
1681
1634
|
else {
|
|
1682
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.
|
|
1635
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
|
|
1683
1636
|
}
|
|
1684
1637
|
}
|
|
1685
1638
|
else {
|
|
1686
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.
|
|
1639
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1687
1640
|
}
|
|
1688
1641
|
}
|
|
1689
|
-
|
|
1690
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1691
|
-
}
|
|
1692
|
-
}
|
|
1642
|
+
});
|
|
1693
1643
|
}
|
|
1694
|
-
handleFC3(frame, response) {
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
if (
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
if (
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1644
|
+
handleFC3(model, frame, response) {
|
|
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
|
+
}
|
|
1714
1669
|
}
|
|
1715
1670
|
else {
|
|
1716
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.
|
|
1671
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
|
|
1717
1672
|
}
|
|
1718
1673
|
}
|
|
1719
1674
|
else {
|
|
1720
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.
|
|
1675
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1721
1676
|
}
|
|
1722
1677
|
}
|
|
1723
|
-
|
|
1724
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1725
|
-
}
|
|
1726
|
-
}
|
|
1678
|
+
});
|
|
1727
1679
|
}
|
|
1728
|
-
handleFC4(frame, response) {
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
if (
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
if (
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1680
|
+
handleFC4(model, frame, response) {
|
|
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
|
+
}
|
|
1748
1705
|
}
|
|
1749
1706
|
else {
|
|
1750
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.
|
|
1707
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
|
|
1751
1708
|
}
|
|
1752
1709
|
}
|
|
1753
1710
|
else {
|
|
1754
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.
|
|
1711
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1755
1712
|
}
|
|
1756
1713
|
}
|
|
1757
|
-
|
|
1758
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1759
|
-
}
|
|
1760
|
-
}
|
|
1714
|
+
});
|
|
1761
1715
|
}
|
|
1762
|
-
handleFC5(frame, response) {
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
if (
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
if (
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1716
|
+
handleFC5(model, frame, response) {
|
|
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
|
+
}
|
|
1778
1737
|
}
|
|
1779
1738
|
else {
|
|
1780
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.
|
|
1739
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
|
|
1781
1740
|
}
|
|
1782
1741
|
}
|
|
1783
1742
|
else {
|
|
1784
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.
|
|
1743
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1785
1744
|
}
|
|
1786
1745
|
}
|
|
1787
|
-
|
|
1788
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1789
|
-
}
|
|
1790
|
-
}
|
|
1746
|
+
});
|
|
1791
1747
|
}
|
|
1792
|
-
handleFC6(frame, response) {
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
if (
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
if (
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1748
|
+
handleFC6(model, frame, response) {
|
|
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
|
+
}
|
|
1808
1769
|
}
|
|
1809
1770
|
else {
|
|
1810
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.
|
|
1771
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
|
|
1811
1772
|
}
|
|
1812
1773
|
}
|
|
1813
1774
|
else {
|
|
1814
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.
|
|
1775
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1815
1776
|
}
|
|
1816
1777
|
}
|
|
1817
|
-
|
|
1818
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1819
|
-
}
|
|
1820
|
-
}
|
|
1778
|
+
});
|
|
1821
1779
|
}
|
|
1822
|
-
handleFC15(frame, response) {
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
if (
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
if (
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1780
|
+
handleFC15(model, frame, response) {
|
|
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
|
+
}
|
|
1842
1805
|
}
|
|
1843
1806
|
else {
|
|
1844
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.
|
|
1807
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
|
|
1845
1808
|
}
|
|
1846
1809
|
}
|
|
1847
1810
|
else {
|
|
1848
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.
|
|
1811
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1849
1812
|
}
|
|
1850
1813
|
}
|
|
1851
|
-
|
|
1852
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1853
|
-
}
|
|
1854
|
-
}
|
|
1814
|
+
});
|
|
1855
1815
|
}
|
|
1856
|
-
handleFC16(frame, response) {
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
if (
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
if (
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1816
|
+
handleFC16(model, frame, response) {
|
|
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
|
+
}
|
|
1876
1841
|
}
|
|
1877
1842
|
else {
|
|
1878
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.
|
|
1843
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
|
|
1879
1844
|
}
|
|
1880
1845
|
}
|
|
1881
1846
|
else {
|
|
1882
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.
|
|
1847
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1883
1848
|
}
|
|
1884
1849
|
}
|
|
1885
|
-
|
|
1886
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1887
|
-
}
|
|
1888
|
-
}
|
|
1889
|
-
}
|
|
1890
|
-
handleFC17(frame, response) {
|
|
1891
|
-
if (frame.data.length === 0) {
|
|
1892
|
-
if (this.model.reportServerId) {
|
|
1893
|
-
Promise.resolve(this.model.reportServerId())
|
|
1894
|
-
.then(({ serverId = this.unit, runIndicatorStatus = true, additionalData = [] }) => {
|
|
1895
|
-
response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: [2 + additionalData.length, serverId, runIndicatorStatus ? 0xff : 0x00].concat(additionalData) })));
|
|
1896
|
-
})
|
|
1897
|
-
.catch((error) => {
|
|
1898
|
-
this.responseError(frame, response, error);
|
|
1899
|
-
});
|
|
1900
|
-
}
|
|
1901
|
-
else {
|
|
1902
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1903
|
-
}
|
|
1904
|
-
}
|
|
1850
|
+
});
|
|
1905
1851
|
}
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
if (
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
return Promise.resolve(this.model.writeSingleRegister(address, (value & andMask) | (orMask & (~andMask & 0xff))));
|
|
1919
|
-
}))
|
|
1920
|
-
.then(() => {
|
|
1921
|
-
response(this.applicationLayer.encode(frame));
|
|
1922
|
-
})
|
|
1923
|
-
.catch((error) => {
|
|
1924
|
-
this.responseError(frame, response, error);
|
|
1925
|
-
});
|
|
1852
|
+
handleFC17(model, frame, response) {
|
|
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
|
+
}
|
|
1926
1864
|
}
|
|
1927
1865
|
else {
|
|
1928
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.
|
|
1866
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1929
1867
|
}
|
|
1930
1868
|
}
|
|
1931
|
-
|
|
1932
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1933
|
-
}
|
|
1934
|
-
}
|
|
1869
|
+
});
|
|
1935
1870
|
}
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
if (
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
Promise.resolve(this.model.writeMultipleRegisters
|
|
1958
|
-
? this.model.writeMultipleRegisters(address.write, value)
|
|
1959
|
-
: Promise.all(value.map((v, i) => this.model.writeSingleRegister(address.write + i, v))))
|
|
1960
|
-
.then(() => Promise.resolve(this.model.readHoldingRegisters(address.read, length.read)))
|
|
1961
|
-
.then((registers) => {
|
|
1962
|
-
const bufferTx = Buffer.alloc(length.read * 2);
|
|
1963
|
-
registers.forEach((register, index) => {
|
|
1964
|
-
bufferTx.writeUInt16BE(register, index * 2);
|
|
1965
|
-
});
|
|
1966
|
-
response(this.applicationLayer.encode(Object.assign(Object.assign({}, frame), { data: [bufferTx.length].concat(Array.from(bufferTx)) })));
|
|
1967
|
-
})
|
|
1968
|
-
.catch((error) => {
|
|
1969
|
-
this.responseError(frame, response, error);
|
|
1970
|
-
});
|
|
1871
|
+
handleFC22(model, frame, response) {
|
|
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
|
+
}
|
|
1971
1892
|
}
|
|
1972
1893
|
else {
|
|
1973
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_ADDRESS));
|
|
1894
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_ADDRESS));
|
|
1974
1895
|
}
|
|
1975
1896
|
}
|
|
1976
1897
|
else {
|
|
1977
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.
|
|
1898
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1978
1899
|
}
|
|
1979
1900
|
}
|
|
1980
|
-
|
|
1981
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1982
|
-
}
|
|
1983
|
-
}
|
|
1901
|
+
});
|
|
1984
1902
|
}
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
1903
|
+
handleFC23(model, frame, response) {
|
|
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
|
+
}
|
|
2006
1939
|
}
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
case 0x04: {
|
|
2010
|
-
if (objectID > 0x06 && objectID < 0x80) {
|
|
2011
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_ADDRESS));
|
|
2012
|
-
return;
|
|
1940
|
+
else {
|
|
1941
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_ADDRESS));
|
|
2013
1942
|
}
|
|
2014
|
-
break;
|
|
2015
1943
|
}
|
|
2016
|
-
|
|
2017
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
|
|
2018
|
-
return;
|
|
1944
|
+
else {
|
|
1945
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
|
|
2019
1946
|
}
|
|
2020
1947
|
}
|
|
2021
|
-
|
|
2022
|
-
.
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
objectID = 0x00;
|
|
2040
|
-
}
|
|
2041
|
-
const ids = [];
|
|
2042
|
-
let totalLength = 10;
|
|
2043
|
-
let lastID = 0;
|
|
2044
|
-
let conformityLevel = 0x81;
|
|
2045
|
-
for (const [id, value] of objects.entries()) {
|
|
2046
|
-
if (id < 0x00 || (id >= 0x07 && id <= 0x7f) || id > 0xff) {
|
|
2047
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.SERVER_DEVICE_FAILURE));
|
|
2048
|
-
return;
|
|
1948
|
+
else {
|
|
1949
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_FUNCTION));
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
});
|
|
1953
|
+
}
|
|
1954
|
+
handleFC43_14(model, frame, response) {
|
|
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;
|
|
2049
1966
|
}
|
|
2050
|
-
|
|
2051
|
-
|
|
1967
|
+
case 0x02: {
|
|
1968
|
+
if (objectID >= 0x80 || (objectID > 0x06 && objectID < 0x80)) {
|
|
1969
|
+
objectID = 0x00;
|
|
1970
|
+
}
|
|
1971
|
+
break;
|
|
2052
1972
|
}
|
|
2053
|
-
|
|
2054
|
-
|
|
1973
|
+
case 0x03: {
|
|
1974
|
+
if (objectID > 0x06 && objectID < 0x80) {
|
|
1975
|
+
objectID = 0x00;
|
|
1976
|
+
}
|
|
1977
|
+
break;
|
|
2055
1978
|
}
|
|
2056
|
-
|
|
2057
|
-
|
|
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;
|
|
2058
1985
|
}
|
|
2059
|
-
|
|
2060
|
-
this.responseError(frame, response, getErrorByCode(ErrorCode.
|
|
1986
|
+
default: {
|
|
1987
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_VALUE));
|
|
2061
1988
|
return;
|
|
2062
1989
|
}
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
1990
|
+
}
|
|
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);
|
|
2069
2002
|
}
|
|
2070
2003
|
}
|
|
2071
|
-
|
|
2072
|
-
totalLength += value.length + 2;
|
|
2073
|
-
ids.push(id);
|
|
2004
|
+
if (!objects.has(objectID)) {
|
|
2074
2005
|
if (readDeviceIDCode === 0x04) {
|
|
2075
|
-
|
|
2006
|
+
yield this.responseError(frame, response, getErrorByCode(ErrorCode.ILLEGAL_DATA_ADDRESS));
|
|
2007
|
+
return;
|
|
2076
2008
|
}
|
|
2009
|
+
objectID = 0x00;
|
|
2077
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
|
+
}
|
|
2047
|
+
}
|
|
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()) })));
|
|
2078
2056
|
}
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
})
|
|
2087
|
-
.catch((error) => {
|
|
2088
|
-
this.responseError(frame, response, error);
|
|
2089
|
-
});
|
|
2090
|
-
}
|
|
2091
|
-
else {
|
|
2092
|
-
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
|
+
}
|
|
2093
2064
|
}
|
|
2094
|
-
}
|
|
2065
|
+
});
|
|
2095
2066
|
}
|
|
2096
2067
|
responseError(frame, response, error) {
|
|
2097
|
-
|
|
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
|
+
});
|
|
2186
|
+
}
|
|
2187
|
+
add(model) {
|
|
2188
|
+
var _a;
|
|
2189
|
+
this.models.set((_a = model.unit) !== null && _a !== void 0 ? _a : 1, model);
|
|
2190
|
+
}
|
|
2191
|
+
remove(unit) {
|
|
2192
|
+
this.models.delete(unit);
|
|
2098
2193
|
}
|
|
2099
2194
|
open(...args) {
|
|
2100
2195
|
return this.physicalLayer.open(...args);
|