| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483 |
- const {
- controlButtonRegisters,
- motorParameterInputRegisters,
- readonlyParamRegisters,
- speedCommandRegister,
- statusRegisters
- } = require('./registers')
- const {
- parseHexInteger
- } = require('./base-utils')
- const {
- getSharedInputDefault,
- mergeInputValues,
- setSharedInputValues,
- updateDriverParams,
- toFiniteNumber
- } = require('./calculation-context')
- const {
- calculateParameterInputWriteValue,
- calculateSpeedCommandWriteValue,
- SCALE_MAX,
- formatFixedValue
- } = require('./conversions')
- const {
- updateStatusRegisterWords
- } = require('./status-format')
- const {
- floatToWords,
- getRegisterWordCache,
- toRegisterWord,
- toAddressKey,
- wordsToFloat
- } = require('./register-value-utils')
- const {
- appendInputUnit
- } = require('./input-value-utils')
- const AUTO_READ_MIN_INTERVAL = 100
- const AUTO_READ_MAX_INTERVAL = 3000
- const DEFAULT_AUTO_READ_INTERVAL = 100
- const MOTOR_PARAM_START_ADDRESS = 0x60
- const MOTOR_PARAM_WORD_COUNT = 8
- const DRIVER_PARAM_START_ADDRESS = 0xA0
- const STATUS_START_ADDRESS = 0xC0
- const USER_STATUS_START_ADDRESS = 0xD3
- const MAX_USER_STATUS_COUNT = statusRegisters.filter((item) => item.name.indexOf('用户状态字') === 0).length
- const DEFAULT_USER_STATUS_COUNT = 0
- function getRegisterSpanWordCount(registers, startAddress) {
- const endAddress = registers.reduce((maxAddress, item) => {
- const address = parseHexInteger(item.address)
- if (!Number.isFinite(address)) return maxAddress
- return Math.max(maxAddress, address + (item.registerCount || 1))
- }, startAddress)
- return endAddress - startAddress
- }
- const DRIVER_PARAM_WORD_COUNT = getRegisterSpanWordCount(readonlyParamRegisters, DRIVER_PARAM_START_ADDRESS)
- const BASE_STATUS_WORD_COUNT = USER_STATUS_START_ADDRESS - STATUS_START_ADDRESS
- const DRIVER_SUMMARY_REGISTER_NAMES = [
- '芯片型号',
- '全区 Flash 校验码',
- '型号'
- ]
- function isDriverSummaryRegister(item) {
- return DRIVER_SUMMARY_REGISTER_NAMES.includes(item.name)
- }
- function getDriverReadonlyParamRegisters(registers = readonlyParamRegisters) {
- return registers.filter((item) => !isDriverSummaryRegister(item))
- }
- function getInputValues(registers) {
- return registers.reduce((result, item) => {
- result[item.name] = toFiniteNumber(item.inputValue, getSharedInputDefault(item.name))
- return result
- }, {})
- }
- function updateMotorWriteValues(registers) {
- const inputValues = getInputValues(registers)
- return registers.map((item) => ({
- ...item,
- writeValue: calculateParameterInputWriteValue(item, item.inputValue, inputValues)
- }))
- }
- function formatReadInputValue(item, value) {
- if (!Number.isFinite(value)) return ''
- if (item.name === 'LD' || item.name === 'LQ') return formatFixedValue(value, 6)
- if (item.name === 'RS') return formatFixedValue(value, 4)
- if (item.type === 'float') return formatFixedValue(value, 2)
- return String(Math.round(value))
- }
- function formatHexWord(value) {
- return `0x${(Number(value) & 0xFFFF).toString(16).toUpperCase().padStart(4, '0')}`
- }
- function wordsToAscii(words, startIndex, byteLength) {
- const chars = []
- const wordCount = Math.ceil(byteLength / 2)
- for (let index = 0; index < wordCount; index += 1) {
- const word = Number(words[startIndex + index])
- if (!Number.isInteger(word)) break
- const bytes = [(word >> 8) & 0xFF, word & 0xFF]
- for (const byte of bytes) {
- if (chars.length >= byteLength || byte === 0) {
- return chars.join('').trim() || '--'
- }
- if (byte >= 0x20 && byte <= 0x7E) {
- chars.push(String.fromCharCode(byte))
- }
- }
- }
- return chars.join('').trim() || '--'
- }
- function clampNumber(value, minValue, maxValue, fallback) {
- const numberValue = toFiniteNumber(value, NaN)
- if (!Number.isFinite(numberValue)) return fallback
- return Math.min(Math.max(Math.round(numberValue), minValue), maxValue)
- }
- function getUserStatusCount(value) {
- return clampNumber(value, 0, MAX_USER_STATUS_COUNT, DEFAULT_USER_STATUS_COUNT)
- }
- function getStatusWordCount(userStatusCount = DEFAULT_USER_STATUS_COUNT) {
- return BASE_STATUS_WORD_COUNT + getUserStatusCount(userStatusCount)
- }
- function cloneRegister(item) {
- return {
- ...item
- }
- }
- function createInitialState() {
- return {
- autoReadInterval: DEFAULT_AUTO_READ_INTERVAL,
- autoReadStatus: false,
- connectedDevice: null,
- controlActionButtons: controlButtonRegisters.filter((item) => item.momentary).map(cloneRegister),
- controlButtons: controlButtonRegisters.filter((item) => !item.momentary).map(cloneRegister),
- errorText: '',
- isAwaitingResponse: false,
- isReadingDriver: false,
- isReadingMotor: false,
- isSending: false,
- isWritingMotor: false,
- chipModel: '--',
- flashChecksum: '--',
- motorModel: '--',
- motorParameterInputRegisters,
- readonlyParamRegisters: getDriverReadonlyParamRegisters(),
- speedCommand: speedCommandRegister,
- systemTip: '',
- userStatusCount: DEFAULT_USER_STATUS_COUNT
- }
- }
- function applyTransportState(data, transportState) {
- const nextState = {
- connectedDevice: transportState.connectedDevice,
- errorText: transportState.errorText,
- isAwaitingResponse: transportState.isAwaitingResponse,
- isSending: transportState.isSending,
- systemTip: transportState.systemTip
- }
- if (!transportState.connectedDevice && data.autoReadStatus) {
- nextState.autoReadStatus = false
- }
- if (!transportState.connectedDevice) {
- nextState.isReadingDriver = false
- nextState.isReadingMotor = false
- nextState.isWritingMotor = false
- }
- return nextState
- }
- function applyMotorParameterInput(data, index, value) {
- const changedRegisters = data.motorParameterInputRegisters.map((item, currentIndex) => {
- if (currentIndex !== index) return item
- return {
- ...item,
- isDirty: true,
- inputValue: value
- }
- })
- const nextRegisters = updateMotorWriteValues(changedRegisters)
- const inputValues = mergeInputValues(nextRegisters)
- setSharedInputValues(nextRegisters)
- return {
- motorParameterInputRegisters: nextRegisters,
- speedCommand: {
- ...data.speedCommand,
- isDirty: true,
- writeValue: calculateSpeedCommandWriteValue(data.speedCommand.inputValue, inputValues)
- }
- }
- }
- function applySpeedCommandInput(data, inputValue) {
- const inputValues = mergeInputValues(data.motorParameterInputRegisters)
- return {
- speedCommand: {
- ...data.speedCommand,
- isDirty: true,
- inputValue,
- writeValue: calculateSpeedCommandWriteValue(inputValue, inputValues)
- }
- }
- }
- function applySpeedCommandReadValue(data, rawValue) {
- const wordValue = Number(rawValue)
- if (!Number.isInteger(wordValue)) return {}
- const inputValues = mergeInputValues(data.motorParameterInputRegisters)
- const speedBase = toFiniteNumber(inputValues['速度基准'])
- const inputValue = speedBase > 0
- ? appendInputUnit(data.speedCommand, formatFixedValue(wordValue / SCALE_MAX * speedBase, 2))
- : data.speedCommand.inputValue
- return {
- speedCommand: {
- ...data.speedCommand,
- isDirty: false,
- inputValue,
- writeValue: String(wordValue & 0xFFFF)
- }
- }
- }
- function getControlButtonWriteValue(button) {
- if (!button) return 0
- return button.writeValue
- }
- function getNextControlButton(button) {
- if (button.momentary) return button
- return {
- ...button,
- name: button.nextName,
- nextName: button.name,
- nextWriteValue: button.writeValue,
- writeValue: button.nextWriteValue
- }
- }
- function applyControlSuccess(data, button) {
- if (!button) return {}
- if (button.momentary) {
- return {
- systemTip: `${button.name}已下发`
- }
- }
- return {
- controlButtons: data.controlButtons.map((item) => (
- item.key === button.key ? getNextControlButton(item) : item
- )),
- systemTip: `${button.name}已下发`
- }
- }
- function getControlButtonFromRead(button, value) {
- if (!button || button.momentary) return button
- const readValue = Number(value)
- if (!Number.isFinite(readValue)) return button
- if (Number(button.writeValue) === readValue) return getNextControlButton(button)
- if (Number(button.nextWriteValue) === readValue) return button
- return button
- }
- function applyControlReadValues(data, coilValues = {}) {
- return {
- controlButtons: data.controlButtons.map((item) => {
- const value = coilValues[toAddressKey(item.address)]
- return value === undefined ? item : getControlButtonFromRead(item, value)
- })
- }
- }
- function buildMotorMainWriteValues(data) {
- const registerMap = data.motorParameterInputRegisters.reduce((result, item) => {
- result[item.name] = item
- return result
- }, {})
- const ldWords = floatToWords(registerMap.LD && registerMap.LD.inputValue)
- const lqWords = floatToWords(registerMap.LQ && registerMap.LQ.inputValue)
- const rsWords = floatToWords(registerMap.RS && registerMap.RS.inputValue)
- const polePairsWord = toRegisterWord(registerMap['极对数'] && registerMap['极对数'].inputValue)
- const speedBaseWord = toRegisterWord(registerMap['速度基准'] && registerMap['速度基准'].inputValue)
- if (!ldWords || !lqWords || !rsWords || !Number.isInteger(polePairsWord) || !Number.isInteger(speedBaseWord)) {
- return {
- errorText: '请检查 LD、LQ、RS、极对数和速度基准的输入值',
- values: null
- }
- }
- return {
- errorText: '',
- values: ldWords.concat(lqWords, rsWords, [polePairsWord, speedBaseWord])
- }
- }
- function applyMotorParameterReadValues(data, registerWordCache) {
- const nextRegisters = data.motorParameterInputRegisters.map((item) => {
- let readValue = null
- if (item.name === 'LD' && registerWordCache[0x60] !== undefined && registerWordCache[0x61] !== undefined) {
- readValue = wordsToFloat(registerWordCache[0x60], registerWordCache[0x61])
- } else if (item.name === 'LQ' && registerWordCache[0x62] !== undefined && registerWordCache[0x63] !== undefined) {
- readValue = wordsToFloat(registerWordCache[0x62], registerWordCache[0x63])
- } else if (item.name === 'RS' && registerWordCache[0x64] !== undefined && registerWordCache[0x65] !== undefined) {
- readValue = wordsToFloat(registerWordCache[0x64], registerWordCache[0x65])
- } else if (item.name === '极对数' && registerWordCache[0x66] !== undefined) {
- readValue = registerWordCache[0x66]
- } else if (item.name === '速度基准' && registerWordCache[0x67] !== undefined) {
- readValue = registerWordCache[0x67]
- }
- if (readValue === null) return item
- return {
- ...item,
- isDirty: false,
- inputValue: appendInputUnit(item, formatReadInputValue(item, readValue))
- }
- })
- const nextWriteRegisters = updateMotorWriteValues(nextRegisters)
- const inputValues = mergeInputValues(nextWriteRegisters)
- setSharedInputValues(nextWriteRegisters)
- return {
- motorParameterInputRegisters: nextWriteRegisters,
- speedCommand: {
- ...data.speedCommand,
- writeValue: calculateSpeedCommandWriteValue(data.speedCommand.inputValue, inputValues)
- }
- }
- }
- function clearMotorParameterDirty(data) {
- return {
- motorParameterInputRegisters: data.motorParameterInputRegisters.map((item) => ({
- ...item,
- isDirty: false
- }))
- }
- }
- function clearSpeedCommandDirty(data) {
- return {
- speedCommand: {
- ...data.speedCommand,
- isDirty: false
- }
- }
- }
- function applyMotorParameterBlur(data, index, value) {
- const item = data.motorParameterInputRegisters[index]
- if (!item) return {}
- return applyMotorParameterInput(data, index, appendInputUnit(item, value === undefined ? item.inputValue : value))
- }
- function applySpeedCommandBlur(data, value) {
- return applySpeedCommandInput(
- data,
- appendInputUnit(data.speedCommand, value === undefined ? data.speedCommand.inputValue : value)
- )
- }
- function applyDriverParameterReadValues(data, words) {
- if (!Array.isArray(words) || words.length < DRIVER_PARAM_WORD_COUNT) return {}
- const carrierFrequencyKHz = (words[0] >> 8) & 0xFF
- const baseVoltage = (words[0] & 0xFF) / 10
- const opAmpGain = words[1] & 0xFFFF
- const samplingResistorMohm = words[2] & 0xFFFF
- const busVoltageDividerRatio = wordsToFloat(words[4], words[5])
- const analogInputDividerRatio = wordsToFloat(words[6], words[7])
- const displayValues = {
- 芯片型号: wordsToAscii(words, 8, 8),
- 型号: wordsToAscii(words, 12, 16),
- 载波频率: String(carrierFrequencyKHz),
- 基准电压: formatFixedValue(baseVoltage, 2),
- 运放倍数: String(opAmpGain),
- 采样电阻: String(samplingResistorMohm),
- '全区 Flash 校验码': formatHexWord(words[3]),
- 母线电压分压比: formatFixedValue(busVoltageDividerRatio, 2),
- 模拟输入电压分压比: formatFixedValue(analogInputDividerRatio, 2)
- }
- updateDriverParams({
- analogInputDividerRatio,
- baseVoltage,
- busVoltageDividerRatio,
- carrierFrequencyKHz,
- opAmpGain,
- samplingResistorMohm
- })
- return {
- chipModel: displayValues['芯片型号'],
- flashChecksum: displayValues['全区 Flash 校验码'],
- motorModel: displayValues['型号'],
- readonlyParamRegisters: getDriverReadonlyParamRegisters(data.readonlyParamRegisters).map((item) => ({
- ...item,
- displayValue: displayValues[item.name] || item.displayValue || '--'
- }))
- }
- }
- function applyStatusReadValues(words, startAddress = STATUS_START_ADDRESS) {
- if (!Array.isArray(words) || !words.length) return {}
- updateStatusRegisterWords(statusRegisters, startAddress, words)
- return {}
- }
- module.exports = {
- AUTO_READ_MAX_INTERVAL,
- AUTO_READ_MIN_INTERVAL,
- DRIVER_PARAM_START_ADDRESS,
- DRIVER_PARAM_WORD_COUNT,
- MAX_USER_STATUS_COUNT,
- MOTOR_PARAM_START_ADDRESS,
- MOTOR_PARAM_WORD_COUNT,
- STATUS_START_ADDRESS,
- applyControlReadValues,
- applyControlSuccess,
- applyDriverParameterReadValues,
- applyMotorParameterBlur,
- applyMotorParameterInput,
- applyMotorParameterReadValues,
- clearMotorParameterDirty,
- clearSpeedCommandDirty,
- applySpeedCommandBlur,
- applySpeedCommandInput,
- applySpeedCommandReadValue,
- applyStatusReadValues,
- applyTransportState,
- buildMotorMainWriteValues,
- clampNumber,
- createInitialState,
- getStatusWordCount,
- getControlButtonWriteValue,
- getRegisterWordCache,
- getUserStatusCount,
- setSharedInputValues
- }
|