Skip to content

Repository files navigation

EMS Simulate - 能源管理系统模拟器

一个用于模拟能源管理系统(EMS)中关键设备行为的软件系统,主要用于测试和开发场景。系统支持多种工业通信协议(Modbus TCP/RTU、IEC 60870-5-101/104、DL/T 645-2007、IEC 61850、DNP3),可模拟真实工业设备(如PCS储能变流器、BMS电池管理系统、电表、断路器等)的数据交互。

📖 查看在线文档 / Online Documentation


🏪 Microsoft Store

EMS Simulate 已上架微软应用商店,可直接在 Windows 10/11 上安装使用。

Microsoft Store

点击上方图片,或 直接访问 Microsoft Store 下载页面


功能特性

功能 说明
多协议联调 Modbus TCP/RTU、IEC 60870-5-101/104、DL/T 645-2007、IEC 61850、DNP3,支持设备模拟与客户端采集
设备管理 设备分组与子分组、通道与从站管理、启停、连接监视;支持批量复制及名称、IP、端口偏移配置
测点管理 YC/YX/YK/YT 分类管理、测点编辑、Excel 点表导入与导出、协议属性配置和运行时更新
数据模拟 固定值、随机、递增、递减、正弦波、斜坡、脉冲;支持单点配置、批量配置和模拟数据监视
读取与控制 单点读取、批量读取、后台自动读取,以及各协议支持的遥控、遥调操作
测点联动 乘法/加法系数、自定义公式、跨设备测点映射,构建设备间的数据关联
变化追踪 查看测点变化时间、前后值和来源,区分手动修改、模拟、映射、协议写入和客户端读取
报文分析 在各协议设备下查看收发报文、原始字节与字段解析,辅助定位通信问题
IEC 61850 工具 数据模型与 DataSet、MMS、GOOSE、Reports、Files、定值组、日志,以及 SCL 文件管理和图形化建模
界面与运行环境 Vue 3 Web 界面、Tauri 桌面客户端、中英文切换、界面缩放、存储目录配置及应用日志查看

技术架构

技术架构图

技术栈

层次 技术
前端 Vue 3, TypeScript, Vite, Element Plus
后端 Python 3.11+, FastAPI, SQLAlchemy
协议 pymodbus 3.12, c104, dlt645, pyiec61850-ng, pydnp3-pure,以及 IEC101 FT1.2 实现
数据库 SQLite (默认) / MySQL
桌面壳 Tauri v2 + Rust

界面展示

已有截图直接展示;待补截图以“截图待补”标记,并附建议文件名和图片语法。将截图放入 resources/img/ 后,取消对应图片语法的 HTML 注释,即可替换占位说明。

通用功能

设备与测点管理

  1. 主界面 — 设备分组树 + 设备详情面板

    主界面与设备分组树

  2. 添加设备分组

    添加设备分组

  3. 添加子设备组

    添加子设备组

  4. 新增设备 — 选择设备类型与协议

    新增设备

  5. 展开列表行编辑测点值

    展开测点并编辑数值

  6. 设置数据模拟方式 — 随机 / 步进 / 固定值

    设置测点模拟方式

  7. 编辑测点信息 — 地址、系数、解析码等

    编辑测点信息

批量复制、从站与连接管理

支持复制单个或多个设备,配置名称前后缀、IP 和端口偏移;通过从站管理和连接监视查看设备通信状态。

点表导入与导出

通过 Excel 模板批量配置测点,支持导出点表。仓库提供 ModbusIEC104DL/T 645DNP3 示例点表。

模拟配置与实时监视

支持固定值、随机、递增、递减、正弦波、斜坡、脉冲等模拟方式,可按测点设置参数,并批量选择参与模拟的测点。

测点模拟配置

模拟数据监视

客户端支持单点、批量和后台自动读取。自动读取在切换页面后继续运行,回到设备页面可恢复查看任务状态;停止设备时结束对应任务。

测点映射、公式与变化追踪

支持以多个源测点构建公式,并将结果映射到目标测点,实现跨设备、跨协议的数据联动。变化历史记录时间、前后值及变化来源,便于追查模拟和通信写入的结果。

应用设置与日志

提供中英文切换、界面缩放、存储目录配置和应用运行日志查看。

应用设置 — 展示界面、语言和存储配置。

应用日志 — 展示日志筛选和日志详情。


协议模块

以下按协议介绍配置、数据操作与报文查看。各协议支持服务端/从站(模拟设备)和客户端/主站(采集或控制设备)角色,具体功能见对应模块。

Modbus TCP / RTU

工业自动化领域应用最广泛的通信协议,支持 TCP 网络连接和 RTU 串口连接两种模式。

属性 TCP RTU
默认端口 502 —(串口)
数据操作 线圈、离散输入、保持寄存器、输入寄存器的读取及可写区写入 同 TCP
解析码 8/16/32/64 位、大小端、字交换 同 TCP
设备配置与数据操作

Modbus 设备配置

Modbus 运行参数

Modbus 协议操作

支持线圈、离散输入、保持寄存器、输入寄存器四类数据区,内置完整解析码系统适配不同厂商设备。

报文查看

Modbus 报文查看


IEC 60870-5-104

电力系统远动通信标准协议,广泛用于变电站与调度中心之间的数据传输。

属性 说明
默认端口 2404
帧类型 YC(遥测)、YX(遥信)、YK(遥控)、YT(遥调)
品质描述 IV/NT/SB/BL/OV 等标准品质位
传输原因 周期、自发、总召等
参数配置与四遥操作

IEC104 运行参数

IEC104 协议操作

支持四遥(YC/YX/YK/YT)、ASDU 类型配置与筛选、总召、时钟同步及品质描述符。

报文查看

IEC104 协议报文


IEC 60870-5-101

IEC104 的串行远动协议版本,与 IEC104 共用 ASDU、四遥点表、品质描述符、传送原因和数值换算。

属性 说明
传输介质 串口(主站 / 从站)
链路层 FT1.2 定长帧、变长帧、单字符确认、校验和、FCB/FCV
地址长度 链路地址 1/2 字节、COT 1/2 字节、公共地址 1/2 字节、IOA 1~3 字节
应用功能 一级/二级数据轮询、总召唤、读命令、遥控/遥调、时钟同步、自发上送

默认采用非平衡传输模式;协议运行参数中可以配置地址宽度、响应超时与轮询间隔。

参数配置与数据操作

📷 IEC101 配置与操作 — 展示串口、链路地址、ASDU 地址宽度和四遥测点。

报文查看

📷 IEC101 报文查看 — 展示 FT1.2 收发帧及链路层、ASDU 字段解析。


DL/T 645-2007

中国电力行业多功能电能表通信协议标准,用于电表数据采集。

属性 说明
默认端口 8899
数据标识 按 DI 配置电能、功率、电压、电流等数据项
系数转换 乘法系数 + 加法系数 → 真实值
电表配置与读写验证

DLT645 设备配置

DLT645 操作

DL/T645 协议测试 — 验证读取值与系数转换的正确性

DLT645 读取与系数转换验证

支持电表数据项标识解析,自动应用乘法/加法系数转换真实值,提供客户端读取验证。

报文查看

DLT645 报文查看


IEC 61850

面向智能变电站的设备模拟与联调,提供 MMS 数据访问、GOOSE 发布/订阅、报告控制、文件浏览、定值组和日志功能,并配套 SCL 管理与图形化建模工具。

子模块 功能
MMS / Data Models 服务端建模、客户端模型发现、树形浏览、数据读写与模型导出
Data Sets 数据集成员浏览与批量读取
GOOSE 发布、订阅、接收历史与报文抓包解析
Reports BRCB/URCB 控制块配置、启停、GI 与报告接收
Files 客户端远程目录浏览和文件下载
Setting Groups 定值组发现、读取、选择编辑组、写入、确认和激活
Logs 日志控制块发现与启停、按时间范围查询日志
SCL 文件管理 ICD/CID/SCD 文件上传、预览、校验、导入与差异对比
图形化建模 模型工程、LD/LN/DO/DA 编辑、CDC 模板、DataSet 与控制块配置、模型校验、版本管理及发布
MMS、数据模型与 DataSet

IEC61850 设备配置

IEC61850 MMS 操作

支持客户端模型发现和模型导出;DataSet 可用于组织测点并进行批量读取。

📷 DataSet 与模型导出 — 展示模型导出格式。

GOOSE 发布、订阅与抓包

IEC61850 GOOSE 配置

IEC61850 GOOSE 抓包

Reports 报告控制

IEC61850 报告控制与接收

Files 文件服务

IEC61850 远程文件浏览与下载

Setting Groups 定值组

查看定值组控制块,选择编辑组、修改定值并确认,再激活目标定值组。

📷 IEC61850 定值组 — 展示当前激活组、编辑组、定值列表及操作结果。

Logs 日志服务

管理日志控制块

SCL 文件管理与图形化建模

支持 SCL 文件预览、导入和差异对比;图形化建模工作区可创建或导入模型工程,编辑逻辑设备、逻辑节点和数据对象,配置数据集与控制块,执行校验、保存版本并发布模型。

IEC61850 SCL 导入建模

报文查看

MMS 报文

IEC61850 MMS 报文查看

GOOSE 报文

IEC61850 GOOSE 报文解析

Reports 报文

IEC61850 报告报文解析


DNP3

支持 Master(主站/客户端)Outstation(从站/服务端),用于 DNP3 设备的数据采集、事件上送与控制联调。

属性 说明
传输与端口 TCP,默认端口 20000;支持 TLS 配置
站点配置 本端与对端站点地址、请求超时、重试与重连参数
点表配置 点索引、静态/事件 Variation、事件 Class、死区、品质位及时间戳
数据采集 Class 0 完整性轮询、Class 1/2/3 事件读取、单点与批量读取
事件上送 可配置 Unsolicited 未请求上报,接收后同步测点值与运行元数据
控制操作 CROB 二进制控制、模拟量输出,支持 Select/Operate 和 Direct Operate
其他操作 时间同步、计数器冻结;支持 Excel 点表导入
主从站配置与数据操作

测点属性与事件配置

报文查看

📷 DNP3 报文查看 — 展示收发方向、链路地址、应用功能码、对象组/变体及原始字节。


快速开始

环境要求

  • Python >= 3.11
  • Node.js >= 18
  • uv、npm、Git(部分 Python 协议依赖从 Git 仓库安装)

安装依赖

在项目根目录安装 Python 依赖并启动后端:

# 如未安装 uv,先执行:pip install uv
uv sync --extra dev
uv run python start_back_end.py

另开一个终端,从项目根目录启动前端:

cd front
npm install
npm run dev

在浏览器中打开 Vite 输出的本地地址。后端配置见 配置说明

Tauri 桌面应用构建

Windows 构建需安装 Rust、MSVC 构建工具及 Tauri CLI。使用仓库打包脚本构建前端、Python 后端及桌面客户端:

# 在项目根目录执行
uv sync --extra dev --extra build
npm install -g @tauri-apps/cli

# 构建 Windows 安装包
.\scripts\build_tauri_windows.ps1

脚本默认生成 MSI 安装包;MSIX 打包入口及额外工具要求见 Windows 打包脚本。Linux 部署见 Debian 打包与部署指南


文档资源


核心概念

测点类型

系统支持四种测点类型:

类型 代码 说明 典型用途
遥测 (YC) frame_type=0 模拟量测量 电压、电流、功率、温度
遥信 (YX) frame_type=1 开关量状态 运行状态、故障标志
遥控 (YK) frame_type=2 开关量命令 启停命令、合分闸
遥调 (YT) frame_type=3 模拟量命令 功率设定、温度设定

协议类型

协议 服务端 客户端 默认端口
Modbus TCP 502
Modbus RTU 串口
IEC 60870-5-104 2404
IEC 60870-5-101 串口
DL/T 645-2007 8899
DNP3 ✅(Outstation) ✅(Master) 20000
IEC 61850 MMS 102
IEC 61850 GOOSE ✅(发布) ✅(订阅) —(以太网二层)
IEC 61850 Reports 复用 MMS 连接
IEC 61850 Files
IEC 61850 Setting Groups 复用 MMS 连接
IEC 61850 Logs 复用 MMS 连接

解析码系统 (Decode)

解析码定义了 Modbus 寄存器数据的解析方式,包括数据类型、字节序和位数。

解析码一览表

16位整数 (1个寄存器)

解析码 名称 说明 字节序
0x20 UINT16_BE 16位无符号整数 大端 (AB)
0x21 INT16_BE 16位有符号整数 大端 (AB)
0xC0 UINT16_LE 16位无符号整数 小端 (BA)
0xC1 INT16_LE 16位有符号整数 小端 (BA)
0xB0 UINT16_BE_SWAP 16位无符号整数 大端字交换
0xB1 INT16_BE_SWAP 16位有符号整数 大端字交换

32位整数/浮点 (2个寄存器)

解析码 名称 说明 字节序
0x40 UINT32_BE 32位无符号整数 大端 (ABCD)
0x41 INT32_BE 32位有符号整数 大端 (ABCD)
0x42 FLOAT_BE 32位浮点数 大端 (ABCD)
0xD0 UINT32_LE 32位无符号整数 小端 (DCBA)
0xD1 INT32_LE 32位有符号整数 小端 (DCBA)
0xD2 FLOAT_LE 32位浮点数 小端 (DCBA)
0x43 UINT32_BE_SWAP 32位无符号整数 大端字交换 (CDAB)
0x44 INT32_BE_SWAP 32位有符号整数 大端字交换 (CDAB)
0x45 FLOAT_BE_SWAP 32位浮点数 大端字交换 (CDAB)
0xD4 UINT32_LE_SWAP 32位无符号整数 小端字交换 (BADC)
0xD5 INT32_LE_SWAP 32位有符号整数 小端字交换 (BADC)
0xD3 FLOAT_LE_SWAP 32位浮点数 小端字交换 (BADC)

64位整数/浮点 (4个寄存器)

解析码 名称 说明 字节序
0x60 UINT64_BE 64位无符号整数 大端
0x61 INT64_BE 64位有符号整数 大端
0x62 DOUBLE_BE 64位双精度浮点 大端
0xE0 UINT64_LE 64位无符号整数 小端
0xE1 INT64_LE 64位有符号整数 小端
0xE2 DOUBLE_LE 64位双精度浮点 小端

8位字符 (1个寄存器)

解析码 名称 说明
0x10 CHAR_8_BE 8位无符号字符
0x11 CHAR_8_BE_SIGNED 8位有符号字符

字节序说明

以32位浮点数 1234.5 为例,其十六进制表示为 449A5000

字节序类型 存储顺序 说明
大端 (BE) 44 9A 50 00 高字节在前,标准网络字节序
小端 (LE) 00 50 9A 44 低字节在前,x86架构常用
大端字交换 (BE_SWAP) 50 00 44 9A 寄存器内大端,寄存器间交换
小端字交换 (LE_SWAP) 9A 44 00 50 寄存器内小端,寄存器间交换

代码使用示例

from src.enums.modbus_register import Decode, DecodeCode

# 方式一:使用解析码字符串
info = Decode.get_info("0x41")
print(f"寄存器数量: {info.register_cnt}")  # 2
print(f"是否有符号: {info.is_signed}")      # True
print(f"字节序: {info.endian}")             # >

# 方式二:使用枚举(推荐)
info = DecodeCode.FLOAT_BE.value
print(f"解析码: {info.code}")              # 0x42
print(f"描述: {info.description}")         # 32位浮点数(大端)

# 数据打包/解包
packed = Decode.pack_value(info.pack_format, 1234.5)
value = Decode.unpack_value(info.pack_format, packed)

# 获取所有解析码(供前端下拉菜单使用)
all_codes = Decode.get_all_codes()

真实值转换

遥测和遥调类型支持系数转换:

真实值 = 寄存器值 × 乘法系数 + 加法系数
寄存器值 = (真实值 - 加法系数) ÷ 乘法系数
属性 说明 默认值
mul_coe 乘法系数 1.0
add_coe 加法系数 0.0

项目结构

ems_simulate/
├── src/                        # 后端源码
│   ├── config/                 # 配置管理
│   │   ├── config.py          # 全局配置
│   │   └── log/               # 日志配置
│   ├── data/                   # 数据层
│   │   ├── dao/               # 数据访问对象
│   │   └── service/           # 业务服务
│   ├── device/                 # 设备模拟器 ⭐
│   │   ├── core/              # 核心类
│   │   │   ├── device.py      # Device 主类
│   │   │   ├── point/        # 测点管理与计算
│   │   │   └── data/         # 数据读取与导出
│   │   ├── protocol/          # 协议处理器
│   │   │   ├── base_handler.py      # 基类
│   │   │   ├── modbus_handler.py    # Modbus
│   │   │   ├── iec104_handler.py    # IEC104
│   │   │   ├── iec101_handler.py    # IEC101
│   │   │   ├── dlt645_handler.py    # DLT645
│   │   │   ├── dnp3_handler.py      # DNP3 Master/Outstation
│   │   │   └── iec61850_handler.py  # IEC61850
│   │   ├── simulator/         # 模拟控制
│   │   ├── factory/           # 设备工厂
│   │   └── types/             # 设备类型
│   ├── enums/                  # 枚举和数据结构
│   │   ├── modbus_register.py # 解析码定义 ⭐
│   │   └── points/            # 测点类型
│   ├── proto/                  # 底层协议实现
│   │   ├── pyModbus/          # Modbus 服务端/客户端
│   │   ├── iec104/            # IEC104 服务端/客户端
│   │   ├── iec101/            # IEC101 FT1.2 主站/从站
│   │   ├── iec60870/           # IEC101/IEC104 公共 ASDU 层
│   │   ├── dlt645/            # DLT645 协议库
│   │   ├── dnp3/              # DNP3 主站/从站、事件、控制与 TLS
│   │   └── iec61850/          # IEC61850 MMS/GOOSE/Reports/Files/SV
│   ├── modeling/               # IEC61850 模型工程、校验与版本管理
│   └── web/                    # Web API
│       └── api/
│           ├── device/        # 设备控制接口
│           ├── channel/       # 通道与协议管理
│           ├── point/         # 测点与映射接口
│           ├── modeling/      # IEC61850 图形化建模接口
│           └── scl/           # SCL/ICD 文件管理
├── front/                      # 前端源码 (Vue3)
│   ├── src/
│   │   ├── components/        # 组件
│   │   ├── views/             # 页面
│   │   └── api/               # API封装
│   └── package.json
├── src-tauri/                  # Tauri 桌面壳 (Rust)
│   ├── src/
│   │   ├── lib.rs             # Tauri Builder
│   │   └── backend.rs         # 后端进程管理
│   └── tauri.conf.json
├── data/                       # SQLite 数据库
├── start_back_end.py          # 后端入口
├── pyproject.toml             # Python 依赖与配置
└── uv.lock                    # Python 依赖锁定文件

开发指南

添加新设备类型

  1. src/device/types/ 下创建新设备类
  2. 继承 Device 基类
  3. 实现 setSpecialDataPointValues() 方法(可选)
from src.device.core.device import Device, DeviceType

class MyDevice(Device):
    def __init__(self):
        super().__init__()
        self.device_type = DeviceType.Other

    def setSpecialDataPointValues(self):
        # 设置特殊测点关联逻辑
        pass

扩展新协议

  1. src/device/protocol/ 下创建处理器
  2. 继承 ServerHandlerClientHandler
  3. 实现抽象方法
from src.device.protocol.base_handler import ServerHandler

class MyProtocolHandler(ServerHandler):
    def initialize(self, config):
        pass

    async def start(self) -> bool:
        self._is_running = True
        return True

    async def stop(self) -> bool:
        self._is_running = False
        return True

    def read_value(self, point):
        pass

    def write_value(self, point, value):
        pass

    def add_points(self, points):
        pass

许可证

本项目采用 GNU General Public License v3.0(GPL-3.0),详见 LICENSE

贡献

欢迎提交 Issue 和 Pull Request!

About

一个用于模拟EMS能源管理系统中关键设备行为的软件系统,主要用于测试和开发场景。系统支持多种工业通信协议(Modbus TCP/RTU、IEC101、IEC104、IEC61850、DL/T645-2007、DNP3),并且支持TLS单向/双向加密认证,可模拟真实工业设备(如PCS储能变流器、BMS电池管理系统、电表等)的数据交互,支持IEC61850建模

Topics

Resources

Stars

39 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages