Metadata-Version: 2.4
Name: mbtoolcli
Version: 0.3.1
Summary: A comprehensive Modbus Master/Slave testing tool supporting TCP, RTU, and ASCII protocols
Author: Modbus Tool Contributors
License: MIT
Project-URL: Homepage, https://github.com/yourusername/modbus-tool
Project-URL: Documentation, https://github.com/yourusername/modbus-tool#readme
Project-URL: Repository, https://github.com/yourusername/modbus-tool
Project-URL: Issues, https://github.com/yourusername/modbus-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.8
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.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pymodbus<4.0.0,>=3.0.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"
Dynamic: license-file

# Modbus Tool 操作手册

## 概述

Modbus Tool 是一款综合性的 **Modbus 主站/从站调试工具**，支持 **TCP**、**RTU** 和 **ASCII** 三种协议。它将 **modpoll**（主站）和 **diagslave**（从站）的功能合二为一，提供命令行式的工业通信调试体验。

### 主要功能

- **主站模式**：读写线圈、离散输入、保持寄存器和输入寄存器
- **从站模式**：模拟 Modbus 从站设备，支持动态仿真
- **扫描模式**：自动发现网络中活动的从站设备
- **实时轮询**：周期性读取寄存器值，支持阈值告警和 CSV 导出
- **多种数据类型**：int16、uint16、int32、uint32、float32、hex
- **灵活的字节序**：同时支持大端序、小端序、字交换等工业变体
- **原始帧调试**：输出 Modbus 协议层的原始收发帧
- **彩色终端输出**：关键字高亮，减少视觉疲劳

---

## 安装

### 从源码安装

```bash
git clone https://github.com/yourusername/modbus-tool.git
cd modbus-tool
pip install -e .
```

### 构建单文件可执行文件

```bash
pip install pyinstaller
pyinstaller --onefile --name mbtool src/modbus_slave_sim/cli.py
```

编译后在 `dist/` 目录下生成 `mbtool`（或 `mbtool.exe`）。

---

## 命令参考

### 模式选择（三选一，必填）

| 选项 | 说明 |
|------|------|
| `--master` | 主站模式：读写 Modbus 从站设备 |
| `--slave` | 从站模式：模拟一个 Modbus 从站设备 |
| `--scan` | 扫描模式：探测网络中活动的从站 ID（1-247） |

### 连接选项

| 选项 | 说明 | 默认值 |
|------|------|--------|
| `-m`, `--mode` | 协议：`tcp`、`rtu`、`ascii` | `tcp` |
| `-H`, `--host` | TCP 目标主机地址 | `127.0.0.1` |
| `-p`, `--port` | TCP 端口或串口路径（如 COM3、/dev/ttyUSB0） | `502` |
| `-a`, `--address` | 从站 ID（单个如 `1`，或多 ID `1,2,3`） | `1` |
| `--timeout` | 通信超时（秒） | `3.0` |

### 串口选项（RTU/ASCII 模式）

| 选项 | 说明 | 默认值 |
|------|------|--------|
| `-b`, `--baudrate` | 波特率 | `9600` |
| `--parity` | 校验位：`N`=无, `E`=偶, `O`=奇 | `N` |
| `--stopbits` | 停止位：`1` 或 `2` | `1` |
| `--bytesize` | 数据位：`7` 或 `8` | `8` |
| `--inter-char-delay` | 字符间延迟（秒，RTU 调优用） | 无 |

### 主站读选项

| 选项 | 说明 | 默认值 |
|------|------|--------|
| `-r`, `--register` | 起始寄存器/线圈地址 | `0` |
| `-c`, `--count` | 读取数量 | `1` |
| `-t`, `--type` | 数据类型：`int16`, `uint16`, `int32`, `uint32`, `float`, `hex` | `int16` |
| `-f`, `--function` | 功能码：`1`(线圈), `2`(离散输入), `3`(保持寄存器), `4`(输入寄存器) | `3` |
| `--hex` | 同时显示十六进制值 | 关闭 |
| `--byte-order` | 32 位类型字节序：`ABCD`, `CDBA`, `BADC`, `DCBA` | `ABCD` |

### 主站写选项

| 选项 | 说明 |
|------|------|
| `--write` | 写寄存器模式（配合 `-v`） |
| `--write-coil` | 写线圈模式（配合 `--coil-value`） |
| `--coil-value {0,1}` | 线圈值：0=OFF, 1=ON |
| `-v`, `--value` | 写入值，多个值用逗号分隔实现批量写入 |

### 轮询选项

| 选项 | 说明 | 默认值 |
|------|------|--------|
| `--poll` | 连续轮询模式 | 关闭 |
| `-i`, `--interval` | 轮询间隔（秒） | `1.0` |
| `-n`, `--iterations` | 轮询次数（`0`=无限） | `0` |
| `--alarm` | 告警表达式：`ADDR>VALUE`，如 `"0>100"` | 无 |
| `-o`, `--output` | 导出结果到 CSV 文件 | 无 |

### 从站选项

| 选项 | 说明 | 默认值 |
|------|------|--------|
| `--register-map` | 从 JSON 文件加载自定义寄存器映射 | 无 |
| `--simulate` | 启用动态值仿真 | 关闭 |
| `--sim-interval` | 仿真更新间隔（秒） | `0.1` |
| `--status` | 显示寄存器状态后退出（仅从站模式） | 关闭 |

### 调试选项

| 选项 | 说明 |
|------|------|
| `-V`, `--verbose` | 启用详细日志输出 |
| `--debug-frame` | 启用 Modbus 原始帧日志 |

---

## 功能码说明

| 功能码 | 名称 | 读写属性 | 数据类型 |
|--------|------|----------|----------|
| 1 | Read Coils（读线圈） | 读写 | 布尔值（0/1） |
| 2 | Read Discrete Inputs（读离散输入） | 只读 | 布尔值（0/1） |
| 3 | Read Holding Registers（读保持寄存器） | 读写 | 16 位值 |
| 4 | Read Input Registers（读输入寄存器） | 只读 | 16 位值 |

## 数据类型

| 类型 | 说明 | 占用寄存器 | 值范围 |
|------|------|-----------|--------|
| `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³⁸ |
| `hex` | 十六进制显示 | 1+ | 0x0000 ~ 0xFFFF |

### modpoll 兼容的类型字符串

```bash
# 3:int 或 3:int32 表示 32 位有符号整数
# 4:float 表示 32 位浮点数
# uint16 或 u16 表示无符号 16 位整数
mbtool --master -a 1 -r 0 -c 4 -t "3:int32"
```

## 字节序说明

对于 32 位数据类型（int32、uint32、float），数据在 2 个寄存器中排列方式可能有多种。默认为标准大端序（ABCD），可通过 `--byte-order` 切换：

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

---

## 操作示例

### 主站模式

#### 基本读取

```bash
# 读取 10 个保持寄存器（FC03）
mbtool --master -a 1 -r 0 -c 10

# 读线圈（FC01）
mbtool --master -f 1 -a 1 -r 0 -c 8

# 读离散输入（FC02）
mbtool --master -f 2 -a 1 -r 0 -c 8

# 读输入寄存器（FC04）
mbtool --master -f 4 -a 1 -r 0 -c 5 -t float

# 以十六进制格式读取并显示
mbtool --master -a 1 -r 0 -c 10 -t hex --hex
```

#### 写入

```bash
# 写单个寄存器
mbtool --master --write -a 1 -r 0 -v 100

# 写浮点数到 2 个寄存器
mbtool --master --write -t float -a 1 -r 0 -v 3.14

# 批量写入：从地址 0 开始写入 3 个值
mbtool --master --write -a 1 -r 0 -v "100,200,300"

# 写线圈（FC05）
mbtool --master --write-coil -a 1 -r 0 --coil-value 1

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

#### 连续轮询

```bash
# 每 2 秒轮询一次，无限循环
mbtool --master --poll -a 1 -r 0 -c 5 -i 2

# 轮询 10 次后停止
mbtool --master --poll -a 1 -r 0 -c 10 -i 1 -n 10

# 带阈值告警：寄存器[0] > 1000 时红色高亮
mbtool --master --poll -a 1 -r 0 -c 5 -t int16 -i 1 --alarm "0>1000"

# 轮询结果导出到 CSV 文件
mbtool --master --poll -a 1 -r 0 -c 5 -i 1 -o data.csv

# 轮询 + 告警 + CSV 导出 + 十六进制显示
mbtool --master --poll -a 1 -r 0 -c 10 -i 2 --hex --output log.csv --alarm "0>500"
```

#### 字节序示例

```bash
# 以 CDBA（字交换）读浮点数
mbtool --master -a 1 -r 0 -c 4 -t float --byte-order CDBA

# 以小端序读 32 位整数
mbtool --master -a 1 -r 0 -c 4 -t int32 --byte-order DCBA
```

#### 原始帧调试

```bash
mbtool --master -a 1 -r 0 -c 10 --debug-frame
```

输出中会包含 Modbus 协议层的收发原始数据，用于排查通信问题。

### 扫描模式

扫描从站 ID 1~247，发现网络中活动的设备：

```bash
# TCP 扫描
mbtool --scan -H 192.168.1.100 -p 502

# RTU 串口扫描
mbtool --scan -m rtu -p COM3 -b 9600
```

### 从站模式

#### TCP 从站

```bash
# 默认端口 502 启动 TCP 从站
mbtool --slave

# 指定端口和从站 ID
mbtool --slave -p 5020 -a 1

# 启用动态仿真
mbtool --slave --simulate
```

#### RTU/ASCII 从站

```bash
# RTU 从站
mbtool --slave -m rtu -p COM3 -b 19200 --parity E

# ASCII 从站
mbtool --slave -m ascii -p COM3 -b 9600
```

#### 自定义寄存器映射

从 JSON 文件加载自定义寄存器定义：

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

JSON 文件格式：

```json
{
  "coils": [
    {"address": 0, "value": false, "description": "电机启动"},
    {"address": 1, "value": true, "description": "电机运行"}
  ],
  "holding_registers": [
    {"address": 0, "value": 100, "description": "温度设定值"},
    {"address": 1, "value": 200, "description": "压力上限"}
  ],
  "input_registers": [
    {"address": 0, "value": 25, "description": "当前温度"},
    {"address": 1, "value": 180, "description": "当前压力"},
    {"address": 2, "value": 80, "description": "液位百分比"},
    {"address": 3, "value": 1500, "description": "转速"},
    {"address": 4, "value": 0, "description": "报警代码"}
  ],
  "discrete_inputs": [
    {"address": 0, "value": false, "description": "门开状态"},
    {"address": 1, "value": true, "description": "急停未按下"}
  ]
}
```

#### 查看寄存器状态

```bash
# 查看默认寄存器状态
mbtool --slave --status

# 查看自定义寄存器映射状态
mbtool --slave --register-map my_device.json --status
```

---

## 彩色输出说明

终端输出使用不同颜色标识不同类型的信息，减少视觉疲劳：

| 颜色 | 用途 |
|------|------|
| **青色粗体** | 标题、参数值、边框 |
| **绿色粗体** | 成功信息（已连接、写入成功、ON） |
| **红色粗体** | 错误信息、告警、OFF 状态 |
| **黄色** | 操作描述文字 |
| **品红色** | 寄存器地址索引 `[N]` |
| **白色粗体** | 标签文字（Protocol、Address 等） |
| **暗灰色** | 次要信息、描述文字 |

---

## CSV 导出格式

使用 `--output` 或 `-o` 参数导出的 CSV 文件格式：

**读操作导出**：两列
```
address,value
0,100
1,200
2,300
```

**轮询导出**：三列（每轮询周期追加行）
```
iteration,address,value
1,0,100
1,1,200
2,0,105
2,1,205
```

---

## 故障排除

### 端口 502 被占用

在 Linux 上 1024 以下端口需要 root 权限：

```bash
sudo mbtool --slave -p 502
```

或使用更高端口：

```bash
mbtool --slave -p 5020
```

### 串口权限（Linux）

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

### 连接被拒绝

确保从站服务器已启动，端口正确，并检查防火墙设置。

### 读取到错误值

如果多寄存器类型（int32、float）读取到的值异常，可能是字节序不匹配。尝试不同的 `--byte-order` 选项：

```bash
# 尝试不同的字节序
mbtool --master -a 1 -r 0 -c 2 -t float --byte-order ABCD
mbtool --master -a 1 -r 0 -c 2 -t float --byte-order CDBA
mbtool --master -a 1 -r 0 -c 2 -t float --byte-order BADC
mbtool --master -a 1 -r 0 -c 2 -t float --byte-order DCBA
```

---

## 项目结构

```
modbus-tool/
├── pyproject.toml                # 项目配置
├── README.md                     # 本文件
├── src/
│   └── modbus_slave_sim/
│       ├── __init__.py           # 包初始化
│       ├── cli.py                # 命令行界面
│       ├── colors.py             # ANSI 颜色工具
│       ├── datatypes.py          # 数据类型与字节序转换
│       ├── master.py             # Modbus 主站客户端
│       ├── registers.py          # 寄存器数据结构
│       ├── simulation.py         # 仿真引擎
│       ├── tcp_server.py         # Modbus TCP 从站服务器
│       └── rtu_server.py         # Modbus 串口从站服务器（RTU/ASCII）
└── tests/
    └── ...
```

---

## 开发

```bash
# 安装开发依赖
pip install -e ".[dev]"

# 运行测试
pytest
```

## 许可证

MIT License
