UNPKG

modbus-connect

Version:

Modbus RTU over Web Serial and Node.js SerialPort

82 lines (66 loc) 3.07 kB
// function-codes/SGM130/read-device-comment.js const FUNCTION_CODE = 0x14; const MAX_CHANNEL = 255; const MAX_COMMENT_LENGTH = 16; const REQUEST_SIZE = 2; const RESPONSE_HEADER_SIZE = 3; // Оптимизированная таблица символов как Uint8Array (индекс = код символа) const SYMBOL_TABLE = new Uint8Array(256).fill(32); // Заполняем пробелами по умолчанию // Инициализация таблицы символов (выполняется один раз при загрузке модуля) (function initSymbolTable() { // Цифры и латинские буквы const symbols = ' 0123456789ABCDEFGHIJKLMNOPQRSTUVXYZ'; for (let i = 0; i < symbols.length; i++) { SYMBOL_TABLE[i] = symbols.charCodeAt(i); } // Русские буквы const cyrillic = 'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ'; for (let i = 0; i < cyrillic.length; i++) { SYMBOL_TABLE[37 + i] = cyrillic.charCodeAt(i); } })(); function buildReadDeviceCommentRequest(channel) { // Быстрая проверка канала if ((channel | 0) !== channel || channel < 0 || channel > MAX_CHANNEL) { throw new RangeError(`Channel must be 0-${MAX_CHANNEL}`); } const request = new Uint8Array(REQUEST_SIZE); request[0] = FUNCTION_CODE; request[1] = channel; return request; } function parseReadDeviceCommentResponse(pdu) { if (!(pdu instanceof Uint8Array)) { throw new TypeError('PDU must be Uint8Array'); } const pduLength = pdu.length; if (pduLength < RESPONSE_HEADER_SIZE) { throw new Error(`PDU too short: expected at least ${RESPONSE_HEADER_SIZE} bytes`); } if (pdu[0] !== FUNCTION_CODE) { throw new Error(`Invalid function code: expected 0x${FUNCTION_CODE.toString(16)}, got 0x${pdu[0].toString(16)}`); } const channel = pdu[1]; const length = pdu[2]; if (length > MAX_COMMENT_LENGTH) { throw new Error(`Comment too long: max ${MAX_COMMENT_LENGTH} bytes, got ${length}`); } if (pduLength < RESPONSE_HEADER_SIZE + length) { throw new Error(`PDU length mismatch: expected ${RESPONSE_HEADER_SIZE + length} bytes, got ${pduLength}`); } // Оптимизированное чтение и преобразование данных const raw = new Uint8Array(pdu.buffer, pdu.byteOffset + RESPONSE_HEADER_SIZE, length); const commentBuffer = new Uint8Array(length); for (let i = 0; i < length; i++) { commentBuffer[i] = SYMBOL_TABLE[raw[i]] || 32; // 32 = пробел } return { channel, raw: Array.from(raw), // Конвертируем в обычный массив для совместимости comment: new TextDecoder('windows-1251').decode(commentBuffer) }; } module.exports = { buildReadDeviceCommentRequest, parseReadDeviceCommentResponse };