params-service.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. const {
  2. paramsState: paramsPageState
  3. } = require('./motor-control-data')
  4. const {
  5. expandItems,
  6. getAreaKey,
  7. getGroupItems,
  8. makeReadSpans,
  9. mergeReadValues,
  10. parseRegisterAddress
  11. } = require('./motor-control-register-groups')
  12. const transport = require('./ble-transport')
  13. const modbusAccess = require('./modbus-access')
  14. const {
  15. floatToWords,
  16. toRegisterWord
  17. } = require('./register-value-utils')
  18. function hasWriteValue(value) {
  19. return value !== '' && value !== undefined && value !== null && value !== '--'
  20. }
  21. function toWriteNumber(value) {
  22. if (!hasWriteValue(value)) return null
  23. const numberValue = Number(value)
  24. if (!Number.isFinite(numberValue)) return null
  25. return numberValue
  26. }
  27. async function readGroup(data, groupKey) {
  28. const slaveAddress = modbusAccess.getSharedSlaveAddress()
  29. if (slaveAddress === null) return false
  30. const items = expandItems(getGroupItems(data, groupKey))
  31. const coilItems = items.filter((item) => getAreaKey(item) === 'coil')
  32. const holdingItems = items.filter((item) => getAreaKey(item) === 'holding')
  33. const inputItems = items.filter((item) => getAreaKey(item) === 'input')
  34. const coilSpans = makeReadSpans(coilItems)
  35. const holdingSpans = makeReadSpans(holdingItems)
  36. const inputSpans = makeReadSpans(inputItems)
  37. const readValues = {
  38. coils: {},
  39. words: {}
  40. }
  41. let sent = false
  42. if (coilSpans.length) {
  43. sent = true
  44. const values = await modbusAccess.readSpans(
  45. slaveAddress,
  46. 0x01,
  47. coilSpans,
  48. '参数读取',
  49. 'params-read'
  50. )
  51. if (!values) return false
  52. mergeReadValues(readValues, values)
  53. }
  54. if (holdingSpans.length) {
  55. sent = true
  56. const values = await modbusAccess.readSpans(
  57. slaveAddress,
  58. 0x03,
  59. holdingSpans,
  60. '参数读取',
  61. 'params-read'
  62. )
  63. if (!values) return false
  64. mergeReadValues(readValues, values)
  65. }
  66. if (inputSpans.length) {
  67. sent = true
  68. const values = await modbusAccess.readSpans(
  69. slaveAddress,
  70. 0x04,
  71. inputSpans,
  72. '参数读取',
  73. 'params-read'
  74. )
  75. if (!values) return false
  76. mergeReadValues(readValues, values)
  77. }
  78. if (!sent) {
  79. transport.showCommandAlert('参数读取', '当前分组没有可读取的寄存器')
  80. return false
  81. }
  82. if (!Object.keys(readValues.coils).length && !Object.keys(readValues.words).length) {
  83. return false
  84. }
  85. return paramsPageState.applyReadValues(data, readValues)
  86. }
  87. async function buildHoldingWriteEntries(slaveAddress, items) {
  88. const normalEntries = []
  89. const byteGroups = {}
  90. items.forEach((item) => {
  91. if (getAreaKey(item) !== 'holding') return
  92. if (item.type === 'uint8_t' && item.bytePosition) {
  93. const address = parseRegisterAddress(item.address)
  94. const group = byteGroups[address] || {
  95. address,
  96. high: null,
  97. low: null
  98. }
  99. group[item.bytePosition] = item
  100. byteGroups[address] = group
  101. return
  102. }
  103. const writeNumber = toWriteNumber(item.writeValue)
  104. if (writeNumber === null) return
  105. const words = item.type === 'float'
  106. ? floatToWords(writeNumber)
  107. : [toRegisterWord(writeNumber)]
  108. if (!words || words.some((word) => word === null)) return
  109. normalEntries.push({
  110. address: parseRegisterAddress(item.address),
  111. label: item.name,
  112. values: words
  113. })
  114. })
  115. for (const addressText of Object.keys(byteGroups)) {
  116. const group = byteGroups[addressText]
  117. const highValue = group.high ? toRegisterWord(group.high.writeValue) : null
  118. const lowValue = group.low ? toRegisterWord(group.low.writeValue) : null
  119. if (highValue === null && lowValue === null) continue
  120. let baseWord = 0
  121. if (highValue === null || lowValue === null) {
  122. const readWord = await modbusAccess.readSingleHoldingWord(
  123. slaveAddress,
  124. group.address,
  125. '读取配对寄存器',
  126. 'params-pair-read'
  127. )
  128. if (!Number.isInteger(readWord)) continue
  129. baseWord = readWord
  130. }
  131. const nextHigh = highValue === null ? ((baseWord >> 8) & 0xFF) : highValue
  132. const nextLow = lowValue === null ? (baseWord & 0xFF) : lowValue
  133. if (nextHigh > 0xFF || nextLow > 0xFF) continue
  134. normalEntries.push({
  135. address: group.address,
  136. label: '8位参数',
  137. values: [(nextHigh << 8) | nextLow]
  138. })
  139. }
  140. return normalEntries.sort((left, right) => left.address - right.address)
  141. }
  142. async function writeGroup(data, groupKey) {
  143. const slaveAddress = modbusAccess.getSharedSlaveAddress()
  144. if (slaveAddress === null) return false
  145. const items = expandItems(getGroupItems(data, groupKey))
  146. const coilItems = items.filter((item) => getAreaKey(item) === 'coil' && item.isDirty)
  147. const holdingItems = items.filter((item) => getAreaKey(item) === 'holding')
  148. let sent = false
  149. for (const item of coilItems) {
  150. const checked = Number(item.writeValue) !== 0
  151. const address = parseRegisterAddress(item.address)
  152. sent = true
  153. const response = await modbusAccess.writeSingleCoil(
  154. slaveAddress,
  155. address,
  156. checked,
  157. item.name,
  158. 'params-coil-write'
  159. )
  160. if (!response) return false
  161. }
  162. const holdingEntries = await buildHoldingWriteEntries(slaveAddress, holdingItems)
  163. for (const entry of holdingEntries) {
  164. sent = true
  165. const response = await modbusAccess.writeMultipleRegisters(
  166. slaveAddress,
  167. entry.address,
  168. entry.values,
  169. entry.label,
  170. 'params-holding-write'
  171. )
  172. if (!response) return false
  173. }
  174. if (!sent) {
  175. transport.showCommandAlert('参数写入', '当前分组没有可写入的参数')
  176. }
  177. return sent
  178. }
  179. async function writeSwitchRegister(item) {
  180. const slaveAddress = modbusAccess.getSharedSlaveAddress()
  181. if (slaveAddress === null || !item) return false
  182. const address = parseRegisterAddress(item.address)
  183. const checked = Number(item.writeValue) !== 0
  184. return modbusAccess.writeSingleCoil(
  185. slaveAddress,
  186. address,
  187. checked,
  188. item.name,
  189. 'params-switch-write'
  190. )
  191. }
  192. module.exports = {
  193. readGroup,
  194. writeGroup,
  195. writeSwitchRegister
  196. }