# Virtual EMS **Repository Path**: PandaX-Go/virtual-ems ## Basic Information - **Project Name**: Virtual EMS - **Description**: **Virtual EMS** 是一个用 Go 语言构建的**完整储能能量管理系统(EMS)仿真环境**。它在一个进程中虚拟了电池组、BMU、BMS、PCS 等全部设备,通过真实的 Modbus TCP 协议进行交互,并提供直观的 Web 可视化界面,让你能够清晰看到每一条控制指令的流动、电流方向以及设备状态变化。 - **Primary Language**: Go - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2026-07-10 - **Last Updated**: 2026-07-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Virtual EMS — 基于 Go 的储能系统全链路仿真与可视化平台 [![Go Version](https://img.shields.io/badge/Go-1.21+-00ADD8?style=flat&logo=go)](https://go.dev/) [![License](https://img.shields.io/badge/license-MulanPSL%202-blue.svg)](LICENSE) [![Docker](https://img.shields.io/badge/Docker-Ready-2496ED?logo=docker&logoColor=white)](https://www.docker.com/) **Virtual EMS** 是一个用 Go 语言构建的**完整储能能量管理系统(EMS)仿真环境**。它在一个进程中虚拟了电池组、BMU、BMS、PCS 等全部设备,通过标准的 Modbus TCP 协议进行交互,并提供直观的 Web 可视化界面。你可以清晰看到每一条控制指令的流动、电流方向以及设备状态变化。 无论是学习 Modbus 通信、验证 EMS 控制策略、进行系统集成测试,还是作为教学演示工具,它都能让你在没有任何硬件的情况下快速开始。**现已支持 Docker 一键部署,开发环境零配置。** --- ## 特性 - **全栈仿真**:单进程运行电池模型、BMU、BMS、PCS,完全模拟真实电气层级。 - **纯 Go 实现的 Modbus TCP 协议栈**:不依赖第三方 Modbus 库,完全自主编写服务器与客户端,兼容各类标准 Modbus 工具(Modbus Poll、qModMaster 等)。 - **指令流与能量流双模式可视化**: - 黄色发光粒子表示控制指令(`EMS → PCS → BMS → 电池组`) - 绿色/红色粒子表示充电/放电能量流动(电网 ↔ PCS ↔ BMS ↔ 电池组),方向明确,实时刷新。 - **电气状态实时看板**:SOC、电压、电流、功率、温度等数据实时显示,充放电状态、效率模型自动计算。 - **寄存器即配置**:通过 JSON 文件定义每个设备的寄存器映射(点位文件),无需修改代码即可调整仿真行为。 - **事件总线与指令追踪**:所有设备间的 Modbus 写操作均生成带时间戳的事件,前端可显示完整指令链路。 - **手动/自动 EMS 控制**:支持 Web 界面按钮手动充放电,也可嵌入自动策略(可扩展)。 - **可扩展设备模型**:预留 `Device` 接口,轻松添加光伏逆变器、环境监测仪等新设备。 - **混合仿真就绪**:可将某个仿真设备替换为真实硬件(真实 Modbus 设备),其余部分仍保持虚拟化,实现半实物仿真。 - **Docker 容器化部署**:一键启动,无需安装 Go 或 Node.js,开箱即用。 --- ## 系统架构 ```mermaid graph TD subgraph “浏览器可视化” UI[Web 前端
拓扑图 / 粒子动画 / 数据看板] end subgraph “Go 仿真引擎 (单进程)” WS[WebSocket Hub] EB[事件总线] subgraph “设备仿真” EMS[EMS 控制器
Modbus 主站] PCS[PCS 仿真器
Modbus 从站 + BMS 客户端] BMS[BMS 仿真器
Modbus 从站 + 内部 BMU 聚合] BMU1[BMU #1] BMU2[BMU #2] BATT1[电池包 #1] BATT2[电池包 #2] end REG[寄存器配置加载器] end UI <-->|WebSocket| WS WS --> EB EB -.->|指令/状态事件| EMS EB -.->|指令/状态事件| PCS EB -.->|指令/状态事件| BMS EMS -->|Modbus TCP 读写| PCS PCS -->|Modbus TCP 读写| BMS BMS -->|内部调用| BMU1 BMS -->|内部调用| BMU2 BMU1 -->|状态更新| BATT1 BMU2 -->|状态更新| BATT2 ``` --- ## 快速开始 ### 环境要求(本地开发) - Go 1.21 或更高版本 - (前端已预编译为静态文件,无需 Node.js) ### 方式一:Docker 容器运行(推荐) **0. 前提**:安装 [Docker](https://www.docker.com/) 和 Docker Compose。 **1. 克隆仓库** ```bash git clone https://gitee.com/cmx1998/virtual-ems.git cd virtual-ems ``` **2. 构建并启动** ```bash docker-compose up -d ``` 首次运行会自动构建镜像,稍等片刻即可。 **3. 访问** 打开浏览器访问 `http://localhost:8080`,你将看到完整的系统拓扑图与实时数据。 **4. 停止** ```bash docker-compose down ``` > **说明**:Web 端口映射为 8080;Modbus 仿真端口(5020、5021)仅在容器内部使用,无需暴露。若需使用外部 Modbus 工具调试,可自行修改 `docker-compose.yml` 增加端口映射。 ### 方式二:本地编译运行 **1. 克隆仓库并进入目录** ```bash git clone https://gitee.com/cmx1998/virtual-ems.git cd virtual-ems ``` **2. 下载依赖并运行** ```bash go mod tidy go run ./cmd/simulator ``` **3. 访问** 打开浏览器访问 `http://localhost:8080`。 ### 使用 Modbus 工具单独调试 仿真器启动后,各设备 Modbus 从站默认地址: | 设备 | IP:Port | |------|----------------| | BMS | 127.0.0.1:5020 | | PCS | 127.0.0.1:5021 | 你可以使用 **Modbus Poll** 或 **qModMaster** 连接到这些端口,按照 `configs/` 中的寄存器表进行读写测试,所有操作都会实时反映到 Web 界面上。 --- ## 配置与寄存器点位文件 所有设备寄存器通过 JSON 文件定义,位于 `configs/` 目录。示例 `configs/pcs.json`: ```json { "device": "PCS", "slave_id": 2, "registers": [ {"address": 200, "name": "运行状态", "type": "uint16", "rw": "r", "desc": "0=待机 1=充电 2=放电 3=故障"}, {"address": 201, "name": "有功功率设定", "type": "int16", "rw": "rw", "desc": "单位 kW,正充电负放电"}, {"address": 202, "name": "直流电压", "type": "uint16", "rw": "r", "desc": "0.1V 精度"}, {"address": 203, "name": "直流电流", "type": "int16", "rw": "r", "desc": "0.1A 精度"}, {"address": 204, "name": "交流电压", "type": "uint16", "rw": "r", "desc": "0.1V 精度"}, {"address": 205, "name": "交流电流", "type": "int16", "rw": "r", "desc": "0.1A 精度"}, {"address": 206, "name": "交流功率", "type": "int16", "rw": "r", "desc": "0.1kW 精度"} ] } ``` 修改这些文件即可自定义设备接口,无需重新编译。程序启动时会自动加载并构建内存寄存器映射。 --- ## 目录结构 ``` . ├── cmd │ └── simulator # 主程序入口,启动所有仿真服务 ├── internal │ ├── config # 寄存器配置加载(JSON/Excel) │ ├── devices # 设备仿真器实现 │ │ ├── battery # 电池电芯模型(SOC/电压/温度) │ │ ├── bmu # 电池管理单元 │ │ ├── bms # 电池管理系统(聚合+Modbus 从站) │ │ ├── pcs # 储能变流器(从站+ BMS 客户端) │ │ └── ems # 能量管理系统(控制命令处理) │ ├── modbus # Modbus TCP 协议栈(服务器/客户端) │ ├── event # 指令事件定义与事件总线 │ └── web # WebSocket Hub,全局状态管理 ├── web # 前端静态文件(HTML/CSS/JS,已内嵌拓扑图动画) ├── configs # 寄存器配置文件 │ ├── bms.json │ └── pcs.json ├── vendor # Go 依赖离线缓存(用于 Docker 构建) ├── Dockerfile ├── docker-compose.yml ├── go.mod ├── go.sum └── README.md ``` --- ## 指令流可视化原理 1. 当 EMS 通过 Modbus 向 PCS 写入寄存器时,PCS 从站捕获到写操作。 2. PCS 仿真器内部触发回调,生成事件 `Event{From:"EMS", To:"PCS", Register:"有功功率设定", Value:50}`。 3. 事件通过事件总线广播,WebSocket Hub 将其推送到前端。 4. 前端收到事件后,在对应连线上创建黄色发光粒子,粒子沿连线移动并在到达后消散,同时目标设备高亮。 5. 若 PCS 随后向 BMS 写寄存器(转发指令),同样产生新事件,形成完整的指令链条。 6. 在充电/放电状态下,前端还会持续产生绿色或红色能量流粒子,模拟实际电能的流动方向。 最终呈现效果:用户点击“充电 50kW”按钮后,界面上一颗金色光点从 EMS 节点出发,到达 PCS 再跳到 BMS,最后分发至电池图标;同时电网节点也参与能量流动动画。 --- ## 可扩展性设计 ### 添加新设备仿真 1. 实现 `Device` 接口: ```go type Device interface { Name() string Init(regMap *modbus.RegisterMap, eventBus *event.Bus) error Start(ctx context.Context) error Stop() error } ``` 2. 在 `configs/` 中提供对应的寄存器 JSON。 3. 在 `cmd/simulator` 中注册设备并指定 Modbus 端口。 4. 前端组件增加新设备节点并订阅事件。 ### 接入真实设备 将某个仿真设备替换为真实 Modbus TCP 设备时,只需在配置中将其 `driver` 设置为 `"real"` 并提供 IP 地址,系统会跳过仿真逻辑,直接向真实设备读写寄存器,其余虚拟部分照常工作。 ### 自定义 EMS 策略 在 `internal/devices/ems` 中实现 `Strategy` 接口: ```go type Strategy interface { Evaluate(bmsData, pcsData map[string]float64) (controlAction string, params map[string]interface{}) } ``` 然后在 Web 界面或配置文件中选择当前运行的策略,支持热切换。 --- ## 迭代路线图 - [x] 基础电池模型与 BMS/PCS 仿真 - [x] 纯 Go 手写 Modbus TCP 协议栈 - [x] 寄存器 JSON 配置驱动 - [x] WebSocket 实时数据推送与状态看板 - [x] 指令粒子动画 + 能量流动可视化 - [x] 手动 EMS 控制与功率自动限制 - [x] **Docker 一键部署** - [ ] Excel 寄存器文件支持 - [ ] SOC-OCV 曲线电池模型(更高精度) - [ ] 故障注入与告警模拟 - [ ] 历史数据存储与回放(SQLite / InfluxDB) - [ ] 策略脚本引擎(Lua / JavaScript) - [ ] 多簇电池并联/串联复杂拓扑仿真 - [ ] 增加电网等更多设备节点 --- ## 贡献 欢迎提交 Issue 和 PR!在开始大的改动之前,建议先开 Issue 讨论设计方案。请遵循项目的 Go 编码规范和前端 ESLint 规则。 --- ## 许可证 本项目采用 [木兰宽松许可证,第2版](https://license.coscl.org.cn/MulanPSL2)(Mulan PSL v2)。 您可以自由复制、使用、修改及分发本软件,但需遵守该许可证的条款。 详见 [LICENSE](LICENSE) 文件。 --- **告别硬件依赖,在代码中自由探索储能系统。** *如有任何问题或建议,欢迎在 Gitee / GitHub 提交反馈。*