| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- const storageAccessProtocol = require('../../protocols/storage-access/index.js')
- const {
- bytesToHex,
- formatHexNumber
- } = require('../../utils/binary-utils.js')
- const {
- normalizeHexDwordText,
- normalizeHexText,
- normalizeHexWordText,
- parseHexBytes,
- parseHexDword,
- parseHexNumber,
- validateHexDwordText,
- validateHexText,
- validateHexWordText
- } = require('../../utils/validation.js')
- const {
- getManualMemoryAreaOptions
- } = require('./memory-areas.js')
- const protocolIo = require('./protocol-io.js')
- const MEMORY_COMMANDS = [
- { key: 'read', label: '读取', description: '按字节读取内存' },
- { key: 'write', label: '写入', description: '按字节写入内存' }
- ]
- const CONTROL_COMMANDS = [
- { key: 'reset', label: '复位', op: storageAccessProtocol.CONTROL_OP.RESET }
- ]
- function getMemoryAreaOptions() {
- return getManualMemoryAreaOptions()
- }
- function resolveMemoryCommand(index) {
- const commandIndex = Number(index) === 1 ? 1 : 0
- return {
- command: MEMORY_COMMANDS[commandIndex],
- index: commandIndex
- }
- }
- function resolveMemoryArea(index, commandKey = 'read') {
- const memoryAreas = getMemoryAreaOptions()
- let areaIndex = Number(index) || 0
- if (commandKey === 'write' && memoryAreas[areaIndex] && memoryAreas[areaIndex].readOnly) {
- areaIndex = 0
- }
- if (!memoryAreas[areaIndex]) areaIndex = 0
- return {
- area: memoryAreas[areaIndex] || memoryAreas[0],
- index: areaIndex,
- options: memoryAreas
- }
- }
- function normalizeDisplayHexText(value, addressWidth = 16) {
- const text = addressWidth === 32
- ? normalizeHexDwordText(value)
- : normalizeHexWordText(value)
- return text.toUpperCase()
- }
- function buildMemoryPreview(commandKey, area, address, length, dataBytes) {
- try {
- const frameOptions = protocolIo.normalizeProtocolIoOptions({
- maxFrameBytes: 0,
- useDeviceCaps: false,
- showModal: false
- })
- if (commandKey === 'write') {
- return bytesToHex(storageAccessProtocol.buildWriteFrame(area, address, dataBytes, frameOptions), ' ')
- }
- return bytesToHex(storageAccessProtocol.buildReadFrame(area, address, length, frameOptions), ' ')
- } catch (error) {
- return ''
- }
- }
- function normalizeMemoryCommandState(current = {}, changed = {}) {
- const next = {
- storageAccessAddress: current.storageAccessAddress || '',
- storageAccessAreaIndex: current.storageAccessAreaIndex || 0,
- storageAccessCommandIndex: current.storageAccessCommandIndex || 0,
- storageAccessDataText: current.storageAccessDataText || '',
- storageAccessLength: current.storageAccessLength || '',
- ...changed
- }
- const resolvedCommand = resolveMemoryCommand(next.storageAccessCommandIndex)
- const command = resolvedCommand.command
- const resolvedArea = resolveMemoryArea(next.storageAccessAreaIndex, command.key)
- const area = resolvedArea.area
- const addressWidth = Number(area.addressWidth) === 32 ? 32 : 16
- const addressText = normalizeDisplayHexText(next.storageAccessAddress, addressWidth)
- const lengthText = normalizeDisplayHexText(next.storageAccessLength, 16)
- const dataText = normalizeHexText(next.storageAccessDataText)
- const dataBytes = dataText ? parseHexBytes(dataText) : []
- const address = parseInt(addressText || '0', 16)
- const byteLength = parseInt(lengthText || '0', 16)
- const hasAddressText = !!addressText.trim()
- const hasLengthText = !!lengthText.trim()
- const addressError = hasAddressText
- ? (addressWidth === 32
- ? validateHexDwordText(addressText, '地址')
- : validateHexWordText(addressText, '地址'))
- : ''
- const lengthError = hasLengthText ? validateHexWordText(lengthText, '长度') : ''
- let errorText = addressError || lengthError
- if (!errorText && hasLengthText && byteLength <= 0) {
- errorText = '长度必须大于 0'
- } else if (!errorText && command.key === 'write') {
- const hexError = validateHexText(next.storageAccessDataText)
- if (hexError) {
- errorText = hexError
- } else if (area.readOnly) {
- errorText = `${area.label} 区不可写`
- } else if (dataBytes.length !== byteLength) {
- errorText = `写入长度为 ${byteLength} 字节,当前数据为 ${dataBytes.length} 字节`
- }
- }
- const canPreview = !errorText && hasAddressText && hasLengthText && byteLength > 0
- return {
- storageAccessAddress: addressText,
- storageAccessAddressMaxLength: addressWidth === 32 ? 8 : 4,
- storageAccessAddressWidthText: `${addressWidth}bit`,
- storageAccessAreaIndex: resolvedArea.index,
- storageAccessAreaLabel: area.label,
- storageAccessAreaLocked: false,
- storageAccessAreaOptions: resolvedArea.options,
- storageAccessCommandIndex: resolvedCommand.index,
- storageAccessCommandLabel: command.label,
- storageAccessDataText: dataText,
- storageAccessErrorText: errorText,
- storageAccessLength: lengthText,
- storageAccessPreviewHexText: canPreview
- ? buildMemoryPreview(command.key, area.key, address, byteLength, dataBytes)
- : '',
- storageAccessPreviewText: canPreview
- ? `${area.label} 0x${formatHexNumber(address, addressWidth === 32 ? 8 : 4)} / ${byteLength} bytes`
- : '',
- storageAccessShowWriteData: command.key === 'write',
- storageAccessTitleText: `${command.label}命令`
- }
- }
- function parseMemoryCommandInput(data = {}) {
- const state = normalizeMemoryCommandState(data)
- const command = resolveMemoryCommand(state.storageAccessCommandIndex).command
- const area = resolveMemoryArea(state.storageAccessAreaIndex, command.key).area
- if (state.storageAccessErrorText) {
- throw new Error(state.storageAccessErrorText)
- }
- if (!String(state.storageAccessAddress || '').trim()) {
- throw new Error('地址请输入十六进制')
- }
- if (!String(state.storageAccessLength || '').trim()) {
- throw new Error('长度请输入十六进制')
- }
- return {
- area,
- areaValue: area.key,
- byteLength: parseHexNumber(state.storageAccessLength, '长度', 0xFFFF),
- command,
- commandKey: command.key,
- dataBytes: command.key === 'write' ? parseHexBytes(state.storageAccessDataText || '') : [],
- startAddress: Number(area.addressWidth) === 32
- ? parseHexDword(state.storageAccessAddress, '地址')
- : parseHexNumber(state.storageAccessAddress, '地址', 0xFFFF),
- state
- }
- }
- async function executeMemoryCommand(data = {}, options = {}) {
- const command = parseMemoryCommandInput(data)
- if (command.commandKey === 'read') {
- const bytes = await protocolIo.readMemory(
- command.areaValue,
- command.startAddress,
- command.byteLength,
- options.label || '存储访问协议读取',
- options.kind || 'communication-storage-read',
- options
- )
- return {
- bytes,
- command,
- ok: !!bytes,
- previewHex: bytes ? bytesToHex(bytes, ' ') : '',
- state: command.state
- }
- }
- const ok = await protocolIo.writeMemory(
- command.areaValue,
- command.startAddress,
- command.dataBytes,
- options.label || '存储访问协议写入',
- options.kind || 'communication-storage-write',
- options
- )
- return {
- command,
- ok,
- state: command.state
- }
- }
- function getControlCommand(commandKey) {
- return CONTROL_COMMANDS.find((command) => command.key === commandKey) || null
- }
- async function executeControlCommand(commandKey, data = {}, options = {}) {
- const command = getControlCommand(commandKey)
- if (!command) {
- return {
- errorText: '特殊指令无效',
- ok: false
- }
- }
- const response = await protocolIo.executeControl(
- command.op,
- [],
- command.label || '特殊指令',
- `storage-control-${command.key}`,
- {
- maxPacketLength: options.maxPacketLength,
- showModal: options.showModal !== false
- }
- )
- if (!response) {
- return {
- errorText: '指令执行失败或超时',
- ok: false
- }
- }
- return {
- command,
- ok: true,
- response
- }
- }
- module.exports = {
- executeControlCommand,
- executeMemoryCommand,
- getControlCommand,
- getMemoryAreaOptions,
- normalizeMemoryCommandState
- }
|