service.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. const storageAccessService = require('../storage-access/service.js')
  2. const transport = require('../../transport/ble-core.js')
  3. const {
  4. AREA
  5. } = require('../../protocols/storage-access/index.js')
  6. const {
  7. bytesToHex,
  8. stringToUtf8Bytes
  9. } = require('../../utils/binary-utils.js')
  10. const {
  11. STORAGE_ACCESS_AREA_OPTIONS,
  12. STORAGE_ACCESS_COMMAND_OPTIONS,
  13. normalizeSerialState,
  14. parseHexBytes,
  15. validateHexText
  16. } = require('./view-model.js')
  17. function getStorageAccessCommand(index) {
  18. return STORAGE_ACCESS_COMMAND_OPTIONS[Number(index) || 0] || STORAGE_ACCESS_COMMAND_OPTIONS[0]
  19. }
  20. function getStorageAccessArea(index) {
  21. return STORAGE_ACCESS_AREA_OPTIONS[Number(index) || 0] || STORAGE_ACCESS_AREA_OPTIONS[0]
  22. }
  23. async function sendSerialFrame(data = {}) {
  24. const serialInputText = String(data.serialInputText || '')
  25. const serialState = normalizeSerialState(data)
  26. const mode = serialState.serialMode
  27. if (!data.connectedDevice) {
  28. return {
  29. errorText: '请先连接蓝牙设备',
  30. ok: false
  31. }
  32. }
  33. if (serialState.serialErrorText) {
  34. return {
  35. errorText: serialState.serialErrorText,
  36. ok: false
  37. }
  38. }
  39. if (mode === 'hex') {
  40. const errorText = validateHexText(serialInputText)
  41. if (errorText) {
  42. return {
  43. errorText,
  44. ok: false
  45. }
  46. }
  47. const bytes = parseHexBytes(serialInputText)
  48. const previewHex = bytesToHex(bytes, ' ')
  49. const ok = await transport.sendRawFrameExact(new Uint8Array(bytes), 'SERIAL')
  50. return {
  51. bytes,
  52. ok,
  53. previewHex,
  54. serialState
  55. }
  56. }
  57. const bytes = stringToUtf8Bytes(serialInputText)
  58. if (!bytes.length) {
  59. return {
  60. errorText: '请输入要发送的文本',
  61. ok: false
  62. }
  63. }
  64. const ok = await transport.sendRawFrameExact(new Uint8Array(bytes), 'SERIAL')
  65. return {
  66. bytes,
  67. ok,
  68. previewHex: bytesToHex(bytes, ' '),
  69. serialState
  70. }
  71. }
  72. async function syncStorageAccessCodeInfo(data = {}) {
  73. const result = await storageAccessService.syncCodeInfo({
  74. maxPacketLength: data.parameterMaxPacketLength,
  75. showModal: true
  76. })
  77. if (!result || !result.ok) {
  78. return {
  79. ok: false
  80. }
  81. }
  82. const codeInfoAddressText = result.codeInfoAddressText || Number(result.codeInfoAddress || 0).toString(16).toUpperCase().padStart(4, '0')
  83. const codeInfoByteLengthText = result.codeInfoByteLengthText || Number(result.codeInfoByteLength || 0).toString(16).toUpperCase().padStart(4, '0')
  84. return {
  85. codeInfoAddress: result.codeInfoAddress,
  86. codeInfoAddressText,
  87. codeInfoByteLength: result.codeInfoByteLength,
  88. codeInfoByteLengthText,
  89. ok: true,
  90. syncInfoText: `0x0F info ${codeInfoAddressText}/${codeInfoByteLengthText}`
  91. }
  92. }
  93. async function executeStorageAccessProtocol(data = {}) {
  94. const command = getStorageAccessCommand(data.storageAccessCommandIndex)
  95. const area = getStorageAccessArea(data.storageAccessAreaIndex)
  96. const address = parseInt(data.storageAccessAddress || '0000', 16) || 0
  97. const length = parseInt(data.storageAccessLength || '0004', 16) || 0
  98. const dataBytes = parseHexBytes(data.storageAccessDataText || '')
  99. if (!data.connectedDevice) {
  100. return {
  101. errorText: '请先连接蓝牙设备',
  102. ok: false
  103. }
  104. }
  105. if (data.storageAccessErrorText) {
  106. return {
  107. errorText: data.storageAccessErrorText,
  108. ok: false
  109. }
  110. }
  111. if (command.key === 'sync') {
  112. return syncStorageAccessCodeInfo(data)
  113. }
  114. if (command.key === 'write' && (area.key === AREA.CODE || area.key === AREA.INFO)) {
  115. return {
  116. errorText: 'code/info 区暂不支持写入',
  117. ok: false
  118. }
  119. }
  120. if (command.key === 'read') {
  121. const bytes = await storageAccessService.readMemory(
  122. area.key,
  123. address,
  124. length,
  125. '私有协议读取',
  126. 'communication-storage-read',
  127. {
  128. maxPacketLength: data.parameterMaxPacketLength,
  129. showModal: true
  130. }
  131. )
  132. return {
  133. bytes,
  134. ok: !!bytes,
  135. previewHex: bytes ? bytesToHex(bytes, ' ') : ''
  136. }
  137. }
  138. const errorText = validateHexText(data.storageAccessDataText)
  139. if (errorText) {
  140. return {
  141. errorText,
  142. ok: false
  143. }
  144. }
  145. if (dataBytes.length !== length) {
  146. return {
  147. errorText: `写入长度为 ${length} 字节,当前数据为 ${dataBytes.length} 字节`,
  148. ok: false
  149. }
  150. }
  151. const ok = await storageAccessService.writeMemory(
  152. area.key,
  153. address,
  154. dataBytes,
  155. '私有协议写入',
  156. 'communication-storage-write',
  157. {
  158. maxPacketLength: data.parameterMaxPacketLength,
  159. showModal: true
  160. }
  161. )
  162. return {
  163. ok
  164. }
  165. }
  166. module.exports = {
  167. executeStorageAccessProtocol,
  168. sendSerialFrame
  169. }