UNPKG

node-red-contrib-symi

Version:

Node-RED nodes for smart home device communication with Home Assistant integration, supporting HassKit, Clowire, Alive, LF and complete Symi protocols

146 lines (129 loc) 3.85 kB
/** * 亖米(Symi)协议 - 面板设备处理 * 支持屏显面板等设备,这是一个新的设备类型 */ /** * 缓冲区数据转对象 * @param {Buffer} data 命令缓冲 * @param {object} obj 节点对象 */ function buf2obj(data, obj) { const protocolData = _protocol(data); if (!protocolData) return null; protocolData.uid = obj.entity_id; if (obj.uid === protocolData.localAddress && (protocolData.devAddress * 4 - 4 + protocolData.devChannel) === obj.address) { return protocolData; } else { return null; } } /** * 协议解析 * @param {Buffer} data 15字节数据帧 */ function _protocol(data) { if (!data || data.length < 15) return null; let obj = {}; // 解析数据帧结构 obj.localAddress = data[1]; // 本地地址 obj.type = _getTypeFromByte(data[2]); // 消息类型 obj.devAddress = data[6]; // 设备地址 obj.devChannel = data[7]; // 设备通道 obj.info = data[12]; // 状态信息 obj.code = data[11]; // 代码 // 只处理set类型的消息 if (obj.type !== 'set') return null; // 面板设备可能有多种状态 obj.val = obj.info === 1 ? 'on' : 'off'; obj.deviceType = 'panel'; // 面板设备可能包含额外的信息 obj.panelData = { address: obj.devAddress, channel: obj.devChannel, code: obj.code, rawInfo: obj.info }; return obj; } /** * 根据字节值获取消息类型 * @param {number} byte */ function _getTypeFromByte(byte) { switch (byte) { case 0x01: return 'response'; case 0x02: return 'query'; case 0x03: return 'set'; case 0x04: return 'report'; default: return 'unknown'; } } /** * 根据消息类型获取字节值 * @param {string} type */ function _getByteFromType(type) { switch (type) { case 'response': return 0x01; case 'query': return 0x02; case 'set': return 0x03; case 'report': return 0x04; default: return 0x04; // 默认为report } } /** * 对象转缓冲区 * @param {object} obj HA状态对象 * @param {object} obj1 节点对象 */ function obj2buf(obj, obj1) { if (obj1.entity_id === obj.entity_id) { // 构建状态反馈数据帧 let buf = [ 0x00, // 帧头将由主处理器设置 obj1.uid, // 本地地址 _getByteFromType('report'), // 消息类型:report 15, // 数据长度 1, // 固定值 0, // 保留 2, // 设备地址(根据channel计算) 1, // 设备通道(根据channel计算) 0, // 保留 0, // 保留 0, // 保留 0, // 代码 obj.state === 'on' ? 1 : 0, // 状态信息 0, // CRC将由主处理器计算 0 // 帧尾将由主处理器设置 ]; // 根据按键地址计算设备地址和通道 let channel = obj1.address || 1; if (channel >= 1 && channel <= 8) { buf[6] = 1; // 设备类型1 buf[7] = channel; // 直接使用按键编号作为通道 } // 面板设备可能需要特殊的状态处理 if (obj.attributes && obj.attributes.brightness) { // 如果有亮度属性,可以在这里处理 buf[11] = Math.round(obj.attributes.brightness / 255 * 100); // 转换为百分比 } return buf; } else { return null; } } module.exports = { buf2obj, obj2buf };