const genericModbusService = require('./service.js') const POLL_TIMER_ID = '__genericPoll' const MEMORY_AREA_ORDER = { DATA: 0, IDATA: 1, XDATA: 2, CODE: 3, BIT: 4 } function getMemoryAreaOrder(group = {}) { const key = String(group.sourceMemoryArea || '').trim().toUpperCase() return Object.prototype.hasOwnProperty.call(MEMORY_AREA_ORDER, key) ? MEMORY_AREA_ORDER[key] : 99 } function getGroupAddress(group = {}) { const sourceAddress = Number(group.sourceAddress) if (Number.isFinite(sourceAddress)) return Math.max(0, Math.floor(sourceAddress)) const startAddress = Number(group.startAddress) return Number.isFinite(startAddress) ? Math.max(0, Math.floor(startAddress)) : 0 } function shouldPoll(data) { return !!data && (data.activeParamView === 'genericModbus' || data.activeParamView === 'genericModbusGroup') && !!data.connectedDevice && !!data.genericModbusAutoPollEnabled } function getPollableGroups(data) { return (data.genericModbusGroups || []) .filter((group) => { if (!group || group.addressOverflow) return false if ((group.registers || []).some((register) => register && register.isDirty)) return false if (data.isPrivateProtocol) return !!group.sourceMemoryArea return group.isReadOnly }) .sort((left, right) => ( getMemoryAreaOrder(left) - getMemoryAreaOrder(right) || getGroupAddress(left) - getGroupAddress(right) || String(left.name || '').localeCompare(String(right.name || '')) )) } function createGenericModbusPoller(getData) { const timers = {} function clearTimer(timerId) { if (!timers[timerId]) return clearTimeout(timers[timerId]) delete timers[timerId] } function clearAll() { Object.keys(timers).forEach(clearTimer) } function schedule(delay) { clearTimer(POLL_TIMER_ID) timers[POLL_TIMER_ID] = setTimeout(async () => { const data = getData() if (!shouldPoll(data)) { clearTimer(POLL_TIMER_ID) return } for (const group of getPollableGroups(data)) { const latestData = getData() if (!shouldPoll(latestData)) break await genericModbusService.readGroup(group.id, { maxPacketLength: latestData.genericModbusMaxPacketLength, showModal: false }) } const latestData = getData() if (shouldPoll(latestData)) { schedule(latestData.genericModbusPollInterval || 100) } }, delay) } function scheduleVisible() { const data = getData() if (!shouldPoll(data)) { clearAll() return } schedule(data.genericModbusPollInterval || 100) } return { clearAll, clearTimer, schedule, scheduleVisible } } module.exports = { createGenericModbusPoller }