Metadata-Version: 2.4
Name: mbtoolcli
Version: 0.4.2
Summary: A comprehensive Modbus Master/Slave testing tool supporting TCP, RTU, and ASCII protocols
Author: Modbus Tool Contributors
License: MIT
Project-URL: Homepage, https://gitee.com/xihari/modbus-simulation-tool
Project-URL: Documentation, https://gitee.com/xihari/modbus-simulation-tool#readme
Project-URL: Repository, https://gitee.com/xihari/modbus-simulation-tool
Project-URL: Issues, https://gitee.com/xihari/modbus-simulation-tool/issues
Keywords: modbus,master,slave,tcp,rtu,ascii,industrial,testing
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Interface Engine/Protocol Translator
Classifier: Topic :: System :: Hardware :: Hardware Drivers
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pymodbus<4.0.0,>=3.14.0
Requires-Dist: PyYAML>=6.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
Requires-Dist: pyinstaller>=5.0.0; extra == "dev"
Provides-Extra: mqtt
Requires-Dist: paho-mqtt>=2.0.0; extra == "mqtt"
Dynamic: license-file

# Modbus Tool 使用手册

> 版本：v0.4.2 ｜ 适用平台：Windows / Linux / macOS
> 本手册所有示例均经过实际运行验证，命令输入与程序输出均为真实结果。

---

## 目录

- [一、产品介绍](#一产品介绍)
- [二、快速开始](#二快速开始)
- [三、五种工作模式](#三五种工作模式)
- [四、从站模式：模拟真实设备](#四从站模式模拟真实设备)
- [五、主站模式：读写与调试](#五主站模式读写与调试)
- [六、流量录制与回放](#六流量录制与回放)
- [七、故障注入：测试容错能力](#七故障注入测试容错能力)
- [八、虚拟产线仿真](#八虚拟产线仿真)
- [九、监控与数据导出](#九监控与数据导出)
- [十、机器接口与自动化集成](#十机器接口与自动化集成)
- [十一、端到端实战场景](#十一端到端实战场景)
- [十二、参数速查表](#十二参数速查表)
- [十三、常见问题排查](#十三常见问题排查)

---

## 一、产品介绍

**Modbus Tool 是一款集成主站与从站能力的综合 Modbus 调试工具**，一个命令即可完成从设备模拟、协议调试到自动化集成的全部工作。它同时替代了传统方案中需要分别安装的两类工具，并在此基础上增加了**流量录制回放、故障注入、虚拟产线仿真、JSON 机器接口、交互式命令行、HTTP 服务**等高级能力。

### 1.1 它能帮你做什么

| 场景 | 传统做法 | 使用 Modbus Tool |
|------|----------|------------------|
| 现场设备没到位，先联调上位机 | 等设备到货 | 用从站模式模拟设备，立即开测 |
| 调试时反复读写寄存器 | 手工改数、反复敲命令 | 一条命令读写，12 种数据类型自动解释 |
| 想复制真实设备的通信行为 | 无法实现 | 录制一次，永久回放 |
| 测试主站遇到异常时的表现 | 难以构造故障 | 按规则注入丢帧/坏帧/异常码 |
| 产线调试需要多台设备 | 逐台部署 | 一个进程模拟多从站 + 内置 6 类设备模板 |
| 给脚本/Agent 调用 | 解析人读文本 | JSON 结构化输出 + HTTP 服务 + 交互式 REPL |

### 1.2 传输协议支持

支持 5 种传输方式，覆盖从标准 TCP 到真实串口的全部场景：

| 协议 | 说明 | 是否需要硬件 |
|------|------|--------------|
| TCP | 标准 Modbus TCP | 仅网络 |
| RTU | 串口 RTU（RS-232/485） | 需要串口（如 USB 转 485） |
| ASCII | 串口 ASCII | 需要串口 |
| RTU over TCP | RTU 帧封装在 TCP 中传输 | 仅网络（虚拟串口） |
| ASCII over TCP | ASCII 帧封装在 TCP 中传输 | 仅网络（虚拟串口） |

其中 **RTU over TCP / ASCII over TCP** 无需任何串口硬件，即可用 TCP 链路模拟串口通信，非常适合无硬件环境下的联调。

### 1.3 安装

```bash
git clone https://gitee.com/xihari/modbus-simulation-tool.git
cd modbus-simulation-tool
pip install -e .
```

安装后即可使用 `mbtool` 命令（同时注册了 `modbus-tool`、`modbus-slave` 两个别名）。MQTT 发布为可选功能，需要时执行：

```bash
pip install "mbtoolcli[mqtt]"
```

验证安装：

```bash
$ mbtool --version
mbtool 0.4.0
```

> **兼容性提示**：若执行 `mbtool --version` 时提示与依赖库相关的错误（如 `ImportError`），通常是因为环境中残留了**旧版本的 mbtoolcli** 与本工具的新依赖冲突。请先执行 `pip uninstall mbtoolcli` 清理旧安装，再按上文重新安装（本工具会自动匹配正确依赖版本，无需手动降级任何组件）。Windows 上建议使用 Windows Terminal 以获得最佳显示效果。

---

## 二、快速开始

### 2.1 三分钟跑通"两个设备对话"

**第 1 步：打开终端 A，启动一个从站设备**

```bash
mbtool --slave -p 1502
```

程序会输出设备状态横幅并保持运行：

```
============================================================
Modbus Slave Server Status:
  Protocol:  TCP
  Address:   127.0.0.1:1502
  Slave ID:  1
  Simulation: Disabled
============================================================

Server is running. Press Ctrl+C to stop.
```

**第 2 步：打开终端 B，用主站读取这个设备**

```bash
mbtool --master -a 1 -p 1502 -r 0 -c 10
```

实际输出：

```
Connecting to TCP 127.0.0.1:1502...
Connected!

Reading 10 register(s) from address 0...

Results (10 values):
  [0] = 100
  [1] = 200
  [2] = 300
  [3] = 400
  [4] = 500
  [5] = 600
  [6] = 700
  [7] = 800
  [8] = 900
  [9] = 1000
```

**第 3 步：向设备写入一个值**

```bash
mbtool --master -a 1 -p 1502 --write -r 0 -v 1234
```

实际输出：

```
Connected!

Writing 1234 to register 0...
Write successful!
```

再读回来验证：

```bash
mbtool --master -a 1 -p 1502 -r 0 -c 1
```

```
Result: 1234
```

至此，你已经完成了从"模拟设备"到"读写验证"的完整闭环。整个过程中没有使用任何真实硬件。

### 2.2 查看帮助

所有参数均可通过帮助查看：

```bash
mbtool --help
```

---

## 三、五种工作模式

Modbus Tool 有五种互斥的工作模式，一次运行只能选择一种。不指定任何模式时，程序进入交互式 REPL（见 10.3 节）。

| 模式 | 命令 | 角色 | 典型用途 |
|------|------|------|----------|
| 主站 | `--master` | 客户端 | 读写从站、轮询监控、扫描 |
| 从站 | `--slave` | 服务端 | 模拟设备，供主站/上位机连接 |
| 扫描 | `--scan` | 探测器 | 发现网络中 1-247 号活动从站 |
| 录制 | `--record 文件.jsonl` | 透明代理 | 记录真实设备与主站间的全部报文 |
| 生成 | `--generate 文件.jsonl` | 合成器 | 按设备模板生成仿真报文 |

五种模式一次只选一种，从站模式常驻运行，主站模式执行完即退出。

---

## 四、从站模式：模拟真实设备

从站模式的本质是"扮演一台设备"：监听端口，等待主站来读写。从最简单的启动开始，逐级叠加功能。

### 4.1 启动最简从站

```bash
mbtool --slave
```

- 监听 `0.0.0.0:502`（Modbus 标准端口），从站 ID = 1
- 内置默认寄存器表：8 个线圈、8 个离散输入、10 个输入寄存器、10 个保持寄存器

> 502 端口常被占用，Linux 下还要求 root 权限，所以示例中普遍使用高位端口（如 1502）。

### 4.2 指定端口与从站 ID

```bash
mbtool --slave -p 1502 -a 1
```

### 4.3 一个端口模拟多个从站

```bash
mbtool --slave -p 1502 -a 1,2,3
```

同一个端口上同时响应 ID 1、2、3 三台"设备"，主站指定从站 ID 即可单独访问，实测验证各设备数据相互隔离：

```bash
# 读 2 号设备
mbtool --master -a 2 -p 1502 -r 0 -c 2
```
```
Results (2 values):
  [0] = 100
  [1] = 200
```

```bash
# 向 2 号设备写入 777
mbtool --master -a 2 -p 1502 --write -r 0 -v 777
mbtool --master -a 2 -p 1502 -r 0 -c 1
```
```
Result: 777
```

```bash
# 1 号设备不受影响，仍是 100
mbtool --master -a 1 -p 1502 -r 0 -c 1
```
```
Result: 100
```

典型用途：一台电表三个费率、一个网关带多台仪表。

### 4.4 让数据动起来（动态仿真）

```bash
mbtool --slave -p 1502 --simulate
```

启用内置仿真：输入寄存器 0-4 输出正弦波、5-6 计数器递增、保持寄存器 9 线性递增。用 `--sim-interval` 可调更新频率（默认 0.1 秒）。

配合主站轮询即可观察数值连续变化：

```bash
mbtool --master -p 1502 -f 4 -r 0 -c 1 --poll -i 0.5
```

### 4.5 使用内置设备模板

```bash
mbtool --list-devices
```

实际输出（6 个内置模板）：

```
Available device templates:
  conveyor  (conveyor.json)
  encoder  (encoder.json)
  energy_meter  (energy_meter.json)
  imu  (imu.json)
  laser_ranger  (laser_ranger.json)
  pid_controller  (pid_controller.json)
```

| 模板 | 模拟对象 |
|------|----------|
| `conveyor` | 输送线：带速、位移、状态 |
| `encoder` | 编码器：转速、累计值 |
| `laser_ranger` | 激光测距仪 |
| `imu` | 倾角仪 |
| `pid_controller` | 温控器 |
| `energy_meter` | 电表（配合 `-a 1,2,3` 可模拟三块电表） |

启动输送线仿真设备：

```bash
mbtool --slave -p 1502 --device conveyor --simulate
```

读取仿真数据（数值随时间变化，实测输出）：

```bash
mbtool --master -a 1 -p 1502 -f 4 -r 0 -c 5
```
```
Results (5 values):
  [0] = 4272
  [1] = -9558
  [2] = 621
  [3] = 799
  [4] = 2531
```

再次读取，数值已更新（证明数据在持续演化）：

```
Results (5 values):
  [0] = 6552
  [1] = -7216
  [2] = 914
  [3] = 1084
  [4] = 3820
```

三块电表同时运行：

```bash
mbtool --slave -p 1502 --device energy_meter -a 1,2,3
```

### 4.6 模拟你自己的设备

内置模板不够用时，用自定义寄存器表文件定义专属设备：

```bash
mbtool --slave -p 1502 --register-map my_device.json
```

`my_device.json` 示例（定义一个温度变送器：寄存器间可用表达式关联，如"当前温度 = 设定值/100 + 正弦波动"）：

```json
{
  "identity": {"vendor": "Acme", "product": "ACME-100", "revision": "1.0"},
  "holding_registers": [
    {"address": 0, "value": 2500, "description": "温度设定值"},
    {"address": 1, "value": 100,  "description": "报警上限"}
  ],
  "input_registers": [
    {"address": 0, "value": 25, "description": "当前温度", "expression": "h0 / 100 + 10 * sin(t)"}
  ],
  "coils": [
    {"address": 0, "value": false, "description": "加热器开关"},
    {"address": 1, "value": false, "description": "报警输出", "expression": "i0 > 80"}
  ]
}
```

字段说明：

| 字段 | 必填 | 说明 |
|------|------|------|
| `address` | 是 | 寄存器地址（0-65535） |
| `value` | 否 | 初始值（线圈 true/false，寄存器 0-65535） |
| `description` | 否 | 描述文字（`--status` 中显示） |
| `expression` | 否 | 动态计算表达式（配合 `--simulate` 生效） |
| `identity` | 否 | 设备身份信息（主站查询设备标识时返回） |

表达式支持变量（`h0` 保持寄存器 0、`i0` 输入寄存器 0、`c0` 线圈 0、`t` 运行秒数）、四则运算、比较与逻辑运算、数学函数（sin/cos/tan/sqrt/abs/min/max/clamp/exp/log/pow 等）以及常量 `pi`、`e`。表达式在安全沙箱中求值，配置外部文件可放心使用。

### 4.7 状态持久化（掉电不丢数据）

```bash
# 终端 A：启动从站，每 5 秒自动保存一次状态
mbtool --slave -p 1502 --save-state state.json --save-interval 5

# 终端 B：主站写入一个值
mbtool --master -p 1502 --write -r 0 -v 1234
# 输出：Write successful!

# 重启从站，加载之前保存的状态
mbtool --slave -p 1502 --load-state state.json

# 验证：寄存器 0 的值还是 1234
mbtool --master -p 1502 -r 0 -c 1
```
```
Result: 1234
```

状态文件保存了全部寄存器值（包括运行期间被主站写入的值），实测中主站写入地址 5 的 `1234` 被正确持久化并恢复。

### 4.8 选择传输协议

```bash
# RTU 帧走 TCP —— 无需物理串口，适合与 rtu-tcp 主站联调
mbtool --slave -m rtu-tcp -p 1502

# ASCII 帧走 TCP
mbtool --slave -m ascii-tcp -p 1502

# 真实串口 RTU（需要物理串口，如 USB 转 485）
mbtool --slave -m rtu -p COM3 -b 9600 --parity N --stopbits 1 --bytesize 8

# 真实串口 ASCII
mbtool --slave -m ascii -p COM3 -b 9600
```

`rtu-tcp` 主站实测（读写完全正常）：

```bash
mbtool --master -m rtu-tcp -a 1 -p 1502 -r 0 -c 3
```
```
Results (3 values):
  [0] = 100
  [1] = 200
  [2] = 300
```

### 4.9 查看从站寄存器状态

打印当前全部寄存器数值（含描述）后立即退出，不启动服务器，适合检查配置：

```bash
mbtool --slave --register-map my_device.json --status
```

实际输出（节选）：

```
=== Register Status ===

Coils (Read/Write):
  [    0] = ON  - Coil 0
  [    1] = OFF - Coil 1
  ...

Discrete Inputs (Read-Only):
  [    0] = OFF - Discrete Input 0
  [    1] = ON  - Discrete Input 1
  ...

Input Registers (Read-Only):
  [    0] =  1234 - Temperature
  [    1] =  5678 - Pressure
  ...
```

---

## 五、主站模式：读写与调试

主站是"调试设备的人"：向从站发起读写请求。以下示例默认连接 `127.0.0.1:1502`（可用 4.1 节启动一个从站配合实验）。

### 5.1 四种功能码

| 功能码 `-f` | 名称 | 读写属性 | 说明 |
|------------|------|----------|------|
| `1` | 读线圈（FC01） | 可读写 | 布尔值，如继电器、开关 |
| `2` | 读离散输入（FC02） | 只读 | 布尔值，如限位开关 |
| `3` | 读保持寄存器（FC03） | 可读写 | 16 位值（默认），如设定值 |
| `4` | 读输入寄存器（FC04） | 只读 | 16 位值，如测量值 |

实测三种功能码（默认寄存器表中线圈偶数位 ON、离散输入奇数位 ON，便于对照验证）：

```bash
# 读 8 个线圈
mbtool --master -f 1 -a 1 -p 1502 -r 0 -c 8
```
```
Results (8 values):
  [0] = 1
  [1] = 0
  [2] = 1
  [3] = 0
  [4] = 1
  [5] = 0
  [6] = 1
  [7] = 0
```

```bash
# 读 8 个离散输入
mbtool --master -f 2 -a 1 -p 1502 -r 0 -c 8
```
```
Results (8 values):
  [0] = 0
  [1] = 1
  [2] = 0
  [3] = 1
  [4] = 0
  [5] = 1
  [6] = 0
  [7] = 1
```

```bash
# 读 5 个输入寄存器
mbtool --master -f 4 -a 1 -p 1502 -r 0 -c 5
```
```
Results (5 values):
  [0] = 1234
  [1] = 5678
  [2] = 9012
  [3] = 3456
  [4] = 7890
```

### 5.2 数据类型：如何解释读到的值

同一份 16 位数据，用不同数据类型解释结果完全不同。**注意 `-c` 是寄存器个数**：32 位类型占 2 个寄存器、64 位类型占 4 个。

支持 12 种数据类型：`int16`（默认）、`uint16`、`int32`、`uint32`、`float`、`int64`、`uint64`、`float64`、`bcd`、`bcd32`、`string`、`hex`。

实测示例：

```bash
# 读 10 个寄存器 = 5 个 float（每 2 个寄存器一个浮点数）
mbtool --master -a 1 -p 1502 -r 0 -c 10 -t float
```
```
Results (5 values):
  [0] = 0.000000
  [1] = 0.000000
  ...
```

```bash
# BCD 编码（电表读数常见）
mbtool --master -a 1 -p 1502 -r 0 -c 1 -t bcd
```
```
Result: 64
```

```bash
# 十六进制显示（看原始位模式）
mbtool --master -a 1 -p 1502 -r 0 -c 4 --hex
```
```
Results (4 values):
  [0] = 100 (0x0064)
  [1] = 200 (0x00C8)
  [2] = 300 (0x012C)
  [3] = 400 (0x0190)
```

### 5.3 字节序：32/64 位数据读不出正常值？

多寄存器类型在不同设备上的排列方式不同，读出值不合理时依次尝试四种字节序：

| 字节序 | 32 位寄存器排列 | 常见设备 |
|--------|----------------|----------|
| `ABCD` | Reg[0]=高16位, Reg[1]=低16位 | 标准 Modbus 设备（默认） |
| `CDBA` | Reg[0]=低16位, Reg[1]=高16位 | Siemens S7 系列 |
| `BADC` | 每个寄存器内字节互换 | 部分国产设备 |
| `DCBA` | 完全小端排列 | 部分 PLC |

```bash
mbtool --master -a 1 -p 1502 -r 0 -c 2 -t float --byte-order CDBA
```

### 5.4 写入（单值 / 批量 / 线圈 / 各种类型）

```bash
# 写单个保持寄存器（FC06）
mbtool --master -a 1 -p 1502 --write -r 0 -v 100
```
```
Writing 100 to register 0...
Write successful!
```

```bash
# 写浮点数（占 2 个寄存器，FC16）
mbtool --master -a 1 -p 1502 --write -t float -r 0 -v 3.14
# 输出：Write successful!
```

```bash
# 写字符串 / BCD / 64 位整数
mbtool --master -a 1 -p 1502 --write -t string -r 100 -v "HELLO"
mbtool --master -a 1 -p 1502 --write -t bcd -r 0 -v 2024
mbtool --master -a 1 -p 1502 --write -t int64 -r 0 -v 123456789012
```

```bash
# 批量写入：从地址 0 起依次写 100,200,300
mbtool --master -a 1 -p 1502 --write -r 10 -v "100,200,300"
```
```
  [0] = 100 OK
  [1] = 200 OK
  [2] = 300 OK
Batch write successful!
```

```bash
# 批量写浮点
mbtool --master -a 1 -p 1502 --write -t float -r 0 -v "1.5,2.5,3.5"

# 写线圈（FC05）：1=ON, 0=OFF
mbtool --master -a 1 -p 1502 --write-coil -r 0 --coil-state 1
# 输出：Writing coil 0 = True... / Coil write successful!
mbtool --master -a 1 -p 1502 --write-coil -r 0 --coil-state 0

# 写入时指定字节序
mbtool --master -a 1 -p 1502 --write -t float -r 0 -v 123.456 --byte-order CDBA
```

浮点写入后读回验证：

```bash
mbtool --master -a 1 -p 1502 -r 0 -c 2 -t float
```
```
Result: 3.140000
```

### 5.5 轮询监控：数据不停刷新

```bash
# 每 2 秒轮询一次，无限循环（Ctrl+C 停止）
mbtool --master -a 1 -p 1502 --poll -r 0 -c 5 -i 2

# 轮询 10 次后自动停止
mbtool --master -a 1 -p 1502 --poll -r 0 -c 10 -i 1 -n 10
```

轮询实测输出：

```
Interval: 0.3s, Iterations: 5
Press Ctrl+C to stop

[1] [16456, -2621, 300]
[2] [16456, -2621, 300]
[3] [16456, -2621, 300]
[4] [16456, -2621, 300]
[5] [16456, -2621, 300]
Completed 5 iterations
```

**迷你趋势图**（最近 80 次采样的块状走势）：

```bash
mbtool --master -a 1 -p 1502 --poll -r 0 -c 1 -i 0.3 -n 6 --sparkline
```
```
[1] 16456 ▅
[2] 16456 ▅▅
[3] 16456 ▅▅▅
[4] 16456 ▅▅▅▅
[5] 16456 ▅▅▅▅▅
[6] 16456 ▅▅▅▅▅▅
Completed 6 iterations
```

**阈值告警**（寄存器越限时红色高亮提示）：

```bash
mbtool --master -a 1 -p 1502 --poll -r 0 -c 1 -i 0.3 -n 5 --alarm "0>500"
```
```
[1] 16456  !!! ALARM: register[0] > 500 (current: 16456) !!!
[2] 16456  !!! ALARM: register[0] > 500 (current: 16456) !!!
...
Completed 5 iterations
```

告警表达式格式为 `寄存器号 运算符 阈值`，支持 `> >= < <= == !=`，多个条件用 `;` 分隔。

### 5.6 扫描：发现设备 / 反向工程寄存器表

**从站 ID 扫描**（1-247 逐个探测，发现网络中的活动设备）：

```bash
mbtool --scan -H 192.168.1.100 -p 502
```

实测（本机 1502 端口的从站被正确发现）：

```bash
mbtool --scan -H 127.0.0.1 -p 1502
```
```
Range: Slave ID 1-247
Target: 127.0.0.1:1502

  [1/247] Slave ID 1 - Found
  [2/247] Slave ID 2 - No response
  [3/247] Slave ID 3 - No response
  ...
  [247/247] Slave ID 247 - No response

  Found 1 active slave(s): 1
```

**寄存器范围扫描**（探测一段地址内哪些寄存器有数据，用于反向工程未知设备）：

```bash
mbtool --master -a 1 -p 1502 --scan-regs -r 0 -c 2000
```
```
Scanning 2000 register(s) from address 0 (FC03)...

  Found 100 live register(s):
  [    0] = 16456
  [    1] = 62915
  [    2] = 300
  [    3] = 400
  ...
```

加 `--show-zeros` 可同时显示值为 0 的寄存器；配合 `-f 4`、`-f 1` 可扫描输入寄存器区、线圈区。

### 5.7 设备身份查询（FC43 / FC11）

```bash
# 设备标识：厂商/产品/版本
mbtool --master -a 1 -p 1502 --read-device-info
```
```
Device Identification:
  Vendor:  Modbus Slave Simulator
  Product Code:  MBS-001
  Revision:  1.0.0
```

```bash
# 报告服务器 ID
mbtool --master -a 1 -p 1502 --report-server-id
```
```
Server ID: Modbus Slave Simulator-MBS-001-1.0.0
```

### 5.8 显示增强

**工程单位缩放**（原始值 × scale + offset，仅影响显示）：

```bash
# 0.01°C/LSB 的温度传感器：原始值 2000 → 显示 2000×0.01-40 = -20
mbtool --master -a 1 -p 1502 -r 0 -c 1 --scale 0.01 --offset -40
```

**位域解码**（状态字按位显示可读名称）：

```bash
mbtool --master -a 1 -p 1502 -r 8 -c 1 --bitfield "运行,报警,故障,远程"
```
```
Result: 900 故障
```

### 5.9 并行轮询多台设备

用 YAML 配置同时轮询多台设备，每台设备独立线程：

```yaml
tasks:
  - name: 设备A
    host: 192.168.1.10
    port: 502
    address: 0
    count: 10
    interval: 1.0
    alarm: "0>1000"
  - name: 设备B
    host: 192.168.1.20
    port: 502
    address: 100
    count: 2
    data_type: float
    interval: 0.5
```

```bash
mbtool --master --poll-config poll.yaml
# 可叠加 MQTT
mbtool --master --poll-config poll.yaml --mqtt-host 192.168.1.50
```

---

## 六、流量录制与回放

这是本工具最具特色的能力之一：**把真实设备"拷贝"下来，从此不再需要设备本身**。

### 6.1 录制：透明代理模式

录制代理监听一个端口，把主站的请求转发给真实设备，同时把**请求、响应、时延**全部记录到文件：

```bash
# 终端 A：录制代理。监听 1502，转发到真实设备 192.168.1.100:502
mbtool --record traffic.jsonl -H 192.168.1.100 -p 502 --listen-port 1502

# 终端 B：主站照常操作真实设备，所有报文被记录
mbtool --master -p 1502 -r 0 -c 3 --poll -i 2 -n 5

# 终端 A：Ctrl+C 停止录制，得到 traffic.jsonl
```

实测录制的报文文件（每行一条请求-响应-时延）：

```json
{"req": "010300000003", "resp": "0103064048f5c3012c", "latency_ms": 6.301}
{"req": "010300000003", "resp": "0103064048f5c3012c", "latency_ms": 3.935}
{"req": "010300000003", "resp": "0103064048f5c3012c", "latency_ms": 1.138}
```

### 6.2 回放：按录制行为精确应答

不再需要真实设备，从站按录制文件中的响应和时延精确应答：

```bash
# 终端 A：回放从站
mbtool --slave -p 1503 --replay traffic.jsonl

# 终端 B：效果与连真实设备一致
mbtool --master -p 1503 -r 0 -c 3
```
```
Results (3 values):
  [0] = 16456
  [1] = -2621
  [2] = 300
```

与录制时读取的数值完全一致（16456, -2621, 300），说明回放精确复现了真实设备的通信行为。

**未命中请求的处理方式**（`--replay-fallback`）：

| 取值 | 行为 |
|------|------|
| `exception`（默认） | 返回异常码（模拟设备不认识的地址） |
| `zeros` | 返回全零数据 |
| `normal` | 按寄存器表正常应答 |

```bash
mbtool --slave -p 1503 --replay traffic.jsonl --replay-fallback zeros
mbtool --slave -p 1503 --replay traffic.jsonl --replay-fallback normal
```

---

## 七、故障注入：测试容错能力

按规则让从站"出故障"，验证主站/上位机在异常下的表现。故障规则文件示例：

```json
{
  "faults": [
    {"match": {"fc": 3, "addr": 0}, "action": "exception", "code": 2},
    {"match": {"fc": 4}, "action": "drop", "count": 1, "every": 2},
    {"match": {"fc": 16}, "action": "delay", "ms": 1500},
    {"match": {"fc": 3, "addr": 100}, "action": "garble", "byte": 2, "value": 0xFF},
    {"match": {"fc": 3}, "action": "bad_crc"}
  ]
}
```

支持的故障动作：

| 动作 | 参数 | 效果 |
|------|------|------|
| `exception` | `code`: 1-4 | 返回异常响应（1=非法功能、2=非法地址、3=非法数据、4=从站故障） |
| `drop` | `count`/`every` | 不响应（主站超时）。`count=1, every=2` 表示每 3 个请求丢 1 个 |
| `delay` | `ms` | 延时毫秒后响应（测主站超时处理） |
| `garble` | `byte`/`bit`/`value` | 翻转响应中的字节或位 |
| `bad_crc` | — | 响应 CRC 写坏（RTU 模式，主站丢弃响应） |

`match` 中的 `fc`/`addr`/`count` 均可省略（省略表示匹配任意），规则按顺序匹配第一条。

启动故障设备并验证主站表现（实测）：

```bash
# 终端 A：故障设备
mbtool --slave -p 1502 --faults faults.json

# 终端 B：读地址 0 → 触发"非法地址"异常
mbtool --master -p 1502 -r 0 -c 1 --timeout 1
```
```
Connecting to TCP 127.0.0.1:1502...
Connected!
Reading 1 register(s) from address 0...
Read failed!
```

主站正确报错而不是挂死；配置了"每 3 个请求丢 1 个"的轮询则表现为偶发超时但轮询继续，容错逻辑得到充分验证。

---

## 八、虚拟产线仿真

无需任何硬件，用一条命令搭出多条"虚拟产线设备"：输送线 + 三块电表 + 一台故障设备，各自独立端口，主站/上位机程序像连真实设备一样连接它们。

```bash
# 输送线（带表达式仿真）+ 状态持久化
mbtool --slave -p 1502 --device conveyor --save-state conveyor.json --save-interval 10

# 三块电表，一个端口模拟三个从站
mbtool --slave -p 1503 --device energy_meter -a 1,2,3

# 故障设备用于容错测试
mbtool --slave -p 1504 --faults faults.json
```

### 合成流量生成：无设备联调

按设备模板 + 表达式生成任意数量的仿真请求-响应报文文件，再交给回放从站使用：

```bash
# 生成 100 条仿真报文（按 encoder 模板的表达式演化数据）
mbtool --generate synth.jsonl --device encoder -f 4 -r 0 -c 2 -n 100
```
```
Generating 5 request/response pair(s) -> synth.jsonl
Done.
```

生成的报文（实测）：

```json
{"req": "010400000002", "resp": "01040400000078", "latency_ms": 4.418}
{"req": "010400000002", "resp": "01040407d0007c", "latency_ms": 2.2}
```

```bash
# 回放给上位机
mbtool --slave -p 1502 --replay synth.jsonl
```

---

## 九、监控与数据导出

### 9.1 CSV 导出

```bash
mbtool --master -a 1 -p 1502 --poll -r 0 -c 3 -i 0.4 -n 4 -o log.csv
```

生成的 CSV（实测）：

```
iteration,address,value
1,0,100
1,1,200
1,2,300
2,0,100
2,1,200
2,2,300
...
```

### 9.2 JSONL 导出

```bash
mbtool --master -a 1 -p 1502 --poll -r 0 -c 2 -i 0.4 -n 3 -o log.jsonl
```

生成的 JSONL（实测，每行一个采样）：

```json
{"ts": "2026-08-05 14:55:26", "iteration": 1, "address": 0, "count": 2, "value": [100, 200]}
{"ts": "2026-08-05 14:55:27", "iteration": 2, "address": 0, "count": 2, "value": [100, 200]}
{"ts": "2026-08-05 14:55:27", "iteration": 3, "address": 0, "count": 2, "value": [100, 200]}
```

### 9.3 MQTT 发布

设置 `--mqtt-host` 后，轮询结果实时发布到 `{前缀}/poll`（单设备）或 `{前缀}/{任务名}`（并行轮询）：

```bash
mbtool --master -a 1 -p 1502 --poll -r 0 -c 5 -i 1 --mqtt-host 192.168.1.50
mbtool --master -a 1 -p 1502 --poll -r 0 -c 5 -i 1 --mqtt-host 192.168.1.50 --mqtt-port 1884 --mqtt-prefix factory
```

MQTT 载荷格式：

```json
{"ts": "2026-08-05 14:55:26", "address": 0, "count": 2, "value": [100, 200]}
```

### 9.4 组合使用

告警 + 趋势图 + CSV + 缩放显示一条命令搞定：

```bash
mbtool --master -a 1 -p 1502 --poll -r 0 -c 1 -i 1 --alarm "0>500" \
        --sparkline --scale 0.1 --output temp.csv
```

---

## 十、机器接口与自动化集成

面向脚本、CI、Agent 的结构化能力，让 Modbus 调试可编程化。

### 10.1 JSON 结构化输出（--json）

所有命令加 `--json`（或环境变量 `MBTOOL_JSON=1`）后，stdout 只输出统一的 JSON 文档，字段固定，方便脚本断言：

实测输出：

```json
{
    "schema_version": 1,
    "tool": "mbtool",
    "version": "0.4.0",
    "run_id": "0140a79ff054",
    "command": "master",
    "exit_code": 0,
    "error": null,
    "stdout": "...人类可读输出...",
    "stderr": "",
    "artifacts": [],
    "metadata": {
        "protocol": "tcp",
        "target": "127.0.0.1:1502"
    },
    "result": {
        "operation": "read",
        "address": 0,
        "count": 3,
        "data_type": "int16",
        "function_code": 3,
        "value": [16456, -2621, 300],
        "raw": [16456, 62915, 300]
    }
}
```

轮询模式下是 **JSONL 流**：每个采样一行，最后一行是汇总文档。脚本可直接解析：

```bash
# 脚本断言退出码为 0
mbtool --json --master -a 1 -p 1502 -r 0 -c 1 | jq -e '.exit_code == 0'

# JSONL 轮询喂给管道
mbtool --json --master -a 1 -p 1502 --poll -r 0 -c 1 -i 1 -n 10 | jq -c 'select(.iteration) | .value'
```

**错误码参考**（脚本按 `error.code` 分支，不要解析人类消息）：

| error.code | exit_code | 含义 |
|------------|-----------|------|
| `INVALID_ARGS` | 2 | 参数/取值非法 |
| `CONNECT_FAIL` | 3 | 连接从站失败 |
| `TIMEOUT` | 3 | 请求超时 |
| `READ_FAIL` | 4 | 读操作失败 |
| `WRITE_FAIL` | 4 | 写操作失败 |
| `SERVER_START_FAIL` | 5 | 从站服务器启动失败 |
| `CONFIG_FAIL` | 6 | 配置/寄存器表/回放文件错误 |
| `FILE_NOT_FOUND` | 6 | 文件不存在 |
| `NOT_SUPPORTED` | 7 | 选项组合不支持 |
| `UNAUTHORIZED` | 8 | HTTP 服务鉴权失败 |
| `INTERRUPTED` | 130 | 用户中断（Ctrl+C） |
| `EXEC_FAIL` | 1 | 未预期的内部错误 |

### 10.2 交互式 REPL

不带任何参数直接运行 `mbtool` 进入交互式界面，适合边调试边操作。实测完整会话：

```
Modbus Tool v0.4.2 — 交互式界面
输入 help 查看命令列表；quit 退出；Ctrl+C 中断当前操作。

mbtool> connect 127.0.0.1 1502 tcp 1
已连接 TCP 127.0.0.1:1502 slave_id=1

mbtool> read 0 3
结果 (3 个值):
  [0] = 16456
  [1] = -2621
  [2] = 300

mbtool> write 1 999
写入成功: [1] = 999

mbtool> read 0 2
结果 (2 个值):
  [0] = 16456
  [1] = 999

mbtool> coil 0 1
线圈写入成功: [0] = True

mbtool> poll 0 2 0.3 3
轮询中: addr=0 count=2 interval=0.3s iters=3
[1] [16456, 999]
[2] [16456, 999]
[3] [16456, 999]
Completed 3 iterations

mbtool> status
会话状态:
  主站: TCP 127.0.0.1:1502 slave_id=1
  从站: 未运行

mbtool> quit
```

命令一览：`connect`、`disconnect`、`read`、`write`、`coil`、`poll`、`scan`、`slave start|stop|status`、`sim on|off`、`set`、`status`、`help`、`quit`。

### 10.3 HTTP 服务（--serve）

启动本地 HTTP 服务，供远程工具/Agent 调用：

```bash
MBTOOL_SKILL_TOKEN=secret mbtool --serve --serve-port 8765
```

| 端点 | 说明 |
|------|------|
| `POST /run` | 提交命令，返回统一 JSON 文档 |
| `GET /status` | 服务信息（版本、运行时长、鉴权状态） |
| `GET /health` | 存活探测 |

实测三个端点：

```bash
curl -s http://127.0.0.1:8765/health
```
```json
{"status": "ok", "version": "0.4.0"}
```

```bash
curl -s http://127.0.0.1:8765/status
```
```json
{"status": "running", "version": "0.4.0", "uptime_s": 3.4, "endpoints": ["POST /run", "GET /status", "GET /health"], "auth": true}
```

```bash
# 未带 token 返回 401
curl -s -X POST http://127.0.0.1:8765/run \
  -H "Content-Type: application/json" \
  -d '{"args": ["--master","-a","1","-p","1502","-r","0","-c","2"]}'
# HTTP 401
```

```bash
# 带 token 正常执行
curl -s -X POST http://127.0.0.1:8765/run \
  -H "Authorization: Bearer secret" -H "Content-Type: application/json" \
  -d '{"args": ["--master","-a","1","-p","1502","-r","0","-c","2"]}'
```
```json
{
  "exit_code": 0,
  "result": {"operation": "read", "address": 0, "count": 2,
             "value": [16456, 999], "raw": [16456, 999]},
  "metadata": {"protocol": "tcp", "target": "127.0.0.1:1502"}
}
```

设置 `MBTOOL_SKILL_TOKEN` 后，`/run` 请求必须带 `Authorization: Bearer <token>` 或 `X-MBTOOL-Token: <token>`。

> 注意：`/run` 是同步调用，长驻命令（`--slave`、无限 `--poll`、`--record`）会阻塞请求，请只提交一次性命令；持续仿真请用 REPL。

### 10.4 沙箱与资源限制

面向多租户/无人值守场景的安全选项：

```bash
# 一键沙箱：CPU 30 秒 / 内存 512MB / 进程 64
mbtool --sandbox --slave -p 1502

# 自定义限制
mbtool --limit-cpu 60 --limit-mem 1024 --limit-nproc 32 --master ...

# 启动后降权运行（POSIX）
sudo mbtool --drop-user nobody --slave -p 502
```

---

## 十一、端到端实战场景

### 场景 A：本地零硬件联调

```bash
# 终端 A：虚拟设备（输送线模板）
mbtool --slave -p 1502 --device conveyor

# 终端 B：模拟上位机读写
mbtool --master -p 1502 -f 4 -r 0 -c 5 --poll -i 1 --sparkline   # 观察测量值
mbtool --master -p 1502 --write -r 0 -v 200                       # 改设定值
```

### 场景 B：录制真实设备 → 无设备回放

```bash
# 终端 A：录制代理，监听 1502，转发到真实设备 192.168.1.100:502
mbtool --record traffic.jsonl -H 192.168.1.100 -p 502 --listen-port 1502

# 终端 B：主站指向代理，正常操作真实设备，报文被记录
mbtool --master -p 1502 -r 0 -c 10 --poll -i 2 -n 5

# 终端 A：Ctrl+C 停止录制

# 以后不需要真实设备了
mbtool --slave -p 1503 --replay traffic.jsonl
mbtool --master -p 1503 -r 0 -c 10     # 效果与连真实设备一致
```

### 场景 C：故障注入测试主站容错

```bash
# 终端 A：故障设备
mbtool --slave -p 1502 --faults faults.json

# 终端 B：验证主站正确报错而不是挂死
mbtool --master -p 1502 -r 0 -c 1 --timeout 1     # 读到异常 → 报错退出
mbtool --master -p 1502 -f 4 -r 0 -c 1 --poll -i 1 # 偶发超时但轮询继续
```

### 场景 D：合成流量无设备联调

```bash
mbtool --generate synth.jsonl --device encoder -f 4 -r 0 -c 2 -n 100
mbtool --slave -p 1502 --replay synth.jsonl
```

### 场景 E：搭建完整监控站

```bash
# 1) 先扫一遍网络，确认有哪些设备
mbtool --scan -H 192.168.1.100 -p 502

# 2) 反向工程某台设备的寄存器表
mbtool --master -a 1 -H 192.168.1.100 -p 502 --scan-regs -r 0 -c 2000

# 3) 确认数据类型与字节序
mbtool --master -a 1 -H 192.168.1.100 -p 502 -r 0 -c 2 -t float --byte-order CDBA

# 4) 写入设定值
mbtool --master -a 1 -H 192.168.1.100 -p 502 --write -t float -r 0 -v 25.5

# 5) 挂上长期监控：告警 + 趋势图 + CSV 落盘 + MQTT 推送
mbtool --master -a 1 -H 192.168.1.100 -p 502 --poll -r 0 -c 5 -t float -i 1 \
        --alarm "0>80" --sparkline --output history.csv --mqtt-host 192.168.1.50

# 6) 出问题时开原始帧看协议细节
mbtool --master -a 1 -H 192.168.1.100 -p 502 -r 0 -c 5 --debug-frame
```

### 场景 F：脚本 / CI 集成

```bash
# 脚本断言
mbtool --json --master -a 1 -p 1502 -r 0 -c 1 | jq -e '.exit_code == 0'

# HTTP 服务供远程调用
MBTOOL_SKILL_TOKEN=secret mbtool --serve --serve-port 8765
curl -s -X POST http://127.0.0.1:8765/run \
  -H "Authorization: Bearer secret" -H "Content-Type: application/json" \
  -d '{"args": ["--master", "-a", "1", "-p", "1502", "-r", "0", "-c", "1"]}'
```

---

## 十二、参数速查表

### 12.1 模式与连接参数

| 参数 | 含义 | 默认值 |
|------|------|--------|
| `--master` | 主站模式 | — |
| `--slave` | 从站模式 | — |
| `--scan` | 扫描模式（1-247） | — |
| `--record FILE` | 录制模式 | — |
| `--generate FILE` | 合成流量生成 | — |
| `-m, --mode` | 传输协议：tcp/rtu/ascii/rtu-tcp/ascii-tcp | `tcp` |
| `-H, --host` | 目标主机 IP | `127.0.0.1` |
| `-p, --port` | TCP 端口或串口设备路径 | `502` |
| `-a, --slave-id` | 从站 ID（从站可逗号分隔多 ID） | `1` |
| `--timeout` | 响应超时（秒） | `3.0` |

### 12.2 串口参数（仅 rtu/ascii）

| 参数 | 含义 | 默认值 |
|------|------|--------|
| `-b, --baudrate` | 波特率 | `9600` |
| `--parity` | 校验位 N/E/O | `N` |
| `--stopbits` | 停止位 | `1` |
| `--bytesize` | 数据位 | `8` |

> 串口参数必须与对端设备完全一致，设备手册常标注如 `9600 8E1`。

### 12.3 主站读取参数

| 参数 | 含义 | 默认值 |
|------|------|--------|
| `-r, --register` | 起始寄存器地址（0 基址） | `0` |
| `-c, --count` | 寄存器个数（32 位占 2 个、64 位占 4 个） | `1` |
| `-t, --data-type` | 数据类型（12 种） | `int16` |
| `-f, --function-code` | 功能码 1/2/3/4 | `3` |
| `--hex` | 附带十六进制显示 | 关 |
| `--byte-order` | 字节序 ABCD/CDBA/BADC/DCBA | `ABCD` |
| `--scan-regs` | 寄存器范围扫描 | 关 |
| `--show-zeros` | 扫描时显示零值寄存器 | 关 |
| `--read-device-info` | 读设备标识（FC43） | 关 |
| `--report-server-id` | 报告服务器 ID（FC11） | 关 |
| `--scale` / `--offset` | 显示缩放：显示值 = 原始×scale+offset | 无/0 |
| `--bitfield` | 位域名称表 | 无 |

### 12.4 主站写入参数

| 参数 | 含义 | 示例 |
|------|------|------|
| `--write` | 写入模式（FC06/FC16） | `--write -r 0 -v 100` |
| `-v, --value` | 写入值（可逗号分隔批量） | `-v "100,200,300"` |
| `--write-coil` | 写线圈（FC05） | `--write-coil -r 0 --coil-state 1` |
| `--coil-state` | 线圈状态 0/1 | 默认 `1` |

### 12.5 轮询参数

| 参数 | 含义 | 默认值 |
|------|------|--------|
| `--poll` | 连续轮询模式 | 关 |
| `-i, --interval` | 轮询间隔（秒） | `1.0` |
| `-n, --iterations` | 轮询次数（0=无限） | `0` |
| `--alarm` | 越限告警表达式 | 无 |
| `-o, --output` | 导出 .csv / .jsonl | 无 |
| `--sparkline` | 迷你趋势图 | 关 |
| `--mqtt-host` | MQTT broker 地址 | 关 |
| `--mqtt-port` | broker 端口 | `1883` |
| `--mqtt-prefix` | MQTT 主题前缀 | `modbus` |

### 12.6 从站参数

| 参数 | 含义 |
|------|------|
| `--register-map FILE.json` | 自定义寄存器表 |
| `--device NAME` | 内置设备模板（`--list-devices` 查看） |
| `--simulate` | 动态数值仿真 |
| `--sim-interval SEC` | 仿真更新间隔（默认 0.1s） |
| `--status` | 显示寄存器状态后退出 |
| `--replay FILE.jsonl` | 回放模式 |
| `--replay-fallback MODE` | 回放未命中处理：exception/zeros/normal |
| `--faults FILE.json` | 故障注入规则 |
| `--load-state FILE.json` | 启动恢复状态 |
| `--save-state FILE.json` | 保存状态（退出+周期） |
| `--save-interval SEC` | 自动保存间隔（默认 0=仅退出） |

### 12.7 机器接口与安全参数

| 参数 | 含义 | 默认值 |
|------|------|--------|
| `--json` | JSON 结构化输出（或 `MBTOOL_JSON=1`） | 关 |
| `--interactive` / `--repl` | 交互式 REPL | 关 |
| `--serve` | 本地 HTTP 服务 | 关 |
| `--serve-host` | HTTP 监听地址 | `127.0.0.1` |
| `--serve-port` | HTTP 端口 | `8765` |
| `--sandbox` | 资源限制沙箱 | 关 |
| `--limit-cpu/--limit-mem/--limit-nproc` | 资源上限 | 无 |
| `--drop-user USER` | 降权运行（POSIX） | 无 |

### 12.8 调试参数

| 参数 | 含义 |
|------|------|
| `-V, --verbose` | 详细调试日志 |
| `--debug-frame` | 协议原始帧日志（十六进制收发报文） |
| `--list-devices` | 列出内置设备模板 |
| `--version` | 版本号 |
| `-h, --help` | 帮助 |

---

## 十三、常见问题排查

### 13.1 端口被占用

```bash
# 换端口
mbtool --slave -p 5020

# Linux 上 502 端口需要 root
sudo mbtool --slave -p 502
```

### 13.2 串口权限（Linux）

```bash
sudo usermod -a -G dialout $USER   # 重新登录后生效
```

### 13.3 连接被拒绝

- 确认从站已启动且端口正确
- 检查防火墙
- 用 `mbtool --scan -H <IP> -p <端口>` 确认网络可达

### 13.4 读取超时

- 串口参数（波特率/校验/停止位）与设备不一致
- 从站 ID 错误（用 `--scan` 探测）
- 通信距离过远/线缆问题，尝试加大 `--timeout`

### 13.5 读到错误值（乱码/负数/巨大值）

- 数据类型不对：`-t float` 读成了 `int16`
- 字节序不对：尝试四种 `--byte-order`
- 地址偏移：部分设备 1 基址，尝试 `-r 1` 或 `-r 0`

### 13.6 轮询输出出现 `Error reading registers`

- 设备暂时无响应（超时）
- 读取数量超过设备支持范围（保持寄存器一次最多 125 个，线圈 2000 个）

### 13.7 中文/符号显示乱码

- 确认终端使用 UTF-8 编码（Windows 建议 Windows Terminal）
- 趋势图等块字符在旧版 cmd 中可能无法显示

### 13.8 机器接口相关

- `--json` 输出被日志污染：日志走 stderr、JSON 走 stdout，管道时应分别重定向（`2>/dev/null`）
- HTTP 服务 401：检查 `MBTOOL_SKILL_TOKEN` 环境变量与请求头是否一致
- REPL 无 Tab 补全：安装 readline（Windows 可装 pyreadline3）

---

## 附：功能码支持

| 功能码 | 名称 | 读写属性 | 工具支持 |
|--------|------|----------|----------|
| 1 (0x01) | Read Coils 读线圈 | 读写 | 主站/从站 |
| 2 (0x02) | Read Discrete Inputs 读离散输入 | 只读 | 主站/从站 |
| 3 (0x03) | Read Holding Registers 读保持寄存器 | 读写 | 主站/从站 |
| 4 (0x04) | Read Input Registers 读输入寄存器 | 只读 | 主站/从站 |
| 5 (0x05) | Write Single Coil 写单线圈 | 读写 | 主站/从站 |
| 6 (0x06) | Write Single Register 写单寄存器 | 读写 | 主站/从站 |
| 15 (0x0F) | Write Multiple Coils 写多线圈 | 读写 | 主站/从站 |
| 16 (0x10) | Write Multiple Registers 写多寄存器 | 读写 | 主站/从站 |
| 8 (0x08) | Diagnostics 诊断计数 | — | 从站 |
| 11 (0x0B) | Report Server ID 报告服务器 ID | — | 主站/从站 |
| 20 (0x14) | Read File Record 读文件记录 | 读写 | 从站 |
| 21 (0x15) | Write File Record 写文件记录 | 读写 | 从站 |
| 43 (0x2B) | Read Device Identification 读设备标识 | — | 主站/从站 |

## 附：数据类型速查

| 类型 `-t` | 说明 | 占用寄存器 | 值范围 |
|-----------|------|-----------|--------|
| `int16` | 有符号 16 位整数（默认） | 1 | -32768 ~ 32767 |
| `uint16` | 无符号 16 位整数 | 1 | 0 ~ 65535 |
| `int32` | 有符号 32 位整数 | 2 | -2³¹ ~ 2³¹-1 |
| `uint32` | 无符号 32 位整数 | 2 | 0 ~ 2³²-1 |
| `float` | 32 位 IEEE 754 浮点数 | 2 | ±3.4×10⁻³⁸ ~ ±3.4×10³⁸ |
| `int64` | 有符号 64 位整数 | 4 | -2⁶³ ~ 2⁶³-1 |
| `uint64` | 无符号 64 位整数 | 4 | 0 ~ 2⁶⁴-1 |
| `float64` | 64 位双精度浮点数 | 4 | ±1.8×10³⁰⁸ |
| `bcd` | 打包 BCD 码（4 位数字） | 1 | 0 ~ 9999 |
| `bcd32` | 打包 BCD 码（8 位数字） | 2 | 0 ~ 99999999 |
| `string` | ASCII 字符串（每寄存器 2 字符） | 每 2 字符 1 个 | 任意 ASCII |
| `hex` | 十六进制显示 | 1+ | 0x0000 ~ 0xFFFF |

---

*本手册示例基于 v0.4.2 实测，输出内容因寄存器当前值不同可能略有差异，功能行为保持一致。*
