const express = require('express'); const cors = require('cors'); const routes = require('./routes'); const webhookRouter = require('./webhook/webhook'); const logger = require('./logger'); // 引入日志记录器 const fs = require('fs'); const path = require('path'); // 主应用服务器 const app = express(); // 记录应用启动信息 logger.info('正在初始化应用服务器...'); // 启用 CORS app.use(cors()); logger.info('CORS 中间件已启用'); // 解析 JSON 请求体 app.use(express.json()); logger.info('JSON 解析中间件已启用'); // 解析 URL 编码的请求体 app.use(express.urlencoded({ extended: true })); logger.info('URL 编码解析中间件已启用'); // 请求日志中间件 app.use((req, res, next) => { const start = Date.now(); res.on('finish', () => { const duration = Date.now() - start; logger.info(`${req.method} ${req.originalUrl} - ${res.statusCode} - ${duration}ms`); }); next(); }); // 加载路由 app.use('/', routes); // 将主路由挂载到 /api 路径 app.use('/', webhookRouter); // 将 Webhook 路由挂载到 /webhook 路径 logger.info('路由模块已加载'); // 404 处理 app.use((req, res, next) => { logger.warn(`404 Not Found: ${req.method} ${req.originalUrl}`); res.status(404).json({ success: false, message: '请求的资源不存在' }); }); // 错误处理中间件 app.use((err, req, res, next) => { logger.error('应用错误:', err); logger.error('错误堆栈:', err.stack); res.status(500).json({ success: false, message: '服务器内部错误' }); }); // 主服务器配置 const MAIN_PORT = 3000; const MAIN_HOST = '0.0.0.0'; // 启动主服务器 app.listen(MAIN_PORT, MAIN_HOST, () => { logger.info(`主服务器已启动: http://${MAIN_HOST}:${MAIN_PORT}`); logger.info('主服务器配置信息:'); logger.info(`- 监听端口: ${MAIN_PORT}`); logger.info(`- 监听地址: ${MAIN_HOST}`); logger.info(`- 环境: ${process.env.NODE_ENV || 'development'}`); }); // OTA 服务器 const otaApp = express(); // 添加 JSON 解析中间件 otaApp.use(express.json()); otaApp.use(express.urlencoded({ extended: true })); // 固件文件路径 const FIRMWARE_PATH = path.join(__dirname, '../sketch_feb24a.ino.bin'); // 确保固件文件与服务器代码在同一目录下 // 最新固件版本 const LATEST_FIRMWARE_VERSION = "1.0.4"; // 服务器上的最新固件版本 // 需要更新的设备ID列表 const TARGET_DEVICES = ["54:32:04:0C:ED:C8", ""]; // 替换为实际的设备ID // 修改检查更新路由 otaApp.post('/check-update', (req, res) => { logger.debug('收到请求体:', req.body); if (!req.body || !req.body.device_id || !req.body.version) { logger.error('无效的请求体:', req.body); return res.status(400).json({ success: false, message: '请求体必须包含 device_id 和 version 字段' }); } // 获取设备ID和当前固件版本 const { device_id, version } = req.body; logger.info(`收到设备ID: ${device_id}, 当前固件版本: ${version}`); // 检查设备是否需要更新 if (TARGET_DEVICES.includes(device_id) && version !== LATEST_FIRMWARE_VERSION) { logger.info(`设备 ${device_id} 需要更新。`); res.send("update"); // 返回"update"表示需要更新 } else { logger.info(`设备 ${device_id} 无需更新。`); res.send("no_update"); // 返回"no_update"表示无需更新 } }); // 固件下载路由 otaApp.get('/firmware', (req, res) => { // 返回固件文件 logger.info("正在下发固件..."); if (fs.existsSync(FIRMWARE_PATH)) { res.download(FIRMWARE_PATH, (err) => { if (err) { logger.error("固件下发失败:", err); res.status(500).send("固件下发失败"); } }); } else { logger.error("固件文件未找到"); res.status(404).send("固件文件未找到"); } }); // OTA 服务器配置 const OTA_PORT = 2999; const OTA_HOST = '0.0.0.0'; // 启动 OTA 服务器 otaApp.listen(OTA_PORT, OTA_HOST, () => { logger.info(`OTA 服务器已启动: http://${OTA_HOST}:${OTA_PORT}`); logger.info('OTA 服务器配置信息:'); logger.info(`- 监听端口: ${OTA_PORT}`); logger.info(`- 监听地址: ${OTA_HOST}`); }); // 捕获未处理的异常 process.on('uncaughtException', (err) => { logger.error('未捕获的异常:', err); logger.error('错误堆栈:', err.stack); // 给进程一点时间来记录日志 setTimeout(() => { process.exit(1); }, 1000); }); // 捕获未处理的 Promise 拒绝 process.on('unhandledRejection', (reason, promise) => { logger.error('未处理的 Promise 拒绝:', reason); logger.error('Promise:', promise); }); // 优雅关闭 process.on('SIGTERM', () => { logger.info('收到 SIGTERM 信号,准备关闭服务器...'); // 在这里可以添加清理代码 process.exit(0); }); process.on('SIGINT', () => { logger.info('收到 SIGINT 信号,准备关闭服务器...'); // 在这里可以添加清理代码 process.exit(0); }); // app.use('/', otaRouter); // 修改 // app.use('/', otaRouter); module.exports = app;