const { buildReadFrame, getMaxReadQuantity } = require('./modbus-rtu') const controlState = require('./control-page-state') const controlService = require('./control-service') const paramsPageState = require('./params-page-state') const transport = require('./ble-transport') const { notifyPageToast } = require('./page-toast') const { addCoilReadValues, addWordReadValues } = require('./register-value-utils') const readValues = { coils: {}, words: {} } let paramsSnapshot = paramsPageState.createInitialState() let paramsSnapshotVersion = 0 const READ_STEPS = [ { address: 0x00, functionCode: 0x01, label: '同步线圈 00-10', quantity: 17, onResponse(response, step) { addCoilReadValues(readValues, step.address, step.quantity, response) controlService.applyControlReadValues(readValues.coils) } }, { address: 0x30, functionCode: 0x03, label: '同步估算器参数 30-4A', quantity: 27, onResponse(response, step) { addWordReadValues(readValues, step.address, response) } }, { address: 0x60, functionCode: 0x03, label: '同步参数配置 60-8D', quantity: 46, onResponse(response, step) { addWordReadValues(readValues, step.address, response) controlService.applyMotorReadWords(response.words || [], step.address) } }, { address: controlState.DRIVER_PARAM_START_ADDRESS, functionCode: 0x04, label: '同步驱动器硬件参数 A0-B3', quantity: controlState.DRIVER_PARAM_WORD_COUNT, onResponse(response, step) { addWordReadValues(readValues, step.address, response) controlService.applyDriverReadWords(response.words || []) } }, { address: controlState.STATUS_START_ADDRESS, functionCode: 0x04, label: '同步状态 C0-DC', quantity: controlState.STATUS_WORD_COUNT, onResponse(response, step) { addWordReadValues(readValues, step.address, response) controlService.applyStatusReadWords(response.words || [], step.address) } } ] function splitReadStep(step) { const maxQuantity = getMaxReadQuantity(step.functionCode) if (!maxQuantity || step.quantity <= maxQuantity) return [step] const chunks = [] let offset = 0 while (offset < step.quantity) { const quantity = Math.min(step.quantity - offset, maxQuantity) const address = step.address + offset chunks.push({ ...step, address, label: `${step.label} ${address.toString(16).toUpperCase()}-${(address + quantity - 1).toString(16).toUpperCase()}`, quantity }) offset += quantity } return chunks } let syncing = false const subscribers = [] function getState() { return { isSyncing: syncing, syncVersion: paramsSnapshotVersion } } function notify() { const state = getState() subscribers.slice().forEach((subscriber) => { subscriber(state) }) } function setSyncing(value) { syncing = !!value notify() } transport.subscribe((transportState) => { if (!transportState.connectedDevice && syncing) { setSyncing(false) } }) function subscribe(subscriber) { if (typeof subscriber !== 'function') return () => {} subscribers.push(subscriber) subscriber(getState()) return () => { const index = subscribers.indexOf(subscriber) if (index >= 0) subscribers.splice(index, 1) } } function getSharedSlaveAddress() { try { return transport.getSlaveAddress() } catch (error) { transport.showCommandAlert('从机地址错误', error.message) return null } } function resetReadValues() { readValues.coils = {} readValues.words = {} } function getParamsSnapshot() { return { ...paramsSnapshot, syncVersion: paramsSnapshotVersion } } async function syncAllRegisters() { if (syncing) return false const transportState = transport.getState() if (!transportState.connectedDevice) return false const slaveAddress = getSharedSlaveAddress() if (slaveAddress === null) return false setSyncing(true) resetReadValues() try { for (const step of READ_STEPS) { for (const chunk of splitReadStep(step)) { const response = await transport.sendManagedFrame( buildReadFrame(slaveAddress, chunk.functionCode, chunk.address, chunk.quantity), chunk.label, { address: chunk.address, functionCode: chunk.functionCode, kind: 'sync-read', quantity: chunk.quantity, slaveAddress } ) if (!response) return false if (typeof chunk.onResponse === 'function') { chunk.onResponse(response, chunk) } } } paramsSnapshot = paramsPageState.applyReadValues(paramsSnapshot, readValues) paramsSnapshotVersion += 1 notify() notifyPageToast('同步完成') return true } finally { setSyncing(false) } } module.exports = { getParamsSnapshot, getState, subscribe, syncAllRegisters }