Files
petwash/MODBUS_INTEGRATION.md

253 lines
6.9 KiB
Markdown
Raw Normal View History

2026-03-03 16:55:02 +08:00
# Modbus TCP 设备集成说明
## 概述
系统已集成 Modbus TCP 通信功能,用于与洗宠设备进行实时通信和控制。使用 NModbus 3.0.81 库实现,支持生产环境部署。
## 配置参数
`ConfigurationService.cs` 中配置 Modbus TCP 连接参数:
```csharp
// Modbus TCP 配置
public string ModbusIpAddress { get; set; } = "192.168.1.10"; // 设备 IP 地址
public int ModbusPort { get; set; } = 502; // Modbus TCP 端口
public byte ModbusSlaveId { get; set; } = 1; // 从站 ID
public int ModbusConnectTimeoutMs { get; set; } = 5000; // 连接超时(毫秒)
public int ModbusReadTimeoutMs { get; set; } = 3000; // 读写超时(毫秒)
```
## 功能特性
### 1. 自动连接与重连
- 系统初始化时自动连接设备
- 连接失败时自动重试
- 心跳检测每10秒确保连接稳定
- 连接断开时自动尝试重连
### 2. 连接状态监控
- `IsModbusConnected` 属性实时反映连接状态
- `ConnectionStatusChanged` 事件通知连接状态变化
- 界面显示连接状态提示
### 3. 完整的 Modbus 功能
#### 读取操作
```csharp
// 读取保持寄存器
ushort[] values = await _modbusService.ReadHoldingRegistersAsync(startAddress, count);
// 读取输入寄存器
ushort[] inputs = await _modbusService.ReadInputRegistersAsync(startAddress, count);
// 读取线圈状态
bool[] coils = await _modbusService.ReadCoilsAsync(startAddress, count);
```
#### 写入操作
```csharp
// 写入单个寄存器
await _modbusService.WriteSingleRegisterAsync(address, value);
// 写入多个寄存器
await _modbusService.WriteMultipleRegistersAsync(startAddress, values);
// 写入单个线圈
await _modbusService.WriteSingleCoilAsync(address, true);
// 写入多个线圈
await _modbusService.WriteMultipleCoilsAsync(startAddress, coilStates);
```
## 使用示例
### 在 MainViewModel 中使用
```csharp
// 1. 读取设备温度(假设温度存储在寄存器地址 100
try
{
var tempData = await _modbusService.ReadHoldingRegistersAsync(100, 1);
WaterTemperature = tempData[0] / 10.0; // 假设温度值需要除以10
}
catch (Exception ex)
{
_logger.LogError("读取温度失败", ex);
}
// 2. 控制设备门(假设门控制在线圈地址 0
try
{
await _modbusService.WriteSingleCoilAsync(0, true); // 打开门
IsDoorOpen = true;
}
catch (Exception ex)
{
_logger.LogError("控制门失败", ex);
}
// 3. 启动洗护流程(假设控制寄存器在地址 200
try
{
ushort[] controlData = new ushort[] { 1, 30 }; // 启动30分钟
await _modbusService.WriteMultipleRegistersAsync(200, controlData);
}
catch (Exception ex)
{
_logger.LogError("启动洗护失败", ex);
}
// 4. 读取液位传感器(假设在输入寄存器 300-302
try
{
var levels = await _modbusService.ReadInputRegistersAsync(300, 3);
Shampoo1Level = levels[0];
Shampoo2Level = levels[1];
Shampoo3Level = levels[2];
}
catch (Exception ex)
{
_logger.LogError("读取液位失败", ex);
}
```
## 设备地址映射示例
根据实际设备的 Modbus 地址映射表进行配置:
### 保持寄存器(读写)
| 地址 | 功能 | 数据类型 | 说明 |
|------|------|----------|------|
| 0 | 系统状态 | UINT16 | 0=待机, 1=运行, 2=故障 |
| 100 | 水温设定 | UINT16 | 单位0.1°C |
| 101 | 室温设定 | UINT16 | 单位0.1°C |
| 200 | 流程控制 | UINT16 | 0=停止, 1=启动 |
| 201 | 流程时长 | UINT16 | 单位:分钟 |
### 输入寄存器(只读)
| 地址 | 功能 | 数据类型 | 说明 |
|------|------|----------|------|
| 100 | 当前水温 | UINT16 | 单位0.1°C |
| 101 | 当前室温 | UINT16 | 单位0.1°C |
| 300 | 沐浴露1液位 | UINT16 | 0-100% |
| 301 | 沐浴露2液位 | UINT16 | 0-100% |
| 302 | 沐浴露3液位 | UINT16 | 0-100% |
### 线圈(读写)
| 地址 | 功能 | 说明 |
|------|------|------|
| 0 | 门控制 | 0=关闭, 1=打开 |
| 1 | 喷水阀 | 0=关闭, 1=打开 |
| 2 | 热风机 | 0=关闭, 1=打开 |
| 3 | 冷风机 | 0=关闭, 1=打开 |
| 4 | 紫外线灯 | 0=关闭, 1=打开 |
## 错误处理
### 连接错误
- 连接超时:检查网络连接和设备 IP 地址
- 连接被拒绝:检查设备是否启用 Modbus TCP 服务
- 设备无响应:检查从站 ID 是否正确
### 读写错误
- 非法地址:检查寄存器地址是否在设备支持范围内
- 非法数据值:检查写入的数据是否符合设备要求
- 超时:增加 `ModbusReadTimeoutMs`
## 日志记录
所有 Modbus 操作都会记录到日志系统:
```
[INFO] 正在连接 Modbus TCP 设备: 192.168.1.10:502
[INFO] Modbus TCP 连接成功: 192.168.1.10:502
[INFO] 读取保持寄存器成功: 地址=100, 数量=1
[INFO] 写入单个线圈成功: 地址=0, 值=True
[ERROR] 读取保持寄存器失败: 地址=100
[WARNING] 心跳检测: 连接已断开,尝试重连...
```
## 生产环境部署建议
### 1. 网络配置
- 确保控制端与设备在同一网络或可路由网络
- 配置静态 IP 地址避免地址变化
- 使用专用网络隔离 Modbus 通信
### 2. 超时设置
- 根据网络延迟调整超时参数
- 局域网环境:连接超时 3-5 秒,读写超时 1-3 秒
- 跨网段环境:适当增加超时时间
### 3. 错误恢复
- 启用自动重连机制(已实现)
- 监控连接状态并记录日志
- 设置告警通知管理员
### 4. 性能优化
- 批量读写操作使用 `ReadMultiple``WriteMultiple` 方法
- 避免频繁的单个寄存器读写
- 合理设置心跳检测间隔
### 5. 安全考虑
- 使用防火墙限制 Modbus TCP 端口访问
- 实施访问控制和身份验证
- 定期更新设备固件
## 测试验证
### 1. 连接测试
```csharp
// 测试基本连接
var connected = await _modbusService.ConnectAsync();
Assert.IsTrue(connected);
Assert.IsTrue(_modbusService.IsConnected);
```
### 2. 读写测试
```csharp
// 测试读取
var data = await _modbusService.ReadHoldingRegistersAsync(0, 1);
Assert.IsNotNull(data);
// 测试写入
await _modbusService.WriteSingleRegisterAsync(0, 100);
var verify = await _modbusService.ReadHoldingRegistersAsync(0, 1);
Assert.AreEqual(100, verify[0]);
```
### 3. 断线重连测试
- 断开网络连接
- 观察日志中的重连尝试
- 恢复网络连接
- 验证自动重连成功
## 故障排查
### 问题:无法连接设备
1. 检查设备 IP 和端口是否正确
2. 使用 ping 命令测试网络连通性
3. 使用 Modbus 测试工具验证设备响应
4. 检查防火墙设置
### 问题:连接频繁断开
1. 检查网络稳定性
2. 增加超时时间
3. 检查设备负载
4. 查看设备日志
### 问题:读写操作失败
1. 验证寄存器地址是否正确
2. 检查从站 ID 配置
3. 确认数据格式符合设备要求
4. 查看详细错误日志
## 技术支持
如遇到问题,请提供以下信息:
- 设备型号和固件版本
- 网络拓扑结构
- 完整的错误日志
- Modbus 地址映射表
- 问题复现步骤