params.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. const paramsPageState = require('../../utils/params-page-state')
  2. const paramsService = require('../../utils/params-service')
  3. const controlService = require('../../utils/control-service')
  4. const genericModbusService = require('../../utils/generic-modbus-service')
  5. const {
  6. createGenericModbusPoller
  7. } = require('../../utils/generic-modbus-poller')
  8. const settingsService = require('../../utils/settings-service')
  9. const themeService = require('../../utils/theme-service')
  10. const {
  11. createGenericGroupConfig,
  12. createGenericGroupDialogState,
  13. createGenericModbusDialogState,
  14. createGenericRegisterChangedData,
  15. createGenericRegisterDialogState,
  16. findGenericGroup,
  17. findGenericRegister,
  18. getCombinedGroupKeys,
  19. getCombinedGroupLabel,
  20. getControlViewState,
  21. getGenericDialogDataTypeState,
  22. getGenericOption,
  23. getGroupLabel,
  24. getPageState,
  25. getSettingsPageState,
  26. getVisiblePageState,
  27. hasWritableGroupChanges,
  28. resolveActiveParamView
  29. } = require('../../utils/params-view-model')
  30. const syncService = require('../../utils/sync-service')
  31. const {
  32. createPageToast
  33. } = require('../../utils/page-toast')
  34. Page({
  35. data: {
  36. ...getPageState(),
  37. activeParamView: '',
  38. genericModbusDialog: createGenericModbusDialogState()
  39. },
  40. onTabItemTap() {
  41. this.backToParamsHome()
  42. },
  43. onLoad() {
  44. this.pageToast = createPageToast(this, this.data)
  45. this.genericModbusPoller = createGenericModbusPoller(() => this.data)
  46. this.genericModbusTouchStarts = {}
  47. controlService.init()
  48. genericModbusService.init()
  49. themeService.init()
  50. settingsService.init()
  51. this.unsubscribeSync = syncService.subscribe((syncState) => {
  52. if (!syncState.syncVersion || syncState.syncVersion === this.data.syncVersion) return
  53. const nextState = getPageState(
  54. syncService.getParamsSnapshot(),
  55. controlService.getState()
  56. )
  57. this.setData(nextState)
  58. this.pageToast.showFromState(nextState)
  59. })
  60. this.unsubscribeControl = controlService.subscribe((controlState) => {
  61. const nextState = getControlViewState(controlState)
  62. this.setData(nextState)
  63. this.pageToast.showFromState(nextState)
  64. if (nextState.connectedDevice) {
  65. this.scheduleVisibleGenericAutoReads()
  66. } else {
  67. this.clearGenericAutoTimers()
  68. }
  69. })
  70. this.unsubscribeTheme = themeService.subscribe((themeState) => {
  71. this.setData(themeState)
  72. })
  73. this.unsubscribeGenericModbus = genericModbusService.subscribe((genericState) => {
  74. this.setData(genericState)
  75. })
  76. this.unsubscribeSettings = settingsService.subscribe((settingsState) => {
  77. const nextState = getSettingsPageState(this.data, settingsState)
  78. const activeParamView = nextState.activeParamView
  79. this.setData(nextState)
  80. if (activeParamView === 'genericModbus') {
  81. setTimeout(() => this.scheduleVisibleGenericAutoReads(), 0)
  82. } else {
  83. this.clearGenericAutoTimers()
  84. }
  85. })
  86. },
  87. onShow() {
  88. if (this.pageToast) {
  89. this.pageToast.setActive(true)
  90. }
  91. controlService.syncSharedInputs()
  92. const pageState = getVisiblePageState(this.data)
  93. this.setData(pageState)
  94. this.pageToast.showFromState(pageState)
  95. this.scheduleVisibleGenericAutoReads()
  96. },
  97. onHide() {
  98. if (this.pageToast) {
  99. this.pageToast.setActive(false)
  100. }
  101. this.clearGenericAutoTimers()
  102. },
  103. onUnload() {
  104. if (this.pageToast) {
  105. this.pageToast.destroy()
  106. this.pageToast = null
  107. }
  108. if (this.unsubscribeSync) {
  109. this.unsubscribeSync()
  110. this.unsubscribeSync = null
  111. }
  112. if (this.unsubscribeControl) {
  113. this.unsubscribeControl()
  114. this.unsubscribeControl = null
  115. }
  116. if (this.unsubscribeTheme) {
  117. this.unsubscribeTheme()
  118. this.unsubscribeTheme = null
  119. }
  120. if (this.unsubscribeGenericModbus) {
  121. this.unsubscribeGenericModbus()
  122. this.unsubscribeGenericModbus = null
  123. }
  124. if (this.unsubscribeSettings) {
  125. this.unsubscribeSettings()
  126. this.unsubscribeSettings = null
  127. }
  128. this.clearGenericAutoTimers()
  129. },
  130. async onGroupRead(event) {
  131. if (!this.data.connectedDevice) return
  132. const groupKey = event.currentTarget.dataset.group
  133. const nextState = await paramsService.readGroup(this.data, groupKey)
  134. if (nextState) {
  135. this.setData(nextState)
  136. if (this.pageToast) this.pageToast.show(`${getGroupLabel(groupKey)}读取完成`)
  137. }
  138. },
  139. async onGroupWrite(event) {
  140. if (!this.data.connectedDevice) return
  141. const groupKey = event.currentTarget.dataset.group
  142. const written = await paramsService.writeGroup(this.data, groupKey)
  143. if (written) {
  144. this.setData(paramsPageState.clearGroupDirty(this.data, groupKey))
  145. if (this.pageToast) this.pageToast.show(`${getGroupLabel(groupKey)}写入完成`)
  146. }
  147. },
  148. async readCombinedGroups(viewKey) {
  149. if (!this.data.connectedDevice) return false
  150. const groupKeys = getCombinedGroupKeys(viewKey)
  151. let nextState = this.data
  152. for (const groupKey of groupKeys) {
  153. const updatedState = await paramsService.readGroup(nextState, groupKey)
  154. if (!updatedState) {
  155. if (nextState !== this.data) this.setData(nextState)
  156. return false
  157. }
  158. nextState = updatedState
  159. this.setData(nextState)
  160. }
  161. if (this.pageToast) this.pageToast.show(`${getCombinedGroupLabel(viewKey)}读取完成`)
  162. return true
  163. },
  164. async writeCombinedGroups(viewKey) {
  165. if (!this.data.connectedDevice) return false
  166. const groupKeys = getCombinedGroupKeys(viewKey)
  167. let nextState = this.data
  168. let writtenAny = false
  169. for (const groupKey of groupKeys) {
  170. if (!hasWritableGroupChanges(nextState, groupKey)) continue
  171. const written = await paramsService.writeGroup(nextState, groupKey)
  172. if (!written) {
  173. if (writtenAny) this.setData(nextState)
  174. return false
  175. }
  176. nextState = paramsPageState.clearGroupDirty(nextState, groupKey)
  177. writtenAny = true
  178. this.setData(nextState)
  179. }
  180. if (!writtenAny) {
  181. if (this.pageToast) this.pageToast.show('暂无需要写入的参数')
  182. return false
  183. }
  184. if (this.pageToast) this.pageToast.show(`${getCombinedGroupLabel(viewKey)}写入完成`)
  185. return true
  186. },
  187. readStartupManagement() {
  188. this.readCombinedGroups('startup')
  189. },
  190. writeStartupManagement() {
  191. this.writeCombinedGroups('startup')
  192. },
  193. readSpeedManagement() {
  194. this.readCombinedGroups('speed')
  195. },
  196. writeSpeedManagement() {
  197. this.writeCombinedGroups('speed')
  198. },
  199. onEstimatorUpdate() {
  200. this.setData(paramsPageState.refreshState(this.data))
  201. if (this.pageToast) this.pageToast.show('估算器参数更新完成')
  202. },
  203. openParamView(event) {
  204. if (this.pageToast) this.pageToast.clear()
  205. this.closeGenericModbusDraft()
  206. const activeParamView = event.currentTarget.dataset.view
  207. if (!activeParamView) return
  208. this.setData({
  209. activeParamView
  210. })
  211. if (activeParamView === 'genericModbus') {
  212. setTimeout(() => this.scheduleVisibleGenericAutoReads(), 0)
  213. }
  214. },
  215. backToParamsHome() {
  216. if (this.pageToast) this.pageToast.clear()
  217. this.closeGenericModbusDraft()
  218. this.clearGenericAutoTimers()
  219. const activeParamView = resolveActiveParamView('', this.data)
  220. this.setData({
  221. activeParamView
  222. })
  223. if (activeParamView === 'genericModbus') {
  224. setTimeout(() => this.scheduleVisibleGenericAutoReads(), 0)
  225. }
  226. },
  227. onMotorParameterInput(event) {
  228. controlService.updateMotorParameterInput(
  229. Number(event.currentTarget.dataset.index),
  230. event.detail.value
  231. )
  232. },
  233. onMotorParameterBlur(event) {
  234. controlService.updateMotorParameterBlur(
  235. Number(event.currentTarget.dataset.index),
  236. event.detail.value
  237. )
  238. },
  239. writeMotorParameters() {
  240. if (!this.data.connectedDevice) return
  241. controlService.writeMotorParameters()
  242. },
  243. async readDriverPageParameters() {
  244. if (!this.data.connectedDevice) return
  245. await controlService.readDriverParameters()
  246. await controlService.readMotorParameters()
  247. },
  248. readStatus() {
  249. if (!this.data.canReadStatus) return
  250. controlService.readStatus()
  251. },
  252. onInputChange(event) {
  253. this.setData(paramsPageState.applyParameterInput(
  254. this.data,
  255. Number(event.currentTarget.dataset.index),
  256. event.detail.value
  257. ))
  258. },
  259. onAtoBandwidthInput(event) {
  260. this.setData(paramsPageState.applyAtoBandwidthInput(
  261. this.data,
  262. Number(event.currentTarget.dataset.index),
  263. event.detail.value
  264. ))
  265. },
  266. onDqGainInput(event) {
  267. this.setData(paramsPageState.applyDqGainInput(
  268. this.data,
  269. Number(event.currentTarget.dataset.index),
  270. event.detail.value
  271. ))
  272. },
  273. onSpeedLoopExtraInput(event) {
  274. this.setData(paramsPageState.applySpeedLoopExtraInput(
  275. this.data,
  276. Number(event.currentTarget.dataset.index),
  277. event.detail.value
  278. ))
  279. },
  280. onOilParameterInput(event) {
  281. this.setData(paramsPageState.applyOilParameterInput(
  282. this.data,
  283. Number(event.currentTarget.dataset.index),
  284. event.detail.value
  285. ))
  286. },
  287. onPrepositionParameterInput(event) {
  288. this.setData(paramsPageState.applyPrepositionParameterInput(
  289. this.data,
  290. Number(event.currentTarget.dataset.index),
  291. event.detail.value
  292. ))
  293. },
  294. onInputBlur(event) {
  295. this.setData(paramsPageState.applyInputBlur(
  296. this.data,
  297. event.currentTarget.dataset.inputGroup,
  298. Number(event.currentTarget.dataset.index),
  299. event.detail.value
  300. ))
  301. },
  302. onTailwindSwitchChange(event) {
  303. if (!this.data.connectedDevice) return
  304. const index = Number(event.currentTarget.dataset.index)
  305. const nextState = paramsPageState.applyTailwindSwitchChange(
  306. this.data,
  307. index,
  308. !!event.detail.value
  309. )
  310. this.setData(nextState)
  311. paramsService.writeSwitchRegister(nextState.tailwindSwitchRegisters[index]).then((written) => {
  312. if (written) {
  313. this.setData(paramsPageState.clearTailwindSwitchDirty(this.data, index))
  314. if (this.pageToast) this.pageToast.show(`${nextState.tailwindSwitchRegisters[index].name}写入完成`)
  315. }
  316. })
  317. },
  318. onProtectionSwitchChange(event) {
  319. if (!this.data.connectedDevice) return
  320. const index = Number(event.currentTarget.dataset.index)
  321. const nextState = paramsPageState.applyProtectionSwitchChange(
  322. this.data,
  323. index,
  324. !!event.detail.value
  325. )
  326. this.setData(nextState)
  327. paramsService.writeSwitchRegister(nextState.protectionSwitchRegisters[index]).then((written) => {
  328. if (written) {
  329. this.setData(paramsPageState.clearProtectionSwitchDirty(this.data, index))
  330. if (this.pageToast) this.pageToast.show(`${nextState.protectionSwitchRegisters[index].name}写入完成`)
  331. }
  332. })
  333. },
  334. onProtectionInputChange(event) {
  335. this.setData(paramsPageState.applyProtectionInput(
  336. this.data,
  337. Number(event.currentTarget.dataset.index),
  338. event.detail.value
  339. ))
  340. },
  341. noop() {},
  342. updateGenericModbusDialog(changedData) {
  343. this.setData({
  344. genericModbusDialog: {
  345. ...this.data.genericModbusDialog,
  346. ...changedData
  347. }
  348. })
  349. },
  350. openGenericModbusDraft(event) {
  351. const groupId = event && event.currentTarget && event.currentTarget.dataset
  352. ? event.currentTarget.dataset.groupId
  353. : ''
  354. const group = groupId ? findGenericGroup(this.data.genericModbusGroups, groupId) : null
  355. this.updateGenericModbusDialog(createGenericGroupDialogState(group))
  356. },
  357. closeGenericModbusDraft() {
  358. this.genericModbusGroupLongPressGuard = ''
  359. this.genericModbusRegisterLongPressGuard = ''
  360. this.updateGenericModbusDialog(createGenericModbusDialogState())
  361. },
  362. onGenericDraftInput(event) {
  363. const field = event.currentTarget.dataset.field
  364. if (!field) return
  365. this.updateGenericModbusDialog({
  366. [field]: event.detail.value
  367. })
  368. },
  369. onGenericDraftTypeChange(event) {
  370. const registerTypeIndex = Number(event.detail.value)
  371. const registerType = getGenericOption(this.data.genericModbusRegisterTypeOptions, registerTypeIndex)
  372. this.updateGenericModbusDialog({
  373. registerTypeIndex,
  374. registerTypeText: registerType.label || ''
  375. })
  376. },
  377. onGenericDialogDataTypeChange(event) {
  378. const dataTypeIndex = Number(event.detail.value)
  379. this.updateGenericModbusDialog(getGenericDialogDataTypeState(
  380. this.data.genericModbusDialog,
  381. this.data.genericModbusDataTypeOptions,
  382. dataTypeIndex
  383. ))
  384. },
  385. openGenericGroupEdit(event) {
  386. const groupId = event.currentTarget.dataset.groupId
  387. const group = findGenericGroup(this.data.genericModbusGroups, groupId)
  388. if (!group) return
  389. this.genericModbusGroupLongPressGuard = groupId
  390. this.updateGenericModbusDialog(createGenericGroupDialogState(group))
  391. },
  392. openGenericRegisterInfo(event) {
  393. const groupId = event.currentTarget.dataset.groupId
  394. const registerIndex = Number(event.currentTarget.dataset.index)
  395. const registerKey = `${groupId}:${registerIndex}`
  396. if (this.genericModbusRegisterLongPressGuard === registerKey) {
  397. this.genericModbusRegisterLongPressGuard = ''
  398. return
  399. }
  400. const {
  401. group,
  402. register
  403. } = findGenericRegister(this.data.genericModbusGroups, groupId, registerIndex)
  404. if (!register) return
  405. this.updateGenericModbusDialog(createGenericRegisterDialogState('viewRegister', group, register, registerIndex))
  406. },
  407. openGenericRegisterEdit(event) {
  408. const groupId = event.currentTarget.dataset.groupId
  409. const registerIndex = Number(event.currentTarget.dataset.index)
  410. const {
  411. group,
  412. register
  413. } = findGenericRegister(this.data.genericModbusGroups, groupId, registerIndex)
  414. if (!register) return
  415. this.genericModbusRegisterLongPressGuard = `${groupId}:${registerIndex}`
  416. this.updateGenericModbusDialog(createGenericRegisterDialogState('editRegister', group, register, registerIndex))
  417. },
  418. async confirmGenericModbusDialog() {
  419. const dialog = this.data.genericModbusDialog || createGenericModbusDialogState()
  420. const mode = dialog.mode
  421. if (mode === 'createGroup') {
  422. const group = genericModbusService.addGroupFromConfig(createGenericGroupConfig(dialog))
  423. if (group) {
  424. if (this.pageToast) this.pageToast.show(`${group.name}已添加`)
  425. this.closeGenericModbusDraft()
  426. }
  427. return
  428. }
  429. if (mode === 'editGroup') {
  430. const group = genericModbusService.updateGroupConfig(dialog.groupId, createGenericGroupConfig(dialog))
  431. if (group) {
  432. if (this.pageToast) this.pageToast.show(`${group.name}已更新`)
  433. this.closeGenericModbusDraft()
  434. }
  435. return
  436. }
  437. if (mode === 'editRegister') {
  438. const changedData = createGenericRegisterChangedData(dialog, this.data.genericModbusDataTypeOptions)
  439. genericModbusService.updateRegister(dialog.groupId, dialog.registerIndex, changedData)
  440. if (this.pageToast) this.pageToast.show(`${dialog.name || '寄存器'}已更新`)
  441. this.closeGenericModbusDraft()
  442. }
  443. },
  444. async importGenericModbusJson() {
  445. const count = await genericModbusService.importJsonFromMessageFile()
  446. if (count && this.pageToast) this.pageToast.show(`已导入 ${count} 个寄存器组`)
  447. },
  448. async saveGenericModbusJson() {
  449. const count = await genericModbusService.saveJsonToChat()
  450. if (count && this.pageToast) this.pageToast.show(`已保存 ${count} 个寄存器组`)
  451. },
  452. toggleGenericModbusGroup(event) {
  453. const groupId = event.currentTarget.dataset.groupId
  454. if (this.genericModbusGroupLongPressGuard === groupId) {
  455. this.genericModbusGroupLongPressGuard = ''
  456. return
  457. }
  458. const group = findGenericGroup(this.data.genericModbusGroups, groupId)
  459. if (!group) return
  460. genericModbusService.setGroupExpanded(groupId, !group.expanded)
  461. },
  462. onGenericRegisterValueInput(event) {
  463. genericModbusService.updateRegisterValue(
  464. event.currentTarget.dataset.groupId,
  465. Number(event.currentTarget.dataset.index),
  466. event.detail.value
  467. )
  468. },
  469. onGenericRegisterValueBlur(event) {
  470. const groupId = event.currentTarget.dataset.groupId
  471. const registerIndex = Number(event.currentTarget.dataset.index)
  472. try {
  473. genericModbusService.validateRegisterInputValue(groupId, registerIndex, event.detail.value)
  474. } catch (error) {
  475. if (this.pageToast) this.pageToast.show(error.message || '输入值无效', 'error')
  476. }
  477. },
  478. async readGenericModbusGroup(event) {
  479. if (!this.data.connectedDevice) return
  480. const groupId = event.currentTarget.dataset.groupId
  481. const ok = await genericModbusService.readGroup(groupId, {
  482. maxPacketLength: this.data.genericModbusMaxPacketLength
  483. })
  484. if (ok && this.pageToast) this.pageToast.show('通用Modbus读取完成')
  485. },
  486. async writeGenericModbusGroup(event) {
  487. if (!this.data.connectedDevice) return
  488. const groupId = event.currentTarget.dataset.groupId
  489. const ok = await genericModbusService.writeGroup(groupId)
  490. if (ok && this.pageToast) this.pageToast.show('通用Modbus写入完成')
  491. },
  492. onGenericGroupTouchStart(event) {
  493. const groupId = event.currentTarget.dataset.groupId
  494. const touch = (event.changedTouches || [])[0]
  495. if (!groupId || !touch) return
  496. this.genericModbusTouchStarts[groupId] = touch.clientX
  497. },
  498. onGenericGroupTouchEnd(event) {
  499. const groupId = event.currentTarget.dataset.groupId
  500. const group = findGenericGroup(this.data.genericModbusGroups, groupId)
  501. const touch = (event.changedTouches || [])[0]
  502. const startX = this.genericModbusTouchStarts[groupId]
  503. if (!groupId || !group || group.expanded || !touch || !Number.isFinite(startX)) return
  504. const deltaX = touch.clientX - startX
  505. if (deltaX > 42) {
  506. genericModbusService.setGroupDeleteVisible(groupId, true)
  507. } else if (deltaX < -24) {
  508. genericModbusService.setGroupDeleteVisible(groupId, false)
  509. }
  510. },
  511. deleteGenericModbusGroup(event) {
  512. const groupId = event.currentTarget.dataset.groupId
  513. this.clearGenericAutoTimer(groupId)
  514. genericModbusService.removeGroup(groupId)
  515. if (this.pageToast) this.pageToast.show('寄存器组已删除')
  516. },
  517. clearGenericAutoTimer(groupId) {
  518. if (this.genericModbusPoller) this.genericModbusPoller.clearTimer(groupId)
  519. },
  520. clearGenericAutoTimers() {
  521. if (this.genericModbusPoller) this.genericModbusPoller.clearAll()
  522. },
  523. scheduleVisibleGenericAutoReads() {
  524. if (this.genericModbusPoller) this.genericModbusPoller.scheduleVisible()
  525. },
  526. scheduleGenericAutoPoll(delay) {
  527. if (this.genericModbusPoller) this.genericModbusPoller.schedule(delay)
  528. }
  529. })