#ifndef MSGQUEUE_H
#define MSGQUEUE_H
#include <QObject>
#include <mqueue.h>
#include <thread>
#include <QSharedPointer>
#include <QMutex>
#include <QVariantMap>
class MsgQueue : public QObject
{
Q_OBJECT
public:
explicit MsgQueue(QObject *parent = nullptr);
~MsgQueue();
// 获取通信对象
static MsgQueue *getInstance();
// 下发消息到消息进程
void pushCmdToSlave(QJsonObject jsObj);
// 获取消息进程响应消息
QVariantMap getReceiveCmd();
// 将来自界面的数据存储到发送列表中
Q_INVOKABLE void appendModuleData(const QVariantMap& vMap);
signals:
void sig_recvCmd(QVariantMap vMap);
private:
// 初始化消息队列
void initMsgQueue();
// 发送数据
void sendData();
// 接收数据
void recvData();
private:
mqd_t msg_qt_to_com{-1}; // qt_to_com消息队列描述符
mqd_t msg_com_to_qt{-1}; // com_to_qt消息队列描述符
QSharedPointer<std::thread> m_sendThread{nullptr};
QSharedPointer<std::thread> m_recvThread{nullptr};
QList<QVariantMap> m_sendList;
QMutex m_sendMutex;
};
#endif // MSGQUEUE_H
#include "msgqueue.h"
#include <QScopedPointer>
#include <QJsonDocument>
#include <QJsonObject>
#include <QThread>
#include <QDebug>
#define COMM_UIB_QT_TO_COM_NAME "/posix_msg_qt_to_com" // qt to communication
#define COMM_UIB_COM_TO_QT_NAME "/posix_msg_com_to_qt" // communication to qt
static bool flag = true;
MsgQueue::MsgQueue(QObject *parent)
: QObject{parent}
{
m_sendList.clear();
initMsgQueue();
m_recvThread = QSharedPointer<std::thread>(new std::thread(&MsgQueue::recvData, this));
}
MsgQueue::~MsgQueue()
{
flag = false;
if (!m_sendThread.isNull()) {
if (m_sendThread->joinable()) {
m_sendThread->join();
}
}
if (!m_recvThread.isNull()) {
if (m_recvThread->joinable()) {
m_recvThread->join();
}
}
}
MsgQueue *MsgQueue::getInstance()
{
static MsgQueue instance;
return &instance;
}
void MsgQueue::appendModuleData(const QVariantMap& vMap)
{
if (m_sendThread.isNull()) {
m_sendThread = QSharedPointer<std::thread>(new std::thread(&MsgQueue::sendData, this));
}
QMutexLocker locker(&m_sendMutex);
m_sendList.append(vMap);
}
// 发送数据
void MsgQueue::sendData()
{
while (flag) {
QVariantMap vMap;
if (m_sendList.isEmpty()) {
QThread::msleep(10);
continue;
} else {
QMutexLocker locker(&m_sendMutex);
vMap = m_sendList.takeFirst();
}
// 下发消息
QJsonObject jsObj = QJsonObject::fromVariantMap(vMap);
pushCmdToSlave(jsObj);
}
}
// 接收数据
void MsgQueue::recvData()
{
QVariantMap vMap;
while (flag) {
QThread::msleep(10);
vMap = getReceiveCmd();
if (vMap.isEmpty()) {
continue;
}
emit sig_recvCmd(vMap);
}
}
void MsgQueue::pushCmdToSlave(QJsonObject jsObj)
{
QByteArray posixmsg = QJsonDocument(jsObj).toJson();
qDebug().noquote()<<"____Send__MsgQueue___"<<posixmsg;
int ret = mq_send(msg_qt_to_com, posixmsg.data(), posixmsg.size(),0);
if (ret < 0) {
QString errMsg = strerror(errno);
int command = jsObj.toVariantMap().value("command").toInt();
QString errStr = QString("qt to com failed, by result: %1, Command: %2, MsgLen: %3, Errno: %4, ErrMsg: %5").
arg(ret).arg(command).arg(posixmsg.size()).arg(errno).arg(errMsg);
qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<<errStr;
return;
}
}
QVariantMap MsgQueue::getReceiveCmd()
{
// 获取消息进程消息
QVariantMap recvMap;
struct mq_attr attr;
if (msg_com_to_qt < 0) {
return recvMap;
} else {
mq_getattr(msg_com_to_qt, &attr);
}
// 智能指针
QScopedPointer<char> recv(new char[attr.mq_msgsize]);
memset(recv.data(), 0, attr.mq_msgsize);
ssize_t readposix = mq_receive(msg_com_to_qt,recv.data(),attr.mq_msgsize,NULL);
if (readposix < 0) {
return recvMap;
}
QByteArray replyByteArray(recv.data());
QJsonParseError jsonError;
QJsonDocument jsonDouc = QJsonDocument::fromJson(replyByteArray, &jsonError);
if (jsonDouc.isObject()) {
qDebug().noquote()<<"_____Rev__MsgQueue____"<<jsonDouc.toJson(QJsonDocument::Indented);
QJsonObject jsonObj = jsonDouc.object();
recvMap = jsonObj.toVariantMap();
return recvMap;
} else {
qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<<"com to qt data is not Json"<<jsonError.errorString();
}
return recvMap;
}
void MsgQueue::initMsgQueue()
{
struct mq_attr attr_posix;
attr_posix.mq_flags = 0;
attr_posix.mq_maxmsg = 10;
attr_posix.mq_msgsize = 2048;
attr_posix.mq_curmsgs = 0;
msg_qt_to_com = mq_open(COMM_UIB_QT_TO_COM_NAME, O_RDWR|O_NONBLOCK|O_CREAT, 0644, &attr_posix);
if (msg_qt_to_com < 0) {
QString errStr = QString("Qt mq_open %1 failed!, errnoStr = %2").arg(COMM_UIB_QT_TO_COM_NAME).arg(strerror(errno));
qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<<errStr;
return;
}
msg_com_to_qt = mq_open(COMM_UIB_COM_TO_QT_NAME, O_RDWR|O_NONBLOCK|O_CREAT, 0644, &attr_posix);
if (msg_com_to_qt < 0) {
QString errStr = QString("Qt mq_open %1 failed!, errnoStr = %2").arg(COMM_UIB_COM_TO_QT_NAME).arg(strerror(errno));
qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<<errStr;
return;
}
}