error: Malformed value for push.default: 无

博客提及了dos命令,这是信息技术领域中常用的命令行操作方式,可用于系统管理、文件操作等,在计算机操作和开发中具有重要作用。

git config --global push.default matching 

dos命令

// ========== 功能码映射表 ========== const fcMap = { 1: "读线圈状态 (Read Coils)", 2: "读离散输入 (Read Discrete Inputs)", 3: "读保持寄存器 (Read Holding Registers)", 4: "读输入寄存器 (Read Input Registers)", 5: "写单个线圈 (Write Single Coil)", 6: "写单个寄存器 (Write Single Register)", 15: "写多个线圈 (Write Multiple Coils)", 16: "写多个寄存器 (Write Multiple Registers)" }; // ========== 工具函数 ========== const readAddrQty = (buf) => ({ address: buf.readUInt16BE(0), quantity: buf.readUInt16BE(2) }); function buildParsedFrame(buf) { if (!Buffer.isBuffer(buf) || buf.length < 8) { return { type: "Invalid Frame", raw: buf?.toString("hex") }; } const transactionId = buf.readUInt16BE(0); const protocolId = buf.readUInt16BE(2); const length = buf.readUInt16BE(4); // number of bytes following this field (unitId + pdu) const unitId = buf.readUInt8(6); const functionCode = buf.readUInt8(7); const data = buf.slice(8); const desc = fcMap[functionCode & 0x7F] || "未知功能码"; const isException = (functionCode & 0x80) !== 0; let direction = "Request"; // 默认为请求 let parsed = {}; try { // ======== 判断方向更准确的方式:基于 FC 和数据格式 ========= if (isException) { direction = "Response"; } else { // 对于读命令,响应的数据第一个字节是 byte count if ([1, 2, 3, 4].includes(functionCode & 0x7F)) { if (data.length >= 1 && data[0] === data.length - 1) { direction = "Response"; } } // 写命令的响应通常是 echo 地址+值,长度固定 else if ([5, 6].includes(functionCode)) { if (data.length === 4) direction = "Response"; } // 批量写响应只返回地址和数量(4字节) else if ([15, 16].includes(functionCode)) { if (data.length === 4) direction = "Response"; } } // ======== 异常响应解析 ======== if (isException) { const exceptionCode = data.length > 0 ? data.readUInt8(0) : null; parsed = { direction: "Response", type: "异常响应 (Exception)", exceptionCode, exceptionMsg: getExceptionMessage(exceptionCode) }; } // ======== 请求帧解析 ======== else if (direction === "Request") { switch (functionCode) { case 1: case 2: case 3: case 4: if (data.length >= 4) { const { address, quantity } = readAddrQty(data); // 标准规定 quantity 不能超过 0x7D0 (2000) 等限制可加校验 parsed = { type: desc, address, quantity }; } else { parsed = { type: "Malformed Read Request", raw: data.toString("hex") }; } break; case 5: if (data.length >= 4) { const addr = data.readUInt16BE(0); const val = data.readUInt16BE(2); parsed = { type: desc, address: addr, value: val === 0xFF00 // Modbus 规范要求写线圈时 ON=0xFF00, OFF=0x0000 }; } else { parsed = { type: "Malformed Write Single Coil", raw: data.toString("hex") }; } break; case 6: if (data.length >= 4) { parsed = { type: desc, address: data.readUInt16BE(0), value: data.readUInt16BE(2) }; } else { parsed = { type: "Malformed Write Single Register", raw: data.toString("hex") }; } break; case 15: if (data.length >= 5) { const addr = data.readUInt16BE(0); const qty = data.readUInt16BE(2); const byteCount = data.readUInt8(4); // 数量合法性检查 if (qty === 0 || qty > 1968) { parsed = { type: "Invalid Quantity", quantity: qty, raw: data.toString("hex") }; break; } const expectedBytes = Math.ceil(qty / 8); if (byteCount !== expectedBytes) { parsed = { type: "Byte count mismatch", expected: expectedBytes, actual: byteCount, raw: data.toString("hex") }; break; } if (data.length < 5 + byteCount) { parsed = { type: "Truncated Data", raw: data.toString("hex") }; break; } const values = []; for (let i = 0; i < byteCount; i++) { const b = data[5 + i]; for (let j = 0; j < 8; j++) { if (values.length < qty) { // 注意:低位在前(LSB),即 bit0 是第一个线圈 values.push(Boolean((b >> j) & 1)); } } } parsed = { type: desc, address: addr, quantity: qty, values }; } else { parsed = { type: "Malformed Write Multiple Coils", raw: data.toString("hex") }; } break; case 16: if (data.length >= 5) { const addr = data.readUInt16BE(0); const qty = data.readUInt16BE(2); const byteCount = data.readUInt8(4); if (qty === 0 || qty > 123) { parsed = { type: "Invalid Quantity", quantity: qty, raw: data.toString("hex") }; break; } if (byteCount !== qty * 2) { parsed = { type: "Byte count mismatch", expected: qty * 2, actual: byteCount, raw: data.toString("hex") }; break; } if (data.length < 5 + byteCount) { parsed = { type: "Truncated Data", raw: data.toString("hex") }; break; } const values = []; for (let i = 0; i < qty; i++) { values.push(data.readUInt16BE(5 + i * 2)); } parsed = { type: desc, address: addr, quantity: qty, values }; } else { parsed = { type: "Malformed Write Multiple Registers", raw: data.toString("hex") }; } break; default: parsed = { type: "Unsupported Function Code", functionCode, raw: data.toString("hex") }; } } // ======== 响应帧解析 ======== else if (direction === "Response") { switch (functionCode) { case 1: case 2: if (data.length >= 1) { const byteCount = data.readUInt8(0); if (data.length !== 1 + byteCount) { parsed = { type: "Data length mismatch", raw: data.toString("hex") }; break; } const values = []; for (let i = 0; i < byteCount; i++) { const b = data[1 + i]; for (let j = 0; j < 8; j++) { if (values.length < 2000) { // 安全上限 values.push(Boolean((b >> j) & 1)); // LSB first } } } parsed = { type: `${desc} 响应`, byteCount, values }; } else { parsed = { type: "Malformed Response", raw: data.toString("hex") }; } break; case 3: case 4: if (data.length >= 1) { const byteCount = data.readUInt8(0); if (byteCount % 2 !== 0) { parsed = { type: "Odd byte count in register response", byteCount }; break; } const regCount = byteCount / 2; const values = []; for (let i = 0; i < regCount; i++) { if (1 + i * 2 + 1 < data.length) { values.push(data.readUInt16BE(1 + i * 2)); } } parsed = { type: `${desc} 响应`, byteCount, values }; } else { parsed = { type: "Malformed Response", raw: data.toString("hex") }; } break; case 5: case 6: case 15: case 16: if (data.length === 4) { parsed = { type: `${desc} 响应`, address: data.readUInt16BE(0), quantity: data.readUInt16BE(2) }; } else { parsed = { type: "Malformed Write Response", raw: data.toString("hex") }; } break; default: parsed = { type: "Unknown Response", raw: data.toString("hex") }; } } } catch (err) { parsed = { type: "Parse Error", error: err.message, raw: buf.toString("hex") }; } // ======== MBAP 长度一致性检查 ======== const pduLength = buf.length - 6; // unitId + PDU if (Math.abs(pduLength - length) > 1) { parsed.mbapWarning = `MBAP长度不符 (expected=${length}, actual=${pduLength})`; } // ======== 地址标签映射支持 ======== const map = global.get("modbusMap") || {}; if (parsed.address !== undefined && map[parsed.address]) { parsed.tagName = map[parsed.address]; } return { transactionId, protocolId, length, unitId, functionCode, description: desc, direction, ...parsed }; } // 辅助函数:异常码解释 function getExceptionMessage(code) { const messages = { 1: "Illegal Function", 2: "Illegal Data Address", 3: "Illegal Data Value", 4: "Slave Device Failure", 5: "Acknowledge", 6: "Slave Device Busy", 7: "Negative Acknowledge", 8: "Memory Parity Error", 10: "Gateway Path Unavailable", 11: "Gateway Target Device Failed to Respond" }; return messages[code] || "Unknown Exception"; } // ========== 主逻辑 ========== const buf = msg.payload; if (!Buffer.isBuffer(buf)) { node.warn("Payload is not a Buffer"); return null; } const frames = []; let offset = 0; while (offset < buf.length) { if (offset + 8 > buf.length) { node.warn("Incomplete frame header — waiting for more data"); break; } const len = buf.readUInt16BE(offset + 4); const totalFrameLength = 6 + len; // MBAP (6字节) + 后续内容 const end = offset + totalFrameLength; if (end > buf.length) { node.warn(`Incomplete Modbus frame detected (need ${end - buf.length} more bytes)`); break; } const frame = buf.slice(offset, end); frames.push(buildParsedFrame(frame)); offset = end; } if (frames.length === 0) { node.status({ fill: "red", shape: "dot", text: "No complete frame" }); return null; } node.status({ fill: "green", shape: "dot", text: `${frames.length} frame(s), FC${frames[frames.length - 1]?.functionCode}` }); msg.payload = frames.length === 1 ? frames[0] : frames; return msg; 优化代码并修正错误
最新发布
11-01
const buf = msg.payload; if (!Buffer.isBuffer(buf) || buf.length < 8) { if (typeof node !== "undefined" && node.warn) node.warn("无效或过短的Modbus报文"); return null; } // 解析 MBAP 头 const transactionId = buf.readUInt16BE(0); const protocolId = buf.readUInt16BE(2); const length = buf.readUInt16BE(4); const unitId = buf.readUInt8(6); const functionCode = buf.readUInt8(7); const data = buf.slice(8); let parsed = { type: 'Unknown', raw: data.toString('hex') }; try { switch (functionCode) { case 1: case 2: case 3: case 4: if (data.length >= 4) { const startAddr = data.readUInt16BE(0); const quantity = data.readUInt16BE(2); const names = { 1: 'Read Coils', 2: 'Read Discrete Inputs', 3: 'Read Holding Registers', 4: 'Read Input Registers' }; parsed = { type: names[functionCode], startAddress: startAddr, quantity }; } break; case 5: if (data.length >= 4) { const addr = data.readUInt16BE(0); const value = data.readUInt16BE(2) === 0xFF00; parsed = { type: 'Write Single Coil', address: addr, value }; } break; case 6: if (data.length >= 4) { const addr = data.readUInt16BE(0); const value = data.readUInt16BE(2); parsed = { type: 'Write Single Register', address: addr, value }; } break; case 15: if (data.length >= 5) { const byteCount = data.readUInt8(4); if (data.length >= 5 + byteCount) { const addr = data.readUInt16BE(0); const qty = data.readUInt16BE(2); const coilBytes = data.slice(5, 5 + byteCount); const coils = []; for (let i = 0; i < qty; i++) { const byte = coilBytes[Math.floor(i / 8)]; coils.push(((byte >> (i % 8)) & 0x01) === 1); } parsed = { type: 'Write Multiple Coils', address: addr, quantity: qty, values: coils }; } } break; case 16: if (data.length >= 5) { const byteCount = data.readUInt8(4); if (data.length >= 5 + byteCount) { const addr = data.readUInt16BE(0); const qty = data.readUInt16BE(2); const values = []; for (let i = 0; i < qty; i++) { const val = data.readUInt16BE(5 + i * 2); values.push(val); } parsed = { type: 'Write Multiple Registers', address: addr, quantity: qty, values }; } } break; default: parsed = { type: `Unsupported (FC=${functionCode})`, raw: data.toString('hex') }; break; } } catch (err) { if (typeof node !== "undefined" && node.error) node.error(`解析Modbus报文出错: ${err.message}`); msg.payload = { ok: false, error: err.message, raw: buf.toString('hex') }; return msg; } msg.payload = { ok: true, transactionId, protocolId, length, unitId, functionCode, ...parsed }; if (typeof node !== "undefined" && node.status) { node.status({ text: `${parsed.type} (FC${functionCode})` }); } return msg; 检查错误并修改
11-01
const buf = msg.payload; // 验证基础帧结构 if (!Buffer.isBuffer(buf) || buf.length < 8) { node.warn("Invalid or too short Modbus frame"); return null; } // ========== MBAP 头部 ========== const transactionId = buf.readUInt16BE(0); const protocolId = buf.readUInt16BE(2); const length = buf.readUInt16BE(4); const unitId = buf.readUInt8(6); const functionCode = buf.readUInt8(7); const data = buf.slice(8); // ========== 功能码表 ========== const fcMap = { 1: "读线圈状态 (Read Coils)", 2: "读离散输入 (Read Discrete Inputs)", 3: "读保持寄存器 (Read Holding Registers)", 4: "读输入寄存器 (Read Input Registers)", 5: "写单个线圈 (Write Single Coil)", 6: "写单个寄存器 (Write Single Register)", 15: "写多个线圈 (Write Multiple Coils)", 16: "写多个寄存器 (Write Multiple Registers)" }; // ========== 通用函数 ========== const readAddrQty = (buf) => ({ address: buf.readUInt16BE(0), quantity: buf.readUInt16BE(2) }); let parsed = {}; node.status({ text: `FC${functionCode} len:${length}` }); try { switch (functionCode) { // ======== 读请求 01~04 ======== case 1: case 2: case 3: case 4: if (data.length >= 4) { const { address, quantity } = readAddrQty(data); parsed = { type: fcMap[functionCode], address, quantity }; } else { parsed = { type: 'Malformed Read Request', raw: data.toString('hex') }; } break; // ======== 写单个线圈 ======== case 5: if (data.length >= 4) { const address = data.readUInt16BE(0); const valueRaw = data.readUInt16BE(2); parsed = { type: fcMap[5], address, value: valueRaw === 0xFF00 }; } else { parsed = { type: 'Malformed Write Single Coil', raw: data.toString('hex') }; } break; // ======== 写单个寄存器 ======== case 6: if (data.length >= 4) { parsed = { type: fcMap[6], address: data.readUInt16BE(0), value: data.readUInt16BE(2) }; } else { parsed = { type: 'Malformed Write Single Register', raw: data.toString('hex') }; } break; // ======== 写多个线圈 ======== case 15: if (data.length >= 5) { const address = data.readUInt16BE(0); const quantity = data.readUInt16BE(2); const byteCount = data.readUInt8(4); const actualBytes = Math.ceil(quantity / 8); if (byteCount !== actualBytes || data.length < 5 + byteCount) { parsed = { type: 'Byte count mismatch', raw: data.toString('hex') }; break; } const values = []; for (let i = 0; i < byteCount; i++) { const b = data[5 + i]; for (let j = 0; j < 8 && values.length < quantity; j++) { values.push(Boolean((b >> j) & 1)); } } parsed = { type: fcMap[15], address, quantity, values }; } else { parsed = { type: 'Malformed Write Multiple Coils', raw: data.toString('hex') }; } break; // ======== 写多个寄存器 ======== case 16: if (data.length >= 5) { const address = data.readUInt16BE(0); const quantity = data.readUInt16BE(2); const byteCount = data.readUInt8(4); if (byteCount !== quantity * 2 || data.length < 5 + byteCount) { parsed = { type: 'Byte count mismatch', raw: data.toString('hex') }; break; } const values = []; for (let i = 0; i < quantity; i++) { values.push(data.readUInt16BE(5 + i * 2)); } parsed = { type: fcMap[16], address, quantity, values }; } else { parsed = { type: 'Malformed Write Multiple Registers', raw: data.toString('hex') }; } break; // ======== 未支持功能码 ======== default: parsed = { type: 'Unsupported Function', raw: data.toString('hex') }; node.warn(`Unsupported Modbus FC: ${functionCode}`); } } catch (err) { node.error(`Modbus parse error: ${err.message}`); parsed = { type: 'Parse Error', error: err.message, raw: buf.toString('hex') }; } // ======== 输出结构 ======== msg.payload = { transactionId, protocolId, length, unitId, functionCode, description: fcMap[functionCode] || "未知功能码", ...parsed }; return msg; 运行后报错:"Invalid or too short Modbus frame"
11-01
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值