基于Qt的上位机通讯库

1.前言

做Qt上位机已经有两年的时间了,上位机主要是和下游器件打交道的,通过modbus、tcp、串口等协议来控制这些设备,通过一定的时序控制,完成所需要的工作流程。这其中最重要的就是通讯了,上位机开发过程中的相当一部分问题都是通讯问题导致的。如何总结、抽象出一套稳定的通讯逻辑,在上位机开发中尤为重要。

2.几种通讯类型

这里参考zmq的几种通讯场景,分别是Requester/ResponderPublisher/Subscriber ,还有最常用的modbus协议。通过将制定统一的通讯接口,实现了基于串口、网口的两种通讯具体实现,基本可以满足大部分的上位机通讯场合。

2.1.Requester/Responder 模式

Requester/Responder 模式

适用场景

  • 客户端与服务端之间的点对点通信。
  • 操作需要明确的响应,例如 设备控制、查询状态。
  1. Requester
  • 负责发起请求,等待响应。
  • 需要定义请求的超时和重试机制。
  • 支持不同底层协议(如TCP、UDP、Serial)
cpp 复制代码
class BaseRequester : public BaseCommunication
{
    Q_OBJECT
public:
    explicit BaseRequester(QObject *parent = nullptr);

public:
    virtual QByteArray request(QByteArray data);

    virtual bool requestNoReply(QByteArray data);

public slots:
};
  1. Responder
  • 负责接收请求并返回响应。
  • 需要支持请求解析和响应生成逻辑。
cpp 复制代码
class BaseResponder : public BaseCommunication
{
    Q_OBJECT
public:
    explicit BaseResponder(QObject *parent = nullptr);

signals:
    void onRequest(QByteArray data);

public:
    virtual void response(QByteArray data);

public slots:
};

2.2.Publisher/Subscriber 模式

适用场景

  • 多对多的消息分发,例如 日志广播、实时监控、状态推送。
  • 数据流量较大,不需要逐条确认的场景。
  1. Publisher
  • 负责发布消息给多个订阅者。
  • 支持主题或频道的概念,用于区分消息类别。
cpp 复制代码
class BasePublisher : public BaseCommunication
{
    Q_OBJECT
public:
    explicit BasePublisher(QObject *parent = nullptr);

    virtual bool publish(QByteArray data);

signals:

public slots:
};
  1. Subscriber
  • 负责接收感兴趣的消息。
  • 支持动态订阅和取消订阅。
cpp 复制代码
class BaseSubscriber : public BaseCommunication
{
    Q_OBJECT
public:
    explicit BaseSubscriber(QObject *parent = nullptr);

signals:
    void receive(QByteArray msg);

public slots:
};

2.3.Modbus

cpp 复制代码
class BaseModbus : public BaseCommunication
{
    Q_OBJECT
public:
    Q_INVOKABLE  explicit BaseModbus(QObject *parent = nullptr);
    ~BaseModbus();

    QList<uint16_t> readRegisters(int addr,int count);
    uint16_t readRegister(int addr);

    QList<uint16_t> readInputRegisters(int addr,int count);
    uint16_t readInputRegister(int addr);

    bool writeRegisters(int addr, int count, QList<uint16_t> inputList);
    bool writeRegister(int addr, uint16_t inputList);

    QList<bool> readBits(int addr,int count);
    bool readBit(int addr);

    QList<bool> readInputBits(int addr,int count);
    bool readInputBit(int addr);

    bool writeBits(int addr, int count, QList<bool> coilStates);
    bool writeBit(int addr, bool coilState);

signals:

public slots:

    // BaseCommunicationZZZ interface
public:
    virtual bool connectToHost() override;
    virtual bool isConnected() override;
    virtual bool disConnect() override;

public:
    template<typename T>
    static void pointToList(T *source,int size, QList<T> &target)
    {
        for (int i = 0; i < size; i++)
        {
            target.append(source[i]); // 逐个添加元素到 QList 中
        }
    }

private:
    QMutex  _mutex;   //可以是私有成员变量,也可以是全局变量

protected:
    modbus_t *m_ctx;
};

3.类结构图

4.项目地址

https://gitee.com/zhang_jie_sc/ucc_communication

使用指南

基于Qt5.9.4+visuaostudio2015 32bit开发

demo共分为modbus、publisher、subscriber、responder、requester几种模式。

相关推荐
用户805533698033 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner4 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz8 天前
QML Hello World 入门示例
qt
xcyxiner12 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner12 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner12 天前
DicomViewer (添加模型类)3
qt
xcyxiner13 天前
DicomViewer (目录调整) 2
qt
xcyxiner13 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00615 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术15 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript