利用QtRO解决QSerialPort跨线程调用问题

news/2024/11/16 0:57:08/

目录

 

一、关于QT多线程串口通信问题

二、QtRo介绍

三、串口控制光源

3.1接口

3.2 服务端

3.3 客户端


 

一、关于QT串口跨线程使用问题

     在机器视觉项目中经常使用串口通信,如光源控制。当串口的创建和读写不在同一个线程时,qt会提示不能跨线程使用的警告,此时很有可能吞并指令或者接收不到数据的情况。有人提出了使用moveToThread+信号槽的方式使得串口的操作在同一个线程中,

https://www.zhihu.com/question/3151

最近在学习RPC通信,所以想了想是否可以通过进程间通信的方式来解决此问题。

二、QtRo介绍

Qt Remote Object简称QtRO,这是Qt5.9以后官方推出来的新模块,专门用于进程间通信(IPC)。在这之前,要实现进程间通信有多种方式,这里就不做介绍了,而Qt官方推出的这个新模块是基于Socket来封装的,使用起来非常方便,兼容LPC和RPC。LPC即Local Process Communication,而RPC是指Remote Process Communication,两者都属于IPC。QtRO能够工作于这两种不同的模式:如果用于LPC,则QtRO使用QLocalSocket;如果是用于RPC,则使用QTcpSocket。对于一个Qt开发者来说,如果项目中涉及到进程间通信,那么直接使用现成的模块进行开发, 莫过于是最好的选择,集成度高,代码量少。

 

三、串口控制光源

https://blog.csdn.net/luoyayun361/article/details/91588654

参考上述博客,自己实现了光源的控制,通过进程间通信的方式可以避免串口多线程问题。

3.1接口

首先定义接口文件 commoninterface.rep

class CommonInterface
{SIGNAL(measurePressed())SLOT(int deviceConnect())SLOT(int deviceDisconnect())SLOT(int isConnected())SLOT(void writeLight(int bottomLight, int coaxialLight))SLOT(void writeGreenLed(bool isOn))SLOT(void writeRedLed(bool isOn))
}

 

3.2 服务端

pro文件加入

QT       += remoteobjects
QT       += serialport

REPC_SOURCE  += \
    ../../Reps/commoninterface.rep
 

#ifndef VMDEVICEINTERFACE_H
#define VMDEVICEINTERFACE_H#include <QObject>#include "rep_commoninterface_source.h"
class QSerialPort;
class CommonInterface : public CommonInterfaceSource
{Q_OBJECT
public:explicit CommonInterface(QObject *parent = nullptr);public Q_SLOTS:int deviceConnect() override;int deviceDisconnect() override;int isConnected() override;void writeLight(int bottomLight, int coaxialLight) override;void writeGreenLed(bool isOn) override;void writeRedLed(bool isOn) override;signals:void sigReceiveMsg(const QString &msg);void sigSendLog(const QString &msg);private slots:void slot_ReadData();private:int write(const QString &cmd);private:QSerialPort *m_serialPort;bool m_lightResponsed = false;
};#endif // VMDEVICEINTERFACE_H
#include "VMDeviceInterface.h"
#include <QDebug>
#include <QSerialPort>CommonInterface::CommonInterface(QObject *parent):CommonInterfaceSource(parent)
{m_serialPort = new QSerialPort();connect(m_serialPort, &QSerialPort::readyRead,this, &CommonInterface::slot_ReadData);
}int CommonInterface::deviceConnect()
{m_serialPort->setPortName("COM1");m_serialPort->setBaudRate(19200);m_serialPort->setDataBits(static_cast<QSerialPort::DataBits>(8));m_serialPort->setStopBits(static_cast<QSerialPort::StopBits>(1));if(m_serialPort->open(QIODevice::ReadWrite)){emit sigSendLog("The serial port is in read/write mode");qDebug() << "The serial port is in read/write mode";return 0;}else{QString errorStr = m_serialPort->errorString();emit sigSendLog("Serial port open exception:" + errorStr);qDebug() << "Serial port open exception:" + errorStr;m_serialPort->clearError();return -1;}writeLight(50, 50);return 0;
}int CommonInterface::deviceDisconnect()
{writeLight(0, 0);m_serialPort->close();m_serialPort->deleteLater();return 0;
}int CommonInterface::isConnected()
{return m_serialPort->isOpen();
}void CommonInterface::writeLight(int bottomLight, int coaxialLight)
{QString cmd;cmd.append("42");cmd.append(QString("%1").arg(coaxialLight, 2, 16, QChar('0')));cmd.append("00");cmd.append("00");cmd.append(QString("%1").arg(bottomLight, 2, 16, QChar('0')));cmd.append("45");cmd.append("2a");write(cmd);
}void CommonInterface::writeGreenLed(bool isOn)
{QString cmd = (isOn == true) ?  QString("B201") : QString("B200");write(cmd);
}void CommonInterface::writeRedLed(bool isOn)
{QString cmd = (isOn == true) ? QString("B101") : QString("B100");write(cmd);
}void CommonInterface::slot_ReadData()
{const QByteArray info = m_serialPort->readAll();emit sigSendLog("readyRead:" + info.toHex());qDebug() << "readyRead:" + info.toHex();if("26" == info.toHex()){emit measurePressed();}if("4f4b" == info.toHex()){m_lightResponsed = true;}
}int CommonInterface::write(const QString &cmd)
{if(!m_serialPort->isOpen()){emit sigSendLog("Failed to send, the serial port is not open");
//        qCritical() << "Failed to send, the serial port is not open";return -1;}emit sigSendLog("cmd: " + cmd);
//    qDebug() << "cmd: " + cmd;QByteArray cmdByteArray = QByteArray::fromHex(cmd.toUtf8());int len = m_serialPort->write(cmdByteArray);emit sigSendLog("write length: " + QString::number(len));
//    if(!m_serialPort->waitForBytesWritten(3 * 1000))
//    {
//        QString errorStr = m_serialPort->errorString();
//        emit sigSendLog("Command sending exception:" + errorStr);
//        qCritical() << "Command sending exception:" + errorStr;
//        m_serialPort->clearError();
//        return -1;
//    }return 0;
}

ui界面

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>namespace Ui
{class MainWindow;
}
class CommonInterface;
class QRemoteObjectHost;
class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();private slots:void on_pushButton_clicked();private:Ui::MainWindow *ui;CommonInterface *m_pInterface = nullptr;QRemoteObjectHost *m_pHost = nullptr;
};#endif // MAINWINDOW_H
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QDebug>
#include "VMDeviceInterface.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);m_pHost = new QRemoteObjectHost(this);m_pHost->setHostUrl(QUrl("local:interfaces"));m_pInterface = new CommonInterface(this);m_pHost->enableRemoting(m_pInterface);connect(m_pInterface, &CommonInterface::sigSendLog, this,[ = ](const QString & msg){ui->textEdit->append(msg);});m_pInterface->deviceConnect();
}MainWindow::~MainWindow()
{m_pInterface->deviceDisconnect();delete ui;
}void MainWindow::on_pushButton_clicked()
{}

3.3 客户端

pro文件加入

QT       += remoteobjects
QT       += concurrent

REPC_REPLICA   += \
    ../../Reps/commoninterface.rep
 

UI界面

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE
namespace Ui
{class MainWindow;
}
QT_END_NAMESPACEclass QRemoteObjectNode;
class CommonInterfaceReplica;class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_bSlider_sliderReleased();void on_cSlider_sliderReleased();void on_btnThreadSend_clicked();void on_btnL1_clicked();void on_btnL2_clicked();void on_btnL3_clicked();void on_btnSend_clicked();private:Ui::MainWindow *ui;QRemoteObjectNode      *m_pRemoteNode = nullptr;CommonInterfaceReplica *m_pInterface  = nullptr;
};
#endif // MAINWINDOW_H
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QDebug>
#include <QtConcurrent>#include "rep_CommonInterface_replica.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);ui->textEdit->append(QString("..."));m_pRemoteNode = new QRemoteObjectNode(this);bool b = m_pRemoteNode->connectToNode(QUrl("local:interfaces"));if(b){ui->textEdit->append(QString("connect true"));}else{ui->textEdit->append(QString("connect flase"));}m_pInterface = m_pRemoteNode->acquire<CommonInterfaceReplica>();connect(m_pInterface, &CommonInterfaceReplica::measurePressed,this, [ = ](){ui->textEdit->append(QString("measurePressed"));});
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_bSlider_sliderReleased()
{ui->textEdit->append(tr("%1,%2").arg(ui->bSlider->value()).arg( ui->cSlider->value()));m_pInterface->writeLight(ui->bSlider->value(),ui->cSlider->value());
}void MainWindow::on_cSlider_sliderReleased()
{ui->textEdit->append(tr("%1,%2").arg(ui->bSlider->value()).arg( ui->cSlider->value()));m_pInterface->writeLight(ui->bSlider->value(),ui->cSlider->value());
}void Delay_MSec(unsigned int msec)
{QEventLoop loop;QTimer::singleShot(msec, &loop, SLOT(quit()));loop.exec();
}void MainWindow::on_btnThreadSend_clicked()
{auto runFun = [ = ](){int ms = ui->spinBox->value();m_pInterface->writeLight(1, 200);Delay_MSec(ms);m_pInterface->writeLight(200, 1);Delay_MSec(ms);m_pInterface->writeLight(50, 50);};
//    std::thread thread(runFun);QtConcurrent::run(runFun);
}void MainWindow::on_btnL1_clicked()
{m_pInterface->writeLight(1, 200);
}void MainWindow::on_btnL2_clicked()
{m_pInterface->writeLight(200, 1);
}void MainWindow::on_btnL3_clicked()
{m_pInterface->writeLight(50, 50);
}void MainWindow::on_btnSend_clicked()
{int ms = ui->spinBox->value();m_pInterface->writeLight(1, 200);Delay_MSec(ms);m_pInterface->writeLight(200, 1);Delay_MSec(ms);m_pInterface->writeLight(50, 50);
}

 

 


http://www.ppmy.cn/news/696627.html

相关文章

Cetos7.x连接不上网络解决办法

Cetos7.x连接不上网络解决办法 Cetos7.x连接不上网络解决办法 在VM中设置网络连接为桥接&#xff0c;修改后仍无法连接网络 ##配置centos7中ens33&#xff0c;将默认的no修改为yes 启动CentOS系统&#xff0c;并打开一个连接终端会话&#xff0c;使用root登录&#xff1b;进…

RTMB实现视屏直播

最近一段时间&#xff0c;视频直播可谓大火。在视频直播领域&#xff0c;有不同的商家提供各种的商业解决方案&#xff0c;包括软硬件设备&#xff0c;摄像机&#xff0c;编码器&#xff0c;流媒体服务器等。本文要讲解的是如何使用一系列免费工具&#xff0c;打造一套视频直播…

《视频直播技术详解》系列:(6)编码和封装

原文来自七牛云&#xff0c;感谢原作者。 《视频直播技术详解》系列&#xff1a;&#xff08;0&#xff09;汇总 视频编码是本系列一个重要的部分&#xff0c;如果把整个流媒体比喻成一个物流系统&#xff0c;那么编解码就是其中配货和装货的过程&#xff0c;这个过程非常重要…

极客日报:人人影视字幕组因侵权被查;GitHub 评论区支持上传视频;

一、互联网快讯 1、用户起诉腾讯&#xff0c;深圳南山法院一审判决认定&#xff1a;微信好友关系不属于个人隐私 2 月 3 日消息&#xff0c;1 月 22 日&#xff0c;深圳市南山区人民法院在审理一起用户起诉腾讯的侵权责任纠纷案时作出判决&#xff0c;明确微信好友关系不属于个…

视频直播技术详解(3)编码和封装

声明&#xff1a;本文为CSDN原创投稿文章&#xff0c;未经许可&#xff0c;禁止任何形式的转载。 作者&#xff1a;七牛云 责编&#xff1a;钱曙光&#xff0c;关注架构和算法领域&#xff0c;寻求报道或者投稿请发邮件qianshgcsdn.net&#xff0c;另有「CSDN 高级架构师群」…

Android视频直播的实现

转自&#xff1a;http://blog.csdn.net/huaxun66/article/details/53427771 最近一段时间&#xff0c;视频直播可谓大火。在视频直播领域&#xff0c;有不同的商家提供各种的商业解决方案&#xff0c;包括软硬件设备&#xff0c;摄像机&#xff0c;编码器&#xff0c;流媒体服务…

视频直播技术详解之编码和封装

七牛云于6月底发布了一个针对视频直播的实时流网络LiveNet和完整的直播云解决方案&#xff0c;很多开发者对这个网络和解决方案的细节和使用场景非常感兴趣。 结合该实时流网络LiveNet和直播云解决方案的实践&#xff0c;我们将用七篇文章&#xff0c;更系统化地介绍当下大热的…

移动端实时音视频详解(三):编码和封装

移动端实时音视频详解&#xff08;三&#xff09;&#xff1a;编码和封装 视频编码是本系列一个重要的部分&#xff0c;如果把整个流媒体比喻成一个物流系统&#xff0c;那么编解码就是其中配货和装货的过程&#xff0c;这个过程非常重要&#xff0c;它的速度和压缩比对物流系…