使用说明
Modbus TCP服务器仿真
Modbus TCP服务器·内存存储·Web UI·REST·Swagger·基于HTTP的MCP
Web UI v2.2.0:Modbus寄存器矩阵, 地址映射, 模拟规则、自动刷新、Swagger和MCP。
A. Modbus TCP 模拟器与a 单内存存储:web UI, REST API, 昂首阔步,以及 MCP(模型上下文协议) 对于Cursor等客户端,通过HTTP。内置于 火箭, 东京-Modbus,以及 rmcp.
✨ 特征
- Modbus TCP --保持/输入寄存器、线圈和离散输入。
- JavaScript模拟脚本 --服务器端QuickJS脚本
script/对寄存器写入做出反应,并在计时器上运行(见下文)。 - 表征状态转移 --与Modbus和MCP相同的数据。
- Web用户界面 (
/ui/)--寄存器矩阵,UInt16/Int32/浮点/双格式,位掩码,可配置间隔的自动刷新,MCP提示mcp.json示例和下载。 英语 (默认)和 俄语 通过 EN / 俄 在标题栏中;选择存储在浏览器中。 - 主控程序 --可流式HTTP
/mcp工具,如modbus_read_holding_registers,modbus_write_holding_registers以及更多。 - 可安装PWA --在中打开UI 铬 或 边缘 在
http://127.0.0.1:9090/ui/(或你的主人);页面加载后,使用 安装 在地址栏中(与 油管 / 声破天 web:独立窗口,无标签)。用途manifest.json+最低限度的服务人员/ui/.
📋 需求
- 来源: 生锈的工具链。
- 集装箱: Docker(或仅从Docker Hub拉取)。
🚀 快速启动
Docker Hub镜像(推荐)
当前标签: 2.2.0.
docker pull allexd2010/modbus-server-sim:2.2.0
docker run -d --name modbus-sim \
-p 9090:9090 \
-p 502:502 \
-e RUST_LOG=info \
allexd2010/modbus-server-sim:2.2.0
| 主机 | 容器 | 用途 |
|---|---|---|
| 9090 | 9090 | HTTP:REST、Swagger、, /ui/,MCP /mcp |
| 502 | 502 | Modbus TCP |
在本地构建映像:
docker build -t allexd2010/modbus-server-sim:2.2.0 .
Docker Compose
docker compose up -d
端口和图像在中定义 docker-compose.yml.
没有Docker
cargo run --release
默认值:web 9090 (UI+neneneba API+MCP位于 /mcp)Modbus 502.UI: http://127.0.0.1:9090/ui/.
作为应用程序安装(PWA)
- 启动服务器(
cargo run --release或带有端口的Docker 9090 出版)。 - 打开
http://127.0.0.1:9090/ui/在 铬 或 微软边缘 (安全上下文:localhost/127.0.0.1作品)。 - 当浏览器显示 安装 在地址栏(或菜单)中→ 将此网站安装为应用程序),confirm--UI将在其 自己的窗口 没有正常的浏览器工具栏。
已安装的应用程序仍在与 同源 作为页面;保持后端运行。对于远程服务器,请在安装前在URL中使用该主机。
🌐 启动后的服务
| 服务 | URL/地址 |
|---|---|
| Web用户界面 | http://<host>:9090/ui/ |
| 斯瓦格 | http://<host>:9090/api/v1/swagger/ |
| REST | 基础前缀 /api/v1/ |
| Modbus TCP | <host>:502 (或港口从 MB_SERVER_PORT 以及你的Docker -p 映射) |
| MCP | http://<host>:9090/mcp (与UI/API端口相同) |
🖥️ Web用户界面
- 标签:保持/输入/线圈/离散输入。
- 偏移 和 计数 设置读取窗口。限制来自服务器(
MB_MAX_ADDRESS,MB_MAX_READ_COUNT;违约 65535 每个)。UI从以下位置加载它们GET /api/v1/ui-config因此输入保持同步。寄存器矩阵在网格区域内滚动。 - 自动 --定期读取;间隔(秒);当单元格聚焦时,自动刷新不会覆盖您的输入。
- 脚本 --顶部酒吧 Modbus/脚本:编辑服务器端JavaScript(
*.js),保存发动机重新加载。禁用模拟脚本时隐藏。 - 人工智能 --MCP帮助文本、光标的当前URL、,
mcp.json下载(主机如页面上所示,端口 18081 默认情况下,或?mcpPort=在页面URL中)。
📍 Modbus寻址
协议和API使用 零基偏移 (第一个持有寄存器是地址 0).Modicon风格文档:持有 40001 → 抵消 0, 40021 → 20.
🔌 REST API(简称)
所有路线都在 /api/v1/;举个例子:
GET /api/v1/ui-config--JSONmax_modbus_address,max_read_count(与下面的env变量相同的限制;由web UI使用)GET /api/v1/holding-registers/{addr}/{cnt}--阅读POST /api/v1/holding-register/{addr}/{data}--单个单词POST /api/v1/holding-registers/{addr}--JSON正文{"data":[…]}
超出配置限制的读/写请求将返回 400输入、线圈和离散的URL模式相同——请参见Swagger。
🤖 MCP(光标和其他)
- 运输: 流式HTTP,端点
/mcp. - 与REST相同的商店。
- 在工具中,
addr是 协议偏移,而不是40001款式号。
Modbus: modbus_read_holding_registers, modbus_write_holding_register,…(之前的所有读/写工具)。
地址图: var_map_get, var_map_save, var_map_import --数据与 /api/v1/var-map (命名变量为 map.* 在脚本中;支持 type: "bit" 和 bit: 0…15).
模拟规则: sim_scripts_list, sim_scripts_read, sim_scripts_write, sim_scripts_delete, sim_scripts_reload, sim_scripts_export, sim_scripts_import (需要脚本引擎;在以下情况下禁用 SIM_SCRIPTS_DISABLE).
组合: simulation_export, simulation_import --脚本+地址映射在一个JSON包中(mode: merge 或 replace).
示例 mcp.json (全球 %USERPROFILE%\.cursor\mcp.json 或项目 .cursor/mcp.json):
{
"mcpServers": {
"modbus-tcp-sim": {
"url": "http://127.0.0.1:9090/mcp"
}
}
}
在改变配置之后, 完全重启 光标。
禁用MCP: MCP_SERVER_PORT=0.
📜 模拟脚本(JavaScript)
后端运行 JavaScript 目录中的脚本(默认 ./script)使用嵌入式 QuickJS 运行时。脚本在启动时加载,并与TCP、REST和MCP共享相同的内存Modbus存储。
触发器:
modbus.onWrite(kind, fn)--在对寄存器/线圈进行任何写入之后(holding,input,coil,discreteInput):来自Modbus TCP、REST、MCP, 或其他脚本.回拨:(addr, values).modbus.setInterval(ms, fn)--周期性回调(最小间隔1ms)。
来自脚本的API:
| 方法 | 说明 |
|---|---|
modbus.holdingRead(addr, count?) |
读取保持寄存器 |
modbus.inputRead(addr, count?) |
读取输入寄存器 |
modbus.coilRead(addr, count?) |
读取线圈 |
modbus.discreteInputRead(addr, count?) |
读取离散输入 |
modbus.holdingWrite(addr, value) |
写一个单词或数组 |
modbus.inputWrite(addr, value) |
输入寄存器也是如此 |
modbus.coilWrite(addr, value) |
写bool或布尔数组 |
modbus.discreteInputWrite(addr, value) |
离散输入也是如此 |
打字寄存器 (布局与web UI相同:Int32/Float32使用2个单词,单词顺序可选 'HL' 违约或 'LH';Double/Int64使用4个字大端序):
| 方法 | 说明 |
|---|---|
modbus.holdingReadInt32(addr, order?) / holdingWriteInt32 |
32位签名 |
modbus.holdingReadFloat(addr, order?) / holdingWriteFloat |
IEEE754浮点32 |
modbus.holdingReadDouble(addr) / holdingWriteDouble |
IEEE754浮点64 |
modbus.holdingReadInt64(addr) / holdingWriteInt64 |
64位签名(数字或 {hi, lo} 零件) |
modbus.holdingReadInt64Parts(addr) |
{ hi, lo } 没有精度损失 |
modbus.inputReadInt32 … inputWriteInt64 |
输入寄存器也是如此 |
比特 (16位Modbus字,位0=LSB):
| 方法 | 说明 |
|---|---|
modbus.getBit(word, n) |
读取位 n (0…15) |
modbus.testBit(word, n) |
true 如果位设置 |
modbus.setBit(word, n, on) |
设置/清除位,返回新单词 |
modbus.getBits(word, start, len) |
提取位字段 |
modbus.setBits(word, start, len, value) |
插入位字段,返回新单词 |
modbus.int64FromNumber(n) / int64ToNumber(hi, lo) |
转换int64部分↔ 数字(安全范围) |
地址地图(map) --从中读取/写入命名点 地址映射 选项卡(存储在 conf/var-map.json).与上述布局类型相同:
| 方法 | 说明 |
|---|---|
map.read(name) / map.get(name) |
按变量名读取 |
map.write(name, value) / map.set(name, value) |
按姓名书写 |
map.has(name) |
true 如果该名称存在于地图中 |
map.list() |
所有变量名的数组 |
map.def(name) |
{ name, kind, addr, type, order } 或 null |
map.def(name).bit |
位索引 0…15 当 type 是 "bit" (LSB=b0) |
map.onChange(name, fn) |
在任何与变量重叠的写入操作之后: fn(value, name) |
map.onChange(fn) |
查看所有地图变量: fn(name, value) |
onChange 从Modbus TCP、REST、MCP或脚本(包括 map.write).回调函数接收 解码 键入值(与 map.read).
例子:
map.onChange("Temperature", function (value) {
map.write("Alarm", value > 80);
});
map.onChange(function (name, value) {
if (name === "HR0_counter") {
/* … */
}
});
避免反馈循环 onWrite 处理程序(例如,写入与您反应的地址相同的地址)。
示例(script/example.js):
modbus.setInterval(1000, function () {
var v = modbus.holdingRead(100);
modbus.holdingWrite(100, (v + 1) % 65536);
});
modbus.onWrite('holding', function (addr, values) {
if (addr !== 0) return;
var v = Array.isArray(values) ? values[0] : values;
modbus.inputWrite(0, v);
});
在Docker中挂载自定义脚本:
docker run -d -p 9090:9090 -p 502:502 \
-v /path/to/my-scripts:/app/script \
-v /path/to/my-conf:/app/conf \
allexd2010/modbus-server-sim:2.2.0
Web用户界面: 地址映射 选项卡——命名为Modbus点; 出口 / 导入 对于地图。 脚本 选项卡--编辑 *.js 文件夹; 出口 / 导入 仅限脚本,或 全部导出 / 全部导入 用于脚本+映射在一起。 保存 写入磁盘并重新加载QuickJS引擎; 重新加载发动机 无需编辑即可应用于磁盘文件。
REST(与UI相同):
GET /api/v1/sim-scripts--列表GET /api/v1/sim-scripts/{name}--阅读PUT /api/v1/sim-scripts/{name}--拯救身体{ "content": "…" }POST /api/v1/sim-scripts--创建{ "name": "foo.js", "content": "…" }DELETE /api/v1/sim-scripts/{name}POST /api/v1/sim-scripts/reload--重新装载发动机GET /api/v1/sim-scripts/export--脚本JSON包POST /api/v1/sim-scripts/import--身体{ "version": 1, "scripts": […], "mode": "merge"|"replace" }GET /api/v1/var-map/PUT /api/v1/var-map--读取/保存地址映射GET /api/v1/var-map/export--映射JSON{ "version": 1, "variables": […] }POST /api/v1/var-map/import--身体{ "version": 1, "variables": […], "mode": "merge"|"replace" }GET /api/v1/simulation/export--组合{ "version": 1, "scripts": […], "varMap": {…} }POST /api/v1/simulation/import--导入脚本和/或varMap/顶级variables
| 变量 | 默认值 | 描述 |
|---|---|---|
SIM_SCRIPTS_DIR |
script (或 /app/script 在Docker中) |
仅 目录 *.js 模拟脚本(读取/保存)。遗产 scripts/ 已合并到 script/ 启动并删除。 |
SIM_SCRIPTS_DISABLE |
(未设置) | 设置为 1 或 true 禁用脚本引擎 |
VAR_MAP_PATH |
conf/var-map.json (或 /app/conf/var-map.json 在Docker中) |
为 地址映射 选项卡和 map.* 在脚本中 |
⚙️ 环境变量
| 变量 | 默认值 | 描述 |
|---|---|---|
WEB_SERVER_PORT |
9090 |
HTTP(REST、Swagger、静态 /ui) |
MB_SERVER_PORT |
502 |
Modbus TCP |
MCP_SERVER_PORT |
任何非零 | 0 禁用MCP;启用时,MCP处于 /mcp 上 WEB_SERVER_PORT |
MB_MAX_ADDRESS |
65535 |
最大值 协议地址 (含)。窗口 addr … addr + cnt - 1 不得越过此界限。 |
MB_MAX_READ_COUNT |
65535 |
最大值 单词或比特 在一次HTTP读取中,最大 元素 在一批写入正文中。 |
RUST_LOG |
info |
日志级别通过 tracing示例: info, debug, modbus_tcp_server_rust=debug,info下的HTTP静态资产 /ui/ 此处省略 info 以降低噪声。 |
看 更改日志.md 发布历史。
Modbus客户端: 使用从映射的主机端口 MB_SERVER_PORT (默认值 502).这 MB_MAX_* 变量适用于 HTTP REST API (以及web UI调用的内容),而不是内部的原始Modbus TCP帧限制 tokio-modbus.
📋 日志记录
后端使用结构化日志记录(tracing).启动时,您将看到Modbus TCP绑定、web/MCP状态、脚本引擎和var映射路径。
RUST_LOG=info cargo run --release # default
RUST_LOG=debug cargo run --release # HTTP requests + script load
RUST_LOG=modbus_tcp_server_rust=debug,info cargo run --release
在Docker/Compose中, RUST_LOG=info 默认设置为。静态文件位于 /ui/ 未登录 info 以降低噪声。
🔧 故障排除
- 正在使用的端口 --检查
netstat/任务经理;改变-p映射或环境变量。 - MCP在游标中没有响应 --URL必须是
http://<host>:9090/mcp(与web UI端口相同)。 - UI中的数据为空或错误 -API必须返回 JSON数组;来自代理的HTML不会填充表格。
📦 图像和注册表
- Docker Hub:
allexd2010/modbus-server-sim - 标签:例如。
2.2.0
📄 许可证
麻省理工学院
Documentation · latest tag 2.2.0
