| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- const {
- parseHexInteger
- } = require('../../utils/base-utils.js')
- const transport = require('../../transport/ble-core.js')
- const modbusProtocol = require('../../protocols/modbus-rtu/index.js')
- const {
- decodeRegisterValue,
- formatCoilDisplayValue,
- formatRegisterValue,
- getDataType,
- getGroupEncodedWords,
- getRegisterEncodedWords,
- getRegisterWordsFromWordCache,
- getRegisterWriteValueText,
- isBitRegisterType,
- isByteRegister,
- parseCoilValue,
- splitWordSpans
- } = require('../../domain/parameter-groups/model.js')
- function getWriteSpanMaxQuantity(totalQuantity, maxPacketLength) {
- if (maxPacketLength === 0) return Math.max(1, totalQuantity)
- return Math.max(1, modbusProtocol.client.getMaxWriteMultipleRegisterQuantity(maxPacketLength))
- }
- async function readGroup(group, options = {}) {
- const totalQuantity = Math.max(1, group.wordQuantity || group.quantity || 0)
- const wordCache = {}
- const slaveAddress = modbusProtocol.client.getSharedSlaveAddress()
- if (slaveAddress === null) return null
- const values = await modbusProtocol.client.readSpans(
- slaveAddress,
- group.functionCode,
- [{
- address: group.startAddress,
- quantity: totalQuantity
- }],
- group.name || '参数组读取',
- 'parameter-group-read',
- {
- maxFrameBytes: options.maxPacketLength,
- showModal: options.showModal !== false
- }
- )
- if (!values) return null
- if (isBitRegisterType(group.registerType)) {
- Object.keys(values.coils || {}).forEach((addressText) => {
- wordCache[parseHexInteger(addressText)] = Number(values.coils[addressText]) ? 1 : 0
- })
- } else {
- Object.keys(values.words || {}).forEach((addressText) => {
- wordCache[parseHexInteger(addressText)] = Number(values.words[addressText]) & 0xFFFF
- })
- }
- return wordCache
- }
- function getRegisterWordsForWrite(group) {
- const words = group.isStructLayout
- ? getGroupEncodedWords(group)
- : Array.from({ length: Math.max(1, group.wordQuantity || 1) }, () => 0)
- if (group.isStructLayout) return words
- for (let index = 0; index < group.registers.length; index += 1) {
- const register = group.registers[index]
- const registerWords = getRegisterEncodedWords(register)
- if (!Array.isArray(registerWords) || !registerWords.length) {
- throw new Error(`${register.name || `寄存器 ${index + 1}`} 没有有效写入值`)
- }
- const dataType = getDataType(register.dataType).key
- const relativeAddress = Math.max(0, register.address - group.startAddress)
- if (isByteRegister(dataType)) {
- const byteValue = Number(registerWords[0]) & 0xFF
- const currentWord = words[relativeAddress] || 0
- words[relativeAddress] = register.byteOffset === 0
- ? (((byteValue << 8) | (currentWord & 0x00FF)) & 0xFFFF)
- : (((currentWord & 0xFF00) | byteValue) & 0xFFFF)
- } else {
- for (let offset = 0; offset < register.registerCount; offset += 1) {
- words[relativeAddress + offset] = Number(registerWords[offset]) & 0xFFFF
- }
- }
- }
- return words
- }
- function createWrittenRegisterSnapshots(group, words = []) {
- const writtenWordCache = words.reduce((cache, word, offset) => {
- cache[group.startAddress + offset] = word
- return cache
- }, {})
- return group.registers.map((register) => {
- const rawWords = getRegisterWordsFromWordCache(register, writtenWordCache) || []
- const rawValue = decodeRegisterValue(register, rawWords)
- const displayValue = formatRegisterValue(register, rawValue)
- return {
- rawWords,
- rawValue,
- displayValue
- }
- })
- }
- async function writeCoilGroup(group, options = {}) {
- const slaveAddress = modbusProtocol.client.getSharedSlaveAddress()
- if (slaveAddress === null) return null
- const writtenRegisters = []
- for (let index = 0; index < group.registers.length; index += 1) {
- const register = group.registers[index]
- const coilValue = parseCoilValue(getRegisterWriteValueText(register))
- if (coilValue === null) {
- transport.showCommandAlert('参数组写入', `${register.name || `寄存器 ${index + 1}`} 没有有效写入值`)
- return null
- }
- const response = await modbusProtocol.client.writeSingleCoil(
- slaveAddress,
- group.startAddress + index,
- !!coilValue,
- register.name || group.name || '参数组写入',
- 'parameter-group-coil-write',
- {
- maxFrameBytes: options.maxPacketLength
- }
- )
- if (!response) return null
- writtenRegisters.push({
- rawBytes: [],
- rawValue: coilValue,
- rawWords: [],
- displayValue: formatCoilDisplayValue(coilValue)
- })
- }
- return writtenRegisters
- }
- async function writeRegisterGroup(group, options = {}) {
- const slaveAddress = modbusProtocol.client.getSharedSlaveAddress()
- if (slaveAddress === null) return null
- let words
- try {
- words = getRegisterWordsForWrite(group)
- } catch (error) {
- transport.showCommandAlert('参数组写入', error.message || '寄存器组没有有效写入值')
- return null
- }
- const writtenRegisters = createWrittenRegisterSnapshots(group, words)
- const maxWriteQuantity = getWriteSpanMaxQuantity(words.length, options.maxPacketLength)
- const spans = splitWordSpans(group.startAddress, words.length, maxWriteQuantity)
- let cursor = 0
- for (const span of spans) {
- const spanWords = words.slice(cursor, cursor + span.quantity)
- cursor += span.quantity
- const response = await modbusProtocol.client.writeMultipleRegisters(
- slaveAddress,
- span.address,
- spanWords,
- group.name || '参数组写入',
- 'parameter-group-write',
- {
- maxFrameBytes: options.maxPacketLength
- }
- )
- if (!response) return null
- }
- return writtenRegisters
- }
- async function writeGroup(group, options = {}) {
- return group.registerType === 'coil'
- ? writeCoilGroup(group, options)
- : writeRegisterGroup(group, options)
- }
- module.exports = {
- readGroup,
- writeGroup
- }
|