| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- const settingsService = require('../../store/settings-store.js')
- const transport = require('../../transport/ble-core.js')
- const modbusProtocol = require('../../protocols/modbus-rtu/index.js')
- const {
- addCoilReadValues,
- addWordReadValues
- } = require('../../utils/register-value-utils.js')
- function getSharedSlaveAddress(title = '从机地址错误') {
- try {
- return settingsService.getModbusSlaveAddress()
- } catch (error) {
- transport.showCommandAlert(title, error.message)
- return null
- }
- }
- function formatAddress(value) {
- return Number(value || 0).toString(16).toUpperCase()
- }
- function getChunkLabel(label, chunks, chunk) {
- if (!label || chunks.length <= 1) return label
- return `${label} ${formatAddress(chunk.address)}-${formatAddress(chunk.address + chunk.quantity - 1)}`
- }
- function isBroadcastAddress(slaveAddress) {
- return Number(slaveAddress) === 0
- }
- function showBroadcastReadAlert(label) {
- transport.showCommandAlert(label || '读取命令错误', '广播地址 0x00 不支持读取')
- }
- async function sendReadChunk(slaveAddress, functionCode, chunk, label, kind, options = {}) {
- if (isBroadcastAddress(slaveAddress)) {
- showBroadcastReadAlert(label)
- return false
- }
- return transport.sendManagedFrame(
- modbusProtocol.buildReadFrame(slaveAddress, functionCode, chunk.address, chunk.quantity, {
- maxFrameBytes: options.maxFrameBytes
- }),
- label,
- {
- address: chunk.address,
- functionCode,
- kind,
- protocol: modbusProtocol.PROTOCOL_NAME,
- quantity: chunk.quantity,
- slaveAddress
- },
- {
- maxFrameBytes: options.maxFrameBytes,
- showModal: options.showModal
- }
- )
- }
- async function readSpans(slaveAddress, functionCode, spans, label, kind, options = {}) {
- const readValues = {
- coils: {},
- words: {}
- }
- const normalizedSpans = (spans || []).filter((span) => span && span.quantity > 0)
- for (const span of normalizedSpans) {
- const chunks = modbusProtocol.getReadChunks(functionCode, span.address, span.quantity, options)
- for (const chunk of chunks) {
- const responseValue = await sendReadChunk(
- slaveAddress,
- functionCode,
- chunk,
- getChunkLabel(label, chunks, chunk),
- kind,
- options
- )
- if (!responseValue) return null
- if (functionCode === 0x01 || functionCode === 0x02) {
- addCoilReadValues(readValues, chunk.address, chunk.quantity, responseValue)
- } else {
- addWordReadValues(readValues, chunk.address, responseValue)
- }
- if (typeof options.onChunk === 'function') {
- options.onChunk(responseValue, chunk)
- }
- }
- }
- return readValues
- }
- async function readRegisterWords(slaveAddress, functionCode, startAddress, quantity, label, kind, options = {}) {
- const words = []
- const chunks = modbusProtocol.getReadChunks(functionCode, startAddress, quantity, options)
- for (const chunk of chunks) {
- const responseValue = await sendReadChunk(
- slaveAddress,
- functionCode,
- chunk,
- getChunkLabel(label, chunks, chunk),
- kind,
- options
- )
- if (!responseValue) return null
- const chunkWords = responseValue.words || []
- chunkWords.forEach((word, index) => {
- words[chunk.address - startAddress + index] = Number(word) & 0xFFFF
- })
- if (typeof options.onChunk === 'function') {
- options.onChunk(responseValue, chunk)
- }
- }
- return words
- }
- async function readBitValues(slaveAddress, functionCode, startAddress, quantity, label, kind, options = {}) {
- const result = await readSpans(
- slaveAddress,
- functionCode,
- [{ address: startAddress, quantity }],
- label,
- kind,
- options
- )
- return result ? result.coils : null
- }
- async function readSingleHoldingWord(slaveAddress, address, label = '读取配对寄存器', kind = 'holding-word-read') {
- const words = await readRegisterWords(slaveAddress, 0x03, address, 1, label, kind)
- return words && Number.isInteger(words[0]) ? words[0] & 0xFFFF : null
- }
- function writeSingleCoil(slaveAddress, address, checked, label, kind = 'coil-write', options = {}) {
- const coilValue = checked ? 0xFF00 : 0x0000
- return transport.sendManagedFrame(
- modbusProtocol.buildWriteSingleCoilFrame(slaveAddress, address, checked),
- label,
- isBroadcastAddress(slaveAddress) ? null : {
- address,
- functionCode: 0x05,
- kind,
- protocol: modbusProtocol.PROTOCOL_NAME,
- quantity: 1,
- slaveAddress,
- value: coilValue
- },
- {
- maxFrameBytes: options.maxFrameBytes,
- showModal: options.showModal
- }
- )
- }
- function writeSingleRegister(slaveAddress, address, value, label, kind = 'register-write', options = {}) {
- return transport.sendManagedFrame(
- modbusProtocol.buildWriteSingleRegisterFrame(slaveAddress, address, value),
- label,
- isBroadcastAddress(slaveAddress) ? null : {
- address,
- functionCode: 0x06,
- kind,
- protocol: modbusProtocol.PROTOCOL_NAME,
- quantity: 1,
- slaveAddress,
- value
- },
- {
- maxFrameBytes: options.maxFrameBytes,
- showModal: options.showModal
- }
- )
- }
- function writeMultipleRegisters(slaveAddress, address, values, label, kind = 'registers-write', options = {}) {
- return transport.sendManagedFrame(
- modbusProtocol.buildWriteMultipleRegistersFrame(slaveAddress, address, values, {
- maxFrameBytes: options.maxFrameBytes
- }),
- label,
- isBroadcastAddress(slaveAddress) ? null : {
- address,
- functionCode: 0x10,
- kind,
- protocol: modbusProtocol.PROTOCOL_NAME,
- quantity: values.length,
- slaveAddress
- },
- {
- maxFrameBytes: options.maxFrameBytes,
- showModal: options.showModal
- }
- )
- }
- module.exports = {
- getMaxReadQuantity: modbusProtocol.getMaxReadQuantity,
- getMaxWriteMultipleRegisterQuantity: modbusProtocol.getMaxWriteMultipleRegisterQuantity,
- getReadChunks: modbusProtocol.getReadChunks,
- getSharedSlaveAddress,
- readBitValues,
- readRegisterWords,
- readSingleHoldingWord,
- readSpans,
- splitQuantity: modbusProtocol.splitQuantity,
- writeMultipleRegisters,
- writeSingleCoil,
- writeSingleRegister
- }
|