UNPKG

modbus-connect

Version:

Modbus RTU over Web Serial and Node.js SerialPort

88 lines (72 loc) 3.1 kB
// function-codes/read-device-identification.js const FUNCTION_CODE = 0x2B; const MEI_TYPE = 0x0E; const MIN_RESPONSE_SIZE = 7; const TEXT_ENCODING = 'windows-1251'; // Создаем декодер один раз для повторного использования const TEXT_DECODER = new TextDecoder(TEXT_ENCODING); function buildReadDeviceIdentificationRequest(categoryId = 0x01, objectId = 0x00) { // Используем ArrayBuffer + DataView для единообразия const buffer = new ArrayBuffer(4); const view = new DataView(buffer); view.setUint8(0, FUNCTION_CODE); view.setUint8(1, MEI_TYPE); view.setUint8(2, categoryId); view.setUint8(3, objectId); return new Uint8Array(buffer); } function parseReadDeviceIdentificationResponse(response) { if (!(response instanceof Uint8Array)) { throw new TypeError('Response must be Uint8Array'); } const responseLength = response.length; if (responseLength < MIN_RESPONSE_SIZE) { throw new Error(`Response too short: expected at least ${MIN_RESPONSE_SIZE} bytes`); } // Используем оригинальный буфер без копирования const buffer = response.buffer || response; const byteOffset = response.byteOffset || 0; const view = new DataView(buffer, byteOffset, responseLength); const functionCode = view.getUint8(0); if (functionCode !== FUNCTION_CODE) { throw new Error(`Invalid function code: expected 0x${FUNCTION_CODE.toString(16)}, got 0x${functionCode.toString(16)}`); } const meiType = view.getUint8(1); if (meiType !== MEI_TYPE) { throw new Error(`Invalid MEI type: expected 0x${MEI_TYPE.toString(16)}, got 0x${meiType.toString(16)}`); } const result = { functionCode, meiType, category: view.getUint8(2), conformityLevel: view.getUint8(3), moreFollows: view.getUint8(4), nextObjectId: view.getUint8(5), numberOfObjects: view.getUint8(6), objects: Object.create(null) // Чистый объект без прототипа }; let offset = 7; const objects = result.objects; const numberOfObjects = result.numberOfObjects; for (let i = 0; i < numberOfObjects; i++) { if (offset + 2 > responseLength) { throw new Error('Invalid object header length'); } const objectId = view.getUint8(offset); const length = view.getUint8(offset + 1); offset += 2; if (offset + length > responseLength) { throw new Error('Invalid object data length'); } // Декодируем строку напрямую из буфера objects[objectId] = TEXT_DECODER.decode( new Uint8Array(buffer, byteOffset + offset, length) ); offset += length; } return result; } module.exports = { buildReadDeviceIdentificationRequest, parseReadDeviceIdentificationResponse };