UNPKG

modbus-connect

Version:

Modbus RTU over Web Serial and Node.js SerialPort

60 lines (49 loc) 2.42 kB
// function-codes/SGM130/read-file-length.js const FUNCTION_CODE = 0x52; const MAX_FILENAME_LENGTH = 250; const RESPONSE_SIZE = 5; const FILE_NOT_FOUND = 0xFFFFFFFF; /** * Формирует запрос для функции 0x52 (Read File Length). * @param {string} filename - Имя файла ASCII (без завершающего нуля) * @returns {Uint8Array} - PDU запроса * @throws {Error} Если имя файла слишком длинное */ function buildReadFileLengthRequest(filename) { const nameBytes = new TextEncoder().encode(filename); const nameLength = nameBytes.length; if (nameLength > MAX_FILENAME_LENGTH) { throw new Error(`Filename too long, max ${MAX_FILENAME_LENGTH} bytes allowed`); } // Оптимальное выделение памяти с учетом всех частей PDU const pdu = new Uint8Array(2 + nameLength + 1); const view = new DataView(pdu.buffer); // Заполняем PDU view.setUint8(0, FUNCTION_CODE); view.setUint8(1, nameLength); pdu.set(nameBytes, 2); view.setUint8(pdu.length - 1, 0x00); // завершающий нулевой байт return pdu; } /** * Парсит ответ функции 0x52. * @param {Uint8Array} responsePdu - PDU ответа * @returns {number} - длина файла или -1, если файл отсутствует * @throws {Error} При неверном формате ответа */ function parseReadFileLengthResponse(responsePdu) { if (!(responsePdu instanceof Uint8Array)) { throw new TypeError('Response must be Uint8Array'); } if (responsePdu.length !== RESPONSE_SIZE || responsePdu[0] !== FUNCTION_CODE) { throw new Error(`Invalid response: expected ${RESPONSE_SIZE} bytes starting with 0x${FUNCTION_CODE.toString(16)}, got ${responsePdu.length} bytes starting with 0x${responsePdu[0]?.toString(16) || 'null'}`); } // Используем DataView для эффективного чтения 32-битного значения const view = new DataView(responsePdu.buffer, responsePdu.byteOffset); const length = view.getUint32(1, false); // big-endian return length === FILE_NOT_FOUND ? -1 : length; } module.exports = { buildReadFileLengthRequest, parseReadFileLengthResponse };