const paramsPageState = require('../../utils/params-page-state') const paramsService = require('../../utils/params-service') const controlService = require('../../utils/control-service') const genericModbusService = require('../../utils/generic-modbus-service') const { createGenericModbusPoller } = require('../../utils/generic-modbus-poller') const settingsService = require('../../utils/settings-service') const themeService = require('../../utils/theme-service') const { createGenericGroupConfig, createGenericGroupDialogState, createGenericModbusDialogState, createGenericRegisterChangedData, createGenericRegisterDialogState, findGenericGroup, findGenericRegister, getCombinedGroupKeys, getCombinedGroupLabel, getControlViewState, getGenericDialogDataTypeState, getGenericOption, getGroupLabel, getPageState, getSettingsPageState, getVisiblePageState, hasWritableGroupChanges, resolveActiveParamView } = require('../../utils/params-view-model') const syncService = require('../../utils/sync-service') const { createPageToast } = require('../../utils/page-toast') Page({ data: { ...getPageState(), activeParamView: '', genericModbusDialog: createGenericModbusDialogState() }, onTabItemTap() { this.backToParamsHome() }, onLoad() { this.pageToast = createPageToast(this, this.data) this.genericModbusPoller = createGenericModbusPoller(() => this.data) this.genericModbusTouchStarts = {} controlService.init() genericModbusService.init() themeService.init() settingsService.init() this.unsubscribeSync = syncService.subscribe((syncState) => { if (!syncState.syncVersion || syncState.syncVersion === this.data.syncVersion) return const nextState = getPageState( syncService.getParamsSnapshot(), controlService.getState() ) this.setData(nextState) this.pageToast.showFromState(nextState) }) this.unsubscribeControl = controlService.subscribe((controlState) => { const nextState = getControlViewState(controlState) this.setData(nextState) this.pageToast.showFromState(nextState) if (nextState.connectedDevice) { this.scheduleVisibleGenericAutoReads() } else { this.clearGenericAutoTimers() } }) this.unsubscribeTheme = themeService.subscribe((themeState) => { this.setData(themeState) }) this.unsubscribeGenericModbus = genericModbusService.subscribe((genericState) => { this.setData(genericState) }) this.unsubscribeSettings = settingsService.subscribe((settingsState) => { const nextState = getSettingsPageState(this.data, settingsState) const activeParamView = nextState.activeParamView this.setData(nextState) if (activeParamView === 'genericModbus') { setTimeout(() => this.scheduleVisibleGenericAutoReads(), 0) } else { this.clearGenericAutoTimers() } }) }, onShow() { if (this.pageToast) { this.pageToast.setActive(true) } controlService.syncSharedInputs() const pageState = getVisiblePageState(this.data) this.setData(pageState) this.pageToast.showFromState(pageState) this.scheduleVisibleGenericAutoReads() }, onHide() { if (this.pageToast) { this.pageToast.setActive(false) } this.clearGenericAutoTimers() }, onUnload() { if (this.pageToast) { this.pageToast.destroy() this.pageToast = null } if (this.unsubscribeSync) { this.unsubscribeSync() this.unsubscribeSync = null } if (this.unsubscribeControl) { this.unsubscribeControl() this.unsubscribeControl = null } if (this.unsubscribeTheme) { this.unsubscribeTheme() this.unsubscribeTheme = null } if (this.unsubscribeGenericModbus) { this.unsubscribeGenericModbus() this.unsubscribeGenericModbus = null } if (this.unsubscribeSettings) { this.unsubscribeSettings() this.unsubscribeSettings = null } this.clearGenericAutoTimers() }, async onGroupRead(event) { if (!this.data.connectedDevice) return const groupKey = event.currentTarget.dataset.group const nextState = await paramsService.readGroup(this.data, groupKey) if (nextState) { this.setData(nextState) if (this.pageToast) this.pageToast.show(`${getGroupLabel(groupKey)}读取完成`) } }, async onGroupWrite(event) { if (!this.data.connectedDevice) return const groupKey = event.currentTarget.dataset.group const written = await paramsService.writeGroup(this.data, groupKey) if (written) { this.setData(paramsPageState.clearGroupDirty(this.data, groupKey)) if (this.pageToast) this.pageToast.show(`${getGroupLabel(groupKey)}写入完成`) } }, async readCombinedGroups(viewKey) { if (!this.data.connectedDevice) return false const groupKeys = getCombinedGroupKeys(viewKey) let nextState = this.data for (const groupKey of groupKeys) { const updatedState = await paramsService.readGroup(nextState, groupKey) if (!updatedState) { if (nextState !== this.data) this.setData(nextState) return false } nextState = updatedState this.setData(nextState) } if (this.pageToast) this.pageToast.show(`${getCombinedGroupLabel(viewKey)}读取完成`) return true }, async writeCombinedGroups(viewKey) { if (!this.data.connectedDevice) return false const groupKeys = getCombinedGroupKeys(viewKey) let nextState = this.data let writtenAny = false for (const groupKey of groupKeys) { if (!hasWritableGroupChanges(nextState, groupKey)) continue const written = await paramsService.writeGroup(nextState, groupKey) if (!written) { if (writtenAny) this.setData(nextState) return false } nextState = paramsPageState.clearGroupDirty(nextState, groupKey) writtenAny = true this.setData(nextState) } if (!writtenAny) { if (this.pageToast) this.pageToast.show('暂无需要写入的参数') return false } if (this.pageToast) this.pageToast.show(`${getCombinedGroupLabel(viewKey)}写入完成`) return true }, readStartupManagement() { this.readCombinedGroups('startup') }, writeStartupManagement() { this.writeCombinedGroups('startup') }, readSpeedManagement() { this.readCombinedGroups('speed') }, writeSpeedManagement() { this.writeCombinedGroups('speed') }, onEstimatorUpdate() { this.setData(paramsPageState.refreshState(this.data)) if (this.pageToast) this.pageToast.show('估算器参数更新完成') }, openParamView(event) { if (this.pageToast) this.pageToast.clear() this.closeGenericModbusDraft() const activeParamView = event.currentTarget.dataset.view if (!activeParamView) return this.setData({ activeParamView }) if (activeParamView === 'genericModbus') { setTimeout(() => this.scheduleVisibleGenericAutoReads(), 0) } }, backToParamsHome() { if (this.pageToast) this.pageToast.clear() this.closeGenericModbusDraft() this.clearGenericAutoTimers() const activeParamView = resolveActiveParamView('', this.data) this.setData({ activeParamView }) if (activeParamView === 'genericModbus') { setTimeout(() => this.scheduleVisibleGenericAutoReads(), 0) } }, onMotorParameterInput(event) { controlService.updateMotorParameterInput( Number(event.currentTarget.dataset.index), event.detail.value ) }, onMotorParameterBlur(event) { controlService.updateMotorParameterBlur( Number(event.currentTarget.dataset.index), event.detail.value ) }, writeMotorParameters() { if (!this.data.connectedDevice) return controlService.writeMotorParameters() }, async readDriverPageParameters() { if (!this.data.connectedDevice) return await controlService.readDriverParameters() await controlService.readMotorParameters() }, readStatus() { if (!this.data.canReadStatus) return controlService.readStatus() }, onInputChange(event) { this.setData(paramsPageState.applyParameterInput( this.data, Number(event.currentTarget.dataset.index), event.detail.value )) }, onAtoBandwidthInput(event) { this.setData(paramsPageState.applyAtoBandwidthInput( this.data, Number(event.currentTarget.dataset.index), event.detail.value )) }, onDqGainInput(event) { this.setData(paramsPageState.applyDqGainInput( this.data, Number(event.currentTarget.dataset.index), event.detail.value )) }, onSpeedLoopExtraInput(event) { this.setData(paramsPageState.applySpeedLoopExtraInput( this.data, Number(event.currentTarget.dataset.index), event.detail.value )) }, onOilParameterInput(event) { this.setData(paramsPageState.applyOilParameterInput( this.data, Number(event.currentTarget.dataset.index), event.detail.value )) }, onPrepositionParameterInput(event) { this.setData(paramsPageState.applyPrepositionParameterInput( this.data, Number(event.currentTarget.dataset.index), event.detail.value )) }, onInputBlur(event) { this.setData(paramsPageState.applyInputBlur( this.data, event.currentTarget.dataset.inputGroup, Number(event.currentTarget.dataset.index), event.detail.value )) }, onTailwindSwitchChange(event) { if (!this.data.connectedDevice) return const index = Number(event.currentTarget.dataset.index) const nextState = paramsPageState.applyTailwindSwitchChange( this.data, index, !!event.detail.value ) this.setData(nextState) paramsService.writeSwitchRegister(nextState.tailwindSwitchRegisters[index]).then((written) => { if (written) { this.setData(paramsPageState.clearTailwindSwitchDirty(this.data, index)) if (this.pageToast) this.pageToast.show(`${nextState.tailwindSwitchRegisters[index].name}写入完成`) } }) }, onProtectionSwitchChange(event) { if (!this.data.connectedDevice) return const index = Number(event.currentTarget.dataset.index) const nextState = paramsPageState.applyProtectionSwitchChange( this.data, index, !!event.detail.value ) this.setData(nextState) paramsService.writeSwitchRegister(nextState.protectionSwitchRegisters[index]).then((written) => { if (written) { this.setData(paramsPageState.clearProtectionSwitchDirty(this.data, index)) if (this.pageToast) this.pageToast.show(`${nextState.protectionSwitchRegisters[index].name}写入完成`) } }) }, onProtectionInputChange(event) { this.setData(paramsPageState.applyProtectionInput( this.data, Number(event.currentTarget.dataset.index), event.detail.value )) }, noop() {}, updateGenericModbusDialog(changedData) { this.setData({ genericModbusDialog: { ...this.data.genericModbusDialog, ...changedData } }) }, openGenericModbusDraft(event) { const groupId = event && event.currentTarget && event.currentTarget.dataset ? event.currentTarget.dataset.groupId : '' const group = groupId ? findGenericGroup(this.data.genericModbusGroups, groupId) : null this.updateGenericModbusDialog(createGenericGroupDialogState(group)) }, closeGenericModbusDraft() { this.genericModbusGroupLongPressGuard = '' this.genericModbusRegisterLongPressGuard = '' this.updateGenericModbusDialog(createGenericModbusDialogState()) }, onGenericDraftInput(event) { const field = event.currentTarget.dataset.field if (!field) return this.updateGenericModbusDialog({ [field]: event.detail.value }) }, onGenericDraftTypeChange(event) { const registerTypeIndex = Number(event.detail.value) const registerType = getGenericOption(this.data.genericModbusRegisterTypeOptions, registerTypeIndex) this.updateGenericModbusDialog({ registerTypeIndex, registerTypeText: registerType.label || '' }) }, onGenericDialogDataTypeChange(event) { const dataTypeIndex = Number(event.detail.value) this.updateGenericModbusDialog(getGenericDialogDataTypeState( this.data.genericModbusDialog, this.data.genericModbusDataTypeOptions, dataTypeIndex )) }, openGenericGroupEdit(event) { const groupId = event.currentTarget.dataset.groupId const group = findGenericGroup(this.data.genericModbusGroups, groupId) if (!group) return this.genericModbusGroupLongPressGuard = groupId this.updateGenericModbusDialog(createGenericGroupDialogState(group)) }, openGenericRegisterInfo(event) { const groupId = event.currentTarget.dataset.groupId const registerIndex = Number(event.currentTarget.dataset.index) const registerKey = `${groupId}:${registerIndex}` if (this.genericModbusRegisterLongPressGuard === registerKey) { this.genericModbusRegisterLongPressGuard = '' return } const { group, register } = findGenericRegister(this.data.genericModbusGroups, groupId, registerIndex) if (!register) return this.updateGenericModbusDialog(createGenericRegisterDialogState('viewRegister', group, register, registerIndex)) }, openGenericRegisterEdit(event) { const groupId = event.currentTarget.dataset.groupId const registerIndex = Number(event.currentTarget.dataset.index) const { group, register } = findGenericRegister(this.data.genericModbusGroups, groupId, registerIndex) if (!register) return this.genericModbusRegisterLongPressGuard = `${groupId}:${registerIndex}` this.updateGenericModbusDialog(createGenericRegisterDialogState('editRegister', group, register, registerIndex)) }, async confirmGenericModbusDialog() { const dialog = this.data.genericModbusDialog || createGenericModbusDialogState() const mode = dialog.mode if (mode === 'createGroup') { const group = genericModbusService.addGroupFromConfig(createGenericGroupConfig(dialog)) if (group) { if (this.pageToast) this.pageToast.show(`${group.name}已添加`) this.closeGenericModbusDraft() } return } if (mode === 'editGroup') { const group = genericModbusService.updateGroupConfig(dialog.groupId, createGenericGroupConfig(dialog)) if (group) { if (this.pageToast) this.pageToast.show(`${group.name}已更新`) this.closeGenericModbusDraft() } return } if (mode === 'editRegister') { const changedData = createGenericRegisterChangedData(dialog, this.data.genericModbusDataTypeOptions) genericModbusService.updateRegister(dialog.groupId, dialog.registerIndex, changedData) if (this.pageToast) this.pageToast.show(`${dialog.name || '寄存器'}已更新`) this.closeGenericModbusDraft() } }, async importGenericModbusJson() { const count = await genericModbusService.importJsonFromMessageFile() if (count && this.pageToast) this.pageToast.show(`已导入 ${count} 个寄存器组`) }, async saveGenericModbusJson() { const count = await genericModbusService.saveJsonToChat() if (count && this.pageToast) this.pageToast.show(`已保存 ${count} 个寄存器组`) }, toggleGenericModbusGroup(event) { const groupId = event.currentTarget.dataset.groupId if (this.genericModbusGroupLongPressGuard === groupId) { this.genericModbusGroupLongPressGuard = '' return } const group = findGenericGroup(this.data.genericModbusGroups, groupId) if (!group) return genericModbusService.setGroupExpanded(groupId, !group.expanded) }, onGenericRegisterValueInput(event) { genericModbusService.updateRegisterValue( event.currentTarget.dataset.groupId, Number(event.currentTarget.dataset.index), event.detail.value ) }, onGenericRegisterValueBlur(event) { const groupId = event.currentTarget.dataset.groupId const registerIndex = Number(event.currentTarget.dataset.index) try { genericModbusService.validateRegisterInputValue(groupId, registerIndex, event.detail.value) } catch (error) { if (this.pageToast) this.pageToast.show(error.message || '输入值无效', 'error') } }, async readGenericModbusGroup(event) { if (!this.data.connectedDevice) return const groupId = event.currentTarget.dataset.groupId const ok = await genericModbusService.readGroup(groupId, { maxPacketLength: this.data.genericModbusMaxPacketLength }) if (ok && this.pageToast) this.pageToast.show('通用Modbus读取完成') }, async writeGenericModbusGroup(event) { if (!this.data.connectedDevice) return const groupId = event.currentTarget.dataset.groupId const ok = await genericModbusService.writeGroup(groupId) if (ok && this.pageToast) this.pageToast.show('通用Modbus写入完成') }, onGenericGroupTouchStart(event) { const groupId = event.currentTarget.dataset.groupId const touch = (event.changedTouches || [])[0] if (!groupId || !touch) return this.genericModbusTouchStarts[groupId] = touch.clientX }, onGenericGroupTouchEnd(event) { const groupId = event.currentTarget.dataset.groupId const group = findGenericGroup(this.data.genericModbusGroups, groupId) const touch = (event.changedTouches || [])[0] const startX = this.genericModbusTouchStarts[groupId] if (!groupId || !group || group.expanded || !touch || !Number.isFinite(startX)) return const deltaX = touch.clientX - startX if (deltaX > 42) { genericModbusService.setGroupDeleteVisible(groupId, true) } else if (deltaX < -24) { genericModbusService.setGroupDeleteVisible(groupId, false) } }, deleteGenericModbusGroup(event) { const groupId = event.currentTarget.dataset.groupId this.clearGenericAutoTimer(groupId) genericModbusService.removeGroup(groupId) if (this.pageToast) this.pageToast.show('寄存器组已删除') }, clearGenericAutoTimer(groupId) { if (this.genericModbusPoller) this.genericModbusPoller.clearTimer(groupId) }, clearGenericAutoTimers() { if (this.genericModbusPoller) this.genericModbusPoller.clearAll() }, scheduleVisibleGenericAutoReads() { if (this.genericModbusPoller) this.genericModbusPoller.scheduleVisible() }, scheduleGenericAutoPoll(delay) { if (this.genericModbusPoller) this.genericModbusPoller.schedule(delay) } })