# FranklinWH-ToolBox Service 设计文档 > 本文档为项目技术设计说明,供新加入的开发者快速了解系统全貌。 --- ## 目录 1. [项目概述](#1-项目概述) 2. [系统架构](#2-系统架构) 3. [目录结构](#3-目录结构) 4. [核心依赖](#4-核心依赖) 5. [配置管理](#5-配置管理) 6. [路由与API](#6-路由与api) 7. [业务模块](#7-业务模块) 8. [数据模型](#8-数据模型) 9. [基础设施](#9-基础设施) 10. [任务系统](#10-任务系统) 11. [外部集成](#11-外部集成) 12. [部署与运行](#12-部署与运行) --- ## 1. 项目概述 ### 1.1 项目定位 FranklinWH-ToolBox Service 是 FranklinWH 家庭储能系统的**内部运维工具平台后端**,为运维团队提供站点监控、数据下载、设备管理、告警分析、OTA 升级配置等核心能力。 ### 1.2 核心功能 - **站点信息管理** — 从 FWH Pro 平台同步全量站点数据,支持多维度筛选、标签管理和 Excel 导出 - **批量数据下载** — 批量抓取站点运行数据(功率流、MQTT 日志、事件告警、EMS 日志、故障录波等),异步打包为 ZIP - **站点监控与分析** — 实时查看站点功率流、告警、模式信息;分析站点历史时间线 - **自动升级配置** — 管理 aGate/aPower 设备 OTA 升级包和升级策略 - **停机与告警统计** — 按区域统计每日停机数据,汇总告警码和受影响站点 - **SIM 卡管理** — 定时采集 SmartHub/Acceleronix 平台 SIM 卡状态及流量 - **故障录波** — 通过 MQTT 向设备下发故障录波参数设置指令 - **设备日志(Xlog)** — 管理站点 Xlog 连接,通过 WebSocket 发送终端命令 ### 1.3 技术栈 | 层级 | 技术选型 | |------|----------| | 语言 | Go 1.25 | | Web 框架 | Fiber v2 | | ORM | GORM + Gen(代码生成) | | 数据库 | PostgreSQL + MongoDB + MySQL(只读) | | 缓存 | Redis(go-redis v9) | | 对象存储 | MinIO | | 消息通信 | MQTT(Paho) | | 异步任务 | Asynq + 自研 Redis Stream 队列 | | 定时任务 | robfig/cron + Asynq Scheduler | | 认证 | Casdoor SSO + JWT | | 日志 | Zap(结构化日志) | | 配置 | Viper(.env 文件 + 环境变量) | | API 文档 | Swagger(swaggo 自动生成) | | 网络事件 | Evio(高性能事件驱动) | --- ## 2. 系统架构 ### 2.1 整体架构图 ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ 客户端(Web 前端) │ └───────────────────────────────────┬─────────────────────────────────────┘ │ HTTP / WebSocket ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ Fiber HTTP 服务 (:8301) │ │ ┌──────────┐ ┌──────────────┐ ┌──────────┐ ┌────────────────────┐ │ │ │ Swagger │ │ Auth Route │ │ /ping │ │ /api/* (Protected)│ │ │ └──────────┘ └──────────────┘ └──────────┘ └────────────────────┘ │ └───────────────────────────────────┬─────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ Middleware 层 │ │ Casdoor JWT 认证 │ 请求日志 │ Panic 恢复 │ └───────────────────────────────────┬─────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ Controller 层 │ │ 解析请求参数,调用 Service,返回响应 │ └───────────────────────────────────┬─────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ Service 层(业务逻辑) │ │ │ │ │ ┌────────────────────┼────────────────────┐ │ │ ▼ ▼ ▼ │ │ 直通 CRUD 模式 任务触发模式 缓存优先模式 │ │ (入队异步执行) (Redis → DB) │ └──────────────┬────────────────────┬────────────────────┬─────────────────┘ │ │ │ │ ┌─────▼──────┐ │ │ │ Task Queue │ │ │ │ (FWH队列) │ │ │ │ (SimCard队列) │ │ └─────┬──────┘ │ │ │ │ │ ┌─────▼──────┐ │ │ │ Jobs 层 │ │ │ │ (后台作业) │ │ │ └─────┬──────┘ │ │ │ │ ▼ ▼ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ Repository 层(数据访问聚合) │ │ ┌────────┐ ┌──────┐ ┌───────┐ ┌───────┐ ┌──────┐ ┌──────┐ ┌───────┐ │ │ │MongoDB │ │PgSQL │ │ MySQL │ │ Redis │ │MinIO │ │ MQTT │ │FWH API│ │ │ └────────┘ └──────┘ └───────┘ └───────┘ └──────┘ └──────┘ └───────┘ │ └─────────────────────────────────────────────────────────────────────────┘ ``` ### 2.2 请求处理流 ``` Client (HTTP Request) │ ▼ Route (Fiber 路由匹配) │ ▼ Middleware (JWT 认证 / 日志记录) │ ▼ Controller (参数解析、校验) │ ▼ Service (业务逻辑) ──────────────────────────────┐ │ ▼ │ Task (实时任务) / Scheduler (定时任务) │ │ │ ▼ │ Jobs (后台作业) ▼ │ Repository (数据访问聚合) ◀──────────────────────┘ │ ▼ Database / Cache / 外部服务 (FWH API / MQTT / MinIO) ``` ### 2.3 多数据源架构 ``` ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ MySQL (只读) │ │ PostgreSQL │ │ MongoDB │ │ FWH Pro 生产库 │ │ 本地业务数据 │ │ 文档型业务数据 │ │ - iot_gateway │ │ - 告警快照 │ │ - 站点信息 │ │ │ │ - 原始数据存储 │ │ - 批量下载配置 │ │ │ │ │ │ - 升级配置 │ │ │ │ │ │ - SIM卡数据 │ └──────────────────┘ └──────────────────┘ └──────────────────┘ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ Redis │ │ MinIO │ │ MQTT │ │ - 会话缓存 │ │ - 下载文件存储 │ │ - 设备通信 │ │ - 任务队列 │ │ - 升级配置文件 │ │ - Xlog 使能 │ │ - 分布式锁 │ │ │ │ - 故障录波 │ │ - Dashboard缓存 │ │ │ │ │ └──────────────────┘ └──────────────────┘ └──────────────────┘ ``` --- ## 3. 目录结构 ```bash service/ ├── main.go # 应用入口(初始化所有组件 + 启动服务) ├── .env # 环境变量配置文件 ├── config.env # 备选配置文件 ├── go.mod / go.sum # Go 模块依赖 ├── DESIGN.md # 本设计文档 ├── README.md # 项目简介 │ ├── config/ # 配置管理 │ └── config.go # Viper 加载配置,定义 Config/AppConfig/FwhApiConfig 等结构体 │ ├── logger/ # 日志系统 │ └── logger.go # Zap 初始化,环境区分(dev/pro),全局 Logger │ ├── database/ # 数据库连接 │ ├── database.go # 统一初始化入口(PostgreSQL + MongoDB) │ ├── postgresql.go # GORM PostgreSQL 连接 + 自定义 Logger │ ├── mysql.go # GORM MySQL 连接(当前未启用) │ └── mongodb.go # MongoDB 连接 + GetCollection │ ├── cache/ # 缓存封装 │ ├── cache.go # 统一 API 暴露(Set/Get/HSet/XAdd/TryLock 等) │ ├── cache_aside.go # Cache-Aside 模式(GetOrSet/GetOrSetMany) │ ├── stale.go # Stale 异步刷新模式 │ ├── options.go # 可选配置(TTL/锁/前缀等) │ └── redisx/ # Redis 底层操作封装 │ ├── stringx.go # String 操作 │ ├── hashx.go # Hash 操作 │ ├── listx.go # List 操作 │ ├── setx.go # Set 操作 │ ├── zsetx.go # ZSet 操作 │ ├── streamx.go # Stream 操作(任务队列核心) │ ├── jsonx.go # 泛型 JSON 序列化操作 │ ├── lockx.go # 分布式锁(SET NX + Lua) │ ├── pipelinex.go # Pipeline 管道 │ ├── pubsubx.go # 发布/订阅 │ └── scriptx.go # Lua 脚本 │ ├── routes/ # 路由注册 │ ├── routes.go # 主路由入口 Setup() │ ├── authRoutes.go # 认证路由(/auth) │ ├── batchDownloadRoutes.go │ ├── sitesMonitorRoutes.go │ ├── sitesAnalysisRoutes.go │ ├── autoUpdateConfigRoutes.go │ ├── siteInfoManageRoutes.go │ ├── shutdownRoutes.go │ ├── simCardManageRoutes.go │ └── ... # 各业务模块独立路由文件 │ ├── middleware/ # 中间件 │ └── auth.go # Casdoor JWT 认证 + 角色检查 │ ├── controllers/ # 控制器层 │ ├── batchDownloadControllers.go │ ├── autoUpdateConfigControllers.go │ ├── siteInfoManageControllers.go │ ├── sitesMonitorControllers.go │ ├── sitesAnalysisControllers.go │ ├── authControllers.go │ └── ... # 各业务模块控制器 │ ├── services/ # 业务逻辑层 │ ├── batchDownloadServices.go │ ├── siteInfoManageServices.go │ ├── sitesAnalysisServices.go │ ├── authServices.go │ ├── simCardManageServices.go │ └── ... # 各业务模块服务 │ ├── repositories/ # 数据访问层(聚合模式) │ ├── repositories.go # 统一入口,暴露所有子模块方法 │ ├── mongo/ # MongoDB 数据操作 │ ├── redis/ # Redis 数据操作(Session/缓存/队列) │ ├── pgsql/ # PostgreSQL 数据操作(告警快照) │ ├── mysql/ # MySQL 数据操作(FWH Pro 只读) │ ├── api/ # 外部 API 调用 │ │ ├── fwh_pro/ # FWH Pro 平台 API │ │ ├── smartHub/ # SmartHub SIM 卡 API │ │ └── acceleronix/ # Acceleronix SIM 卡 API │ ├── mqtt/ # MQTT 通信 │ │ └── fwh_mqtt/ # FWH MQTT 客户端 │ └── events/ # Xlog 事件管理 │ ├── domain/ # 领域对象(业务核心模型) │ ├── siteInfo.go # 站点信息 Domain │ ├── batchDownload.go # 批量下载配置/数据 │ ├── siteAnalysis.go # 站点分析配置/数据 │ ├── autoUpdate.go # 自动升级配置 │ ├── simCard.go # SIM 卡信息 │ ├── shutdown.go # 停机统计 │ ├── auth.go # 认证信息 │ ├── mqttLogTypes.go # MQTT 日志类型定义(201/357 等) │ └── ... # 其他领域对象 │ ├── models/ # GORM 数据库模型(Gen 生成) │ ├── model_pgsql/ # PostgreSQL 表模型 │ ├── query_alarm_snapshot/ # 告警快照 Query 层 │ ├── query_fwh_pro/ # FWH Pro MySQL Query 层 │ └── fwh_pro/ # FWH Pro 模型定义 │ ├── dto/ # 数据传输对象(API 请求/响应) │ ├── siteInfo.go # 站点信息 DTO │ ├── batchDownload.go # 批量下载 DTO │ ├── simCard.go # SIM 卡 DTO │ ├── powerFlow.go # 功率流 DTO │ ├── common.go # 通用 DTO(ResPage 等) │ └── ... │ ├── task/ # 异步任务系统 │ ├── task.go # 任务系统入口 InitTask() │ ├── core/ # TaskCore 核心封装 │ ├── plugin/ # SchedulerManager + AggregatorManager │ └── queue/ # 业务队列 │ ├── fwhQueue/ # FWH 主任务队列(Redis Stream) │ └── simCardQueue/ # SIM 卡采集队列(Asynq) │ ├── scheduler/ # 定时任务(robfig/cron) │ └── scheduler.go # Cron 初始化 + 任务注册 │ ├── jobs/ # 后台作业(任务具体执行逻辑) │ ├── callFwhFile.go # FWH 文件召唤(EMS日志/故障录波) │ ├── saveBatchDownloadData.go # 批量下载数据保存(Excel/图表 → MinIO) │ ├── analysisSiteData.go # 站点数据分析(时间线/运行时) │ ├── statisticsShutdown.go # 停机统计 │ ├── statisticsAlarm.go # 告警统计 │ ├── getAlarmSnapshot.go # 告警快照获取与解析 │ └── createAutoUpdateConfigFile.go # 升级配置文件生成 │ ├── utils/ # 工具函数 │ ├── httpClient/ # HTTP 客户端封装(自动 reLogin) │ ├── mqttClient/ # MQTT 客户端封装(自动重连) │ ├── minio/ # MinIO 对象存储客户端 │ ├── snowflakeID/ # 分布式 ID 生成 │ ├── casdoor/ # Casdoor 认证集成 │ ├── files/ # 文件操作(压缩/解压/下载) │ ├── mimetype/ # MIME 类型检测 │ ├── echart/ # 图表生成封装 │ ├── emspara/ # EMS 参数同步 │ ├── xlog/ # Xlog 协议解析 │ ├── networkEvents/ # Evio 网络事件监听 │ └── global/ # 全局工具函数(Ternary/Deref) │ ├── pkg/ # 自定义通用包 ├── docs/ # Swagger 文档(自动生成) └── cmd/ # 脚本与工具 ├── gen/ # GORM Gen 代码生成 ├── deploy.sh # 部署脚本 ├── only_build.sh # 仅编译脚本 ├── showLog.sh # 日志查看 ├── showTodayLog.sh # 今日日志 └── showTodayErrorLog.sh # 今日错误日志 ``` --- ## 4. 核心依赖 ### 4.1 主要依赖版本表 | 依赖包 | 版本 | 用途 | |--------|------|------| | `go` | 1.25.0 | 编程语言 | | `gofiber/fiber/v2` | v2.52.9 | 高性能 Web 框架 | | `gorm.io/gorm` | v1.30.1 | ORM 框架 | | `gorm.io/driver/mysql` | v1.6.0 | MySQL 驱动 | | `gorm.io/driver/postgres` | v1.6.0 | PostgreSQL 驱动 | | `gorm.io/gen` | v0.3.27 | GORM 代码生成工具 | | `go.mongodb.org/mongo-driver` | v1.17.4 | MongoDB 官方驱动 | | `redis/go-redis/v9` | v9.21.0 | Redis 客户端 | | `spf13/viper` | v1.20.1 | 配置管理 | | `go.uber.org/zap` | v1.27.0 | 结构化日志 | | `robfig/cron/v3` | v3.0.1 | 定时任务 | | `hibiken/asynq` | v0.26.0 | 异步任务队列 | | `hibiken/asynqmon` | v0.7.2 | 任务队列监控 UI | | `eclipse/paho.mqtt.golang` | v1.5.1 | MQTT 客户端 | | `minio/minio-go/v7` | v7.0.95 | 对象存储客户端 | | `casdoor/casdoor-go-sdk` | v1.21.0 | SSO/鉴权 SDK | | `gofiber/swagger` | v1.1.1 | Swagger UI 集成 | | `swaggo/swag` | v1.16.4 | Swagger 文档生成 | | `xuri/excelize/v2` | v2.10.0 | Excel 文件读写 | | `tidwall/evio` | v1.0.8 | 高性能事件网络库 | | `go-echarts/go-echarts/v2` | v2.6.6 | 图表生成(功率流图) | | `bwmarrin/snowflake` | v0.3.0 | 分布式 ID 生成 | | `tiendc/go-deepcopy` | v1.7.1 | 结构体深拷贝 | ### 4.2 依赖选型说明 - **Fiber** 而非 Gin:Fiber 基于 fasthttp,性能更高,适合高并发场景 - **GORM + Gen**:自动生成类型安全的 Query 代码,减少运行时错误 - **Asynq**:成熟的 Redis 任务队列方案,自带监控面板和定时调度 - **MongoDB + PostgreSQL 混合**:文档型数据用 MongoDB,结构化数据用 PostgreSQL - **Casdoor**:开源 SSO 平台,支持 OAuth2/OIDC,便于统一认证管理 --- ## 5. 配置管理 ### 5.1 配置加载机制 ``` 配置来源优先级(高 → 低): 环境变量 (os.Getenv) ↑ AutomaticEnv() 自动覆盖 ./.env 文件 ↑ 未找到则尝试 ./config.env 文件 ↑ 未找到则使用 缺省默认值 ``` ### 5.2 配置结构体 ```go type Config struct { App AppConfig // 应用基础设施配置 FwhApi FwhApiConfig // FWH 平台 API 配置 FwhMqtt FwhMqttConfig // MQTT Broker 配置 FwhMqttTest FwhMqttConfig // MQTT 测试环境配置 } ``` #### AppConfig — 基础设施 | 字段 | 环境变量 | 说明 | 默认值 | |------|----------|------|--------| | AppEnv | `APP_ENV` | 运行环境 (dev/pro) | dev | | AppPort | `APP_PORT` | HTTP 监听端口 | 8301 | | RedisAddr | `REDIS_ADDR` | Redis 地址 | localhost:6379 | | MySQLDSN | `MYSQL_DSN` | MySQL 连接串 | — | | PostgresDSN | `POSTGRES_DSN` | PostgreSQL 连接串 | — | | MongoDSN | `MONGO_DSN` | MongoDB 连接串 | — | | MinIoEndpoint | `MINIO_ENDPOINT` | MinIO 端点 | localhost:9198 | | MinioAccessKey | `MINIO_ACCESS_KEY` | MinIO 访问密钥 | — | | MinioSecretKey | `MINIO_SECRET_KEY` | MinIO 密钥 | — | | MinioBucketName | `MINIO_BUCKET_NAME` | MinIO 存储桶 | — | | AsynqmonPort | `ASYNQMON_PORT` | Asynqmon 监控端口 | 8081 | #### FwhApiConfig — FWH 平台 API | 字段 | 说明 | |------|------| | FwhEnergy | FWH 能源管理 API 域名 | | FwhOss | FWH OSS 文件服务域名 | | FwhUser | 登录用户名 | | FwhPassword | 登录密码(MD5 加密存储) | #### FwhMqttConfig — MQTT 配置 | 字段 | 说明 | |------|------| | Broker | MQTT Broker 地址 | | Ca | CA 证书路径 | | Cert | 客户端证书路径 | | Key | 客户端私钥路径 | ### 5.3 环境区分 | 特性 | dev(开发) | pro(生产) | |------|------------|------------| | 日志级别 | Debug | Warn | | 日志格式 | Console(可读) | JSON(结构化) | | 日志采样 | 无 | 100/100 | | 堆栈追踪 | Error 级别 | Error 级别 | --- ## 6. 路由与API ### 6.1 路由架构 ``` Fiber App ├── /swagger/* → Swagger 文档 UI ├── /ping → 健康检查 ├── /auth/* → 认证(公开,无需 Token) │ ├── POST /auth/login → OAuth Code 登录 │ ├── GET /auth/session → 获取会话信息 │ ├── POST /auth/refreshToken → 刷新 Token │ └── POST /auth/logout → 登出 │ └── /api/* [AuthMiddleware] → 受保护路由(需 JWT) ├── /api/userInfo/* → 用户配置 ├── /api/shutdownStatistics/* → 停机统计 ├── /api/shutdownManage/* → 停机管理 ├── /api/sitesMonitor/* → 站点监控 ├── /api/sitesAnalysis/* → 站点分析 ├── /api/batchDownload/* → 批量下载 ├── /api/backgroundTask/* → 后台任务 ├── /api/autoUpdateConfig/* → 自动升级配置 ├── /api/xlog/* → 设备日志 ├── /api/siteInfoManage/* → 站点信息管理 ├── /api/despatchConfig/* → 调度配置 ├── /api/faultRecord/* → 故障录波 ├── /api/simCardManage/* → SIM 卡管理 └── WebSocket → 全局 WebSocket 独立服务: └── Asynqmon (:8081) → 异步任务监控面板 ``` ### 6.2 完整 API 接口清单 #### 认证模块 (`/auth`) | 方法 | 路径 | 说明 | |------|------|------| | POST | `/auth/login` | Casdoor OAuth Code 换 Token 登录 | | GET | `/auth/session` | 获取当前会话信息 | | POST | `/auth/refreshToken` | 刷新 Access Token | | POST | `/auth/logout` | 登出(清除 Session) | #### 批量下载 (`/api/batchDownload`) | 方法 | 路径 | 说明 | |------|------|------| | GET | `/batchDownload/manage/list` | 分页查询下载任务列表 | | POST | `/batchDownload/manage/config` | 创建批量下载任务 | | POST | `/batchDownload/manage/description/:id` | 更新任务描述 | | POST | `/batchDownload/manage/owner/:id` | 更新任务归属 | | DELETE | `/batchDownload/manage/config/:id` | 删除下载任务 | | GET | `/batchDownload/data/:id` | 流式 ZIP 下载任务数据 | | GET | `/batchDownload/manage/path` | 获取目录树结构 | | GET | `/batchDownload/manage/fileTree` | 获取 tar.gz 内部目录 | | GET | `/batchDownload/manage/fileDownload` | 单文件下载 | #### 自动升级配置 (`/api/autoUpdateConfig`) | 方法 | 路径 | 说明 | |------|------|------| | GET | `/autoUpdateConfig/option` | 获取配置选项 | | GET | `/autoUpdateConfig/packageInfo` | 获取升级包信息列表 | | POST | `/autoUpdateConfig/packageInfo/create/:type` | 创建升级包 | | POST | `/autoUpdateConfig/packageInfo/update/:id` | 更新升级包 | | DELETE | `/autoUpdateConfig/packageInfo/delete/:type/:id` | 删除升级包 | | GET | `/autoUpdateConfig/aPowerVersion` | 获取 aPower 版本列表 | | POST | `/autoUpdateConfig/aPowerVersion/:version` | 更新 aPower 版本 | | DELETE | `/autoUpdateConfig/aPowerVersion/:version` | 删除 aPower 版本 | | GET | `/autoUpdateConfig/config` | 获取升级配置 | | POST | `/autoUpdateConfig/config/:aGate` | 更新升级配置 | | DELETE | `/autoUpdateConfig/config/:aGate` | 删除升级配置 | | POST | `/autoUpdateConfig/config/special/:aGate` | 创建特殊设备配置 | | DELETE | `/autoUpdateConfig/config/special/:aGate/:id` | 删除特殊设备配置 | | GET | `/autoUpdateConfig/configFile` | 获取配置文件信息 | | POST | `/autoUpdateConfig/configFile/create` | 生成配置文件(Excel) | | GET | `/autoUpdateConfig/configFile/download/:fileName` | 下载配置文件 | #### 站点信息管理 (`/api/siteInfoManage`) | 方法 | 路径 | 说明 | |------|------|------| | GET | `/siteInfoManage/manage/update` | 获取站点信息更新状态 | | POST | `/siteInfoManage/manage/update` | 触发全量同步 | | POST | `/siteInfoManage/dataList` | 分页查询站点列表 | | POST | `/siteInfoManage/dataListExport` | 导出站点 Excel | | GET | `/siteInfoManage/siteInfo/query?sn=` | 按 SN 查询站点详情 | | POST | `/siteInfoManage/operate/enableXlog` | 使能站点 Xlog | #### 站点监控 (`/api/sitesMonitor`) | 方法 | 路径 | 说明 | |------|------|------| | GET | `/sitesMonitor/manage/nameList` | 获取监控配置名列表 | | GET | `/sitesMonitor/manage/config/:name` | 获取指定监控配置 | | POST | `/sitesMonitor/manage/config/:name` | 更新监控配置 | | POST | `/sitesMonitor/manage/pageConfig/:name` | 更新页面配置 | | DELETE | `/sitesMonitor/manage/config/:name` | 删除监控配置 | | GET | `/sitesMonitor/manage/config` | 获取所有监控配置 | | POST | `/sitesMonitor/manage/config` | 创建监控配置 | | POST | `/sitesMonitor/site/infoList` | 批量查询站点信息 | | GET | `/sitesMonitor/site/:site/info` | 单站点详细信息 | | GET | `/sitesMonitor/site/:site/modeInfo` | 站点工作模式 | | GET | `/sitesMonitor/site/:site/powerFlow/:day` | 站点功率流(按天) | | GET | `/sitesMonitor/site/:site/alarmList` | 站点告警列表 | #### 站点分析 (`/api/sitesAnalysis`) | 方法 | 路径 | 说明 | |------|------|------| | GET | `/sitesAnalysis/manage/analysisList` | 分析任务列表 | | POST | `/sitesAnalysis/manage/config` | 创建分析任务 | | GET | `/sitesAnalysis/manage/config/:id` | 获取分析配置 | | POST | `/sitesAnalysis/manage/config/:id` | 更新分析配置 | | POST | `/sitesAnalysis/manage/description/:id` | 更新描述 | | DELETE | `/sitesAnalysis/manage/config/:id` | 删除分析任务 | | GET | `/sitesAnalysis/data/:id` | 获取分析结果数据 | #### 其他模块 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/simCardManage/info` | SIM 卡批量信息 | | GET | `/simCardManage/monthly` | SIM 卡月度数据 | | GET | `/shutdownStatistics/date` | 停机统计日期 | | GET | `/shutdownStatistics` | 停机统计数据 | | GET | `/shutdownManage/date` | 停机管理日期 | | GET | `/shutdownManage/infoMap` | 停机详情映射 | | GET | `/alarmManage/infoMap` | 告警统计映射 | | POST | `/faultRecord/paramSetting` | 故障录波参数设置 | | GET | `/despatchConfig/touTemplatePro/list` | TOU 模板列表 | | GET | `/despatchConfig/touTemplatePro/info` | TOU 模板详情 | | GET | `/userInfo/config` | 获取用户配置 | | POST | `/userInfo/config` | 更新用户配置 | | GET | `/backgroundTask/info` | 后台任务列表 | | GET | `/xlog/manage/siteList` | Xlog 站点列表 | | POST | `/xlog/terminal/:uuid` | 发送终端命令 | --- ## 7. 业务模块 ### 7.1 模块总览 ``` ┌─────────────────────────────────────────────────────────────┐ │ FWH ToolBox 业务模块 │ ├─────────────────┬───────────────────┬───────────────────────┤ │ 数据采集类 │ 运维管理类 │ 监控分析类 │ ├─────────────────┼───────────────────┼───────────────────────┤ │ • 批量数据下载 │ • 自动升级配置 │ • 站点监控 │ │ • 站点信息同步 │ • 故障录波 │ • 站点分析 │ │ • SIM卡信息采集 │ • 调度配置 │ • 停机统计 │ │ │ • Xlog 管理 │ • 告警统计 │ │ │ • 用户配置 │ │ └─────────────────┴───────────────────┴───────────────────────┘ ``` ### 7.2 批量数据下载 (BatchDownload) **功能描述**:批量抓取指定站点在指定时间段内的各类运行数据,异步处理后打包为 ZIP 文件供下载。 **数据类型支持**: - 功率流图(PowerFlow)— 生成 Excel + ECharts 图表 - MQTT 日志(类型 0/101/201/357) - 事件与告警日志(EventAlarm) - 告警快照(AlarmSnapshot) - EMS 日志(召唤式下载) - 故障录波数据(FaultRecord) - 系统升级记录(UpdateLog) **处理流程**: ``` 用户创建任务 → Service 写入 MongoDB(状态: pending) → 入队 FWH 任务队列(Redis Stream) → Worker 消费任务(状态: running) → 按 SN 遍历: → 按数据类型调用 FWH API 获取数据 → Jobs 层处理(生成 Excel/图表) → 存入 MinIO 对象存储 → 全部完成(状态: complete)/ 部分失败(状态: failed) 用户下载 → 流式读取 MinIO 文件 → ZIP 打包 → HTTP Stream 响应 ``` **关键技术**: - 流式 ZIP 打包(`SetBodyStreamWriter`),避免内存溢出 - MinIO 对象存储,支持大文件 - 文件召唤机制(EMS 日志/故障录波需要先召唤再下载) - 任务进度实时跟踪 ### 7.3 自动升级配置 (AutoUpdateConfig) **功能描述**:管理 aGate/aPower 设备的 OTA 固件升级策略。 **核心概念**: - **升级包 (PackageInfo)**:固件文件元信息(版本号、硬件兼容性、文件路径) - **aPower 版本**:aPower 设备可用版本列表 - **升级配置 (Config)**:按 aGate 硬件类型配置默认升级策略和特殊设备策略 - **配置文件**:将配置导出为 Excel 并存储到 MinIO **数据存储**:MongoDB(配置数据) + MinIO(配置文件) + Redis(文件列表缓存) ### 7.4 站点信息管理 (SiteInfoManage) **功能描述**:从 FWH Pro 平台全量同步站点信息到本地 MongoDB,提供多维度查询和 Excel 导出。 **核心流程**: ``` 触发全量同步 → 入队任务 → 分页调用 FWH API → 逐条写入/更新 MongoDB(SiteInfoDomain) → 完成后通知前端 查询站点 → MongoDB 聚合查询(支持多种过滤器类型) → Domain → DTO 转换(标签ID展开为详情) → 分页返回 导出 Excel → 查询全部匹配数据 → excelize 生成工作表 → 流式响应 ``` **筛选器支持**:等于(整数/浮点/字符串)、包含、范围(整数/浮点/时间)、字段存在 ### 7.5 站点监控 (SitesMonitor) **功能描述**:配置监控面板,实时查询站点功率流、告警、工作模式。 **特性**: - 多面板管理(每个面板配置独立站点列表和页面布局) - 实时数据通过 FWH Pro API 获取(功率流、告警列表、TOU 模式) - 站点信息展示(设备状态、固件版本、网络类型) ### 7.6 站点分析 (SitesAnalysis) **功能描述**:分析站点历史 MQTT 日志,生成时间线事件和运行时数据。 **分析数据源**: - MQTT 日志类型 0 — 离线事件 - MQTT 日志类型 101 — 上线事件 - MQTT 日志类型 201 — 运行数据(功率、SOC、模式等) - MQTT 日志类型 357 — 模式切换事件 - 事件日志 / 告警日志 **输出结果**: - **时间线** (`Timeline[]`):离线、上线、告警、模式切换等事件序列 - **运行时数据** (`Runtime[]`):各时段运行状态数据 ### 7.7 停机统计 (ShutdownStatistics) **功能描述**:统计每日停机站点,生成按区域(ALL/US/AU)的周报和年报。 **统计维度**: - 日统计:当日停机数 + 增长率 - 周统计:最近 7 天趋势 - 月统计:当月累计 - 年统计:12 个月趋势 **触发方式**:定时任务(每日执行)+ 手动触发 ### 7.8 SIM 卡管理 (SimCardManage) **功能描述**:定时从第三方平台采集 SIM 卡状态和流量数据。 **数据源**: - SmartHub 平台 — 一类 SIM 卡 - Acceleronix 平台 — 另一类 SIM 卡 **采集模式**: ``` 定时调度(每天 UTC 23:00)→ 创建首页任务 → 链式分页查询(Page 0 → Page 1 → ... → 最后一页) → 聚合器收集多页数据 → 批量写入 MongoDB ``` ### 7.9 故障录波 (FaultRecord) **功能描述**:通过 MQTT 协议向设备下发故障录波参数设置指令。 **通信流程**: ``` API 请求 → Service → MQTT 发送 cmdType=377(参数设置) → 等待设备回复 cmdType=378 → 返回结果 ``` ### 7.10 其他模块 | 模块 | 说明 | |------|------| | **调度配置 (DespatchConfig)** | 代理查询 FWH Pro 的 TOU 调度模板列表和详情 | | **用户配置 (UserInfo)** | 管理用户个性化设置(表格列过滤器、自定义查询条件) | | **后台任务 (BackgroundTask)** | 查询 Redis Stream 中后台任务执行状态 | | **Xlog 管理** | 管理站点 Xlog 连接,通过 WebSocket 转发终端命令 | | **全局 WebSocket** | 维护 WebSocket 连接池,支持心跳检测和消息广播 | --- ## 8. 数据模型 ### 8.1 三层数据对象体系 本项目采用三层数据对象设计,各层职责明确: ``` ┌─────────────────────────────────────────────────────────────┐ │ DTO 层 (dto/) │ │ 面向 API 接口,定义请求/响应结构 │ │ 标签: json ID类型: string (Hex) │ └─────────────────────────────┬───────────────────────────────┘ │ 转换函数 ┌─────────────────────────────▼───────────────────────────────┐ │ Domain 层 (domain/) │ │ 业务核心对象,内部逻辑处理和 MongoDB 存储 │ │ 标签: bson ID类型: primitive.ObjectID │ └─────────────────────────────┬───────────────────────────────┘ │ ┌─────────────────────────────▼───────────────────────────────┐ │ Model 层 (models/) │ │ GORM 模型,映射 PostgreSQL/MySQL 表结构 │ │ 标签: gorm ID类型: int64/string │ └─────────────────────────────────────────────────────────────┘ ``` ### 8.2 数据流转关系 ``` 外部数据源 内部存储 API 响应 ──────────── ──────── ──────── FWH Pro API (FwhSiteInfo) → domain.SiteInfoDomain → dto.SiteInfoDTO (MongoDB 存储) (标签展开为详情) FWH Pro MySQL (IotGateway) → domain.FwhSiteInfo → dto.MonitorSiteInfo (API 响应映射) (精简字段) SmartHub API (SimCardResponse) → domain.SimCardInfo → dto.SimCardInfo (MongoDB 存储) (增加关联SN) ``` ### 8.3 核心 Domain 对象 #### 任务状态枚举 ```go type Progress string // pending | running | failed | error | complete type Trigger string // auto | manual ``` #### SiteInfoDomain — 站点信息(50+ 字段) ```go type SiteInfoDomain struct { Sn string `bson:"_id"` // aGate 序列号(主键) Name *string // 站点名称 ActiveStatus int // 0-未激活 1-已激活 Status int // 0-离线 1-在线 RunStatus int // 0-待机 1-充电 2-放电 3-故障 EmsModel *int // EMS 调度模式 Version string // 固件版本 FhpSn string // aPower SN(逗号分割) ConnType int // 网络类型 TimeZone float32 // 时区 Country string // 国家 ExtTags *[]string // 扩展标签 ID 列表 // ... 更多字段 } ``` #### BatchDownloadConfig — 批量下载任务 ```go type BatchDownloadConfig struct { Id primitive.ObjectID Sn []string // 目标 SN 列表 TimePeriod [2]string // 时间范围 [开始, 结束] Options BatchDownloadOptions // 下载选项 Progress Progress // 任务进度 Data map[string]BatchDownloadData // SN → 数据映射 FailReasons []string // 失败原因 } type BatchDownloadOptions struct { PowerFlow bool // 功率流图 MqttLogs []string // MQTT 日志类型列表 EventAlarm bool // 事件告警 AlarmSnapshot bool // 告警快照 EmsLogs []string // EMS 日志类型 FaultRecord bool // 故障录波 UpdateLog bool // 升级记录 Settings bool // 站点设置 } ``` #### SiteAnalysisConfig — 站点分析 ```go type SiteAnalysisConfig struct { Id primitive.ObjectID Sn string TimePeriod [2]string Options SiteAnalysisOptions Progress Progress Trigger Trigger // auto(定时触发) / manual(手动) Data SiteAnalysisData } type SiteAnalysisData struct { Timeline []TimelineItem // 时间线事件 Runtime []RuntimeItem // 运行时数据 } type TimelineType string // offline | online | mode_change | event | alarm ``` #### ShutdownStatisticsItem — 停机统计 ```go type ShutdownStatisticsItem struct { Date string Status ShutdownStatisticsStatus Count ShutdownStatisticsArea[uint] // 泛型按区域统计 SiteMap map[string]ShutdownStatisticsInfo } type ShutdownStatisticsArea[T any] struct { ALL T US T AU T } ``` ### 8.4 GORM 模型(PostgreSQL) #### 告警快照文件记录 ```go // 表: alarm_snapshot.site_alarm_snapshot_file_record type SiteAlarmSnapshotFileRecord struct { ID int64 `gorm:"primaryKey;autoIncrement"` CodeType int32 FileName string `gorm:"not null"` FileURL string `gorm:"not null"` Sn string `gorm:"not null"` LogTime time.Time State int16 // 0-分析中 1-完成 -1-失败 } ``` #### 告警快照数据 ```go // 表: alarm_snapshot.site_alarm_snapshot_data type SiteAlarmSnapshotData struct { ID int64 `gorm:"primaryKey;autoIncrement"` Sn string `gorm:"not null"` FileRecordID int64 // 外键关联 FileRecord LogTime time.Time JSONData string `gorm:"type:jsonb"` // JSON 格式数据 ZoneInfo string } ``` #### 原始数据存储 ```go // 表: original.site_original_data type SiteOriginalDataModel struct { ID int64 `gorm:"primaryKey"` // 雪花 ID DataType DataTypes // "API" 或 "MQTT" ChildType string // API 路径名 或 MQTT cmdType SN string DataTime time.Time JsonData datatypes.JSON `gorm:"type:jsonb"` } ``` ### 8.5 GORM 模型(MySQL - 只读) ```go // 表: iot_gateway (FWH Pro 生产库) type IotGateway struct { ID string `gorm:"primaryKey"` // 网关 SN Name string Version string // 固件版本 ActiveStatus int32 // 激活状态 Status int32 // 在线状态 RunStatus int32 // 运行状态 EmsModel int32 // EMS 模式 FhpSn string // aPower 编号 TimeZone float32 Country string // ... 60+ 字段,完整映射生产数据库 } ``` ### 8.6 核心 DTO #### 通用分页响应 ```go type ResPage[T any] struct { Data []T `json:"data"` PageSize uint `json:"pageSize"` PageNum uint `json:"pageNum"` Total uint `json:"total"` } ``` #### 站点信息 DTO ```go type SiteInfoDTO struct { // 与 Domain 基本一致,区别: // - json 标签(非 bson) // - ExtTags 展开为 []SiteTagDTO(含名称、颜色等详情) ExtTags []SiteTagDTO `json:"extTags,omitempty"` } type SiteInfoRequest struct { Search string `json:"search"` Filter *domain.SiteInfoFilter `json:"filter"` PageSize uint `json:"pageSize"` PageNum uint `json:"pageNum"` } ``` #### 功率流 DTO ```go type SitePowerFlow struct { Index uint DeviceTimeArray []string // 时间轴 PowerFhpArray []float32 // aPower 功率 PowerGenArray []float32 // 发电功率 PowerLoadArray []float32 // 负载功率 PowerSunArray []float32 // 光伏功率 PowerUtiArray []float32 // 电网功率 SocArray []float32 // SOC 曲线 } ``` ### 8.7 数据库分布 | 数据库 | 访问模式 | 存储内容 | |--------|----------|----------| | **MongoDB** | 读写 | 站点信息、SIM卡、批量下载任务/配置、站点分析、升级配置、用户配置、监控配置、统计数据、标签 | | **PostgreSQL** | 读写 | 告警快照(文件记录+数据)、原始数据存储(API/MQTT 日志) | | **MySQL** | 只读 | FWH Pro 生产库 iot_gateway 表(站点基础信息) | | **Redis** | 读写 | 会话、Dashboard 缓存、任务队列、分布式锁、EMS 参数缓存 | | **MinIO** | 读写 | 批量下载文件、升级配置 Excel 文件 | --- ## 9. 基础设施 ### 9.1 数据库层 (database/) #### 初始化流程 ```go database.Init(cfg *config.AppConfig) ├── InitPostgreSQL(cfg.PostgresDSN) // GORM + postgres driver ├── InitMongo(cfg.MongoDSN) // mongo-driver └── InitMySQL(cfg.MySQLDSN) // 当前已注释 ``` #### PostgreSQL 配置 | 配置项 | 值 | |--------|------| | 驱动 | `gorm.io/driver/postgres` | | 日志 | 自定义 `GormZapLogger`(桥接 Zap) | | 慢查询阈值 | 200ms | | 代码生成 | GORM Gen(`query_alarm_snapshot`) | #### MongoDB 配置 | 配置项 | 值 | |--------|------| | 驱动 | `go.mongodb.org/mongo-driver` | | 连接超时 | 10s | | 数据库名 | 从 URI 末段解析 | | 对外接口 | `GetCollection(collName)` | #### 自定义 GORM Logger 将 GORM 的 SQL 日志、慢查询告警、错误信息全部桥接到 Zap 结构化日志: - Info 级别:普通 SQL - Warn 级别:慢查询(>200ms) - Error 级别:数据库错误 ### 9.2 缓存层 (cache/) #### 架构分层 ``` 上层 API (cache/) │ 统一暴露:Set/Get/HSet/LPush/ZAdd/XAdd/TryLock... │ 高级模式:GetOrSet/GetOrSetMany/GetOrSetStale ▼ 底层封装 (cache/redisx/) │ 按数据结构分文件:stringx/hashx/listx/setx/zsetx/streamx │ 特殊能力:jsonx(泛型序列化)/lockx(分布式锁)/scriptx(Lua) ▼ Redis Client (redis.UniversalClient) │ 支持单机/哨兵/集群模式 ▼ Redis Server (DB=12) ``` #### Cache-Aside 模式 ```go // 单键缓存(防击穿 + 防雪崩) result, err := cache.GetOrSet[T](ctx, key, loaderFunc, opts...) // 执行流程: // 1. GET key → 命中则返回 // 2. 未命中 → 尝试获取分布式锁 // 3. 获取锁成功 → double check → 调用 loader → 写缓存 // 4. 获取锁失败 → 等待缓存更新 or fallback 直接调用 loader // 批量模式 results, err := cache.GetOrSetMany[T](ctx, keys, batchLoaderFunc, opts...) ``` #### Stale 模式(异步刷新) ```go // TTL 即将过期时返回旧值 + 后台刷新 result, err := cache.GetOrSetStale[T](ctx, key, loaderFunc, opts...) // stale 阈值默认 30s,即 TTL < 30s 时触发后台刷新 ``` #### 配置选项 | 选项 | 默认值 | 说明 | |------|--------|------| | TTL | 5min | 缓存过期时间 | | AsyncWrite | true | 异步写入缓存 | | LockEnabled | true | 是否启用分布式锁 | | LockTTL | 5s | 锁过期时间 | | WaitCacheTimeout | 500ms | 等待缓存更新超时 | | StaleThreshold | 30s | Stale 刷新阈值 | #### 分布式锁 基于 `SET key value NX PX timeout` + Lua 脚本安全释放: ```go lock, ok, err := cache.TryLock(ctx, key, ttl) // 尝试获取 cache.LockRelease(ctx, key, token) // 安全释放(Lua 校验 token) ``` ### 9.3 中间件 (middleware/) #### JWT 认证中间件 ```go func AuthMiddleware(requiredRoles ...string) fiber.Handler ``` **处理流程**: ``` 请求 → 提取 Authorization: Bearer → casdoorsdk.ParseJwtToken(token) 验证签名 → 提取用户信息 → 存入 c.Locals("user") → (可选) 检查角色权限 → 通过 / 返回 401 ``` **用户信息结构**: ```go type AuthUserInfo struct { Owner string Name string // 用户名 DisplayName string // 显示名 Id string IsAdmin bool Roles []RoleInfo // 角色列表 Permissions []PermInfo // 权限列表(含 Actions + Effect) Groups []string // 用户组 } ``` **辅助函数**: - `AuthGetUserInfo(c)` — 获取完整用户信息 - `AuthGetUserName(c)` — 获取用户名 - `AuthIsAdmin(c)` — 判断管理员 - `AuthGetRoleNameList(c)` — 角色名列表 - `AuthGetPermissionNameList(c)` — 权限名列表 ### 9.4 日志系统 (logger/) #### 初始化 ```go logger.Init(env string) // 全局变量: // logger.Log *zap.Logger — 结构化日志 // logger.Sugar *zap.SugaredLogger — Sugar 风格日志 // logger.Std *log.Logger — 标准库兼容 ``` #### 环境配置对比 | 配置 | dev | pro | |------|-----|-----| | 编码器 | Console | JSON | | 级别 | Debug | Warn | | 采样 | 无 | Initial=100, Thereafter=100 | | 堆栈 | Error+ | Error+ | | 输出 | stderr | stderr | #### 全局替换 ```go zap.ReplaceGlobals(Log) // 之后可通过 zap.L() / zap.S() 全局访问 ``` --- ## 10. 任务系统 ### 10.1 架构概览 系统包含**两套独立的任务队列**,各自服务不同业务场景: ``` ┌─────────────────────────────────────────────────────────────────┐ │ 任务系统架构 │ ├────────────────────────────┬────────────────────────────────────┤ │ FWH 队列(自研) │ SimCard 队列(Asynq) │ │ 基于 Redis Stream │ 基于 hibiken/asynq │ ├────────────────────────────┼────────────────────────────────────┤ │ • 批量数据下载 │ • SIM 卡信息采集 │ │ • 站点分析 │ • 聚合写入 │ │ • 站点信息同步 │ │ │ • 停机统计 │ │ │ • 告警统计 │ │ ├────────────────────────────┼────────────────────────────────────┤ │ 单 Worker 顺序执行 │ 单线程 + 分组聚合器 │ │ 分布式锁保证唯一性 │ 唯一性(5min 内不重复) │ │ 自动重试(最大3次) │ 成功任务保留7天 │ └────────────────────────────┴────────────────────────────────────┘ ``` ### 10.2 FWH 队列 — Redis Stream 实现 #### 技术方案 基于 Redis Stream + Consumer Group 的自研任务队列: ``` 生产端 消费端 ────── ────── EnqueueTask(type, payload) startTaskQueueWorker() │ │ ▼ ▼ Redis XADD ──────────────→ XREADGROUP (阻塞读取) (stream: fwh_task_queue) │ ▼ handleTaskQueueMsg() │ (按 type 路由) ▼ handleTaskBatchDownload() handleTaskSiteAnalysis() handleTaskSiteInfoUpdate() handleTaskShutdownStatistics() handleTaskAlarmStatistics() ``` #### 设计特点 | 特性 | 说明 | |------|------| | 单 Worker | 顺序执行,避免任务冲突 | | 唯一任务锁 | `EnqueueUniqueTask` 通过 Redis 分布式锁保证同类任务不重复 | | 自动重试 | 最大 3 次,通过 `XAutoClaim` 检测滞留消息 | | 状态管理 | pending → running → complete/failed/error | | 进度追踪 | MongoDB 记录 Progress 字段 | #### 任务类型 | 常量 | 处理函数 | 描述 | |------|----------|------| | `task_BatchDownload` | `handleTaskBatchDownload` | 批量数据下载 | | `task_SiteAnalysis` | `handleTaskSiteAnalysis` | 站点数据分析 | | `task_SiteInfoUpdate` | `handleTaskSiteInfoUpdate` | 全量同步站点信息 | | `task_ShutdownStatistics` | `handleTaskShutdownStatistics` | 停机统计 | | `task_AlarmStatistics` | `handleTaskAlarmStatistics` | 告警统计 | #### 任务状态机 ``` ┌─────────┐ 入队 ┌─────────┐ Worker消费 ┌─────────┐ │ 创建 │ ─────────→ │ Pending │ ──────────────→ │ Running │ └─────────┘ └─────────┘ └────┬────┘ │ ┌──────────────────────────┼──────────────────┐ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Complete │ │ Failed │ │ Error │ │ (全部成功) │ │ (部分失败) │ │ (异常) │ └──────────┘ └──────────┘ └──────────┘ ``` ### 10.3 SimCard 队列 — Asynq 实现 #### 技术方案 基于 `hibiken/asynq` 的分布式任务队列: ``` 定时调度 (每天 UTC 23:00) │ ▼ SyncOnePage(page=0) → 处理数据 → 创建聚合任务 │ │ ▼ ▼ SyncOnePage(page=1) → 处理数据 → 创建聚合任务 │ │ ... ▼ (聚合器收集) │ ┌──────────────────┐ ▼ │ AggregatorManager│ 最后一页完成 │ (30s宽限/5min最大)│ └────────┬─────────┘ │ ▼ Bulk Write → MongoDB ``` #### 配置参数 | 参数 | 值 | 说明 | |------|------|------| | Concurrency | 1 | 单线程串行,控制 API 调用频率 | | GracePeriod | 30s | 聚合宽限期 | | MaxDelay | 5min | 最大等待时间 | | MaxSize | 100 | 单次聚合最大任务数 | | Uniqueness | 5min | 任务唯一性窗口 | | Retention | 7d | 成功任务保留时间 | #### 链式分页模式 ```go // 处理第 N 页后自动创建第 N+1 页任务 func handleSyncOnePage(ctx, task) error { data := fetchPage(page) // 调用外部 API createAggregateTask(data) // 创建聚合任务 if hasNextPage { enqueue(SyncOnePage{page+1}) // 链式创建下一页任务 } return nil } ``` ### 10.4 定时调度 (Scheduler) #### 多时区支持 ```go type SchedulerManager struct { utc *asynq.Scheduler // UTC zh *asynq.Scheduler // Asia/Shanghai sg *asynq.Scheduler // Asia/Singapore la *asynq.Scheduler // America/Los_Angeles ny *asynq.Scheduler // America/New_York } ``` #### 已注册定时任务 | Cron 表达式 | 时区 | 任务 | 状态 | |-------------|------|------|------| | `0 23 * * *` | UTC | SmartHub SIM 卡同步 | 启用 | | `0 23 * * *` | UTC | Acceleronix SIM 卡同步 | 启用 | | `0 5 * * *` | — | 告警统计 | 启用 | | `35 15 * * *` | — | 停机统计 | 暂停 | ### 10.5 Jobs 层 — 后台作业 Jobs 层包含任务的具体执行逻辑: #### FWH 文件召唤 (`callFwhFile.go`) ``` 按 SN 分组 → 每个 SN 独立 Redis Stream 队列 → 并行下载(EMS 日志需先"召唤"再下载) → 最大召唤重试 3 次 → 下载完成写入 MinIO ``` #### 批量下载数据保存 (`saveBatchDownloadData.go`) | 数据类型 | 输出格式 | 存储路径 | |----------|----------|----------| | 功率流 | Excel + ECharts 图 | `BatchDownloadData/{SN}/PowerFlow/{Date}.*` | | MQTT 日志 | Excel | `BatchDownloadData/{SN}/MqttLog/{Type}/{Date}.xlsx` | | 事件告警 | Excel | `BatchDownloadData/{SN}/EventAlarm/{Date}.xlsx` | | 告警快照 | Excel | `BatchDownloadData/{SN}/AlarmSnapshot/{Date}.xlsx` | | 升级记录 | Excel | `BatchDownloadData/{SN}/UpdateLog/...` | #### 站点数据分析 (`analysisSiteData.go`) - `AnalysisSiteTimeline()` — 生成时间线(离线/上线/告警/模式切换事件) - `AnalysisSiteRuntime()` — 运行时数据分析(功率、SOC 趋势) #### 统计分析 - `StatisticsShutdown()` — 停机统计(按 ALL/US/AU 区域分类) - `StatisticsAlarm()` — 告警码统计(触发站点分析回调) ### 10.6 Asynqmon 监控面板 - 独立 HTTP 服务,默认端口 `8081` - 提供 Web UI 查看任务队列状态 - 支持任务重试、删除、归档操作 - 查看定时任务调度情况 --- ## 11. 外部集成 ### 11.1 FWH Pro API #### 概述 FWH Pro 是 FranklinWH 核心业务平台,本系统通过 HTTP API 获取站点数据。 #### 连接配置 | 配置项 | 说明 | |--------|------| | 域名 | 通过代理 `energy.fwh-toolbox.top` 访问 | | OSS 域名 | `energy-oss.fwh-toolbox.top`(文件下载) | | 认证 | 用户名 + MD5 密码登录,获取 `Logintoken` | | 超时 | 3 分钟 | | 重试 | 401 时自动 reLogin 后重试 | #### HTTP 客户端特性 ```go // 泛型反序列化 FwhHttpGetUnmarshal[T](url, params) (*T, error) FwhHttpPostUnmarshalPage[T](url, body) (*PageResult[T], error) // 自动 Token 管理 // 请求头: Logintoken: // 401 响应 → 自动调用 Login() → 重新发送请求 ``` #### API 接口分类 | 分类 | 接口示例 | 说明 | |------|----------|------| | **站点信息** | `selectIotFirmwareGatewayList` | 分页查询站点基础信息 | | | `selectIotGatewayList` | 站点完整信息列表 | | | `getGatewayTouListV2` | 站点 TOU 模式信息 | | **功率流** | 功率流查询接口 | 按天查询站点功率数据 | | **告警** | `QuerySiteAlarmList` | 站点告警列表 | | | `QueryAlarmStatistics` | 告警码统计 | | | `QueryAlarmSnapshotInfo` | 告警快照文件信息 | | **日志** | `QueryMqttLogListOnTimeRange` | MQTT 日志(类型 0/101/201/357) | | | `QueryEventOrAlarmListOnTimeRange` | 事件/告警日志 | | | `QueryCallEmsLog` | 召唤 EMS 日志 | | | `QueryDownloadEmsLogFile` | 下载 EMS 日志文件 | | **故障录波** | `QueryFaultRecordList` | 故障录波列表 | | | `QueryDownloadFaultRecordData` | 下载录波数据 | | **升级** | `QuerySystemUpdateLog` | 系统升级记录 | | | `QueryAHubUpdateLog` | aHub 升级记录 | | **TOU 模板** | `QueryTouTemplateInfoList` | 调度策略模板列表 | | | `QueryTouTemplateDetailInfo` | 模板详情 | | **Shutdown** | `QuerySiteShutdownList` | 停机站点列表 | ### 11.2 SIM 卡平台 API #### SmartHub ```go // 批量查询 SIM 卡信息 smartHub.QueryBatchSimCardInfo(page, size) → []SmartHubSimCardInfo ``` | 字段 | 说明 | |------|------| | ICCID | SIM 卡标识 | | IMEI/IMSI | 设备标识 | | Status | 状态(TEST_READY/ACTIVATE_READY/ACTIVATED/DEACTIVATED/RETIRED) | | DataUsage | 流量使用量 | #### Acceleronix ```go // SIM 卡列表 acceleronix.QuerySimCardList(page, size) → []AcceleronixSimCard // 批量数据用量 acceleronix.QueryBatchSimCardDataInfo(ids, month) → []DataUsageInfo ``` #### 数据统一存储 外部平台数据经转换后统一存储为内部 `domain.SimCardInfo` 格式: ```go // 转换函数 SmartHubSimCardInfoToStorage(info) → domain.SimCardInfo AcceleronixSimCardToStorage(info) → domain.SimCardInfo ``` ### 11.3 MQTT 通信 #### 连接配置 - **Broker**: 通过 TLS 证书认证连接 - **协议**: MQTT v3.1.1 - **客户端特性**: 自动重连、断线恢复订阅 #### 通信主题 | 方向 | 主题模式 | 说明 | |------|----------|------| | 下行 | `fwh/c2s/mng/{sn}` | 服务端 → 设备(管理指令) | | 上行 | `fwh/s2c/mng/{sn}` | 设备 → 服务端(响应) | #### 支持的操作 ```go // Xlog 使能 fwh_mqtt.EnableXlog(ctx, sn string) error // 主题: fwh/c2s/mng/{sn} // 作用: 使能设备 Xlog 功能 // 故障录波参数设置 fwh_mqtt.FaultRecordParamSetting(ctx, para FaultRecordParamInfo) error // 发送: cmdType=377 (参数设置指令) // 等待: cmdType=378 (设备确认响应) ``` ### 11.4 MinIO 对象存储 #### 用途 | 场景 | 存储路径 | 文件类型 | |------|----------|----------| | 批量下载数据 | `BatchDownloadData/{SN}/{Type}/{Date}.*` | Excel、图表、tar.gz | | 升级配置文件 | 配置的 Bucket + Key | Excel | #### 操作接口 ```go minio.Upload(bucket, key, filePath) error // 上传文件 minio.UploadFromReader(bucket, key, reader) error // 流式上传 minio.Download(bucket, key) (io.Reader, error) // 下载文件 minio.List(bucket, prefix) ([]ObjectInfo, error) // 列出文件 minio.Delete(bucket, key) error // 删除文件 minio.ExistsObject(bucket, key) (bool, error) // 检查存在 minio.PresignedURL(bucket, key, expires) (string, error) // 预签名URL ``` ### 11.5 Casdoor SSO #### 集成方式 - **协议**: OAuth 2.0 Authorization Code Flow - **功能**: 统一登录、Token 刷新、JWT 解析 - **会话管理**: Redis Hash 存储,TTL = 7 天 #### 认证流程 ``` 前端 → Casdoor 登录页 → 获取 Authorization Code → POST /auth/login {code, state} → 后端调用 casdoor.GetOAuthToken(code, state) → 获取 AccessToken + RefreshToken → 存入 Redis Session → 返回 SessionId + Tokens ``` --- ## 12. 部署与运行 ### 12.1 启动序列 ``` main.go 启动流程: 1. config.LoadConfig() 加载 .env 配置 2. logger.Init(env) 初始化 Zap 日志 3. database.Init(&cfg.App) 连接 PostgreSQL + MongoDB 4. cache.Init(redisAddr) 连接 Redis (DB=12) 5. minio.InitClient(&cfg.App) 连接 MinIO 对象存储 6. repositories.FwhHttpInit() 初始化 FWH API 客户端 7. scheduler.Init() 注册 Cron 定时任务 8. task.InitTask(redisOpt) 启动 Asynq 异步任务系统 9. casdoor.InitAuthConfig() 配置 SSO 认证 10. repositories.FwhMqttInit() 连接 MQTT Broker 11. routes.Setup(app) 注册 Fiber 路由 12. networkEvents.InitEvio() 启动网络事件监听 (goroutine) 13. Asynqmon HTTP 服务 启动任务监控面板 (:8081) 14. fwh_pro.Login() 预登录 FWH 平台 15. app.Listen(":8301") 启动 HTTP 服务 16. Signal 监听 优雅关闭 (SIGTERM/SIGINT) ``` ### 12.2 环境依赖 | 服务 | 用途 | 开发环境地址 | |------|------|-------------| | PostgreSQL | 本地业务数据 | 本地 | | MongoDB | 文档型数据存储 | `127.0.0.1:27017` | | Redis | 缓存 + 任务队列 | `localhost:6379` | | MinIO | 对象存储 | `localhost:9198` | | MySQL (FWH Pro) | 站点数据(只读) | AWS RDS | | Casdoor | SSO 认证 | 独立部署 | | MQTT Broker | 设备通信 | TLS 连接 | ### 12.3 部署脚本 ```bash # 编译 + 部署 cmd/deploy.sh # 仅编译 cmd/only_build.sh # 查看日志 cmd/showLog.sh # 全部日志 cmd/showTodayLog.sh # 今日日志 cmd/showTodayErrorLog.sh # 今日错误日志 ``` ### 12.4 端口规划 | 端口 | 服务 | 说明 | |------|------|------| | 8301 | Fiber HTTP | 主 API 服务 | | 8081 | Asynqmon | 异步任务监控面板 | | — | Evio | 网络事件监听(自定义端口) | ### 12.5 优雅关闭 ```go // 监听系统信号 quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGTERM, syscall.SIGINT) <-quit // 关闭顺序: // 1. 停止接收新请求 // 2. 等待进行中请求完成 // 3. 关闭数据库连接 // 4. 关闭 Redis 连接 // 5. 关闭 MQTT 连接 // 6. 停止定时任务 // 7. 停止异步任务 Worker ``` ### 12.6 开发指南 #### 新增业务模块步骤 1. **定义 Domain** — 在 `domain/` 中定义业务领域对象 2. **定义 DTO** — 在 `dto/` 中定义 API 请求/响应结构 3. **实现 Repository** — 在 `repositories/` 对应子目录中实现数据访问 4. **注册到聚合层** — 在 `repositories/repositories.go` 中暴露新方法 5. **实现 Service** — 在 `services/` 中编写业务逻辑 6. **实现 Controller** — 在 `controllers/` 中处理 HTTP 请求 7. **注册路由** — 在 `routes/` 中创建路由文件并在 `Setup()` 中注册 8. **编写 Swagger 注释** — 在 Controller 函数上添加 swaggo 注释 9. **生成文档** — 运行 `swag init` 更新 Swagger 文档 #### 代码规范 - **分层原则**:不允许跳层访问(Controller 不能直接调 Repository) - **聚合模式**:所有 Repository 通过聚合包暴露,Service 只导入 `repositories` - **错误处理**:统一通过 Fiber 响应错误码,Service 层返回 error - **日志规范**:使用 `logger.Log` 或 `zap.L()` 记录结构化日志 - **命名规范**: - 文件名:`{模块名}{层级}.go`(如 `batchDownloadServices.go`) - 函数名:大驼峰,动词开头(如 `GetBatchDownloadList`) - Domain 字段:bson tag 用 camelCase - DTO 字段:json tag 用 camelCase - Model 字段:gorm tag 用 snake_case --- ## 附录 ### A. 关键技术模式 #### 流式文件传输 ```go c.Context().SetBodyStreamWriter(func(w *bufio.Writer) { // ZIP 打包 / 文件转发 / Excel 写入 io.Copy(writer, source) w.Flush() }) ``` #### 分布式唯一任务 ```go lock, ok, err := cache.TryLock(ctx, "task:"+taskType+":"+id, 2*time.Hour) if !ok { return ErrTaskAlreadyRunning } defer cache.LockRelease(ctx, key, lock.Token) // 执行任务... ``` #### 泛型 Cache-Aside ```go result, err := cache.GetOrSet[dto.SitePowerFlow](ctx, cacheKey, func() (*dto.SitePowerFlow, error) { return repositories.QuerySitePowerFlow(sn, date) }, cache.WithTTL(24*time.Hour), ) ``` ### B. MQTT 命令类型速查 | cmdType | 方向 | 说明 | |---------|------|------| | 0 | 上报 | 设备离线通知 | | 101 | 上报 | 设备上线通知 | | 201 | 上报 | 运行数据(功率/SOC/模式等 30+ 参数) | | 357 | 上报 | 模式切换事件 | | 377 | 下行 | 故障录波参数设置 | | 378 | 上行 | 故障录波参数设置响应 | ### C. 数据库 Schema 速查 | 数据库 | Schema/Database | 表/集合 | |--------|----------------|---------| | PostgreSQL | `alarm_snapshot` | `site_alarm_snapshot_file_record`、`site_alarm_snapshot_data` | | PostgreSQL | `original` | `site_original_data` | | MongoDB | `FwhToolboxDbDev` | site_info、batch_download、site_analysis、auto_update_config、sim_card_info、shutdown_statistics、user_info、sites_monitor、site_tags 等 | | MySQL | `home_energy_storage_server` | `iot_gateway`(只读) | | Redis | DB=12 | 会话(Hash)、缓存(String)、任务队列(Stream)、锁(String NX) |