UNPKG

modbus-connect

Version:

Modbus RTU over Web Serial and Node.js SerialPort

68 lines (60 loc) 2 kB
// packet-builder.js const crcFns = require('./utils/crc.js'); const { isUint8Array, concatUint8Arrays, toHex, sliceUint8Array } = require('./utils/utils.js'); /** * Формирует ADU-пакет Modbus RTU * @param {number} slaveAddress - адрес устройства (0–247) * @param {Uint8Array} pdu - PDU без slaveAddress и CRC * @returns {Uint8Array} - полный ADU с CRC */ function buildPacket(slaveAddress, pdu, crcFn = crcFns.crc16Modbus) { if (!isUint8Array(pdu)) { throw new Error('PDU must be a Uint8Array'); } const aduWithoutCrc = concatUint8Arrays([new Uint8Array([slaveAddress]), pdu]); const crc = crcFn(aduWithoutCrc); // возвращает Uint8Array из 2 байт return concatUint8Arrays([aduWithoutCrc, crc]); } /** * Разбирает ADU-пакет и проверяет CRC * @param {Uint8Array} packet - полный пакет * @returns {Object} - { slaveAddress, pdu } */ function parsePacket(packet, crcFn = crcFns.crc16Modbus) { if (!isUint8Array(packet) || packet.length < 4) { throw new Error('Invalid packet'); } const receivedCrc = sliceUint8Array(packet, -2); // последние 2 байта const aduWithoutCrc = sliceUint8Array(packet, 0, -2); const calculatedCrc = crcFn(aduWithoutCrc); if (!arraysEqual(receivedCrc, calculatedCrc)) { throw new Error( `CRC mismatch: received 0x${toHex(receivedCrc)}, calculated 0x${toHex(calculatedCrc)}` ); } const slaveAddress = packet[0]; const pdu = sliceUint8Array(packet, 1, -2); return { slaveAddress, pdu }; } /** * Сравнивает два Uint8Array * @param {Uint8Array} a * @param {Uint8Array} b * @returns {boolean} */ function arraysEqual(a, b) { if (a.length !== b.length) return false; for (let i = 0; i < a.length; i++) { if (a[i] !== b[i]) return false; } return true; } module.exports = { buildPacket, parsePacket };