MQTT驱动解析报文返回结果为什么会少一个字段
设备接入
-
解析脚本如下
// Parse the received data.(解析接收数据) // This method will be called to parse the messages received by this server and topic. The message topic is the method parameter topic, and the message content is the method parameter package.(该服务器和主题收到的消息会调用此方法进行解析,消息主题是方法参数topic,消息内容是方法参数package.) // The type of topic is string. Considering that the message content of some devices is binary data, the type of package is byte array.(topic类型为字符串;考虑到部分设备的消息内容为二进制数据,package类型为字节数组,) // When the uploaded data is a JSON string, first use JSON.parse(package) to convert the received data into a JSON object.(当上传数据为json字符串时,首先使用JSON.parse(package)将收到的数据转为json对象.) ParseHandle = function (topic, package) { // 1. 将输入数据转换为HEX字符串 let hexData = ''; if (typeof package === 'string') { hexData = package; } else if (package instanceof Uint8Array || Buffer.isBuffer(package)) { hexData = Array.from(package).map(b => b.toString(16).padStart(2, '0')).join(''); } else { console.error('[ERROR] 不支持的数据格式'); return []; } hexData = hexData.toLowerCase().replace(/\s+/g, ''); console.log('[DEBUG] 原始HEX数据:', hexData); // 2. 去除头部51(严格验证位置) if (hexData.startsWith('51')) { hexData = hexData.slice(2); console.log('[DEBUG] 去除头部51后的数据:', hexData); } // 3. 验证起始符(0xAC)和结束符(0xCA) // ------------------------------------------------------------ // 关键修复:正确提取结束符位置(倒数第4-2字节为结束符0xCA) // ------------------------------------------------------------ const endFlagPosition = hexData.length - 4; // 结束符位于倒数第4-2字节 const actualEndFlag = hexData.substr(endFlagPosition, 2); if (!hexData.startsWith('ac')) { console.error('[ERROR] 起始符校验失败: 期望ac,实际为', hexData.substr(0,2)); return []; } if (actualEndFlag !== 'ca') { console.error('[ERROR] 结束符校验失败: 期望ca,实际为', actualEndFlag); return []; } // 4. 提取核心数据区(去除起始符ac和结束符ca及后续字节) const coreData = hexData.slice(2, endFlagPosition); console.log('[DEBUG] 核心数据区:', coreData); if (coreData.length % 2 !== 0) { console.error('[ERROR] 数据长度异常: 非偶数字节长度'); return []; } // 5. 转换为字节数组 const bytes = []; for (let i = 0; i < coreData.length; i += 2) { bytes.push(parseInt(coreData.substr(i, 2), 16)); } console.log('[DEBUG] 字节数组:', bytes); // 6. 关键字段解析(根据协议文档索引) const params = { isDaytime: "未知", batteryVoltage: null, loadCurrent: null, loadVoltage: null, isWorking: false, temp:null }; try { // 6.1 蓄电池电压(命令字0x03-0x04,索引4-5) if (bytes.length >= 6) { // 至少需要6字节 const batHigh = bytes[4]; const batLow = bytes[5]; params.batteryVoltage = ((batHigh << 8 | batLow) / 100).toFixed(2); console.log('[DEBUG] 蓄电池电压计算:', { batHigh, batLow, voltage: params.batteryVoltage }); } // 6.2 负载电压(命令字0x08,索引8) if (bytes.length >= 9) { // 至少需要7字节 params.loadVoltage = (bytes[8] * 0.1).toFixed(1); console.log('[DEBUG] 负载电压计算:', params.loadVoltage ); } // 6.3 负载电流(命令字0x06-0x07,索引6-7) if (bytes.length >= 8) { // 至少需要8字节 const loadCHigh = bytes[6]; const loadCLow = bytes[7]; params.loadCurrent = ((loadCHigh << 8 | loadCLow) / 10).toFixed(2); console.log('[DEBUG] 负载电流:', {loadCHigh, loadCLow, voltage: params.loadCurrent}); } // 6.4 昼夜模式(命令字0x01,索引2低4位) if (bytes.length >= 4) { const modeByte = bytes[2]; const mode = (modeByte & 0xF0) >> 4; params.isDaytime = mode === 0 ? "白天" : mode === 1 ? "夜晚" : "异常"; console.log('[DEBUG] 昼夜模式:', { modeByte, mode }); } //温度采集 if (bytes.length >= 24) { params.temp = ((bytes[23] + 100) * 0.1).toFixed(1); console.log('[DEBUG] 温度:', params.temp ); } // 6.5 工作状态判断(阈值过滤噪声) params.isWorking = ( params.loadVoltage !== null && parseFloat(params.loadVoltage) > 0 && params.loadCurrent !== null && parseFloat(params.loadCurrent) > 0 ); console.log('[DEBUG] 工作状态:', params.isWorking); } catch (e) { console.error('[ERROR] 解析异常:', e); return []; } // 7. 返回结果(设备ID从topic中提取) const topicParts = topic.split('/').filter(seg => seg !== ''); const deviceId = topicParts.length >= 3 ? topicParts[1] : 'unknown'; return [{ id: deviceId, values: { operating_mode: params.isDaytime, battery_voltage: params.batteryVoltage !== null ? parseFloat(params.batteryVoltage) : 0, load_current: params.loadCurrent !== null ? parseFloat(params.loadCurrent) : 0, load_voltage: params.loadVoltage !== null ? parseFloat(params.loadVoltage) : 0, working_status: params.isWorking, temperature: params.temp !== null ? parseFloat(params.temp) : 0 }, time: Date.now() }]; }; // Build sending data. (构建发送数据。) CommandHandle = function (topic, id, op) { console.log(topic) console.log(id) console.log(JSON.stringify(op)) // Build sending data. (构建发送数据。) let sendTopic = topic let c = JSON.stringify([{ "abc": op.value }]) console.log(c) let sendData = Buffer.from(c) return {sendTopic, sendData} //The names of the keys in the returned object must be sendTopic and sendData. (返回的对象中的 key 的名字必须为 sendTopic、sendData。) }
以下是日志
没有返回 load_current -
-