"use strict"; const path = require("path"); const fs = require("fs"); const { createLogger } = require("./lib/logger"); const { DataCache } = require("./lib/data-cache"); const { DeviceManager } = require("./lib/device-manager"); const { UploadManager } = require("./lib/upload"); const { createDashboard } = require("./dashboard/server"); // 配置读取:优先从工作目录(CWD),便于打包后用户编辑;开发时回退到 __dirname let configPath = path.resolve(process.cwd(), "config.json"); if (!fs.existsSync(configPath)) { configPath = path.join(__dirname, "config.json"); } if (!fs.existsSync(configPath)) { console.error("缺少 config.json,请先创建配置文件(放置于当前工作目录或程序目录)"); process.exit(1); } let config; try { config = JSON.parse(fs.readFileSync(configPath, "utf-8")); } catch (err) { console.error("config.json 解析失败:", err.message); process.exit(1); } // 启动配置校验 if (!Array.isArray(config.devices) || config.devices.length === 0) { console.error("config.json 缺少有效的 devices 数组"); process.exit(1); } for (let i = 0; i < config.devices.length; i++) { const d = config.devices[i]; if (!d.ip || !d.port || !d.serialNumber) { console.error(`config.json devices[${i}] 缺少必填字段 ip/port/serialNumber`); process.exit(1); } } const activeDevices = config.devices.filter((d) => d.enabled !== false); console.log(`配置校验通过: ${activeDevices.length}/${config.devices.length} 台设备启用`); const logDir = path.resolve(process.cwd(), config.logDir || "./logs"); const logger = createLogger({ logDir, retentionDays: config.logRetentionDays || 30, }); logger.sys("联机服务启动"); logger.sys(`日志目录: ${logDir} 保留: ${config.logRetentionDays} 天`); logger.sys(`轮询间隔: ${config.pollIntervalMs / 1000}s 重连退避: ${config.reconnectBaseMs / 1000}s~${config.reconnectMaxMs / 1000}s`); const dataCache = new DataCache(); // 上传模块 const uploadManager = new UploadManager({ mqttConfig: config.mqtt || {}, aliyunConfig: config.aliyun || {}, logger, }); uploadManager.start(); const deviceManager = new DeviceManager({ config, dataCache, logger, uploadManager, }); const dashboard = createDashboard({ port: config.dashboardPort || 3100, dataCache, deviceManager, logger, config, uploadManager, }); deviceManager.startAll(); dashboard.start(); process.on("SIGINT", () => { logger.sys("收到 SIGINT,正在关闭..."); deviceManager.stopAll(); uploadManager.stop(); dashboard.stop(); logger.close(); process.exit(0); }); process.on("SIGTERM", () => { logger.sys("收到 SIGTERM,正在关闭..."); deviceManager.stopAll(); uploadManager.stop(); dashboard.stop(); logger.close(); process.exit(0); }); process.on("uncaughtException", (err) => { logger.error("system", `未捕获异常: ${err.message}`, { stack: err.stack }); }); process.on("unhandledRejection", (reason) => { const msg = reason instanceof Error ? reason.message : String(reason); const stack = reason instanceof Error ? reason.stack : undefined; logger.error("system", `未处理的 Promise 拒绝: ${msg}`, stack ? { stack } : undefined); }); console.log(`\n联机服务已启动 → Dashboard: http://localhost:${config.dashboardPort || 3100}\n`);