通讯遇到的问题
熔炉项目
问题现象
- 炉子2能正常显示"倾炉中",但炉子1超时时,前端没有显示"连接断开"
- 日志显示有错误信息,但前端状态没变
问题根源
错误消息中缺少从站号!
text
❌ 之前发射的信号:
emit error(name, "读取失败: " + errorStr);
→ 结果: "读取失败: Request timeout."
→ 没有从站号,FurnaceController不知道是哪个炉子出错
为什么炉子2能显示?
炉子2是通过 coilsRead 信号更新的,这个信号包含从站号:
cpp
emit coilsRead(name, slaveId, startAddress, values); // ✓ 有slaveId
为什么炉子1不能显示?
错误信号 error 没有从站号:
cpp
emit error(name, "读取失败: " + errorStr); // ✗ 没有slaveId
解决方案
在错误消息中加入从站号:
cpp
QString fullErrorMsg = QString("读取失败: %1 (从站地址:%2)")
.arg(errorStr).arg(slaveId);
emit error(name, fullErrorMsg); // ✓ 现在有slaveId了
问题总结:Modbus通信与状态显示问题排查全过程
一、核心问题
炉子2能正常显示"倾炉中",但炉子1超时时,前端没有显示"连接断开"
二、排查过程
1️⃣ 第一阶段:发现日志问题
从日志看到:
text
IP[ "127.0.0.1" ] 读取失败: "Request timeout." 从站地址: 1 起始地址: 0
但前端没反应 → 说明C++收到错误,但没传到前端
2️⃣ 第二阶段:定位信号问题
发现错误信号发射有问题:
cpp
// ❌ 错误:信号中没有从站号
emit error(name, "读取失败: " + errorStr);
// 结果: "读取失败: Request timeout."
// ✅ 正确:信号中要包含从站号
QString fullErrorMsg = QString("读取失败: %1 (从站地址:%2)")
.arg(errorStr).arg(slaveId);
emit error(name, fullErrorMsg);
3️⃣ 第三阶段:发现重复调用问题
cpp
void startMonitoring() {
// ❌ 每次调用都创建新定时器、新连接
QTimer* timer = new QTimer(this); // 多个定时器!
connect(...); // 多个信号连接!
}
4️⃣ 第四阶段:添加保护机制
cpp
// ✅ 防止重复启动
static bool signalsConnected = false;
if (!signalsConnected) {
connect(...); // 只连接一次
signalsConnected = true;
}
// ✅ 保存定时器指针,避免重复创建
if (m_readTimer) {
m_readTimer->stop();
delete m_readTimer;
}
5️⃣ 第五阶段:解决误判问题
cpp
// ✅ 错误计数,避免网络抖动误判
if (f.errorCount >= 10) { // 连续10次错误才判定断开
f.status = "连接断开";
}
6️⃣ 第六阶段:添加心跳检测
cpp
// ✅ 监控定时器健康状态
connect(m_heartbeatTimer, &QTimer::timeout, [this]() {
if (!m_readTimer->isActive()) {
restartReadTimer(); // 定时器意外关闭时自动重启
}
});
三、最终解决方案
| 问题 | 解决方案 |
|---|---|
| 错误消息缺少从站号 | 在错误信号中加入从站号和起始地址 |
| 重复调用startMonitoring | 添加m_monitoringStarted标志位 |
| 多个定时器同时运行 | 用成员变量保存定时器指针 |
| 多个信号连接 | 用static标志位控制只连接一次 |
| 网络抖动误判 | 错误计数+时间窗口(10次/30秒) |
| 定时器意外关闭 | 心跳检测机制,自动重启 |
| 状态显示不匹配 | QML中添加disconnected状态处理 |
四、关键教训
- 信号要带足够信息:错误信号必须包含从站号
- 防止重复初始化:检查是否已启动
- 资源管理:用成员变量保存指针,避免内存泄漏
- 容错处理:错误计数、心跳检测
- 前后端一致:C++发的状态名要和QML匹配
五、最终效果
text
正常情况:
炉子2 → 收到数据 → 状态"倾炉中" → 绿色
异常情况:
炉子1 → 超时 → 错误计数+1 → 计数≥10 → 状态"连接断开" → 红色
↓
定时器意外关闭 → 心跳检测 → 自动重启 → 恢复正常
系统现在更加稳定、可靠,能准确显示每个炉子的真实状态! 🚀

浙公网安备 33010602011771号