一台电脑 = 21 种工业设备
零成本模拟 PLC、传感器、摄像头,测试你的上位机和物联网网关
🚀 在线体验 · 📖 5分钟上手 · 💬 加入QQ群 · English
✅ Windows · ✅ Linux · ✅ macOS
🔥 V1.2.0 测试平台版 · 122 设备模板 · 21 种工业协议 · 测试计划+合规检测 · CSV 批量导入导出 · EdgeLite 生态对接 · 31 项 E2E 测试全通过
| # | 你遇到的痛点 | 有多痛 | ProtoForge 怎么解决 |
|---|---|---|---|
| 1 | 协议报文对不上,不知道哪里错了 | 客户说读不到数据,你抓包看 hex 对了半天,3天找不到原因 | WebSocket 实时调试日志,按协议/方向/关键词筛选,点击查看报文详情,秒级定位问题 |
| 2 | 模拟器太乖,上线就出事 | 测试环境永远返回正确值,上线后真实 PLC 断连/超时/返回异常码,全炸 | 内置9种故障注入:传感器卡死/漂移/噪声/失效、间歇断连/延迟/丢包、设备故障/执行器卡死,上线前测全异常场景 |
| 3 | 测试全靠手点,回归一下午 | 每次改完代码:手动建设备→启动→读数据→验证,一个回归搞一下午 | 自动化测试引擎:13种断言、变量提取、测试套件、HTML报告+趋势分析,SDK一行代码跑全部测试 |
| 4 | 客户现场出问题,没法复现 | 客户说昨天下午3点数据不对,没有录制,没法回放,只能猜 | 协议录制回放:录制通信报文→按需回放→验证修复,Gzip压缩存储 |
| 5 | 新人不懂协议,教1周才干活 | 地址偏移、功能码、字节序全搞混,手把手教还是出错 | 每个协议内置4语言代码示例(Python/C#/Java/Go),122个模板即用型配置,照着抄就能干 |
| 6 | 多协议联调,环境搭1周 | 同时测 Modbus+S7+MQTT,找3台不同厂商设备,配3套参数 | 21种协议一台电脑全搞定,Docker 30秒启动,一键生成100台虚拟设备 |
| 7 | 协议安全不敢测 | OPC-UA证书/TLS加密/GB28181 SRTP,生产不敢动,测试又没有 | 证书自动生成、TLS加密、SRTP全支持,安全场景随便测 |
| 场景 | 传统方式 | ProtoForge |
|---|---|---|
| 测 Modbus | 买 PLC(¥3000+) | 1 条命令启动虚拟设备 |
| GB28181 联调 | 买摄像头(¥500+) | 自动注册、自动推流 |
| 测 21 种协议 | 买各种厂商设备(¥50000+) | 一台电脑全部模拟 |
| 压力测试 | 部署几十台物理设备 | 一键生成 100 台虚拟设备 |
| 给客户演示 | 带一堆硬件出差 | 笔记本上完整演示 |
docker run -d --name protoforge -p 8000:8000 -e PROTOFORGE_ADMIN_PASSWORD=admin -v protoforge-data:/app/data suoten/protoforge:latest浏览器打开 **http://localhost:8000**,用 admin / admin 登录。
💡 第一次使用?这就是最简单的方式,不需要安装 Python、Node.js、Git。
🌐 http://localhost:8000 就是 Web 界面,不是只有 API。ProtoForge 的后端(FastAPI)会自动托管前端页面,不需要单独的 Nginx 或前端服务器。API 文档在
/docs,前端页面直接访问根路径/。🔐 密码说明:
- 上面的命令通过
-e PROTOFORGE_ADMIN_PASSWORD=admin指定了密码为admin- 如果不加这个参数,系统会自动生成随机密码,查看方式:
docker logs protoforge(找Login:那一行)- 生产环境请务必修改为强密码
设备总数、运行中协议、仿真场景、设备模板数量实时统计,快速操作入口一键触达。
支持按协议筛选、批量启停、快速创建。每台设备显示协议类型、在线状态、测点数量,支持测点读写、链路追踪、编辑配置。
Modbus TCP/RTU、OPC-UA、MQTT、HTTP、GB28181、BACnet、Siemens S7、Mitsubishi MC、Omron FINS、Rockwell AB、OPC-DA、FANUC FOCAS、MTConnect、Mettler-Toledo、PROFINET IO、EtherCAT、IEC 60870-5-104、IEC 61850、CoAP、DDS,全部支持独立配置端口和高级参数。
创建场景、批量管理设备集合,支持导入导出,快速复现工厂环境。
自由拖拽布局设备节点,直观展示设备间关系,支持保存布局、添加设备、一键启停整个场景。
PLC、传感器、数控机床、IoT 设备、摄像头、楼宇设备、电力保护装置、IED、环境传感器等分类筛选,选择模板一键创建仿真设备。
系统根据当前设备和场景自动生成测试任务,一键验证测点读写、场景启停、规则触发等功能。
创建测试计划,定义测试套件和故障场景,一键执行并生成 JUnit XML / JSON / HTML 报告。支持克隆、版本管理、执行历史追踪,CI/CD 集成一行命令搞定。
内置 Modbus TCP、S7、OPC-UA、IEC 104、MQTT 五大协议合规检测器,一键检测通信报文是否符合协议标准,生成合规评分和违规详情报告。
WebSocket 零延迟推送,按协议/方向筛选,关键词搜索,支持暂停、导出 JSON,快速定位开发问题。
对接 EdgeLite 网关,完成设备注册→连接→采集→验证→监控的完整联调链路,5 步可视化流程一目了然。
服务器端口、数据库路径、日志级别、CORS 源、InfluxDB 转发、协议端口等全部可在前端直接修改。
用户操作、资源变更全程记录,支持按用户名、操作类型、资源类型筛选审计。
将设备、场景、模板和审计日志导出为 JSON 备份文件,跨环境迁移、版本控制、灾难恢复轻松搞定。
- 21 种工业协议 — Modbus TCP/RTU、OPC-UA、MQTT、HTTP、GB28181、BACnet、Siemens S7、Mitsubishi MC、Omron FINS、Rockwell AB、OPC-DA、FANUC FOCAS、MTConnect、Mettler-Toledo、PROFINET IO、EtherCAT、IEC 60870-5-104、IEC 61850、CoAP、DDS
- 全链路仿真 — 不只是模拟数据,完整模拟协议交互过程(如 GB28181:SIP注册→目录查询→INVITE→RTP视频推流→BYE)
- 122 设备模板 — PLC、传感器、CNC、摄像头、HVAC、伺服驱动器、保护继电器、IED、环境传感器、微电网,选模板→起名字→一键创建
- 实时调试日志 — WebSocket 实时推送协议交互报文,按协议/方向/关键词筛选,点击查看详情,快速定位开发问题
- 可视化场景编排 — 可视化设备联动规则编辑器,支持阈值/值变化/定时/脚本四种规则类型
- 一键仿真测试 — 自动生成测试用例,智能诊断问题
- 数据转发 — InfluxDB / HTTP Webhook / 文件,一键对接
- 协议录制回放 — 记录通信报文,按需回放验证,支持加密存储
- Prometheus 指标 — 内置监控端点,对接 Grafana
- JWT 认证 + RBAC — 4 种角色(admin/operator/user/viewer),100% API 端点权限覆盖,bcrypt 安全密码存储
- API 限流保护 — 内置速率限制,防止暴力破解和滥用
- 双数据库支持 — SQLite 开箱即用,PostgreSQL 生产级支持
- EdgeLite 网关对接 — 设备配置中填写网关地址,自动注册到 EdgeLite
- 可视化系统设置 — 前端直接修改端口和配置,无需改代码
- 多语言 SDK — Python(同步/异步 90+ 方法,覆盖全部 API)、Java / Go / C#(核心方法:设备/场景/协议管理)
- gRPC 远程管理 — 15 个 RPC 方法,支持跨语言远程调用
- CSV 批量导入导出 — 设备配置一键导出 CSV,批量导入快速创建多台设备,跨环境迁移效率倍增
- 录制回放压缩 — Gzip 压缩存储,节省磁盘空间
- 数据库备份恢复 — 一键导出/导入全库数据 JSON
- 协议安全增强 — OPC-UA 证书自动生成、MQTT TLS 加密、GB28181 SRTP、录制报文加密
- K8s/Helm 部署 — 完整 Kubernetes 部署方案 + Helm Chart
- IoT 测试平台 — 测试计划管理(版本化/克隆/执行历史)、协议合规检测(5 协议合规规则+评分报告)、JUnit/JSON/HTML 报告导出、CI/CD 集成(
protoforge test run) - 故障切换 — 主备健康检查,自动晋升,回调通知
- 前端国际化 — 中英文双语,一键切换
- Docker 多架构 — 支持 amd64/arm64(通过 docker buildx 构建),CI 自动推送 Docker Hub + PyPI
✅ Windows · ✅ Linux · ✅ macOS
如果没有 Docker,也不想手动敲命令,用一键脚本。
第 1 步:下载项目代码
打开 https://github.com/suoten/ProtoForge,点击页面上的绿色 "Code" 按钮 → 点击 "Download ZIP" → 把下载的 ZIP 文件解压到一个文件夹(比如桌面)。
第 2 步:运行安装脚本
- Windows:进入解压出来的文件夹(通常叫
ProtoForge-main),双击install.bat - Linux / macOS:打开终端,进入解压出来的文件夹(通常叫
ProtoForge-main),运行:chmod +x install.sh ./install.sh
脚本会自动检测 Python 版本、创建虚拟环境、安装依赖、构建前端,然后自动启动服务。
启动后,浏览器打开 **http://localhost:8000**(即脚本窗口显示的地址),用 admin / 你设置的密码 登录。
🌐 http://localhost:8000 就是 Web 界面。后端自动托管前端,不需要 Nginx。
💡 如果脚本安装依赖时卡住不动,通常是网络问题。可以先设置国内镜像再重试:
# pip 镜像(二选一,cmd 或 PowerShell 里运行) pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ # npm 镜像 npm config set registry https://registry.npmmirror.com
✅ Windows · ✅ Linux · ✅ macOS
熟悉命令行的用户,或需要自定义配置。详细步骤见 DEPLOYMENT.md。
Windows — 点击展开
git clone https://github.com/suoten/ProtoForge.git
cd ProtoForge
python -m venv venv
.\venv\Scripts\activate
pip install -e ".[all]"
cd web && npm install && npm run build && cd ..
protoforge demo
# 浏览器打开 http://localhost:8000,用 admin / admin 登录
⚠️ 如果.\venv\Scripts\activate报错"在此系统上禁止运行脚本",以管理员身份打开 PowerShell,运行:Set-ExecutionPolicy -Scope CurrentUser RemoteSigned然后重新执行 activate。
Linux / macOS — 点击展开
git clone https://github.com/suoten/ProtoForge.git
cd ProtoForge
python3 -m venv venv
source venv/bin/activate
pip install -e ".[all]"
cd web && npm install && npm run build && cd ..
protoforge demo
# 或后台运行:protoforge demo -d
# 停止后台服务:protoforge stop
# 浏览器打开 http://localhost:8000,用 admin / admin 登录生产环境(Nginx + 域名 + PostgreSQL)— 点击展开
详见 DEPLOYMENT.md。大致流程:
- 安装系统依赖:
python3、nodejs、nginx、postgresql - 克隆代码 + 构建前端 + 安装后端依赖
- 配置
.env数据库连接和端口 - 配置 Nginx 反向代理
- 用
systemd或supervisor管理进程
| 需要安装的 | 方式一(Docker) | 方式二(一键脚本) | 方式三(手动) |
|---|---|---|---|
| Docker Desktop | ✅ 必须 | ❌ | ❌ |
| Python 3.10+ | ❌ | ✅ 必须 | ✅ 必须 |
| Node.js 18+ | ❌ | ✅ 必须 | |
| Git | ❌ | ✅ 必须² | ✅ 必须 |
¹ 没装 Node.js 的话,脚本会自动使用仓库中已构建好的前端文件
² 需要从 GitHub 下载项目代码(可以 git clone,也可以网页下载 ZIP)
各软件下载地址:
| 软件 | 下载链接 | 安装提示 |
|---|---|---|
| Docker Desktop | docker.com | Windows 需启用 WSL2,macOS 直接装 |
| Python | python.org | Windows 安装时务必勾选 "Add Python to PATH" |
| Node.js | nodejs.org | 下载 LTS 版本(左边绿色按钮) |
| Git | git-scm.com | 一路点 Next 就行 |
pip install -e . 只安装核心协议(Modbus TCP/RTU、HTTP、GB28181、MC、FINS、AB、OPC-DA、FANUC、MTConnect、Toledo、PROFINET、EtherCAT、IEC 104、IEC 61850、CoAP、DDS 共 17 种,开箱即用)。以下 4 种协议需要额外依赖:
pip install -e ".[all]" # 安装全部 21 种协议
pip install -e ".[opcua]" # OPC-UA
pip install -e ".[mqtt]" # MQTT
pip install -e ".[bacnet]" # BACnet
pip install -e ".[s7]" # Siemens S7| 协议 | 需要额外安装? | 默认端口 | 说明 |
|---|---|---|---|
| Modbus TCP | 不需要 | 5020 | 工业标准通信协议 |
| HTTP | 不需要 | 8080 | RESTful API 仿真 |
| Modbus RTU | 不需要 | 串口 | 串口通信协议 |
| GB28181 | 不需要 | 5060 | 视频监控国标协议 |
| Mitsubishi MC | 不需要 | 5000 | 三菱 PLC SLMP 协议 |
| Omron FINS | 不需要 | 9600 | 欧姆龙 PLC FINS 协议 |
| Rockwell AB | 不需要 | 44818 | 罗克韦尔 EtherNet/IP |
| OPC-DA | 不需要 | 51340 | OPC 经典数据访问 |
| FANUC FOCAS | 不需要 | 8193 | FANUC CNC 数据采集 |
| MTConnect | 不需要 | 7878 | 机床数据互联标准 |
| Mettler-Toledo | 不需要 | 1701 | 称重仪表协议 |
| PROFINET IO | 不需要 | 34964 | PI组织实时工业以太网协议 |
| EtherCAT | 不需要 | 34980 | 倍福实时工业以太网协议 |
| OPC-UA | [opcua] |
4840 | 统一架构协议 |
| MQTT | [mqtt] |
1883 | 物联网消息协议 |
| BACnet | [bacnet] |
47808 | 楼宇自动化协议 |
| Siemens S7 | [s7] |
102 | 西门子 PLC 协议 |
| IEC 60870-5-104 | 不需要 | 2404 | 电力远动协议 (SCADA) |
| IEC 61850 | 不需要 | 102 | 变电站自动化标准 (MMS) |
| CoAP | 不需要 | 5683 | 受限 IoT 应用协议 (UDP) |
| DDS | 不需要 | 7400 | 数据分发服务 (发布/订阅) |
前提:已按上述任一方式完成部署,浏览器能打开 http://localhost:8000。
🌐 不想安装?直接体验演示站点:https://protoforge.jjtt.net/ 用户名:
admin密码:Protoforge123
- 登录 — 输入
admin/admin - 启动协议 — 左侧菜单「协议服务」→ 点击「一键启动」
- 创建设备 — 左侧菜单「模板市场」→ 选择一个模板 → 填写名称 → 一键创建
- 查看数据 — 设备列表 → 点击「测点」→ 看到实时变化的仿真数据
- 运行测试 — 左侧菜单「仿真测试」→ 点击「一键测试全部」
⚠️ 页面空白? Docker 部署检查docker logs protoforge。源码部署执行:cd web && npm install && npm run build,然后重启后端。
📖 需要更详细的操作指引? 请阅读完整的 操作手册,涵盖设备创建、协议连接、场景编排、故障注入、数据转发、调试排障等全流程。
ProtoForge 是一台「虚拟设备工厂」。它启动标准协议服务端(Modbus TCP Server、OPC-UA Server、S7 Server……),任何能连接这些协议的软件都能直接对接,不需要任何适配层或特殊 SDK。
┌─────────────────────────────────┐
│ ProtoForge(仿真端) │
│ │
│ Modbus TCP Server ←─ 端口 5020 │
│ OPC-UA Server ←─ 端口 4840 │
│ S7 Server ←─ 端口 102 │
│ MQTT Broker ←─ 端口 1883 │
│ HTTP Server ←─ 端口 8080 │
│ GB28181 SIP ←─ 端口 5060 │
│ ...(21 种协议服务端) │
└──────────┬──────────────────────┘
│ 标准 TCP/UDP 协议通信
│(和真实设备一模一样)
┌──────────┬─────────┼─────────┬──────────┐
▼ ▼ ▼ ▼ ▼
┌─────────┐ ┌────────┐ ┌───────┐ ┌───────┐ ┌─────────┐
│ EdgeLite│ │Kepware │ │Node-RED│ │Ignition│ │ 你的程序 │
│ 网关 │ │ 网关 │ │ │ │ SCADA │ │(pymodbus│
│ │ │ │ │ │ │ │ │ 等) │
└─────────┘ └────────┘ └───────┘ └───────┘ └─────────┘
自动注册 手动配置 手动配置 手动配置 直接连接
| 方式 | 适合场景 | 怎么做 |
|---|---|---|
| ① 直接连接(推荐) | 你有自己的采集程序或网关 | ProtoForge 启动协议服务后,你的程序作为客户端连接对应端口即可(如 pymodbus 连 5020) |
| ② EdgeLite 自动注册 | 你用 EdgeLite 做网关 | 设备配置中填 edgelite_url,ProtoForge 自动把设备配置推送到 EdgeLite,免手动配置 |
| ③ 标准网关手动配置 | 你用 Kepware/Node-RED/Ignition 等第三方网关 | 在网关中手动添加设备,地址填 ProtoForge 的 IP 和端口(如 127.0.0.1:5020) |
ProtoForge 启动协议服务后,任何协议客户端都能直接连接。不需要在 ProtoForge 做任何额外配置。
# Python — 用 pymodbus 连接 ProtoForge 的 Modbus TCP 仿真设备
from pymodbus.client import ModbusTcpClient
client = ModbusTcpClient("127.0.0.1", port=5020)
client.connect()
result = client.read_holding_registers(address=100, count=2, device_id=1)
print(f"温度: {result.registers}")// Node.js — 用 mqtt 库连接 ProtoForge 的 MQTT 仿真设备
import mqtt from 'mqtt'
const client = mqtt.connect('mqtt://127.0.0.1:1883')
client.on('message', (topic, message) => {
console.log(`${topic}: ${message.toString()}`)
})
client.subscribe('sensor/temperature')ProtoForge 的每个测点都绑定了具体的 PLC 协议地址,你的上位机/网关按这个地址去读,和读真实 PLC 一模一样。
| 协议 | 地址格式 | 示例 | 说明 |
|---|---|---|---|
| Modbus TCP/RTU | 寄存器偏移量(数字) | address: "0" |
寄存器 40001(holding register),"2" = 40003 |
| Siemens S7 | DB块.类型+偏移 | address: "DB1.DBD2" |
DB块1,D=双字,偏移2字节;DBX = 位,DBW = 字 |
| Omron FINS | 区域+地址 | address: "DM100" |
DM区域地址100;CIO0 = CIO区域地址0 |
| Mitsubishi MC | 设备号+地址 | address: "D100" |
D寄存器100;M0 = 中间继电器0 |
| OPC-UA | 节点ID | address: "ns=2;s=Temperature" |
命名空间2,节点名 Temperature |
| IEC 60870-5-104 | ASDU地址 | address: "1" |
IOA(信息对象地址)= 1 |
设备模板中的测点定义:
{
"name": "total_flow",
"address": "0", // ← Modbus 寄存器 40001
"data_type": "float32",
"unit": "m³",
"generator_type": "increment",
"min_value": 0,
"max_value": 999999
}你的采集程序这样读:
from pymodbus.client import ModbusTcpClient
client = ModbusTcpClient("127.0.0.1", port=5020)
client.connect()
# 读 total_flow(address=0 → 寄存器 40001,float32 占 2 个寄存器)
result = client.read_holding_registers(address=0, count=2, slave_id=1)
# 解析 float32
value = struct.unpack('>f', struct.pack('>HH', *result.registers))[0]
print(f"累计流量: {value} m³")
# 读 instant_flow(address=2 → 寄存器 40003)
result = client.read_holding_registers(address=2, count=2, slave_id=1)
# 同样解析 float32{
"name": "temperature",
"address": "DB1.DBD2", // ← DB块1,双字,偏移2
"data_type": "real",
"unit": "°C"
}用 snap7 读取:
import snap7
client = snap7.client.Client()
client.connect("127.0.0.1", 0, 1) # rack=0, slot=1
# 读 DB1.DBD2(Real/Float,4字节)
data = client.db_read(1, 2, 4) # db_number=1, start=2, size=4
temperature = snap7.util.get_real(data, 0)
print(f"温度: {temperature} °C"){
"name": "motor_speed",
"address": "DM100", // ← DM区域地址100
"data_type": "int16"
}💡 在 Web 界面查看地址:设备管理 → 点击「数据测点」→ 可以看到每个测点的名称、当前值、时间、质量。点击「编辑」设备可以查看和修改每个测点的协议地址、数据类型、生成器参数。
💡 自定义地址:创建设备时可以自由指定每个测点的 PLC 地址,完全匹配你真实设备的地址表。
ProtoForge 支持完整的 Modbus 四种寄存器区域,通过地址格式自动识别:
| 寄存器区域 | 地址格式示例 | Modbus 地址范围 | 功能码 | 说明 |
|---|---|---|---|---|
| 线圈 (Coil) | 0, 00001, 0x0, C0 |
00001–09999 | FC01 读 / FC05 写单 / FC0F 写多 | 位操作,可读可写 |
| 离散输入 (Discrete Input) | 10001, 1x0, DI0 |
10001–19999 | FC02 读 | 位操作,只读 |
| 输入寄存器 (Input Register) | 30001, 3x0, IR0, I0 |
30001–39999 | FC04 读 | 字操作,只读 |
| 保持寄存器 (Holding Register) | 0, 40001, 4x0, HR0, H0 |
40001–49999 | FC03 读 / FC06 写单 / FC10 写多 | 字操作,可读可写 |
💡 纯数字地址的自动判断规则:
bool类型 → 线圈 (Coil);其他类型 → 保持寄存器 (Holding Register)。如果你想使用输入寄存器或离散输入,请使用30001、10001等 5 位 PLC 地址格式,或IR0、DI0等前缀格式。
不同数据类型占用的寄存器数量和字节序:
| 数据类型 | 字节数 | 占用寄存器数 | 字节序 | 适用协议 |
|---|---|---|---|---|
bool |
1 bit | 1 (位) | — | Modbus (Coil/DI)、S7 (DBX)、FINS (CIO bit) |
int16 |
2 | 1 | 大端序 (Big-Endian) | Modbus、S7 (DBW)、FINS、MC |
uint16 |
2 | 1 | 大端序 | Modbus、S7、MC |
int32 |
4 | 2 | 大端序 | Modbus、S7 (DBD)、MC |
uint32 |
4 | 2 | 大端序 | Modbus、S7、MC |
float32 |
4 | 2 | 大端序 (IEEE 754) | Modbus、S7 (DBD Real)、FINS、MC |
float64 |
8 | 4 | 大端序 (IEEE 754) | Modbus、S7 |
string |
可变 | 可变 (每寄存器 2 字节) | 大端序 (UTF-8) | Modbus、S7 |
real |
4 | 2 | 大端序 | S7 专用(等同 float32) |
⚠️ 字节序说明:ProtoForge 所有协议统一使用大端序 (Big-Endian),这是工业设备最常用的字节序。如果你的上位机使用小端序,需要在采集端做字节翻转。例如:
float32值1.0在 ProtoForge 中存储为0x3F800000,拆分为两个寄存器 →HR[n]=0x3F80, HR[n+1]=0x0000。用 pymodbus 读取后:struct.unpack('>f', struct.pack('>HH', 0x3F80, 0x0000))→1.0。
假设你有一份设备说明书上的 Modbus 地址表:
| 参数名 | Modbus 地址 | 数据类型 | 单位 | 读写 |
|---|---|---|---|---|
| A相电压 | 40001 | float32 | V | RO |
| B相电压 | 40003 | float32 | V | RO |
| 有功功率 | 40005 | float32 | kW | RO |
| 功率因数 | 40007 | float32 | - | RO |
| 开关状态 | 00001 | bool | - | RW |
第 1 步:转换为 ProtoForge 地址格式
| 参数名 | 说明书地址 | ProtoForge address | data_type |
|---|---|---|---|
| A相电压 | 40001 | 0 (40001-40001=0) |
float32 |
| B相电压 | 40003 | 2 (40003-40001=0) |
float32 |
| 有功功率 | 40005 | 4 |
float32 |
| 功率因数 | 40007 | 6 |
float32 |
| 开关状态 | 00001 | 00001 或 0 |
bool |
💡 5 位 PLC 地址自动转换:你也可以直接填
40001、30001、10001、00001,ProtoForge 会自动减去基地址(40001→偏移 0,30001→偏移 0)。
第 2 步:在 Web 界面创建设备
- 进入「设备管理」→ 点击「创建设备」
- 选择协议
modbus_tcp,填写设备名称 - 在测点配置中,逐条添加上表中的参数
- 设置
slave_id(如1) - 保存并启动设备
第 3 步:用你的采集程序验证
from pymodbus.client import ModbusTcpClient
import struct
client = ModbusTcpClient("127.0.0.1", port=5020)
client.connect()
# 读 A相电压 (address=0, float32, 占2个寄存器)
result = client.read_holding_registers(address=0, count=2, slave_id=1)
voltage_a = struct.unpack('>f', struct.pack('>HH', *result.registers))[0]
# 读 B相电压 (address=2)
result = client.read_holding_registers(address=2, count=2, slave_id=1)
voltage_b = struct.unpack('>f', struct.pack('>HH', *result.registers))[0]
# 读开关状态 (address=00001 → coil 0)
result = client.read_coils(address=0, count=1, slave_id=1)
switch_status = result.bits[0]
print(f"A相电压: {voltage_a}V, B相电压: {voltage_b}V, 开关: {'ON' if switch_status else 'OFF'}")就是这么简单——ProtoForge 的地址和真实设备完全一致,你的采集代码不需要改一行。
Modbus RTU 模板支持完整的串口参数配置:
{
"protocol": "modbus_rtu",
"protocol_config": {
"slave_id": 2,
"serial_port": "COM3",
"baudrate": 9600,
"databits": 8,
"parity": "even",
"stopbits": 1
}
}| 参数 | 说明 | 可选值 | 默认值 |
|---|---|---|---|
serial_port |
串口设备路径 | Windows: COM3; Linux: /dev/ttyUSB0 |
— |
baudrate |
波特率 | 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200 |
9600 |
databits |
数据位 | 7, 8 |
8 |
parity |
校验位 | none, even, odd |
even |
stopbits |
停止位 | 1, 1.5, 2 |
1 |
💡 无串口硬件也能用:ProtoForge 的 Modbus RTU 模式在没有物理串口时也可以启动(使用虚拟串口或 TCP-over-RTU 桥接)。在 Linux 上可以用
socat创建虚拟串口:socat -d -d PTY,raw,echo=0 PTY,raw,echo=0。
ProtoForge 支持在同一协议端口下同时仿真多台设备,就像一条 RS-485 总线上挂多个从站:
Modbus 多 Slave 共存:
设备A: slave_id=1, 协议=modbus_tcp, 端口=5020
设备B: slave_id=2, 协议=modbus_tcp, 端口=5020 ← 同端口不同 slave_id
设备C: slave_id=3, 协议=modbus_tcp, 端口=5020
采集程序通过 slave_id 区分不同设备:
# 读设备A的数据
result = client.read_holding_registers(address=0, count=2, slave_id=1)
# 读设备B的数据
result = client.read_holding_registers(address=0, count=2, slave_id=2)💡 每个 Modbus 设备在创建时可以指定不同的
slave_id,它们共享同一协议端口但拥有独立的数据空间。
S7/OPC-UA/MQTT 等协议多设备:每种协议都支持在同端口下创建多台虚拟设备,通过设备名/节点空间区分。
当你的采集程序向 ProtoForge 写入数据时,行为与真实 PLC 完全一致:
| 操作 | ProtoForge 响应 | 后续读取行为 |
|---|---|---|
| 写单个线圈 (FC05) | 返回正常响应(回显地址+值) | 读该地址返回写入的值 |
| 写多个线圈 (FC0F) | 返回正常响应(回显起始地址+数量) | 读该地址范围返回写入的值 |
| 写单个寄存器 (FC06) | 返回正常响应(回显地址+值) | 读该地址返回写入的值 |
| 写多个寄存器 (FC10) | 返回正常响应(回显起始地址+数量) | 读该地址范围返回写入的值 |
| 读写多个寄存器 (FC17) | 返回读部分的值 | 写入部分同时生效 |
| 掩码写寄存器 (FC16) | 返回正常响应 | 按掩码 AND/OR 逻辑更新寄存器 |
⚠️ 写入与生成器的关系:如果测点配置了generator_type(如random、sine),生成器会在每次更新周期覆盖写入的值。要保留写入值,请将generator_type设为fixed。
每个测点可以配置数据生成器来模拟真实设备的变化行为:
| 生成器类型 | 说明 | 关键参数 | 适用场景 |
|---|---|---|---|
fixed |
固定值 | fixed_value |
状态量、开关 |
random |
随机值 | min_value, max_value |
传感器噪声模拟 |
sine |
正弦波 | min_value, max_value, period |
周期性变化量 |
increment |
递增值 | min_value, max_value, step |
流量计、计数器 |
ramp |
线性变化 | start_value, end_value, duration |
渐变过程模拟 |
{
"name": "temperature",
"address": "0",
"data_type": "float32",
"generator_type": "sine",
"min_value": 20.0,
"max_value": 80.0,
"period": 60,
"update_frequency": 1.0
}| 参数 | 说明 | 默认值 |
|---|---|---|
update_frequency |
数据更新频率(秒/次) | 1.0(1秒更新一次) |
period |
正弦周期(秒) | 60 |
step |
递增步长 | 1.0 |
duration |
渐变持续时间(秒) | 10 |
💡
update_frequency决定了数据多久变化一次。设为0.5表示每 0.5 秒更新一次(2Hz),设为5表示每 5 秒更新一次。这与真实设备的采样周期类似。
如果你用 EdgeLite 做网关,ProtoForge 可以自动把设备配置推送过去,免去手动在 EdgeLite 中添加设备的步骤。详见下方 EdgeLite 网关对接 章节。
以 Kepware 为例:
- ProtoForge 中启动 Modbus TCP 协议服务(默认端口 5020)
- ProtoForge 中创建一台 Modbus 设备(记住 slave_id 和测点地址)
- Kepware 中新建一个 Modbus TCP 驱动,IP 填 ProtoForge 所在机器 IP,端口填 5020
- Kepware 中新建设备,slave_id 与 ProtoForge 中一致
- Kepware 中添加点位,地址与 ProtoForge 中一致
就是这么简单——ProtoForge 对你的网关来说,和一台真实 PLC 没有任何区别。
💡 核心理解:ProtoForge 不是网关,不采集数据,不转发数据。它是「被采集的对象」——一台虚拟设备。你的网关/SCADA/采集程序去连它,就像连真实设备一样。
ProtoForge 支持将模拟设备自动注册到 EdgeLite 物联网网关,和 GB28181 填「上级SIP服务器地址」一样的体验:
GB28181:设备 protocol_config 填 sip_server_addr → 自动注册到国标平台
EdgeLite:设备 protocol_config 填 edgelite_url → 自动注册到 EdgeLite 网关
使用方式:创建设备时,在协议配置中填写 EdgeLite 网关地址即可:
| 字段 | 说明 | 示例 |
|---|---|---|
edgelite_url |
EdgeLite 网关地址 | http://192.168.1.200:8100 |
edgelite_username |
用户名 | admin |
edgelite_password |
密码 | admin123 |
不填就不推送,不影响 ProtoForge 正常使用。详见 INTEGRATION.md。
不想手动配置两套系统?ProtoForge 提供 docker-compose.joint.yml,一条命令同时启动 ProtoForge + EdgeLite + MQTT + InfluxDB,开箱即用联调。
# 复制环境变量模板
cp .env.joint.example .env.joint
# 用编辑器打开 .env.joint,把所有 change_me_* 改成你自己的密码
# 重点修改这几项:
# PROTOFORGE_ADMIN_PASSWORD=你的强密码
# PROTOFORGE_JWT_SECRET=至少32位随机字符串
# EDGELITE_ADMIN_PASSWORD=你的强密码
# SECRET_KEY=至少32位随机字符串💡 JWT 密钥可以用这个命令生成:
python -c "import secrets; print(secrets.token_urlsafe(32))"
docker compose -f docker-compose.joint.yml --env-file .env.joint up -d等待 30 秒让所有服务就绪,然后:
- ProtoForge 界面:http://localhost:8000 (用
.env.joint里的PROTOFORGE_ADMIN_PASSWORD登录) - EdgeLite 界面:http://localhost:8081 (用
.env.joint里的EDGELITE_ADMIN_PASSWORD登录)
- 打开 ProtoForge(http://localhost:8000),创建一台 Modbus 设备,在协议配置中填写:
edgelite_url: http://edgelite:8100 edgelite_username: admin edgelite_password: (你在 .env.joint 里设的 EDGELITE_ADMIN_PASSWORD) - 启动设备的 Modbus 协议,ProtoForge 会自动把设备推送到 EdgeLite
- 打开 EdgeLite(http://localhost:8081),在设备列表中能看到刚推送的设备,数据实时采集
🔍 也可以调用 ProtoForge 的 API 一键验证全链路:
curl -X POST http://localhost:8000/api/v1/edgelite/verify-pipeline \ -H "Authorization: Bearer <你的token>" \ -H "Content-Type: application/json" \ -d '{"device_id": "你的设备ID", "auto_fix": true}'返回
{"ok": true}说明认证→注册→连接→采集四步全通。
联合部署后,以下端口被占用(如需修改请在 .env.joint 中调整):
| 服务 | 端口 | 说明 |
|---|---|---|
| ProtoForge Web/API | 8000 | 主界面 + REST API |
| ProtoForge Modbus TCP | 5020 | Modbus 仿真设备 |
| ProtoForge OPC-UA | 4840 | OPC-UA 仿真设备 |
| ProtoForge MQTT | 1883 | MQTT 仿真设备 |
| ProtoForge HTTP | 8080 | HTTP Webhook 仿真 |
| EdgeLite Web/API | 8081 | EdgeLite 管理界面(避让 ProtoForge 8080) |
| EdgeLite MQTT | 1884 | EdgeLite MQTT 服务(避让 ProtoForge 1883) |
| InfluxDB | 8086 | 时序数据库 |
Q: 启动时报端口占用?
A: 检查本机是否已有其他服务占用上述端口。Windows 用 netstat -ano | findstr :8000,Linux 用 lsof -i:8000。可在 .env.joint 中修改端口映射。
Q: EdgeLite 设备列表里看不到推送的设备?
A: ① 确认设备协议配置里的 edgelite_url 填的是 http://edgelite:8100(容器内网名),不是 localhost;② 在 ProtoForge 调用 verify-pipeline API 看具体哪一步失败;③ 查看 EdgeLite 日志 docker compose -f docker-compose.joint.yml logs edgelite。
Q: 联调 API 返回 401?
A: EdgeLite 密码不匹配。确认设备配置里的 edgelite_password 与 .env.joint 中的 EDGELITE_ADMIN_PASSWORD 一致。首次登录 EdgeLite 可能要求改密码,改完后同步更新 ProtoForge 设备配置。
Q: 停止联合部署?
A: docker compose -f docker-compose.joint.yml down(加 -v 会同时删除数据卷,谨慎使用)。
ProtoForge 不只是模拟数据值,而是完整模拟协议交互过程,让你在开发时就能发现通信链路中的问题。
1. SIP REGISTER ──→ 上级平台(自动注册,支持 Digest 认证)
2. ←── MESSAGE Catalog(自动响应设备目录查询)
3. ←── INVITE(收到实时视频请求)
4. ──→ 200 OK + SDP(媒体协商应答)
5. ←── ACK
6. ══════════════► RTP/PS 视频流(25fps,352×288 CIF)
7. ←── BYE(停止视频,自动停止推流)
| 协议 | 仿真链路 | 使用方式 |
|---|---|---|
| Modbus TCP | 客户端连接→读寄存器→写寄存器→断开 | 你的程序作为 Modbus 客户端连接 |
| MQTT | Broker启动→客户端订阅→数据发布→客户端收到 | 你的程序作为 MQTT 客户端连接 |
| OPC-UA | 客户端连接→浏览节点→读写值→断开 | 你的程序作为 OPC-UA 客户端连接 |
| S7 | 客户端连接→读DB块→写DB块→断开 | 你的程序作为 S7 客户端连接 |
| HTTP | GET/POST请求→JSON响应 | 直接请求 API |
ProtoForge 内置实时协议调试日志,帮你快速定位开发中的通信问题:
- 打开左侧菜单「调试日志」
- 实时查看所有协议的收发消息(WebSocket 推送,零延迟)
- 按协议筛选(只看 GB28181 / Modbus / MQTT...)
- 按方向筛选(← 收 / → 发 / 系统)
- 关键词搜索(搜索 "error"、"register"、"invite"...)
- 点击任意日志 → 查看完整 detail 信息
- 暂停日志流 → 仔细分析某条消息
- 导出为 JSON → 离线分析或分享
所有配置项均可在 .env 文件中修改,也可登录后台在「系统设置」页面直接修改。
# .env 文件示例
PROTOFORGE_HOST=0.0.0.0 # Web 服务监听地址
PROTOFORGE_PORT=8000 # Web 服务端口
PROTOFORGE_DB_PATH=data/protoforge.db # 数据库路径(SQLite 或 PostgreSQL)
PROTOFORGE_JWT_SECRET= # JWT 密钥(留空自动生成,生产环境建议设置)
PROTOFORGE_ADMIN_PASSWORD=admin # 管理员密码(不设置则自动生成随机密码,生产环境务必设置强密码!)
PROTOFORGE_DEMO_MODE=false # 演示模式
PROTOFORGE_LOG_LEVEL=info # 日志级别
PROTOFORGE_GRPC_PORT=0 # gRPC 端口(0=禁用,设为 50051 启用)
# 协议端口(修改后需重启对应协议生效)
PROTOFORGE_MODBUS_TCP_PORT=5020
PROTOFORGE_OPCUA_PORT=4840
PROTOFORGE_MQTT_PORT=1883
PROTOFORGE_HTTP_PORT=8080
PROTOFORGE_GB28181_PORT=5060| 端口 | 服务 | 说明 |
|---|---|---|
| 8000 | Web API + 前端 | 主服务端口,浏览器访问此端口 |
| 5020 | Modbus TCP | 工业标准通信协议 |
| 4840 | OPC-UA | 统一架构协议(需 [opcua]) |
| 1883 | MQTT | 物联网消息协议(需 [mqtt]) |
| 8080 | HTTP | RESTful API 仿真 |
| 5060 | GB28181 | 视频监控国标协议(TCP + UDP) |
| 47808 | BACnet | 楼宇自动化协议(UDP,需 [bacnet]) |
| 102 | Siemens S7 | 西门子 PLC 协议(需 [s7]) |
| 5000 | Mitsubishi MC | 三菱 PLC SLMP 协议 |
| 9600 | Omron FINS | 欧姆龙 PLC FINS 协议 |
| 44818 | Rockwell AB | 罗克韦尔 EtherNet/IP |
| 51340 | OPC-DA | OPC 经典数据访问 |
| 8193 | FANUC FOCAS | FANUC CNC 数据采集 |
| 7878 | MTConnect | 机床数据互联标准 |
| 1701 | Mettler-Toledo | 称重仪表协议 |
| 34964 | PROFINET IO | PI组织实时工业以太网协议 |
| 34980 | EtherCAT | 倍福实时工业以太网协议 |
| 2404 | IEC 60870-5-104 | 电力远动协议(SCADA) |
| 102 | IEC 61850 | 变电站自动化标准(MMS) |
| 5683 | CoAP | 受限 IoT 应用协议(UDP) |
| 7400 | DDS | 数据分发服务(发布/订阅) |
| 50051 | gRPC | 远程管理接口(默认禁用,设 GRPC_PORT=50051 启用) |
SQLite(默认,适合开发和单机部署):
PROTOFORGE_DB_PATH=data/protoforge.dbPostgreSQL(生产环境推荐):
# 安装 PostgreSQL 支持
pip install -e ".[postgres]"
# 配置连接字符串
PROTOFORGE_DB_PATH=postgresql://user:password@localhost:5432/protoforgeProtoForge 内置 Webhook 通知和告警反应规则系统,支持事件驱动的自动化。
Webhook 通知系统:
# 创建 Webhook
POST /api/v1/webhooks
{
"name": "告警通知",
"url": "https://your-server.com/webhook",
"events": ["rule_triggered", "device_error"],
"secret": "your-hmac-secret" # 可选,启用 HMAC-SHA256 签名
}
# 验证签名(接收端)
# 请求头 X-ProtoForge-Signature = HMAC-SHA256(secret, body)| 特性 | 说明 |
|---|---|
| 事件订阅 | 按事件类型过滤,支持通配符 * |
| HMAC 签名 | X-ProtoForge-Signature 头,防止伪造 |
| 异步队列 | 5000 条消息缓冲,批量发送 |
| 测试端点 | POST /webhooks/{id}/test 发送测试消息 |
告警反应规则:
# 创建告警规则
POST /api/v1/integration/alarm-rules
{
"source_device_id": "device-001",
"severity": "critical",
"action": "stop_device" # stop_device / inject_fault / adjust_generator
}| 动作 | 说明 |
|---|---|
stop_device |
自动停止触发告警的设备 |
inject_fault |
向设备注入故障 |
adjust_generator |
调整数据生成器参数 |
ProtoForge 内置完整的仿真测试框架,支持 14 种断言类型和 HTML 报告。
断言类型:
| 类型 | 说明 | 示例 |
|---|---|---|
equals |
等于 | {"expected": 100} |
not_equals |
不等于 | {"expected": 0} |
contains |
包含 | {"expected": "online"} |
not_contains |
不包含 | {"expected": "error"} |
greater_than |
大于 | {"expected": 0} |
less_than |
小于 | {"expected": 100} |
regex_match |
正则匹配 | {"expected": "^device-"} |
json_path |
JSON 路径提取 | {"json_path": "$.status", "expected": "ok"} |
not_null |
非空 | — |
type_check |
类型检查 | {"expected": "number"} |
status_code |
HTTP 状态码 | {"expected": 200} |
length_equals |
长度等于 | {"expected": 10} |
length_greater |
长度大于 | {"expected": 0} |
length_less |
长度小于 | {"expected": 100} |
变量提取和钩子:
{
"steps": [
{
"name": "创建设备",
"action": "create_device",
"extract": {"device_id": "$.id"},
"post_hook": "log('设备创建成功')"
},
{
"name": "读取测点",
"action": "read_points",
"params": {"device_id": "${device_id}"}
}
]
}测试报告:
GET /tests/reports/{id}/html— 完整 HTML 报告(含步骤详情、断言结果、耗时统计)GET /tests/reports/trend— 历史测试趋势数据POST /tests/quick-test— 一键自动生成并运行测试GET /tests/suggestions— 根据当前状态推荐测试
5 种规则类型 × 5 种动作,支持冷却机制、多设备协同链式联动和时间序列回放。
规则类型:
| 类型 | 说明 | 配置示例 |
|---|---|---|
threshold |
阈值规则(支持 AND/OR 多条件) | {"conditions": [{"operator": ">", "value": 80}], "logic": "and"} |
value_change |
值变化规则(支持 delta 阈值) | {"delta": 10} |
timer |
定时规则 | {"interval": 60} |
script |
脚本规则(安全沙箱) | {"expression": "value > 80 and value < 120"} |
collaboration |
多设备协同联动(链式动作 + 故障注入) | 见下方协同联动示例 |
规则动作:
| 动作 | 说明 |
|---|---|
set |
设定目标测点值 |
toggle |
切换布尔值 |
increment |
递增 |
decrement |
递减 |
inject_fault |
注入故障(传感器噪声/漂移/卡死等) |
协同联动示例(温度超 80°C → 启动风扇 → 注入传感器噪声):
{
"rule_type": "collaboration",
"source_device_id": "temp-sensor",
"source_point": "temperature",
"condition": {"operator": ">", "value": 80},
"actions": [
{"target_device_id": "fan", "target_point": "speed", "action_type": "set", "value": 100},
{"target_device_id": "temp-sensor", "target_point": "temperature", "action_type": "inject_fault", "value": {"fault_type": "sensor_noise", "parameters": {"noise_std": 2.0, "duration": 60}}}
],
"cooldown": 5.0
}时间序列回放:场景支持 replay_config,从历史数据(内联 JSON / CSV 文件)驱动仿真,支持加速回放(speed)和循环(loop):
{
"replay_config": {
"source": [{"ts": 0, "device_id": "sensor", "point": "temp", "value": 25.0}],
"speed": 2.0,
"loop": true
}
}冷却机制:协同规则在 Rule 级设置 cooldown(秒),防止规则频繁触发:
{"cooldown": 30}| 命令 | 说明 |
|---|---|
protoforge run |
启动服务(--host / --port / --reload / --log-level / --daemon) |
protoforge demo |
演示模式(自动创建示例设备和场景,--daemon / -d 后台运行) |
protoforge stop |
停止后台运行的服务(仅 Linux / macOS) |
protoforge init |
初始化数据目录和默认配置(创建 data/ 目录,从 .env.example 复制 .env) |
protoforge migrate |
运行数据库迁移(--revision head) |
protoforge test run |
执行测试计划(CI/CD 集成,支持 --plan-id 指定计划) |
protoforge version |
查看版本号 |
| 场景 | 预估参考值 | 说明 |
|---|---|---|
| Modbus TCP 并发连接 | ~200 连接 | 受限于文件描述符和内存 |
| MQTT 并发客户端 | ~500 连接 | aMQTT 性能有限,生产建议用 Mosquitto |
| OPC-UA 并发会话 | ~50 连接 | asyncua 资源消耗较大 |
| GB28181 RTP 推流 | ~10 路 | 受 CPU 和带宽限制 |
| 内存占用(空载) | ~150MB | Python + FastAPI 基础开销 |
| 内存占用(100 设备) | ~500MB | 含协议栈和仿真数据 |
| CPU 占用(空载) | <5% | 等待连接状态 |
| CPU 占用(100 设备活跃) | 30-60% | 取决于数据更新频率 |
⚠️ 以上为估算值,实际性能取决于硬件配置、协议类型和数据更新频率。建议在目标环境进行基准测试。
升级步骤:
# 1. 备份数据
curl -H "Authorization: Bearer $TOKEN" http://localhost:8000/api/v1/backup -o backup.json
# 2. 拉取最新代码
git pull origin main
# 3. 更新依赖
pip install -e ".[all]"
# 4. 运行数据库迁移
protoforge migrate
# 5. 重新构建前端(如有更新)
cd web && npm install && npm run build && cd ..
# 6. 重启服务
protoforge run回滚:
# 回滚数据库到上一个版本
alembic downgrade -1
# 恢复数据备份
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @backup.json \
http://localhost:8000/api/v1/backup/restorecd web
npm install
npm run dev # 开发服务器(热更新)
npm run build # 生产构建 → web/dist/# 运行全部单元测试
python -m pytest tests/ -v
# 运行测试并生成覆盖率报告
python -m pytest tests/ -v --cov=protoforge --cov-report=htmlProtoForge/
├── protoforge/ # Python 后端包
│ ├── api/v1/ # REST API 端点
│ │ ├── common.py # 统一响应格式和异常处理
│ │ ├── rate_limit.py # API 限流中间件
│ │ ├── router.py # API 路由
│ │ ├── test_plan_routes.py # 测试计划 API
│ │ └── compliance_routes.py # 合规检测 API
│ ├── core/ # 核心引擎
│ │ ├── engine.py # 仿真引擎(设备/场景调度)
│ │ ├── auth.py # JWT 认证与 bcrypt 密码哈希
│ │ ├── audit.py # 操作审计日志
│ │ ├── edgelite.py # EdgeLite 网关对接
│ │ ├── device.py # 设备实例
│ │ ├── scenario.py # 场景规则引擎
│ │ ├── testing.py # 测试框架(14种断言)
│ │ ├── forward.py # 数据转发
│ │ ├── recorder.py # 协议录制回放(含加密)
│ │ ├── failover.py # 故障切换管理
│ │ ├── webhook.py # Webhook 通知系统
│ │ └── metrics.py # Prometheus 指标
│ ├── grpc/ # gRPC 远程管理接口
│ │ ├── protoforge.proto # Protobuf 定义
│ │ └── server.py # gRPC 服务实现
│ ├── config.py # 配置管理
│ ├── db/ # 数据库层(SQLite + PostgreSQL)
│ ├── models/ # 数据模型
│ ├── protocols/ # 21 种协议服务端实现
│ ├── testing/ # IoT 测试平台(计划/执行/合规检测)
│ ├── sdk/ # Python SDK(同步/异步)
│ └── templates/ # 122 设备模板(JSON)
├── sdk/ # 多语言 SDK
│ ├── java/ # Java SDK
│ ├── go/ # Go SDK
│ └── csharp/ # C# SDK
├── web/ # Vue3 前端
│ ├── e2e/ # Playwright E2E 浏试(31 项全通过)
│ └── src/
│ ├── views/ # 页面组件(含 TestPlans/Compliance)
│ ├── App.vue # 主布局(含i18n)
│ ├── i18n.js # 国际化框架(中英文)
│ ├── api.js # API 调用
│ └── main.js # 入口
├── k8s/ # Kubernetes 部署
│ ├── deployment.yaml # ProtoForge + PostgreSQL
│ ├── ingress.yaml # Ingress(WebSocket支持)
│ └── secrets.yaml # 密钥配置
├── helm/ # Helm Chart
│ └── protoforge/
│ ├── Chart.yaml
│ ├── values.yaml
│ └── templates/ # K8s 模板
├── tests/ # 测试用例
├── migrations/ # Alembic 数据库迁移
├── grafana/ # Grafana Dashboard 模板
├── Dockerfile
├── docker-compose.yml
└── pyproject.toml # 项目配置和依赖
后端启动后,访问以下地址查看交互式 API 文档(直接访问后端端口):
- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
这是后端 API 文档,不是前端页面。前端页面请访问
http://localhost:8000(与后端同端口)。
ProtoForge 提供同步和异步两种 Python SDK 客户端,覆盖全部 API 功能。
安装:
pip install protoforge快速上手:
from protoforge.sdk import ProtoForgeClient
# 创建客户端
with ProtoForgeClient("http://localhost:8000") as client:
# 登录
client.login("admin", "admin")
# 列出所有协议
protocols = client.list_protocols()
# 启动 Modbus TCP 协议
client.start_protocol("modbus_tcp")
# 从模板快速创建设备
device = client.quick_create("modbus-plc-controller", "测试PLC")
# 读取设备测点
points = client.read_points(device["id"])
print(points)
# 运行一键测试
report = client.quick_test()
print(report)异步客户端:
from protoforge.sdk import AsyncProtoForgeClient
async with AsyncProtoForgeClient("http://localhost:8000") as client:
await client.login("admin", "admin")
devices = await client.list_devices()
print(devices)SDK 方法一览(70+ 方法):
| 类别 | 方法 | 说明 |
|---|---|---|
| 认证 | login, refresh_token, change_password |
JWT 认证管理 |
| 协议 | list_protocols, start_protocol, stop_protocol, get_protocol_config |
协议启停和配置 |
| 设备 | create_device, quick_create, read_points, write_point, update_device, delete_device |
设备 CRUD + 测点读写 |
| 批量 | batch_create_devices, batch_start_devices, batch_stop_devices, batch_delete_devices |
批量操作 |
| 模板 | list_templates, search_templates, instantiate_template, create_template |
模板搜索和实例化 |
| 场景 | create_scenario, start_scenario, stop_scenario, export_scenario, import_scenario |
场景编排 |
| 测试 | quick_test, create_test_case, run_tests, get_test_report |
仿真测试 |
| 转发 | add_forward_target, start_forward, stop_forward, get_forward_stats |
数据转发 |
| 录制 | start_recording, stop_recording, replay_recording, export_recording |
协议录制回放 |
| 集成 | import_edgelite, import_pygbsentry, list_webhooks, add_webhook |
第三方集成 |
| 系统 | get_settings, update_settings, setup_demo, get_setup_status |
系统管理 |
Java SDK(sdk/java/ProtoForgeClient.java):
import io.github.suoten.protoforge.ProtoForgeClient;
public class Example {
public static void main(String[] args) throws Exception {
ProtoForgeClient client = new ProtoForgeClient("http://localhost:8000");
client.login("admin", "admin");
var devices = client.listDevices();
System.out.println(devices);
}
}Go SDK(sdk/go/protoforge/client.go):
package main
import (
"fmt"
"protoforge"
)
func main() {
client := protoforge.NewClient("http://localhost:8000")
client.Login("admin", "admin")
devices, _ := client.ListDevices()
fmt.Println(devices)
}C# SDK(sdk/csharp/ProtoForgeClient.cs):
using ProtoForge;
var client = new ProtoForgeClient("http://localhost:8000");
await client.LoginAsync("admin", "admin");
var devices = await client.ListDevicesAsync();
Console.WriteLine(devices);| 端点 | 格式 | 说明 |
|---|---|---|
GET /health |
JSON | 健康检查(数据库状态、活跃设备数、协议状态) |
GET /metrics |
Prometheus | 标准指标格式(uptime、设备数、转发/录制计数) |
GET /api/v1/forward/stats |
JSON | 数据转发统计 |
GET /api/v1/recorder/stats |
JSON | 录制统计 |
ProtoForge 内置多层安全机制:
- 密码安全:使用 bcrypt 算法存储密码,自动加盐,抵抗彩虹表攻击
- JWT 认证:访问令牌有效期 30 分钟,支持刷新令牌续期
- 登录保护:连续 5 次登录失败自动锁定账户 5 分钟,防止暴力破解
- API 限流:普通接口 100 次/分钟,认证接口 10 次/分钟
- 密钥管理:JWT 密钥支持环境变量配置,未配置时自动生成随机密钥
生产环境部署前,请务必阅读 SECURITY.md 完成安全加固。
| 角色 | 权限说明 | 可访问端点 |
|---|---|---|
admin |
系统管理员,拥有全部权限 | 所有端点 + 用户管理 + 系统设置 |
operator |
运维人员,可管理设备和协议 | 设备/协议/场景/转发/录制的增删改 |
user |
普通用户,可运行测试 | 读操作 + 测试用例/套件的增删改 |
viewer |
只读用户,仅可查看数据 | 所有 GET 端点 |
| 协议 | 认证支持 | 加密支持 | 说明 |
|---|---|---|---|
| HTTP | ✅ JWT + RBAC | ✅ HTTPS | API 端点受完整认证保护 |
| Modbus TCP | ❌ 无 | ❌ 无 | 协议本身无认证机制,建议网络隔离 |
| OPC-UA | 支持 Sign/SignAndEncrypt 模式,模板默认未启用 | ||
| MQTT | 支持用户名/密码认证,模板默认未启用 | ||
| GB28181 | SIP 支持 Digest 认证,RTP 流可启用 SRTP 加密 | ||
| S7/MC/FINS/AB | ❌ 无 | ❌ 无 | 工业协议通常在 PLC 端做访问控制 |
| BACnet | ❌ 无 | ❌ 无 | BACnet/IP 协议本身无内置认证 |
⚠️ 仿真环境下的协议安全限制与真实设备一致。生产部署时建议通过防火墙、VPN 或网络隔离保护协议端口。
| 协议 | 安全特性 | 配置方式 |
|---|---|---|
| OPC-UA | ✅ 证书自动生成(RSA-2048,10年有效期) | security_mode=Sign 时自动生成,也可指定 certificate_path/private_key_path |
| MQTT | ✅ TLS 加密通道 | 配置 tls_enabled=true + tls_cert_path/tls_key_path |
| GB28181 | ✅ SRTP 加密传输 | 配置 srtp_enabled=true |
| 录制回放 | ✅ 报文加密存储 | 调用 recorder.set_encryption_key("your-key") 启用 |
# 导出全库备份(含设备/场景/模板/测试/用户/录制/审计日志)
curl -H "Authorization: Bearer $TOKEN" \
http://localhost:8000/api/v1/backup -o backup.json
# 恢复备份
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @backup.json \
http://localhost:8000/api/v1/backup/restore备份文件为标准 JSON 格式,可版本控制、差异对比、跨环境迁移。
设置 PROTOFORGE_GRPC_PORT 环境变量即可启用 gRPC 服务:
PROTOFORGE_GRPC_PORT=50051 protoforge run15 个 RPC 方法:
| 方法 | 说明 |
|---|---|
GetHealth |
健康检查 |
ListDevices / GetDevice / CreateDevice / DeleteDevice |
设备管理 |
StartDevice / StopDevice |
设备启停 |
ReadPoints / WritePoint |
测点读写 |
ListScenarios / StartScenario / StopScenario |
场景管理 |
GetSettings / UpdateSettings |
系统设置 |
生成客户端代码:
# Python
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. protoforge/grpc/protoforge.proto
# Go
protoc --go_out=. --go-grpc_out=. protoforge/grpc/protoforge.proto
# Java
protoc --java_out=. --grpc-java_out=. protoforge/grpc/protoforge.proto
# C#
protoc --csharp_out=. --grpc-csharp_out=. protoforge/grpc/protoforge.proto方式一:直接使用 K8s YAML
# 1. 创建 Secret(修改密码!)
kubectl apply -f k8s/secrets.yaml
# 2. 部署应用 + PostgreSQL
kubectl apply -f k8s/deployment.yaml
# 3. 配置 Ingress(可选)
kubectl apply -f k8s/ingress.yaml方式二:使用 Helm Chart
# 1. 修改配置
helm show values helm/protoforge > my-values.yaml
# 编辑 my-values.yaml:修改密码、域名、存储等
# 2. 安装
helm install protoforge helm/protoforge -f my-values.yaml
# 3. 升级
helm upgrade protoforge helm/protoforge -f my-values.yaml
# 4. 卸载
helm uninstall protoforgeHelm values 主要配置:
| 参数 | 默认值 | 说明 |
|---|---|---|
replicaCount |
1 |
副本数 |
image.repository |
suoten/protoforge |
镜像仓库 |
ingress.enabled |
false |
启用 Ingress |
postgresql.enabled |
true |
内置 PostgreSQL |
persistence.size |
5Gi |
数据持久化大小 |
resources.limits.memory |
1Gi |
内存限制 |
配置主备模式实现自动故障切换:
# 主节点
PROTOFORGE_FAILOVER_ROLE=primary
PROTOFORGE_FAILOVER_PRIMARY=http://primary:8000
PROTOFORGE_FAILOVER_STANDBY=http://standby:8000
PROTOFORGE_FAILOVER_INTERVAL=10 # 健康检查间隔(秒)
# 备节点
PROTOFORGE_FAILOVER_ROLE=standby
PROTOFORGE_FAILOVER_PRIMARY=http://primary:8000
PROTOFORGE_FAILOVER_STANDBY=http://standby:8000工作原理:
- 备节点定期检查主节点
/health端点 - 连续 3 次检查失败后,备节点自动晋升为主节点
- 晋升时触发回调通知(可注册自定义回调)
- 原主节点恢复后,可手动降级为备节点
| 特性 | ProtoForge | Modbus Slave/Poll | Kepware | Node-RED Mock | 真实 PLC |
|---|---|---|---|---|---|
| 协议数量 | 21 种 | 仅 Modbus | 150+ (需付费驱动) | 仅 MQTT/HTTP | 单一品牌 |
| 开源免费 | ✅ MIT | ❌ 付费 | ❌ 商业 | ✅ 但需自建 | ❌ |
| 多协议同时仿真 | ✅ 21 种同时 | ❌ | ✅ (需购买驱动) | ❌ | ❌ |
| Web 管理界面 | ✅ 开箱即用 | ❌ 桌面软件 | ✅ | ❌ | 品牌专用 |
| 设备模板库 | ✅ 122+ 模板 | ❌ 手动配置 | ✅ | ❌ | — |
| 批量设备生成 | ✅ 一键 100 台 | ❌ | ✅ (付费) | ❌ | ❌ |
| 数据生成器 | ✅ 5 种 (随机/正弦/递增/渐变/固定) | ❌ 手动改值 | ❌ | ✅ 简单 | ✅ 真实数据 |
| 异常码模拟 | ✅ 设备状态映射异常码 | ❌ | ❌ | ❌ | ✅ |
| 写入支持 | ✅ 完整读写 | ✅ | ✅ | ❌ | ✅ |
| Docker 部署 | ✅ 30 秒启动 | ❌ | ❌ | ✅ | ❌ |
| ARM/树莓派 | ✅ 支持 | ❌ | ❌ | ✅ | — |
| 中文支持 | ✅ 双语 | ❌ | ❌ | ❌ | — |
| 成本 | 免费 | $69+ | $1,500+/驱动 | 免费 | $500+ |
💡 ProtoForge 的独特价值:一台电脑同时仿真 21 种协议设备,零硬件成本。不是替代真实 PLC,而是让你在没有硬件时也能开发、测试、联调。
ProtoForge 严格遵循工业协议标准,确保你的采集程序对接真实设备时无缝切换:
| 协议 | 遵循标准 | 异常码/错误处理 |
|---|---|---|
| Modbus TCP/RTU | Modbus Application Protocol v1.1b3 | 完整异常码:0x01 非法功能、0x02 非法地址、0x03 非法数据值、0x04 从站故障、0x05 确认、0x06 从站忙、0x0A 网关不可达 |
| Siemens S7 | S7 Communication (ISO-on-TCP, RFC1006) | SZL 请求响应、错误帧完整支持 |
| Omron FINS | FINS/TCP (CV-mode 命令) | EndCode 错误码完整返回 |
| Mitsubishi MC | SLMP 3E/4E 帧格式 | 子头 0x5000,大端序读写 |
| OPC-UA | OPC 1.05 Part 6: Mappings | NodeId/QualifiedName/DataValue 完整 |
| IEC 60870-5-104 | IEC 60870-5-104 (TI/CI/CD 等 ASDU) | APDU/APCI 帧、IOA 地址完整 |
| MQTT | MQTT 3.1.1 / 5.0 | QoS 0/1/2、Retain、Last Will |
| BACnet | BACnet/IP (ASHRAE 135) | ReadProperty/WriteProperty 服务 |
💡 设备状态→异常码映射:ProtoForge 仿真设备的运行状态(stop/error/starting/stopping/maintenance/program)会自动映射为对应协议的异常码,就像真实设备在故障时会返回错误一样。例如 Modbus 设备处于
error状态时返回异常码0x04(Slave Device Failure)。
ProtoForge 支持 ARM64 架构,可以在树莓派、工业网关等低功耗设备上运行:
# 树莓派 / ARM64 设备
docker run -d --name protoforge \
-p 8000:8000 \
-e PROTOFORGE_ADMIN_PASSWORD=admin \
-v protoforge-data:/app/data \
suoten/protoforge:latestDocker 镜像自动识别 CPU 架构(amd64 / arm64),无需指定平台。
# 安装 Python 3.10+
sudo apt install python3.10 python3.10-venv
# 克隆并安装
git clone https://github.com/suoten/ProtoForge.git
cd ProtoForge
python3.10 -m venv .venv
source .venv/bin/activate
pip install -e .
# 启动
protoforge run --host 0.0.0.0 --port 8000| 配置项 | 最低要求 | 推荐 | 测试基准 |
|---|---|---|---|
| CPU | ARM Cortex-A53 (1.2GHz) | ARM Cortex-A72 (1.5GHz+) | 树莓派 4B (4GB) |
| 内存 | 256MB (10 台设备) | 512MB (50 台设备) | 1GB (100+ 台设备) |
| 磁盘 | 100MB (应用) | 1GB (含数据) | — |
| 并发设备 | 10 台 | 50 台 | 100+ 台 |
| 协议端口 | 5 个同时 | 10 个同时 | 全部 21 种 |
💡 树莓派实测:在树莓派 4B (4GB) 上运行 50 台设备(Modbus + S7 + MQTT 同时),CPU 占用约 15%,内存约 180MB,完全流畅。
⚠️ ARM 限制:部分协议驱动(如 OPC-DA、FANUC FOCAS)依赖 Windows 原生 DLL,在 ARM 上不可用。核心协议(Modbus、S7、OPC-UA、MQTT、FINS、MC、IEC 104、BACnet、CoAP、DDS)均完整支持 ARM64。
| 功能 | 开源版 (MIT) | 企业版 |
|---|---|---|
| 协议数量 | 21 种全支持 | 21 种 + 定制协议 |
| 设备模板 | 122+ 模板 | 122+ + 行业定制模板 |
| 同时仿真设备数 | 无限制 | 无限制 |
| Web 管理界面 | ✅ 完整功能 | ✅ + 品牌定制 |
| API 接口 | ✅ 完整 REST API | ✅ + gRPC 批量接口 |
| Python SDK | ✅ 同步+异步 | ✅ + Java/Go SDK |
| Docker 部署 | ✅ | ✅ + Helm/K8s Operator |
| ARM 支持 | ✅ | ✅ |
| CSV 导入导出 | ✅ | ✅ |
| 测试计划 | ✅ | ✅ + CI/CD 插件 |
| 合规检查 | ✅ | ✅ + 行业标准包 |
| SSO / LDAP | ❌ | ✅ |
| 多租户 | ❌ | ✅ |
| 审计日志 | ❌ | ✅ |
| SLA 支持 | ❌ | ✅ 7×24 |
| 专业服务 | 社区支持 | 专属技术经理 |
💡 开源版永久免费:ProtoForge 开源版包含全部核心功能,没有任何功能限制、设备数量限制或协议限制。企业版提供组织级管理能力和专业服务支持。
Q: pip install -e . 报 externally-managed-environment?
A: 你没有激活虚拟环境。请先在项目目录执行:
python -m venv venv
# Windows: .\venv\Scripts\activate
# macOS/Linux: source venv/bin/activate
pip install -e .Q: protoforge run 报 No module named 'protoforge'?
A: 依赖还没装,先执行 pip install -e .。
Q: 启动后打开 http://localhost:8000 看到 Swagger 文档?
A: 你可能访问了 http://localhost:8000/docs。直接访问 http://localhost:8000(不带 /docs)就是前端 Web 界面。前端和后端都在 8000 端口上,由 FastAPI 统一托管,不需要 Nginx。
Q: 某些协议(OPC-UA / MQTT / BACnet / S7)启动失败?
A: 这些协议需要额外安装依赖,只用 pip install -e . 是不够的。请执行:
pip install -e ".[all]" # 安装全部协议
# 或按需安装:
pip install -e ".[opcua]" # OPC-UA
pip install -e ".[mqtt]" # MQTT
pip install -e ".[s7]" # Siemens S7
pip install -e ".[bacnet]" # BACnetQ: 端口被占用(port already in use)?
A: 编辑项目根目录的 .env 文件,修改对应端口的配置。也可以运行:
# Windows 查看端口占用
netstat -ano | findstr :8000
# macOS / Linux
lsof -i :8000Q: npm install 报错或很慢?
A: 检查 Node.js 版本是否 ≥ 18:
node --version如果版本太低,去 nodejs.org 下载 LTS 版。
如果网络慢,可设置国内镜像:
npm config set registry https://registry.npmmirror.comQ: 前端页面空白?
A: 按你的部署方式排查:
源码 / Nginx 部署:
- 最常见原因:
web/dist/目录不存在。执行cd web && npm install && npm run build构建前端。 - Nginx 部署:检查
nginx -t配置是否正确,root路径是否指向了正确的web/dist/。 - 确认访问的是
http://localhost:8000(前端和后端都在此端口,由 FastAPI 统一托管)。
Docker 部署:
- 检查容器日志:
docker logs protoforge,看是否有 "前端静态文件目录不存在" 的警告。如果有,说明 Docker 镜像构建时前端编译失败了。 - 确认访问的是
http://localhost:8000(不带/docs)。
通用排查:
- 打开浏览器开发者工具(F12)→ Console / Network,看是否有红色报错或 404 请求。
- 检查后端是否正常:访问
/api/v1/health看是否返回 JSON。
Q: Linux 上部署失败?
A: 按以下步骤逐项排查:
- 检查 Python 版本 —
python3 --version,需要 ≥ 3.10。如果版本太低,用apt install python3.12或dnf install python3.12。 - 检查 Node.js 版本 —
node --version,需要 ≥ 18。如果 apt 装的版本太旧,用 NodeSource 安装:curl -fsSL https://deb.nodesource.com/setup_20.x | sudo bash - sudo apt install -y nodejs - 检查虚拟环境 — 是否激活了 venv?(终端前面应该有
(venv)前缀) - 检查端口 —
lsof -i :8000(或你设置的端口),确认没有被其他进程占用。 - 检查 .env 配置 —
cat .env,确认PROTOFORGE_PORT等配置正确。 - 查看后端日志 — 如果用的
nohup,查看protoforge.log;如果用的systemd,查看journalctl -u protoforge。 - 从源码安装时 — 确保用了
pip install -e "."(带引号和点号),不是pip install -e .(Unix shell 下点号会被解释成当前目录,两者效果相同但格式要正确)。
如果是串口相关错误(Modbus RTU): Linux 上没有 COM1,默认使用 /dev/ttyUSB0。如果你没有物理串口,在设备的协议配置中设置 port=0 即可自动切换到 TCP 桥接模式。
Q: 容器启动后频繁重启?
A: 通常是内存不够。试试用简易部署模式(纯 SQLite,内存更低):
docker compose -f docker-compose.simple.yml up -d或者直接用预构建镜像:
docker run -d --name protoforge -p 8000:8000 -v protoforge-data:/app/data suoten/protoforge:latestQ: docker compose 命令报错?
A: 检查你的 Docker 版本。新版 Docker 用 docker compose(无连字符),旧版用 docker-compose。试试哪个能用:
docker compose version # 或 docker-compose --versionQ: Docker 构建时 npm run build 失败?
A: 建议用 Docker Hub 上的预构建镜像 suoten/protoforge:latest,跳过编译步骤:
docker run -d --name protoforge -p 8000:8000 suoten/protoforge:latest如果你必须从源码构建,最新 Dockerfile 已使用 NodeSource 安装 Node.js 20.x(LTS),确保版本可靠。
Q: 忘记管理员密码怎么办?
A: 删除 data/protoforge.db 文件(SQLite 模式)然后重启,系统会重新创建 admin 账号并生成新的随机密码(显示在终端日志中)。你也可以设置 PROTOFORGE_ADMIN_PASSWORD 环境变量来指定新密码。
⚠️ 这会清空所有数据!如果数据重要,请先备份data/目录。
Q: 怎么备份数据?
A: 登录后进入「系统设置」页面,点击「导出备份」按钮即可下载 JSON 文件。也可以直接用命令:
curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:8000/api/v1/backup -o backup.jsonToken 可以在浏览器开发者工具(F12)→ Application → Local Storage → token 中找到。
| 项目 | 说明 | 仓库地址 |
|---|---|---|
| EdgeLiteGateway | 轻量级边缘计算物联网网关,22 种工业协议开箱即用 | Gitee · GitHub |
ProtoForge 开源版永久免费。如果你的团队需要更深层次的支持,我们提供以下专业服务:
| 服务 | 说明 | 适用场景 |
|---|---|---|
| 🔧 协议联调服务 | 专家协助完成特定协议的联调测试,快速定位报文/地址/编码问题 | 项目上线前联调 |
| 🎨 协议定制开发 | 定制非标协议、特殊报文格式、私有协议扩展 | 标准协议不满足需求 |
| 🚀 私有化部署 | ProtoForge + EdgeLite 私有化部署、集成、培训 | 企业内网环境 |
| 📊 企业版 License | SSO/LDAP、多租户、审计日志、SLA 支持 | 生产级使用 |
| 🎓 技术培训 | 工业协议体系化培训 + ProtoForge 实操 | 团队技能提升 |
💬 联系方式:QQ群(群主)或邮箱
suoten@163.com
ProtoForge 是一个开源项目,如果你觉得它对你有帮助,可以考虑请作者喝杯咖啡 ☕ 你的支持是项目持续维护的动力!
微信赞赏 |
支付宝赞赏 |
💝 感谢每一位支持者!如果在企业项目中使用了 ProtoForge,欢迎反馈使用场景,也欢迎在 GitHub Issues 留言。













