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

187 lines (164 loc) 6.19 kB
/** * 亖米(Symi)协议 - 灯光设备处理 * 设备类型:0x01 * 支持操作类型: * 0x00: 单灯控制 * 0x02: 单色调光控制 * 0x03: 双色温调光控制 * 0x04: RGBW调光控制 * 0x05: 灯光多灯控制 */ const DEVICE_TYPE = 0x01; // 灯光设备类型 // 操作类型定义 const OPERATION_TYPES = { SINGLE_SWITCH: 0x00, // 单灯控制 SINGLE_DIM: 0x02, // 单色调光控制 DUAL_TEMP_DIM: 0x03, // 双色温调光控制 RGBW_DIM: 0x04, // RGBW调光控制 MULTI_LIGHT: 0x05 // 灯光多灯控制 }; /** * 缓冲区数据转对象 * @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 = 'light'; // 根据操作码解析具体操作 switch (obj.operationCode) { case OPERATION_TYPES.SINGLE_SWITCH: // 单灯控制:操作信息为开关状态 obj.action = 'switch'; obj.val = data[12] === 1 ? 'on' : 'off'; break; case OPERATION_TYPES.SINGLE_DIM: // 单色调光:操作信息为亮度百分比 obj.action = 'brightness'; obj.val = data[12]; // 0-100 break; case OPERATION_TYPES.DUAL_TEMP_DIM: // 双色温调光:第一字节色温,第二字节亮度 obj.action = 'dual_temp'; obj.colorTemp = data[12]; // 色温 0-100 obj.brightness = data[13]; // 亮度 0-100 obj.val = { color_temp: obj.colorTemp, brightness: obj.brightness }; break; case OPERATION_TYPES.RGBW_DIM: // RGBW调光:红、绿、蓝、白 obj.action = 'rgbw'; obj.red = data[12]; obj.green = data[13]; obj.blue = data[14]; obj.white = data[15]; obj.val = { rgb_color: [obj.red * 255 / 100, obj.green * 255 / 100, obj.blue * 255 / 100], brightness: obj.white * 255 / 100 }; break; default: // 默认作为开关处理 obj.action = 'switch'; obj.val = data[12] === 1 ? 'on' : 'off'; } 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.SINGLE_SWITCH, operationData: Buffer.alloc(1) }; // 根据HA状态设置操作信息 if (obj.state === 'on' || obj.state === 'off') { // 简单开关控制 frame.operationCode = OPERATION_TYPES.SINGLE_SWITCH; frame.operationData[0] = obj.state === 'on' ? 1 : 0; } else if (obj.attributes) { if (obj.attributes.brightness !== undefined) { if (obj.attributes.color_temp !== undefined) { // 双色温调光 frame.operationCode = OPERATION_TYPES.DUAL_TEMP_DIM; frame.operationData = Buffer.alloc(2); frame.operationData[0] = Math.round(obj.attributes.color_temp / 500 * 100); // 色温映射 frame.operationData[1] = Math.round(obj.attributes.brightness / 255 * 100); // 亮度 } else if (obj.attributes.rgb_color !== undefined) { // RGBW调光 frame.operationCode = OPERATION_TYPES.RGBW_DIM; frame.operationData = Buffer.alloc(4); const [r, g, b] = obj.attributes.rgb_color; frame.operationData[0] = Math.round(r / 255 * 100); // 红 frame.operationData[1] = Math.round(g / 255 * 100); // 绿 frame.operationData[2] = Math.round(b / 255 * 100); // 蓝 frame.operationData[3] = Math.round(obj.attributes.brightness / 255 * 100); // 白/亮度 } else { // 单色调光 frame.operationCode = OPERATION_TYPES.SINGLE_DIM; frame.operationData[0] = Math.round(obj.attributes.brightness / 255 * 100); } } else { // 默认开关控制 frame.operationData[0] = obj.state === 'on' ? 1 : 0; } } return frame; } module.exports = { buf2obj, obj2buf, DEVICE_TYPE, OPERATION_TYPES };