protocol-io.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. const storageAccessProtocol = require('../../protocols/storage-access/index.js')
  2. const settingsService = require('../../store/settings-store.js')
  3. const transport = require('../../transport/ble-core.js')
  4. let syncedDeviceCaps = {
  5. addressWidth: 0,
  6. maxPacketLength: 0,
  7. memoryEndian: ''
  8. }
  9. function getConfiguredMaxPacketLength(value) {
  10. const settings = settingsService.getState()
  11. const numberValue = Number(value === undefined ? settings.parameterMaxPacketLength : value)
  12. if (Number.isFinite(numberValue) && Math.round(numberValue) === 0) return 0
  13. if (Number.isFinite(numberValue) && numberValue > 0) return Math.round(numberValue)
  14. return 64
  15. }
  16. function resolveMaxPacketLength(value) {
  17. const configuredMaxPacketLength = getConfiguredMaxPacketLength(value)
  18. const deviceMaxPacketLength = Number(syncedDeviceCaps.maxPacketLength || 0)
  19. if (!Number.isFinite(deviceMaxPacketLength) || deviceMaxPacketLength <= 0) return configuredMaxPacketLength
  20. if (configuredMaxPacketLength === 0) return Math.round(deviceMaxPacketLength)
  21. return Math.min(configuredMaxPacketLength, Math.round(deviceMaxPacketLength))
  22. }
  23. function normalizeProtocolIoOptions(options = {}) {
  24. const maxPacketLength = options.maxPacketLength === undefined ? options.maxFrameBytes : options.maxPacketLength
  25. return {
  26. expectedByteLength: options.expectedByteLength,
  27. maxFrameBytes: options.useDeviceCaps === false
  28. ? getConfiguredMaxPacketLength(maxPacketLength)
  29. : resolveMaxPacketLength(maxPacketLength),
  30. onChunk: options.onChunk,
  31. showModal: options.showModal !== false
  32. }
  33. }
  34. function updateSyncedDeviceCaps(caps = {}) {
  35. const addressWidth = Number(caps.addressWidth)
  36. const maxPacketLength = Number(caps.maxPacketLength)
  37. const memoryEndian = String(caps.memoryEndian || '').trim().toLowerCase()
  38. syncedDeviceCaps = {
  39. addressWidth: addressWidth === 16 || addressWidth === 32 ? addressWidth : 0,
  40. maxPacketLength: Number.isFinite(maxPacketLength) && maxPacketLength > 0
  41. ? Math.round(maxPacketLength)
  42. : 0,
  43. memoryEndian: memoryEndian === 'little' ? 'little' : (memoryEndian === 'big' ? 'big' : '')
  44. }
  45. }
  46. function getSyncedDeviceCaps() {
  47. return {
  48. ...syncedDeviceCaps
  49. }
  50. }
  51. function createTransportOptions(protocolIoOptions = {}) {
  52. return {
  53. maxFrameBytes: protocolIoOptions.maxFrameBytes,
  54. showModal: protocolIoOptions.showModal
  55. }
  56. }
  57. function notifyChunk(protocolIoOptions = {}, response, chunk) {
  58. if (typeof protocolIoOptions.onChunk === 'function') {
  59. protocolIoOptions.onChunk(response, chunk)
  60. }
  61. }
  62. function sendStorageFrame(frameBytes, label, expected, protocolIoOptions = {}) {
  63. return transport.sendManagedFrame(
  64. frameBytes,
  65. label,
  66. expected,
  67. createTransportOptions(protocolIoOptions)
  68. )
  69. }
  70. async function readMemory(area, startAddress, byteLength, label, kind, options = {}) {
  71. const protocolIoOptions = normalizeProtocolIoOptions(options)
  72. const normalizedArea = storageAccessProtocol.normalizeMemoryArea(area)
  73. const bytes = []
  74. const chunks = storageAccessProtocol.getReadChunks(startAddress, byteLength, {
  75. ...protocolIoOptions,
  76. area: normalizedArea
  77. })
  78. for (const chunk of chunks) {
  79. const response = await sendStorageFrame(
  80. storageAccessProtocol.buildReadFrame(normalizedArea, chunk.address, chunk.quantity, {
  81. maxFrameBytes: protocolIoOptions.maxFrameBytes
  82. }),
  83. storageAccessProtocol.getChunkLabel(label, chunks, chunk),
  84. storageAccessProtocol.createExpected(normalizedArea, chunk.address, chunk.quantity, false, kind),
  85. protocolIoOptions
  86. )
  87. if (!response) return null
  88. const dataBytes = Array.isArray(response.dataBytes) ? response.dataBytes : []
  89. dataBytes.forEach((byte, index) => {
  90. bytes[chunk.address - startAddress + index] = Number(byte) & 0xFF
  91. })
  92. notifyChunk(protocolIoOptions, response, chunk)
  93. }
  94. return bytes
  95. }
  96. async function writeMemory(area, startAddress, bytes, label, kind, options = {}) {
  97. const protocolIoOptions = normalizeProtocolIoOptions(options)
  98. const normalizedArea = storageAccessProtocol.normalizeMemoryArea(area)
  99. const chunks = storageAccessProtocol.getWriteChunks(startAddress, bytes, {
  100. ...protocolIoOptions,
  101. area: normalizedArea
  102. })
  103. for (const chunk of chunks) {
  104. const response = await sendStorageFrame(
  105. storageAccessProtocol.buildWriteFrame(normalizedArea, chunk.address, chunk.dataBytes, {
  106. maxFrameBytes: protocolIoOptions.maxFrameBytes
  107. }),
  108. storageAccessProtocol.getChunkLabel(label, chunks, chunk),
  109. storageAccessProtocol.createExpected(normalizedArea, chunk.address, chunk.quantity, true, kind),
  110. protocolIoOptions
  111. )
  112. if (!response) return false
  113. notifyChunk(protocolIoOptions, response, chunk)
  114. }
  115. return true
  116. }
  117. async function executeControl(operation, dataBytes, label, kind, options = {}) {
  118. const protocolIoOptions = normalizeProtocolIoOptions(options)
  119. const response = await sendStorageFrame(
  120. storageAccessProtocol.buildControlFrame(operation, dataBytes),
  121. label,
  122. storageAccessProtocol.createControlExpected(operation, kind, {
  123. expectedByteLength: protocolIoOptions.expectedByteLength
  124. }),
  125. protocolIoOptions
  126. )
  127. return response || null
  128. }
  129. module.exports = {
  130. executeControl,
  131. getSyncedDeviceCaps,
  132. normalizeProtocolIoOptions,
  133. readMemory,
  134. resolveMaxPacketLength,
  135. updateSyncedDeviceCaps,
  136. writeMemory
  137. }