const controlService = require('./control-service') const { controlState, paramsState: paramsPageState } = require('./motor-control-data') const transport = require('./ble-transport') const modbusAccess = require('./modbus-access') 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, chunk) { addCoilReadValues(readValues, chunk.address, chunk.quantity, response) controlService.applyControlReadValues(readValues.coils) } }, { address: 0x30, functionCode: 0x03, label: '同步估算器参数 30-4A', quantity: 27, onResponse(response, chunk) { addWordReadValues(readValues, chunk.address, response) } }, { address: 0x60, functionCode: 0x03, label: '同步参数配置 60-8D', quantity: 46, onResponse(response, chunk) { addWordReadValues(readValues, chunk.address, response) controlService.applyMotorReadWords(response.words || [], chunk.address) } }, { address: controlState.DRIVER_PARAM_START_ADDRESS, functionCode: 0x04, label: '同步驱动器参数 A0-B3', quantity: controlState.DRIVER_PARAM_WORD_COUNT, onResponse(response, chunk) { addWordReadValues(readValues, chunk.address, response) controlService.applyDriverReadWords(response.words || []) } }, { address: controlState.STATUS_START_ADDRESS, functionCode: 0x04, label: '同步状态', quantity: () => controlState.getStatusWordCount(controlService.getState().userStatusCount), onResponse(response, chunk) { addWordReadValues(readValues, chunk.address, response) controlService.applyStatusReadWords(response.words || [], chunk.address) } } ] 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 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 = modbusAccess.getSharedSlaveAddress() if (slaveAddress === null) return false setSyncing(true) resetReadValues() try { for (const step of READ_STEPS) { const quantity = typeof step.quantity === 'function' ? step.quantity() : step.quantity const values = await modbusAccess.readSpans( slaveAddress, step.functionCode, [{ address: step.address, quantity }], step.label, 'sync-read', { onChunk(response, chunk) { if (typeof step.onResponse === 'function') { step.onResponse(response, chunk) } } } ) if (!values) return false if (values.coils) Object.assign(readValues.coils, values.coils) if (values.words) Object.assign(readValues.words, values.words) } paramsSnapshot = paramsPageState.applyReadValues(paramsSnapshot, readValues) paramsSnapshotVersion += 1 notify() notifyPageToast('同步完成') return true } finally { setSyncing(false) } } module.exports = { getParamsSnapshot, getState, subscribe, syncAllRegisters }