modbus-connect
Version:
Modbus RTU over Web Serial and Node.js SerialPort
92 lines (76 loc) • 3.04 kB
JavaScript
// function-codes/SGM130/write-device-comment.js
const { FUNCTION_CODES } = require('../../constants/constants.js');
const { allocUint8Array, isUint8Array } = require('../../utils/utils.js');
/** Таблица кодов символов по спецификации */
const CHAR_TO_CODE = {
' ': 0, '0': 1, '1': 2, '2': 3, '3': 4, '4': 5, '5': 6, '6': 7, '7': 8, '8': 9, '9': 10,
'A': 11, 'B': 12, 'C': 13, 'D': 14, 'E': 15, 'F': 16, 'G': 17, 'H': 18, 'I': 19, 'J': 20,
'K': 21, 'L': 22, 'M': 23, 'N': 24, 'O': 25, 'P': 26, 'Q': 27, 'R': 28, 'S': 29, 'T': 30,
'U': 31, 'V': 32, 'X': 33, 'Y': 34, 'Z': 35,
'А': 37, 'Б': 38, 'В': 39, 'Г': 40, 'Д': 41, 'Е': 42, 'Ж': 43, 'З': 44, 'И': 45, 'Й': 46,
'К': 47, 'Л': 48, 'М': 49, 'Н': 50, 'О': 51, 'П': 52, 'Р': 53, 'С': 54, 'Т': 55, 'У': 56,
'Ф': 57, 'Х': 58, 'Ц': 59, 'Ч': 60, 'Ш': 61, 'Щ': 62, 'Ъ': 63, 'Ы': 64, 'Ь': 65, 'Э': 66,
'Ю': 67, 'Я': 68
};
/**
* Создаёт PDU-запрос для записи комментария устройства
* @param {number} channel - номер канала (0–255)
* @param {string} comment - строка комментария (макс. 16 символов)
* @returns {Uint8Array}
*/
function buildWriteDeviceCommentRequest(channel, comment) {
if (channel < 0 || channel > 255) {
throw new RangeError('Invalid channel number');
}
if (typeof comment !== 'string') {
throw new TypeError('Comment must be a string');
}
const trimmed = comment.trim().toUpperCase();
if (trimmed.length > 16) {
throw new Error('Comment is too long (max 16 characters)');
}
const encoded = [];
for (const ch of trimmed) {
const code = CHAR_TO_CODE[ch];
if (code === undefined) {
throw new Error(`Unsupported character: "${ch}"`);
}
encoded.push(code);
}
// Дополняем до 16 байт кодом пробела (0)
while (encoded.length < 16) {
encoded.push(0);
}
const pdu = allocUint8Array(3 + 16);
pdu[0] = FUNCTION_CODES.WRITE_DEVICE_COMMENT;
pdu[1] = channel;
pdu[2] = 16;
for (let i = 0; i < 16; i++) {
pdu[3 + i] = encoded[i];
}
return pdu;
}
/**
* Парсит ответ устройства на запись комментария
* @param {Uint8Array} pdu
* @returns {{ channel: number, length: number }}
*/
function parseWriteDeviceCommentResponse(pdu) {
if (!isUint8Array(pdu)) {
throw new TypeError('PDU must be Uint8Array');
}
const fc = FUNCTION_CODES.WRITE_DEVICE_COMMENT;
if (pdu[0] !== fc) {
throw new Error(`Invalid function code: expected 0x${fc.toString(16)}, got 0x${pdu[0].toString(16)}`);
}
const channel = pdu[1];
const length = pdu[2];
if (length !== 16) {
throw new Error(`Invalid string length: expected 16, got ${length}`);
}
return { channel, length };
}
module.exports = {
buildWriteDeviceCommentRequest,
parseWriteDeviceCommentResponse
}