const { toFiniteNumber } = require('./calculation-context') function toAddressKey(address) { if (typeof address === 'number' && Number.isFinite(address)) { return Math.round(address).toString(16).toUpperCase() } const text = String(address || '').trim().toUpperCase() if (!text) return '' const hexText = text.startsWith('0X') ? text.slice(2) : text if (/^[0-9A-F]+$/.test(hexText)) { return parseInt(hexText, 16).toString(16).toUpperCase() } const numberValue = Number(text) if (Number.isFinite(numberValue)) { return Math.round(numberValue).toString(16).toUpperCase() } return text } function wordsToFloat(highWord, lowWord) { const highValue = Number(highWord) const lowValue = Number(lowWord) if (!Number.isInteger(highValue) || !Number.isInteger(lowValue)) return null const buffer = new ArrayBuffer(4) const view = new DataView(buffer) view.setUint16(0, highValue & 0xFFFF, false) view.setUint16(2, lowValue & 0xFFFF, false) return view.getFloat32(0, false) } function floatToWords(value) { const numberValue = toFiniteNumber(value, NaN) if (!Number.isFinite(numberValue)) return null const buffer = new ArrayBuffer(4) const view = new DataView(buffer) view.setFloat32(0, numberValue, false) return [view.getUint16(0, false), view.getUint16(2, false)] } function addCoilReadValues(readValues, startAddress, quantity, response) { if (!readValues || !readValues.coils || !response || !Array.isArray(response.dataBytes)) return for (let offset = 0; offset < quantity; offset += 1) { const byte = response.dataBytes[Math.floor(offset / 8)] || 0 const bit = (byte >> (offset % 8)) & 0x01 readValues.coils[toAddressKey(startAddress + offset)] = bit } } function addWordReadValues(readValues, startAddress, response) { if (!readValues || !readValues.words || !response || !Array.isArray(response.words)) return response.words.forEach((word, index) => { readValues.words[toAddressKey(startAddress + index)] = Number(word) & 0xFFFF }) } function getRegisterWordCache(startAddress, words) { if (!Array.isArray(words)) return {} return words.reduce((result, word, index) => { result[startAddress + index] = Number(word) & 0xFFFF return result }, {}) } module.exports = { addCoilReadValues, addWordReadValues, floatToWords, getRegisterWordCache, toAddressKey, wordsToFloat }