const transport = require('../../transport/ble-core.js') const { DATA_TYPE_OPTIONS, formatManualMultipleQuantity, getManualMultipleValueText, normalizeManualMultipleQuantity, normalizeManualMultipleValues, updateManualMultipleTextLength, updateManualMultipleType, updateManualMultipleValue, validateManualMultipleValue } = require('./multiple-registers.js') const { MODBUS_COMMANDS, buildGeneratedExpectedResponse: buildExpectedResponse, createProtocolState, formatGeneratedResponse, getCommand, getDefaultCommandValue, parseHexNumber } = require('./frame-builder.js') const state = { commandIndex: 2, commandRegisterQuantity: '0001', commandValue: '0001', commandValueLabel: '读取数量', coilEnabled: true, generatedHex: '', protocolCommands: MODBUS_COMMANDS, protocolDataTypeOptions: DATA_TYPE_OPTIONS, protocolErrorText: '', protocolMultipleDialog: { visible: false }, protocolMultipleExpanded: false, protocolMultipleValues: [], protocolResponseText: '', protocolStatusText: '', registerAddress: '0000', showCoilValue: false, showCommandValue: true, showRegisterQuantity: false, slaveAddress: 'F0' } const subscribers = [] function setState(changedData) { Object.assign(state, changedData) subscribers.slice().forEach((subscriber) => { subscriber(getState()) }) } function getState() { return { ...state, protocolCommands: state.protocolCommands.slice(), protocolDataTypeOptions: state.protocolDataTypeOptions.slice(), protocolMultipleDialog: { ...state.protocolMultipleDialog }, protocolMultipleExpanded: !!state.protocolMultipleExpanded, protocolMultipleValues: state.protocolMultipleValues.map((item) => ({ ...item })), protocolStatusText: state.protocolStatusText || '' } } 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 setProtocolInput(changedData) { const command = getCommand(changedData.commandIndex === undefined ? state.commandIndex : changedData.commandIndex) let nextMultipleValues = changedData.protocolMultipleValues let nextCommandValue = changedData.commandValue if ( command.inputMode === 'multiple' && Object.prototype.hasOwnProperty.call(changedData, 'registerAddress') && !Object.prototype.hasOwnProperty.call(changedData, 'protocolMultipleValues') ) { try { const startAddress = parseHexNumber(changedData.registerAddress, '起始地址', 0xFFFF) nextMultipleValues = normalizeManualMultipleValues( normalizeManualMultipleQuantity(state.commandRegisterQuantity), state.protocolMultipleValues, startAddress ) nextCommandValue = getManualMultipleValueText(nextMultipleValues) } catch (error) {} } const nextState = { commandIndex: state.commandIndex, commandRegisterQuantity: state.commandRegisterQuantity, slaveAddress: state.slaveAddress, registerAddress: state.registerAddress, commandValue: state.commandValue, coilEnabled: state.coilEnabled, ...changedData, ...(nextMultipleValues ? { protocolMultipleValues: nextMultipleValues } : {}), ...(nextCommandValue !== undefined ? { commandValue: nextCommandValue } : {}) } setState({ ...changedData, ...(nextMultipleValues ? { protocolMultipleValues: nextMultipleValues } : {}), ...(nextCommandValue !== undefined ? { commandValue: nextCommandValue } : {}), protocolResponseText: '', protocolStatusText: '', ...createProtocolState( nextState.commandIndex, nextState.slaveAddress, nextState.registerAddress, nextState.commandValue, nextState.coilEnabled, nextState.commandRegisterQuantity ) }) } function setCommandIndex(index) { const commandIndex = Number(index) const command = getCommand(commandIndex) let protocolMultipleValues = state.protocolMultipleValues let commandValue = getDefaultCommandValue(command) if (command.inputMode === 'multiple') { let startAddress = 0 try { startAddress = parseHexNumber(state.registerAddress, '起始地址', 0xFFFF) } catch (error) {} protocolMultipleValues = normalizeManualMultipleValues( normalizeManualMultipleQuantity(state.commandRegisterQuantity), state.protocolMultipleValues, startAddress ) commandValue = getManualMultipleValueText(protocolMultipleValues) } setProtocolInput({ commandIndex, commandValue, coilEnabled: true, commandRegisterQuantity: state.commandRegisterQuantity, ...(command.inputMode === 'multiple' ? { protocolMultipleValues } : {}) }) } function openProtocolMultipleDialog() { let startAddress = 0 try { startAddress = parseHexNumber(state.registerAddress, '起始地址', 0xFFFF) } catch (error) { setState({ protocolErrorText: error.message || '起始地址无效' }) return } const quantity = normalizeManualMultipleQuantity(state.commandRegisterQuantity) const values = normalizeManualMultipleValues(quantity, state.protocolMultipleValues, startAddress) setState({ commandRegisterQuantity: formatManualMultipleQuantity(quantity), protocolMultipleDialog: { title: '写多个寄存器', visible: true }, protocolMultipleExpanded: false, protocolMultipleValues: values }) } function closeProtocolMultipleDialog() { setState({ protocolMultipleDialog: { visible: false } }) } function toggleProtocolMultipleExpanded() { setState({ protocolMultipleExpanded: !state.protocolMultipleExpanded }) } function setProtocolMultipleQuantity(value) { const quantity = normalizeManualMultipleQuantity(value) let startAddress = 0 try { startAddress = parseHexNumber(state.registerAddress, '起始地址', 0xFFFF) } catch (error) { setState({ commandRegisterQuantity: value, protocolErrorText: error.message || '起始地址无效' }) return } const values = normalizeManualMultipleValues(quantity, state.protocolMultipleValues, startAddress) const commandValue = getManualMultipleValueText(values) setProtocolInput({ commandRegisterQuantity: value, commandValue, protocolMultipleValues: values }) } function setProtocolMultipleValue(index, value) { const values = updateManualMultipleValue(state.protocolMultipleValues, index, value) let startAddress = 0 try { startAddress = parseHexNumber(state.registerAddress, '起始地址', 0xFFFF) } catch (error) { setState({ protocolErrorText: error.message || '起始地址无效' }) return } const normalizedValues = normalizeManualMultipleValues(normalizeManualMultipleQuantity(state.commandRegisterQuantity), values, startAddress) const commandValue = getManualMultipleValueText(normalizedValues) setProtocolInput({ commandValue, protocolMultipleValues: normalizedValues }) } function setProtocolMultipleType(index, dataTypeIndex) { const changedValues = updateManualMultipleType(state.protocolMultipleValues, index, dataTypeIndex) let startAddress = 0 try { startAddress = parseHexNumber(state.registerAddress, '起始地址', 0xFFFF) } catch (error) { setState({ protocolErrorText: error.message || '起始地址无效' }) return } const values = normalizeManualMultipleValues(normalizeManualMultipleQuantity(state.commandRegisterQuantity), changedValues, startAddress) setProtocolInput({ commandValue: getManualMultipleValueText(values), protocolMultipleValues: values }) } function setProtocolMultipleTextLength(index, value) { const changedValues = updateManualMultipleTextLength(state.protocolMultipleValues, index, value) let startAddress = 0 try { startAddress = parseHexNumber(state.registerAddress, '起始地址', 0xFFFF) } catch (error) { setState({ protocolErrorText: error.message || '起始地址无效' }) return } const values = normalizeManualMultipleValues(normalizeManualMultipleQuantity(state.commandRegisterQuantity), changedValues, startAddress) setProtocolInput({ commandValue: getManualMultipleValueText(values), protocolMultipleValues: values }) } function validateProtocolMultipleValue(index, value) { return validateManualMultipleValue(state.protocolMultipleValues, index, value) } function buildGeneratedExpectedResponse() { return buildExpectedResponse(state) } async function sendGeneratedFrame() { if (!state.generatedHex) { setState({ protocolStatusText: state.protocolErrorText || '请先生成有效帧' }) return false } const expected = buildGeneratedExpectedResponse() setState({ protocolResponseText: '', protocolStatusText: '' }) const response = await transport.enqueueSendFrame(state.generatedHex, 'RTU', expected ? { expected } : {}) if (response) { setState({ protocolResponseText: formatGeneratedResponse(response), protocolStatusText: '' }) } else { setState({ protocolStatusText: '未收到回复' }) } return response } setState(createProtocolState( state.commandIndex, state.slaveAddress, state.registerAddress, state.commandValue, state.coilEnabled, state.commandRegisterQuantity )) module.exports = { buildGeneratedExpectedResponse, closeProtocolMultipleDialog, formatGeneratedResponse, getState, openProtocolMultipleDialog, sendGeneratedFrame, setCommandIndex, setProtocolInput, setProtocolMultipleQuantity, setProtocolMultipleTextLength, setProtocolMultipleType, setProtocolMultipleValue, subscribe, toggleProtocolMultipleExpanded, validateProtocolMultipleValue }