modbus-connect
Version:
Modbus RTU over Web Serial and Node.js SerialPort
57 lines (47 loc) • 2.23 kB
JavaScript
// function-codes/SGM130/openFile.js
const FUNCTION_CODE = 0x55;
const MAX_FILENAME_LENGTH = 250;
const RESPONSE_SIZE = 5;
/**
* Формирует запрос для функции 0x55 (Open File).
* @param {string} filename - Имя файла ASCII (без завершающего нуля)
* @returns {Uint8Array} - PDU запроса
* @throws {Error} Если имя файла слишком длинное
*/
function buildOpenFileRequest(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`);
}
// Создаем буфер оптимального размера
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;
}
/**
* Парсит ответ функции 0x55 (Open File).
* @param {Uint8Array} responsePdu - PDU ответа
* @returns {number} - длина файла (4 байта, big-endian)
* @throws {Error} При неверном формате ответа
*/
function parseOpenFileResponse(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);
return view.getUint32(1, false); // big-endian
}
module.exports = {
buildOpenFileRequest,
parseOpenFileResponse
};