const storageAccessProtocol = require('../../protocols/storage-access/index.js') const settingsService = require('../../store/settings-store.js') const transport = require('../../transport/ble-core.js') let syncedDeviceCaps = { addressWidth: 0, maxPacketLength: 0, memoryEndian: '' } function getConfiguredMaxPacketLength(value) { const settings = settingsService.getState() const numberValue = Number(value === undefined ? settings.parameterMaxPacketLength : value) if (Number.isFinite(numberValue) && Math.round(numberValue) === 0) return 0 if (Number.isFinite(numberValue) && numberValue > 0) return Math.round(numberValue) return 64 } function resolveMaxPacketLength(value) { const configuredMaxPacketLength = getConfiguredMaxPacketLength(value) const deviceMaxPacketLength = Number(syncedDeviceCaps.maxPacketLength || 0) if (!Number.isFinite(deviceMaxPacketLength) || deviceMaxPacketLength <= 0) return configuredMaxPacketLength if (configuredMaxPacketLength === 0) return Math.round(deviceMaxPacketLength) return Math.min(configuredMaxPacketLength, Math.round(deviceMaxPacketLength)) } function normalizeProtocolIoOptions(options = {}) { const maxPacketLength = options.maxPacketLength === undefined ? options.maxFrameBytes : options.maxPacketLength return { expectedByteLength: options.expectedByteLength, maxFrameBytes: options.useDeviceCaps === false ? getConfiguredMaxPacketLength(maxPacketLength) : resolveMaxPacketLength(maxPacketLength), onChunk: options.onChunk, showModal: options.showModal !== false } } function updateSyncedDeviceCaps(caps = {}) { const addressWidth = Number(caps.addressWidth) const maxPacketLength = Number(caps.maxPacketLength) const memoryEndian = String(caps.memoryEndian || '').trim().toLowerCase() syncedDeviceCaps = { addressWidth: addressWidth === 16 || addressWidth === 32 ? addressWidth : 0, maxPacketLength: Number.isFinite(maxPacketLength) && maxPacketLength > 0 ? Math.round(maxPacketLength) : 0, memoryEndian: memoryEndian === 'little' ? 'little' : (memoryEndian === 'big' ? 'big' : '') } } function getSyncedDeviceCaps() { return { ...syncedDeviceCaps } } async function readMemory(area, startAddress, byteLength, label, kind, options = {}) { const protocolIoOptions = normalizeProtocolIoOptions(options) const normalizedArea = storageAccessProtocol.normalizeMemoryArea(area) const bytes = [] const chunks = storageAccessProtocol.getReadChunks(startAddress, byteLength, { ...protocolIoOptions, area: normalizedArea }) for (const chunk of chunks) { const response = await transport.sendManagedFrame( storageAccessProtocol.buildReadFrame(normalizedArea, chunk.address, chunk.quantity, { maxFrameBytes: protocolIoOptions.maxFrameBytes }), storageAccessProtocol.getChunkLabel(label, chunks, chunk), storageAccessProtocol.createExpected(normalizedArea, chunk.address, chunk.quantity, false, kind), { maxFrameBytes: protocolIoOptions.maxFrameBytes, showModal: protocolIoOptions.showModal } ) if (!response) return null const dataBytes = Array.isArray(response.dataBytes) ? response.dataBytes : [] dataBytes.forEach((byte, index) => { bytes[chunk.address - startAddress + index] = Number(byte) & 0xFF }) if (typeof protocolIoOptions.onChunk === 'function') { protocolIoOptions.onChunk(response, chunk) } } return bytes } async function writeMemory(area, startAddress, bytes, label, kind, options = {}) { const protocolIoOptions = normalizeProtocolIoOptions(options) const normalizedArea = storageAccessProtocol.normalizeMemoryArea(area) const chunks = storageAccessProtocol.getWriteChunks(startAddress, bytes, { ...protocolIoOptions, area: normalizedArea }) for (const chunk of chunks) { const response = await transport.sendManagedFrame( storageAccessProtocol.buildWriteFrame(normalizedArea, chunk.address, chunk.dataBytes, { maxFrameBytes: protocolIoOptions.maxFrameBytes }), storageAccessProtocol.getChunkLabel(label, chunks, chunk), storageAccessProtocol.createExpected(normalizedArea, chunk.address, chunk.quantity, true, kind), { maxFrameBytes: protocolIoOptions.maxFrameBytes, showModal: protocolIoOptions.showModal } ) if (!response) return false if (typeof protocolIoOptions.onChunk === 'function') { protocolIoOptions.onChunk(response, chunk) } } return true } async function executeControl(operation, dataBytes, label, kind, options = {}) { const protocolIoOptions = normalizeProtocolIoOptions(options) const response = await transport.sendManagedFrame( storageAccessProtocol.buildControlFrame(operation, dataBytes), label, storageAccessProtocol.createControlExpected(operation, kind, { expectedByteLength: protocolIoOptions.expectedByteLength }), { maxFrameBytes: protocolIoOptions.maxFrameBytes, showModal: protocolIoOptions.showModal } ) return response || null } module.exports = { executeControl, getSyncedDeviceCaps, normalizeProtocolIoOptions, readMemory, resolveMaxPacketLength, updateSyncedDeviceCaps, writeMemory }