| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- 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;
|