function toText(value) { return String(value === undefined || value === null ? '' : value).trim() } function stripHexPrefix(value) { return toText(value).replace(/^0x/i, '') } function normalizeHexText(value) { return toText(value) .replace(/0x/gi, '') .replace(/[\s,;:_-]/g, ' ') .replace(/\s+/g, ' ') .trim() .toUpperCase() } function compactHexText(value) { return toText(value) .replace(/0x/gi, '') .replace(/[\s,;:_-]/g, '') .toUpperCase() } function validateHexText(value, options = {}) { const withoutPrefix = toText(value).replace(/0x/gi, '') const compact = withoutPrefix.replace(/[\s,;:_-]/g, '') const emptyMessage = options.emptyMessage || '请输入十六进制数据' const invalidMessage = options.invalidMessage || '只支持十六进制字符' const oddLengthMessage = options.oddLengthMessage || '十六进制长度必须为偶数' if (!compact) return emptyMessage if (/[^0-9a-fA-F\s,;:_-]/.test(withoutPrefix)) return invalidMessage if (compact.length % 2 !== 0) return oddLengthMessage return '' } function parseHexBytes(value) { const compact = compactHexText(value) const bytes = [] for (let index = 0; index < compact.length; index += 2) { bytes.push(parseInt(compact.slice(index, index + 2), 16) & 0xFF) } return bytes } function normalizeHexUnitText(value, fallback = '') { const text = stripHexPrefix(value).toUpperCase() return text || fallback } function normalizeHexWordText(value, fallback = '') { return normalizeHexUnitText(value, fallback) } function normalizeHexDwordText(value, fallback = '') { return normalizeHexUnitText(value, fallback) } function validateHexWordText(value, label) { const text = normalizeHexWordText(value) if (!text) return `${label}请输入十六进制` if (!/^[0-9A-F]+$/i.test(text)) return `${label}只支持十六进制` if (text.length > 4) return `${label}最多 4 位十六进制` return '' } function validateHexDwordText(value, label) { const text = normalizeHexDwordText(value) if (!text) return `${label}请输入十六进制` if (!/^[0-9A-F]+$/i.test(text)) return `${label}只支持十六进制` if (text.length > 8) return `${label}最多 8 位十六进制` return '' } function parseHexNumber(value, label = '数值', maxValue = 0xFFFF) { const text = normalizeHexWordText(value) if (!text || !/^[0-9A-F]+$/i.test(text)) { throw new Error(`${label}请输入十六进制数值`) } const parsedValue = parseInt(text, 16) if (parsedValue > maxValue) { throw new Error(`${label}超出范围`) } return parsedValue } function parseHexDword(value, label = '地址') { return parseHexNumber(value, label, 0xFFFFFFFF) } function parseHexByte(value, label = '从机地址') { const text = normalizeHexWordText(value) if (!/^[0-9A-F]{1,2}$/i.test(text)) { throw new Error(`${label}需为 00 - FF`) } return parseInt(text, 16) } function normalizeHexByte(value, fallback = '00') { const fallbackText = normalizeHexWordText(fallback, '00') const text = normalizeHexWordText(value) if (!/^[0-9A-F]{1,2}$/i.test(text)) { return parseInt(fallbackText || '0', 16).toString(16).toUpperCase().padStart(2, '0') } return parseInt(text, 16).toString(16).toUpperCase().padStart(2, '0') } module.exports = { compactHexText, normalizeHexDwordText, normalizeHexByte, normalizeHexText, normalizeHexWordText, parseHexByte, parseHexBytes, parseHexDword, parseHexNumber, stripHexPrefix, validateHexDwordText, validateHexText, validateHexWordText }