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

135 lines (114 loc) 3.78 kB
/** * 亖米(Symi)协议 - 场景设备处理 * 设备类型:0x07 * 支持场景控制和触发 */ const DEVICE_TYPE = 0x07; // 场景设备类型 // 操作类型定义 const OPERATION_TYPES = { TRIGGER: 0x01, // 场景触发 STATUS: 0x02 // 场景状态 }; /** * 缓冲区数据转对象 * @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 && obj.address === protocolData.deviceAddress && obj.channel === protocolData.deviceChannel) { return protocolData; } else { return null; } } /** * 协议解析 * @param {Buffer} data 数据帧 */ function _protocol(data) { if (!data || data.length < 15) return null; let obj = {}; // 解析数据帧结构 obj.localAddress = data[1]; // 本地地址 obj.dataType = data[2]; // 数据类型 obj.dataLength = data[3]; // 数据长度 obj.deviceType = data[4]; // 设备类型 obj.brandId = data[5]; // 品牌ID obj.deviceAddress = data[6]; // 设备地址 obj.deviceChannel = data[7]; // 设备通道 obj.roomNumber = data[8]; // 房间号 obj.roomType = data[9]; // 房间类型 obj.roomId = data[10]; // 房间ID obj.operationCode = data[11]; // 操作码 // 检查设备类型 if (obj.deviceType !== DEVICE_TYPE) return null; // 只处理设置和上报类型的消息 if (obj.dataType !== 0x03 && obj.dataType !== 0x04) return null; obj.type = obj.dataType === 0x03 ? 'set' : 'report'; obj.deviceTypeName = 'scene'; // 根据操作码解析具体操作 switch (obj.operationCode) { case OPERATION_TYPES.TRIGGER: // 场景触发 obj.action = 'trigger'; obj.sceneId = data[12]; // 场景ID obj.val = 'trigger'; break; case OPERATION_TYPES.STATUS: // 场景状态 obj.action = 'status'; obj.sceneId = data[12]; // 场景ID obj.status = data[13]; // 场景状态 obj.val = obj.status === 1 ? 'active' : 'inactive'; break; default: // 默认作为触发处理 obj.action = 'trigger'; obj.sceneId = data[12]; obj.val = 'trigger'; } return obj; } /** * 对象转缓冲区 * @param {object} obj HA状态对象 * @param {object} obj1 节点对象 */ function obj2buf(obj, obj1) { if (obj1.entity_id !== obj.entity_id) return null; // 构建基础帧结构 let frame = { localAddress: obj1.uid, dataType: 0x04, // 上报 deviceType: DEVICE_TYPE, brandId: 0x00, deviceAddress: obj1.address, deviceChannel: obj1.channel || 0x00, roomNumber: 0x00, roomType: 0x00, roomId: 0x00, operationCode: OPERATION_TYPES.TRIGGER, operationData: Buffer.alloc(1) }; // 场景通常只有触发操作 if (obj.state === 'on' || obj.state === 'trigger') { frame.operationCode = OPERATION_TYPES.TRIGGER; frame.operationData[0] = obj1.sceneId || 0x01; // 场景ID } else if (obj.attributes && obj.attributes.scene_id !== undefined) { frame.operationCode = OPERATION_TYPES.TRIGGER; frame.operationData[0] = obj.attributes.scene_id; } return frame; } module.exports = { buf2obj, obj2buf, DEVICE_TYPE, OPERATION_TYPES };