{"id":49915615,"url":"https://github.com/600888/ems_simulate","last_synced_at":"2026-06-06T11:01:06.462Z","repository":{"id":334337759,"uuid":"1135762315","full_name":"600888/ems_simulate","owner":"600888","description":"一个用于模拟能源管理系统（EMS）中关键设备行为的软件系统，主要用于测试和开发场景。系统支持多种工业通信协议（Modbus TCP/RTU、IEC104、IEC61850、DL/T645-2007），可模拟真实工业设备（如PCS储能变流器、BMS电池管理系统、电表等）的数据交互","archived":false,"fork":false,"pushed_at":"2026-05-10T11:45:38.000Z","size":21511,"stargazers_count":9,"open_issues_count":0,"forks_count":3,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-10T13:45:15.892Z","etag":null,"topics":["dlt645","ems","iec104-client","iec104-server","iec104-server-simulator","iec61850","iec61850-client","iec61850-server","modbus","python"],"latest_commit_sha":null,"homepage":"https://600888.github.io/ems_simulate/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/600888.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-16T14:58:31.000Z","updated_at":"2026-05-10T11:45:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/600888/ems_simulate","commit_stats":null,"previous_names":["600888/ems_simulate"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/600888/ems_simulate","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/600888%2Fems_simulate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/600888%2Fems_simulate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/600888%2Fems_simulate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/600888%2Fems_simulate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/600888","download_url":"https://codeload.github.com/600888/ems_simulate/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/600888%2Fems_simulate/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33109463,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-16T04:41:52.686Z","status":"ssl_error","status_checked_at":"2026-05-16T04:41:52.009Z","response_time":115,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dlt645","ems","iec104-client","iec104-server","iec104-server-simulator","iec61850","iec61850-client","iec61850-server","modbus","python"],"created_at":"2026-05-16T16:08:40.255Z","updated_at":"2026-05-16T16:08:41.179Z","avatar_url":"https://github.com/600888.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# EMS Simulate - 能源管理系统模拟器\n\n一个用于模拟能源管理系统（EMS）中关键设备行为的软件系统，主要用于测试和开发场景。系统支持多种工业通信协议（Modbus TCP/RTU、IEC 60870-5-104、DL/T 645-2007），可模拟真实工业设备（如PCS储能变流器、BMS电池管理系统、电表等）的数据交互。\n\n\u003e 📖 **[查看在线文档 / Online Documentation](https://600888.github.io/ems_simulate/)**\n\n## 功能特性\n\n- 🔌 **多协议支持**：Modbus TCP/RTU、IEC 60870-5-104、DL/T 645-2007\n- � **设备模拟**：PCS储能变流器、BMS电池管理系统、电表、断路器等\n- 🎯 **数据模拟**：支持随机模拟、步进模拟等多种方式\n- ⚙️ **灵活配置**：支持数据库配置和CSV文件导入\n- 📊 **Web界面**：Vue3 + TypeScript 构建的现代化前端界面\n- � **热重载**：支持运行时修改测点属性\n\n## 技术架构\n\n![技术架构图](resources/img/architecture.png)\n\n### 技术栈\n\n| 层次 | 技术 |\n|------|------|\n| **前端** | Vue 3, TypeScript, Vite, Element Plus |\n| **后端** | Python 3.11+, FastAPI, SQLAlchemy |\n| **协议** | pymodbus 3.12, c104, dlt645 |\n| **数据库** | SQLite (默认) / MySQL |\n\n## 界面展示\n\n1. 主界面\n\n   ![](resources/img/1.png)\n\n2. 添加设备分组\n\n   ![](resources/img/2.png)\n\n3. 添加子设备组\n\n   ![](resources/img/3.png)\n\n4. 新增设备\n\n   ![](resources/img/4.png)\n\n5. 展开列表行可以编辑测点值\n\n   ![](resources/img/5.png)\n\n6. 设置数据模拟方式\n\n   ![](resources/img/6.png)\n\n7. 编辑测点信息\n\n   ![](resources/img/7.png)\n\n8. 以DL/T645-2007协议为例，测试读取值是否正确，需要结合乘法系数和加法系数，可以看到数据读取正确\n\n   ![](resources/img/8.png)\n\n---\n\n## 快速开始\n\n### 环境要求\n\n- Python \u003e= 3.11\n- Node.js \u003e= 18\n- pip, npm\n\n### 安装依赖\n\n```bash\n# 1. 安装 Python 依赖\npip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple\n\n# 2. 前端开发环境\ncd front\nnpm install\nnpm run dev\n\n# 3. 启动后端服务\npython start_back_end.py\n```\n\n\n---\n\n## 文档资源\n\n-   📚 **[项目文档](docs/index.md)**: 完整的项目使用说明和 API 参考\n-   📦 **[Debian 打包与部署指南](docs/packaging_deb.md)**: 详细介绍了如何在 Linux 环境下构建 deb 安装包\n\n---\n\n## 核心概念\n\n### 测点类型\n\n系统支持四种测点类型：\n\n| 类型 | 代码 | 说明 | 典型用途 |\n|------|------|------|----------|\n| **遥测 (YC)** | frame_type=0 | 模拟量测量 | 电压、电流、功率、温度 |\n| **遥信 (YX)** | frame_type=1 | 开关量状态 | 运行状态、故障标志 |\n| **遥控 (YK)** | frame_type=2 | 开关量命令 | 启停命令、合分闸 |\n| **遥调 (YT)** | frame_type=3 | 模拟量命令 | 功率设定、温度设定 |\n\n### 协议类型\n\n| 协议 | 服务端 | 客户端 | 默认端口 |\n|------|--------|--------|----------|\n| Modbus TCP | ✅ | ✅ | 502 |\n| Modbus RTU | ✅ | ✅ | 串口 |\n| IEC 60870-5-104 | ✅ | ✅ | 2404 |\n| DLT/T 645-2007 | ✅ | ✅ | 8899 |\n\n---\n\n## 解析码系统 (Decode)\n\n解析码定义了 Modbus 寄存器数据的解析方式，包括数据类型、字节序和位数。\n\n### 解析码一览表\n\n#### 16位整数 (1个寄存器)\n\n| 解析码 | 名称 | 说明 | 字节序 |\n|--------|------|------|--------|\n| `0x20` | UINT16_BE | 16位无符号整数 | 大端 (AB) |\n| `0x21` | INT16_BE | 16位有符号整数 | 大端 (AB) |\n| `0xC0` | UINT16_LE | 16位无符号整数 | 小端 (BA) |\n| `0xC1` | INT16_LE | 16位有符号整数 | 小端 (BA) |\n| `0xB0` | UINT16_BE_SWAP | 16位无符号整数 | 大端字交换 |\n| `0xB1` | INT16_BE_SWAP | 16位有符号整数 | 大端字交换 |\n\n#### 32位整数/浮点 (2个寄存器)\n\n| 解析码 | 名称 | 说明 | 字节序 |\n|--------|------|------|--------|\n| `0x40` | UINT32_BE | 32位无符号整数 | 大端 (ABCD) |\n| `0x41` | INT32_BE | 32位有符号整数 | 大端 (ABCD) |\n| `0x42` | FLOAT_BE | 32位浮点数 | 大端 (ABCD) |\n| `0xD0` | UINT32_LE | 32位无符号整数 | 小端 (DCBA) |\n| `0xD1` | INT32_LE | 32位有符号整数 | 小端 (DCBA) |\n| `0xD2` | FLOAT_LE | 32位浮点数 | 小端 (DCBA) |\n| `0x43` | UINT32_BE_SWAP | 32位无符号整数 | 大端字交换 (CDAB) |\n| `0x44` | INT32_BE_SWAP | 32位有符号整数 | 大端字交换 (CDAB) |\n| `0x45` | FLOAT_BE_SWAP | 32位浮点数 | 大端字交换 (CDAB) |\n| `0xD4` | UINT32_LE_SWAP | 32位无符号整数 | 小端字交换 (BADC) |\n| `0xD5` | INT32_LE_SWAP | 32位有符号整数 | 小端字交换 (BADC) |\n| `0xD3` | FLOAT_LE_SWAP | 32位浮点数 | 小端字交换 (BADC) |\n\n#### 64位整数/浮点 (4个寄存器)\n\n| 解析码 | 名称 | 说明 | 字节序 |\n|--------|------|------|--------|\n| `0x60` | UINT64_BE | 64位无符号整数 | 大端 |\n| `0x61` | INT64_BE | 64位有符号整数 | 大端 |\n| `0x62` | DOUBLE_BE | 64位双精度浮点 | 大端 |\n| `0xE0` | UINT64_LE | 64位无符号整数 | 小端 |\n| `0xE1` | INT64_LE | 64位有符号整数 | 小端 |\n| `0xE2` | DOUBLE_LE | 64位双精度浮点 | 小端 |\n\n#### 8位字符 (1个寄存器)\n\n| 解析码 | 名称 | 说明 |\n|--------|------|------|\n| `0x10` | CHAR_8_BE | 8位无符号字符 |\n| `0x11` | CHAR_8_BE_SIGNED | 8位有符号字符 |\n\n### 字节序说明\n\n以32位浮点数 `1234.5` 为例，其十六进制表示为 `449A5000`：\n\n| 字节序类型 | 存储顺序 | 说明 |\n|------------|----------|------|\n| **大端 (BE)** | `44 9A 50 00` | 高字节在前，标准网络字节序 |\n| **小端 (LE)** | `00 50 9A 44` | 低字节在前，x86架构常用 |\n| **大端字交换 (BE_SWAP)** | `50 00 44 9A` | 寄存器内大端，寄存器间交换 |\n| **小端字交换 (LE_SWAP)** | `9A 44 00 50` | 寄存器内小端，寄存器间交换 |\n\n### 代码使用示例\n\n```python\nfrom src.enums.modbus_register import Decode, DecodeCode\n\n# 方式一：使用解析码字符串\ninfo = Decode.get_info(\"0x41\")\nprint(f\"寄存器数量: {info.register_cnt}\")  # 2\nprint(f\"是否有符号: {info.is_signed}\")      # True\nprint(f\"字节序: {info.endian}\")             # \u003e\n\n# 方式二：使用枚举（推荐）\ninfo = DecodeCode.FLOAT_BE.value\nprint(f\"解析码: {info.code}\")              # 0x42\nprint(f\"描述: {info.description}\")         # 32位浮点数(大端)\n\n# 数据打包/解包\npacked = Decode.pack_value(info.pack_format, 1234.5)\nvalue = Decode.unpack_value(info.pack_format, packed)\n\n# 获取所有解析码（供前端下拉菜单使用）\nall_codes = Decode.get_all_codes()\n```\n\n### 真实值转换\n\n遥测和遥调类型支持系数转换：\n\n```\n真实值 = 寄存器值 × 乘法系数 + 加法系数\n寄存器值 = (真实值 - 加法系数) ÷ 乘法系数\n```\n\n| 属性 | 说明 | 默认值 |\n|------|------|--------|\n| `mul_coe` | 乘法系数 | 1.0 |\n| `add_coe` | 加法系数 | 0.0 |\n\n---\n\n## 项目结构\n\n```\nems_simulate/\n├── src/                        # 后端源码\n│   ├── config/                 # 配置管理\n│   │   ├── config.py          # 全局配置\n│   │   └── log/               # 日志配置\n│   ├── data/                   # 数据层\n│   │   ├── dao/               # 数据访问对象\n│   │   └── service/           # 业务服务\n│   ├── device/                 # 设备模拟器 ⭐\n│   │   ├── core/              # 核心类\n│   │   │   ├── device.py      # Device 主类\n│   │   │   ├── point_manager.py # 测点管理\n│   │   │   └── data_exporter.py # 数据导出\n│   │   ├── protocol/          # 协议处理器\n│   │   │   ├── base_handler.py    # 基类\n│   │   │   ├── modbus_handler.py  # Modbus\n│   │   │   ├── iec104_handler.py  # IEC104\n│   │   │   └── dlt645_handler.py  # DLT645\n│   │   ├── simulator/         # 模拟控制\n│   │   ├── factory/           # 设备工厂\n│   │   └── types/             # 设备类型\n│   ├── enums/                  # 枚举和数据结构\n│   │   ├── modbus_register.py # 解析码定义 ⭐\n│   │   └── points/            # 测点类型\n│   ├── proto/                  # 底层协议实现\n│   │   ├── pyModbus/          # Modbus 服务端/客户端\n│   │   ├── iec104/            # IEC104 服务端/客户端\n│   │   └── dlt645/            # DLT645 协议库\n│   └── web/                    # Web API\n│       ├── device/            # 设备控制接口\n│       └── data/              # 数据管理接口\n├── front/                      # 前端源码 (Vue3)\n│   ├── src/\n│   │   ├── components/        # 组件\n│   │   ├── views/             # 页面\n│   │   └── api/               # API封装\n│   └── package.json\n├── data/                       # SQLite 数据库\n├── start_back_end.py          # 后端入口\n└── requirements.txt           # Python依赖\n```\n\n---\n\n## 开发指南\n\n### 添加新设备类型\n\n1. 在 `src/device/types/` 下创建新设备类\n2. 继承 `Device` 基类\n3. 实现 `setSpecialDataPointValues()` 方法（可选）\n\n```python\nfrom src.device.core.device import Device, DeviceType\n\nclass MyDevice(Device):\n    def __init__(self):\n        super().__init__()\n        self.device_type = DeviceType.Other\n    \n    def setSpecialDataPointValues(self):\n        # 设置特殊测点关联逻辑\n        pass\n```\n\n### 扩展新协议\n\n1. 在 `src/device/protocol/` 下创建处理器\n2. 继承 `ServerHandler` 或 `ClientHandler`\n3. 实现抽象方法\n\n```python\nfrom src.device.protocol.base_handler import ServerHandler\n\nclass MyProtocolHandler(ServerHandler):\n    def initialize(self, config):\n        pass\n    \n    async def start(self) -\u003e bool:\n        self._is_running = True\n        return True\n    \n    async def stop(self) -\u003e bool:\n        self._is_running = False\n        return True\n    \n    def read_value(self, point):\n        pass\n    \n    def write_value(self, point, value):\n        pass\n    \n    def add_points(self, points):\n        pass\n```\n\n---\n\n## 许可证\n\nApache License 2.0\n\n## 贡献\n\n欢迎提交 Issue 和 Pull Request！","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F600888%2Fems_simulate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F600888%2Fems_simulate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F600888%2Fems_simulate/lists"}