Files
VX5_KRO_GearPump/doc/RFIDManager_Implementation_Plan.md
T

6.3 KiB
Raw Blame History

RFIDManager 实现方案

概述

当前项目中的RFID功能通过__RFID_CARD宏控制,该宏通过条件编译启用或禁用RFID相关代码。这种方法在可维护性、测试和运行时灵活性方面存在局限。为了解决这些问题,我们建议引入RFIDManager类,该类封装所有RFID操作,提供更清洁、更模块化的设计。

RFIDManager将处理RFID初始化、数据读取和验证,仅通过QT信号通知外部卡片检测事件,让外部组件(如InkJetPrinter)负责具体的处理逻辑,替换代码库中分散的#ifdef __RFID_CARD块。

目标

  • 封装:将RFID逻辑集中到一个类中。
  • 运行时控制:允许在运行时而不是编译时启用/禁用RFID功能。
  • 可维护性:通过移除预处理器指令简化代码。
  • 可扩展性:更容易添加新RFID功能或修改现有功能。
  • 测试:无需重新编译即可对RFID组件进行单元测试。

类设计

RFIDManager 类

class RFIDManager : public QObject {
    Q_OBJECT

public:
    RFIDManager(QObject* parent = nullptr);
    ~RFIDManager();

    // 初始化
    bool initialize();

    // 主处理循环(定期调用,例如每300ms)
    void processRFID();

    // 启用/禁用RFID功能
    void setEnabled(bool enabled);
    bool isEnabled() const;

    // 配置
    void setValidationDelay(int seconds); // 例如,5秒用于卡片稳定性
    void setSerialPort(const QString& port); // 例如,"/dev/ttyAS1"
    void setBaudRate(int baudRate); // 例如,9600

    // 数据访问
    QString getLastCardData() const;
    bool isCardPresent() const;

signals:
    // 通知外部卡片检测到
    void cardDetected(QString cardType); // cardType: 'A', 'B', 'C' 等

private:
    // 私有方法
    void readRFIDData();
    void validateCardPresence();

    // 成员变量
    bool m_enabled;
    int m_validationDelay; // 以秒为单位
    QString m_serialPort;
    int m_baudRate;
    QString m_lastCardData;
    bool m_cardPresent;
    int m_stableCount; // 验证延迟计数器
    QString m_previousCardData; // 检测卡片变化

    // 依赖项(内部注入或创建)
    DevOp* m_devOp; // 用于串口通信
};

关键方法

  • initialize():设置串口通信并初始化参数。固定串口名为"/dev/ttyAS1",比特率9600等
  • processRFID():主方法,在定时器循环中调用。读取数据、验证卡片存在,如果验证通过则发射cardDetected信号。
  • setEnabled(bool):RFID功能的运行时切换。
  • setValidationDelay(int):配置卡片验证延迟(例如,5秒)。
  • readRFIDData():与DevOp接口读取串口数据。
  • validateCardPresence():通过计数连续稳定读取实现延迟逻辑,如果延迟满足则发射信号。

集成计划

步骤1:创建RFIDManager类

  • 在项目源目录中创建RFIDManager.h和RFIDManager.cpp。
  • 按照上述大纲实现类。

步骤2:在InkJetPrinter.cpp中替换宏使用

  • 在InkJetPrinter.cpp中移除#ifdef __RFID_CARD块。
  • 将RFIDManager实例添加为成员变量。
  • 在构造函数中初始化RFIDManager,并连接信号到槽函数。
  • 在timerHandler()中,将RFID逻辑替换为调用rfidManager.processRFID()。
  • 添加槽函数(如onCardDetected(QString cardType))来处理卡片检测逻辑,包括显示对话框和更新参数。

在InkJetPrinter.cpp中的示例更改:

// 在构造函数中
rfidManager = new RFIDManager(this);
connect(rfidManager, &RFIDManager::cardDetected, this, &InkJetPrinter::onCardDetected);

// 在timerHandler中
if (rfidManager->isEnabled()) {
    rfidManager->processRFID();
}

// 新增槽函数
void InkJetPrinter::onCardDetected(QString cardType) {
    // 处理卡片逻辑:显示对话框、更新SysPara等
    if (cardType == "A") {
        // 处理墨卡
    } else if (cardType == "B") {
        // 处理维护卡
    } else if (cardType == "C") {
        // 处理其他卡
    }
}

步骤3:更新DevOp.cpp

  • 确保DevOp方法(comForRFID_init、receiveReadRFID_data)可供RFIDManager访问。
  • 可能使DevOp成为单例,或通过依赖注入将其传递给RFIDManager。

步骤4:更新SysPara.h

  • 确保RFIDPara_t可供RFIDManager访问以进行参数更新。

步骤5:配置

  • 将RFID设置添加到配置文件或UI中,允许运行时更改启用/禁用和设置延迟。

步骤6:移除宏

  • 完全集成后,从myinclude.h中移除__RFID_CARD宏并清理任何剩余的条件代码。

验证延迟实现

为了防止误操作,实现5秒延迟:

  • 跟踪具有相同卡片数据的连续读取。
  • 仅在~17次稳定读取后发射cardDetected信号(300ms * 17 ≈ 5.1秒)。
  • 如果卡片数据变化或消失,则重置计数器。
void RFIDManager::validateCardPresence() {
    QString currentData = readRFIDData();
    if (currentData == m_previousCardData && !currentData.isEmpty()) {
        m_stableCount++;
        if (m_stableCount >= (m_validationDelay * 1000) / 300) { // 假设300ms间隔
            emit cardDetected(currentData); // 发射信号,传递卡片类型
            m_stableCount = 0; // 处理后重置
        }
    } else {
        m_stableCount = 0;
    }
    m_previousCardData = currentData;
}

优势

  • 运行时灵活性:无需重新编译即可启用/禁用RFID。
  • 更清洁的代码:逻辑中无预处理器指令混乱。
  • 更好的测试:为单元测试模拟RFIDManager。
  • 模块化:更容易扩展或修改RFID功能。
  • 错误处理:RFID操作的集中错误处理。

潜在挑战

  • 依赖注入:确保DevOp和SysPara正确注入或可访问。
  • 线程安全:如果从定时器调用processRFID(),确保线程安全。
  • 向后兼容性:彻底测试以确保功能无回归。

测试计划

  • RFIDManager方法的单元测试。
  • 与InkJetPrinter的集成测试。
  • 使用实际RFID硬件的手动测试,以验证延迟和检测。

时间表

  1. 第1周:设计并实现RFIDManager类。
  2. 第2周:集成到InkJetPrinter.cpp并测试。
  3. 第3周:更新配置并移除宏。
  4. 第4周:全面测试和文档。

此方案为将RFID功能重构为更可维护和灵活的系统提供了坚实基础。