|
- #pragma once
-
- #include "services/plc_discovery_gateway.h"
-
- #include <QModbusDevice>
- #include <QObject>
- #include <QPointer>
-
- #include <cstddef>
- #include <cstdint>
- #include <functional>
- #include <memory>
- #include <vector>
-
- class QModbusReply;
- class QModbusRtuSerialMaster;
-
- // 使用独立 Qt Modbus RTU 主站逐项探测串口参数,不污染正式 PLC 连接状态
- class PlcDiscoveryService final : public QObject, public PlcDiscoveryGateway
- {
- public:
- /**
- * @brief 创建独立的 PLC 自动搜索服务
- * @param parent Qt 父对象
- */
- explicit PlcDiscoveryService(QObject *parent = nullptr);
- ~PlcDiscoveryService() override;
-
- /**
- * @brief 枚举串口和候选参数,并异步逐项探测 PLC
- * @param preferred 优先尝试的串口参数
- * @return 搜索启动结果,最终搜索结果通过回调返回
- */
- PlcCommunicationResult startDiscovery(
- const PlcSerialConfiguration &preferred) override;
- // 取消当前自动搜索并释放探测串口
- void cancelDiscovery() override;
- // 返回当前是否正在自动搜索
- bool isDiscovering() const override;
- /**
- * @brief 设置搜索进度和最终结果回调
- * @param progress_changed 每次候选参数或进度变化时调用
- * @param discovery_finished 搜索结束、取消或失败时调用
- */
- void setCallbacks(
- std::function<void(const PlcDiscoveryProgress &)> progress_changed,
- std::function<void(const PlcDiscoveryOutcome &)> discovery_finished) override;
-
- private:
- enum class Phase
- {
- Idle, // 等待尝试候选参数
- Connecting, // 正在异步打开候选串口
- Probing, // 已打开串口,正在读取 D0
- Disconnecting // 正在释放当前候选串口
- };
-
- // 尝试当前候选参数并等待串口异步打开
- void tryCurrentCandidate();
- // 串口打开后发送只读 D0 探测请求
- void sendProbe();
- /**
- * @brief 处理当前 D0 探测结果
- * @param reply 当前候选串口的异步 Modbus 回复
- * @param attempt_generation 发起请求时的尝试代次,用于丢弃过期回复
- */
- void handleProbeFinished(QModbusReply *reply, std::uint64_t attempt_generation);
- /**
- * @brief 释放当前串口,释放完成后进入下一个候选或报告结果
- * @param found 当前候选参数是否已经探测到 PLC
- */
- void disconnectCurrent(bool found);
- // 当前串口完全释放后完成状态迁移
- void continueAfterDisconnect();
- /**
- * @brief 报告最终结果并清理搜索状态
- * @param outcome 要交给调用方的最终搜索结果
- */
- void finishDiscovery(const PlcDiscoveryOutcome &outcome);
- /**
- * @brief 处理 Qt Modbus 主站连接状态变化
- * @param state Qt Modbus 主站的新连接状态
- */
- void handleDeviceStateChanged(QModbusDevice::State state);
-
- std::unique_ptr<QModbusRtuSerialMaster> master_; // 独立的探测主站对象
- std::vector<PlcSerialConfiguration> candidates_; // 待依次尝试的串口参数
- std::size_t current_candidate_ = 0; // 当前候选参数下标
- QPointer<QModbusReply> pending_reply_; // 当前未完成的 D0 探测回复
- Phase phase_ = Phase::Idle; // 当前搜索阶段
- bool discovering_ = false; // 是否正在执行搜索
- bool cancel_requested_ = false; // 是否已收到取消请求
- bool found_pending_ = false; // 当前候选是否探测到 PLC
- std::uint64_t attempt_generation_ = 0; // 尝试代次,用于丢弃旧异步回复
- std::function<void(const PlcDiscoveryProgress &)> progress_changed_callback_; // 搜索进度回调
- std::function<void(const PlcDiscoveryOutcome &)> discovery_finished_callback_; // 搜索结束回调
- };
|