const AuthzCheck = require('./AuthzCheck'); const Device = require('./Device'); const logger = require('../logger'); // 引入日志记录器 const HeaterUsageService = require('../services/HeaterUsageService'); const RelayState = require('./RelayState'); // 需要新建RelayState模型 class WebhookService { // 将 UTC 时间转换为北京时间(UTC+8) static convertToBeijingTime(utcTimestamp) { const date = new Date(utcTimestamp); date.setHours(date.getHours() + 8); // 转换为北京时间 return date.toISOString().slice(0, 19).replace('T', ' '); } // 处理设备上下线事件 static handleDeviceEvent(eventData) { const client_id = eventData.clientid || undefined; const status = eventData.event === 'client.connected' ? 'online' : 'offline'; const timestamp = WebhookService.convertToBeijingTime(eventData.timestamp); const ip_address = eventData.peername || 'unknown:0'; logger.info(`处理设备${status}事件: ${client_id}`); logger.debug('事件数据:', { client_id, status, timestamp, ip_address }); // 查询设备的当前状态 Device.getDeviceById(client_id, (err, device) => { if (err) { logger.error('查询设备失败:', err); return; } // 如果设备不存在,插入新设备 if (!device) { const first_online_time = status === 'online' ? timestamp : null; logger.info(`新设备首次上线: ${client_id}`); Device.insert( client_id, status, timestamp, first_online_time, status === 'online' ? timestamp : null, ip_address, (err, result) => { if (err) { logger.error('插入新设备失败:', err); return; } logger.info(`新设备插入成功,设备ID:${result.insertId}`); } ); } else { // 设备存在,更新状态 if (status === 'online') { const first_online_time = (!device || !device.first_online_time) ? timestamp : device.first_online_time; logger.info(`设备 ${client_id} 上线`); Device.updateOnlineStatus( client_id, status, timestamp, first_online_time, timestamp, ip_address, (err) => { if (err) { logger.error('更新设备在线状态失败:', err); return; } logger.info(`设备 ${client_id} 在线状态更新成功`); } ); } else { logger.info(`设备 ${client_id} 下线`); Device.updateOfflineStatus( client_id, status, timestamp, timestamp, (err) => { if (err) { logger.error('更新设备离线状态失败:', err); return; } logger.info(`设备 ${client_id} 离线状态更新成功`); } ); } } }); } // 处理温度回传事件 // 在handleTemperatureEvent方法中: // 修改handleTemperatureEvent调用方式 static async handleTemperatureEvent(eventData) { const topic = eventData.topic; const payload = eventData.payload; const timestamp = WebhookService.convertToBeijingTime(eventData.timestamp); const device_id = topic.split('/')[1]; logger.info(`处理温度事件: 设备=${device_id}, 温度=${payload}`); const room_number = eventData.room_number || 'default_room'; const room_name = eventData.room_name || '默认房间'; try { await new Promise((resolve, reject) => { Device.updateTemperature( device_id, payload, timestamp, room_number, // 新增参数 room_name, // 新增参数 (err) => { // 保持回调函数存在 if (err) return reject(err); resolve(); } ); }); // 删除重复的updateTemperature调用 const device = await new Promise((resolve) => { Device.getDeviceById(device_id, (err, device) => { resolve(device || {}); }); }); logger.debug('开始处理加热器业务逻辑', { device_id, status: device.status, temperature: payload, switch_status: device.switch_status }); await HeaterUsageService.handleHeaterUsage( device_id, device.status, payload, device.switch_status, timestamp ); logger.info(`设备 ${device_id} 温度处理完成`); } catch (error) { logger.error(`温度事件处理失败: ${error.message}`, { device_id, stack: error.stack }); } // 添加方法结束括号 } // 此处添加方法结束括号 // 处理开关指令事件 static handleSwitchEvent(eventData) { const topic = eventData.topic; const payload = eventData.payload; const timestamp = WebhookService.convertToBeijingTime(eventData.timestamp); const device_id = topic.split('/')[1]; logger.info(`处理开关事件: 设备=${device_id}, 状态=${payload}`); // 修正参数传递 const room_number = eventData.room_number || 'N/A'; const room_name = eventData.room_name || '未命名房间'; Device.updateSwitchStatus( device_id, payload, // 修正为使用 payload 而不是未定义的 switch_status timestamp, room_number, room_name, (err) => { if (err) { logger.error('更新开关状态失败:', err); return; } logger.info(`设备 ${device_id} 开关状态更新成功`); } ); } // 处理继电器状态事件 static handleRelayStateEvent(eventData) { const topic = eventData.topic; const payload = eventData.payload; const timestamp = WebhookService.convertToBeijingTime(eventData.timestamp); const device_id = topic.split('/')[1]; logger.info(`处理继电器状态事件: 设备=${device_id}, 状态=${payload}`); Device.updateSwitchStatus(device_id, payload, timestamp, (err) => { if (err) { logger.error('更新继电器状态失败:', err); return; } logger.info(`设备 ${device_id} 继电器状态更新成功: ${payload}`); }); } // 处理 GPIO 状态事件 static handleGpioStateEvent(eventData) { const topic = eventData.topic; const payload = eventData.payload; const timestamp = WebhookService.convertToBeijingTime(eventData.timestamp); const device_id = topic.split('/')[1]; logger.info(`处理GPIO状态事件: 设备=${device_id}, 状态=${payload}`); Device.updateLevelStatus(device_id, payload, timestamp, (err) => { if (err) { logger.error('更新GPIO状态失败:', err); return; } logger.info(`设备 ${device_id} GPIO状态更新成功: ${payload}`); }); } // 处理授权检查完成事件 static handleAuthzCheckEvent(eventData) { const client_id = eventData.clientid || eventData.client_id; const topic = eventData.topic; const action = eventData.action; const result = eventData.result || 'deny'; const timestamp = eventData.timestamp || Date.now(); logger.info(`处理授权检查事件: 客户端=${client_id}, 主题=${topic}`); logger.debug('授权检查详情:', { action, result }); if (!client_id) { logger.error('无效的授权检查事件: 缺少客户端ID'); return; } const authzData = { client_id, topic, action, result: result === 'allow' ? 'allow' : 'deny', timestamp: WebhookService.convertToBeijingTime(timestamp) }; AuthzCheck.insert(authzData, (err, result) => { if (err) { logger.error('记录授权检查事件失败:', err); return; } logger.info(`授权检查事件记录成功: ID=${result.insertId}`); }); } // 处理消息传递事件 static handleMessageDeliveredEvent(eventData) { const client_id = eventData.clientid || eventData.client_id || undefined; const { topic, payload, timestamp } = eventData; console.log('Message delivered:', { client_id, topic, payload, timestamp: WebhookService.convertToBeijingTime(timestamp) // 使用北京时间 }); } // 处理消息丢弃事件 static handleMessageDroppedEvent(eventData) { const client_id = eventData.clientid || eventData.client_id || undefined; const { topic, payload, reason, timestamp } = eventData; console.log('Message dropped:', { client_id, topic, payload, reason, timestamp: WebhookService.convertToBeijingTime(timestamp) // 使用北京时间 }); } } // 导出 WebhookService 类 module.exports = WebhookService;