QT+ESP8266+STM32项目构建三部曲三--QT从环境配置到源程序的解析

news2024/9/28 22:46:14

一、阿里云环境配置

        大家在编写QT连接阿里云的程序之前,先按照下面这篇文章让消息可以在阿里云上顺利流转

QT+ESP8266+STM32项目构建三部曲二--阿里云云端处理之云产品流转-CSDN博客文章浏览阅读485次,点赞7次,收藏4次。创建两个设备:一个用于stm32端连接并动态上传数据,一个用于上位机端订阅获取数据添加功能,也就是物模型的的标签,这里根据自己在设计过程中需要的标签,自由设计我这里定义了两个不同数据类型的功能标签自定义一个Topic主题,用来后面进行消息转运点击消息转发中的云产品流转:将两个设备间的消息进行流转,实现下位机上传的数据可以通过云端发送的上位机创建数据源后,在数据源内,创建一个Topic,设备选择用于与下位机相连的创建数据目的数据目的中的这个数字后面编写解析器的时候会用到。https://blog.csdn.net/weixin_54210362/article/details/142445868?spm=1001.2014.3001.5502

二、MQTT外部库的引入

        1、MQTT库下载路径        

github地址:https://github.com/qt/qtmqtt icon-default.png?t=O83Ahttps://github.com/qt/qtmqtt选择和自己使用的QT版本相匹配的库下载,我使用的是5.14.2版本

 

将MQTT库文件构建一下,构建的环境要使用Cmake,Cmake可能有的人有,有的人没有,没有的大家,可以在平台上搜索一下配置过程,我这里就不过多描述了。

构建完成后,在自己新建的工程中新建lib文件夹和include文件夹,

①从构建生成的bulid文件下的lib文件夹中找到以下两个文件复制到新建工程下的lib中

②从自己下载下来的那个MQTT库中qtmqtt-5.14.2\src\mqtt,将这个文件夹下的所有.h头文件复制到自己工程新建的include文件夹下

        2、 如何在QT软件中设置

添加库

 选择外部库

添加下图中方框中的代码 

之后就可以进行MQTT库的使用了 ,下面是使用MQTT库应包含的头文件

三、nlohmann/json解析模块引入 

因为阿里云传递的信息是Json格式的,我们么可以利用相关库中的函数进行解析,我这里使用了比较受欢迎的nlohman模块.

这里只要将 json/include at develop · nlohmann/json · GitHub 下的 nlohmann 目录拷贝到新建工程的 include 目录下,并添加路径到 VS 工程中,后面只需要引用一个头文件即可:


 

 .pro文件中

四、 MQTT库常用函数解析

下面这五行代码是用来配置客户端的,并没有直接发送出去

            mqtt_client->setHostname(HostName);//
            mqtt_client->setPort(Port);
            mqtt_client->setUsername(username);
            mqtt_client->setPassword(password);
            mqtt_client->setClientId(ClientId);

在这里开始尝试建立联系 

 //尝试连接云端
            mqtt_client->connectToHost();

成员函数state是用来检测连接状态的 

QMqttClient::ClientState QMqttClient::state() const
{
    Q_D(const QMqttClient);
    return d->m_state;
}

 开启订阅的函数

QMqttSubscription *QMqttClient::subscribe(const QMqttTopicFilter &topic, quint8 qos)
{
    return subscribe(topic, QMqttSubscriptionProperties(), qos);
}

发送消息的成员函数publish 

//发送消息到云端  {"params":{"temp":137}} 程序运行后,应该用这种方式发送,云端才可以正确解析
qint32 QMqttClient::publish(const QMqttTopicName &topic, const QMqttPublishProperties &properties,
                            const QByteArray &message, quint8 qos, bool retain)
{
    Q_D(QMqttClient);
    if (qos > 2)
        return -1;

    if (d->m_state != QMqttClient::Connected)
        return -1;

    return d->m_connection.sendControlPublish(topic, message, qos, retain, properties);
}

五、整体工程的源码UI设计:

1、mainwindow.ui

2、mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include "QDebug"
#include "QLabel"
#include "QFile"
#include "QtMqtt/qmqttclient.h"
#include "QJsonObject"
#include "QJsonDocument"
#include "QJsonArray"
#include "QMessageBox"
#include <nlohmann/json.hpp>
#include <QTextBrowser>
#include <QDateTime>
#include <QTimer>
#include <QFont>
#include <QPalette>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public://定义可以公开访问的成员变量和成员函数
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    void init_mqtt();

    void sendTopic(QString data);

    void ConnectOrDisConnect();

    void Subcribe();

    void Publish(QString topic);

    void AnalyzeJson(const QString& jsonString);

    void  Date();

public slots://public slots关键字用于声明类的槽函数(slot functions)。槽函数是与信号(signals)关联的特殊类型的成员函数,可以被信号触发。
    void receiveMess(QByteArray message,QMqttTopicName name);



private:
    QMqttClient *mqtt_client;
    Ui::MainWindow *ui;
    QTextBrowser *ui_textBrowser_recv;
    QTextEdit *textEdit_weight;
    QTextEdit *textEdit_ID;
    QTimer *timer;
};
#endif // MAINWINDOW_H

3、mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <iostream>


using json = nlohmann::json;

static QString HostName="iot-06z00eu4cdskqb7.mqtt.iothub.aliyuncs.com";
static quint16 Port = 1883;
static QString username = "App-Port&k1pcuujbQwk" ;
static QString password = "4b6f2beb66d93e54b9f79a6796d6281ed656a0ea07130df995ecb253d3bfd47c";
static QString ClientId = "k1pcuujbQwk.App-Port|securemode=2,signmethod=hmacsha256,timestamp=1727516084925|";
static QString m_topic_publish= "/sys/k1pcuujbQwk/App-Port/thing/event/property/post";
static QString m_topic_get= "/k1pcuujbQwk/App-Port/user/MessageShift";//放自己自定义的可订阅可发布Topic

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
//    this->setLayout(ui->verticalLayout);
//    ui->widgetBottom->setLayout(ui->horizontalLayout);
    mqtt_client=new QMqttClient;
    ConnectOrDisConnect();

    // 初始化未初始化的成员变量
       ui_textBrowser_recv = ui->textBrowser_recv; // 假设你的 UI 中有一个名为 textBrowser_recv 的 QTextBrowser 控件
       textEdit_weight = ui->textEdit_weight; // 假设你的 UI 中有一个名为 textEdit_weight 的 QTextEdit 控件
       textEdit_ID = ui->textEdit_ID; // 假设你的 UI 中有一个名为 textEdit_ID 的 QTextEdit 控件


        Publish(m_topic_publish);
        // 创建一个 QTimer 并设置间隔为 1000 毫秒(1 秒),有了定时就可以达到时间实时显示的效果了
        timer = new QTimer(this);
        connect(timer, &QTimer::timeout, this, &MainWindow::Date);

        // 启动定时器
        timer->start(1000);

        // 初始更新时间
        Date();

 }

MainWindow::~MainWindow()//删除UI,释放资源
{
    delete ui;
}
/* 此处函数是连接云端的作用,connect(ui->pushButton_connect,&QPushButton::clicked,this,[=](){ 这里使用了Lamda表达式的方法,构建了
一个与按键联系的发送连接信号的事件*/


void MainWindow::ConnectOrDisConnect()
{
    connect(ui->pushButton_connect,&QPushButton::clicked,this,[=](){ //connect,将按键和连接云服务器,点击连接后向服务器发送相应的信息进行连接
        if(mqtt_client->state()==QMqttClient::Disconnected) //检测当前连接客户端的状态,确认是否连接着、QMqttClient::Disconnected,成员函数
        {
            //下面五个语句的作用是配置MQTT客户端,并没有发送任何消息到云端
            mqtt_client->setHostname(HostName);//
            mqtt_client->setPort(Port);
            mqtt_client->setUsername(username);
            mqtt_client->setPassword(password);
            mqtt_client->setClientId(ClientId);
            //尝试连接云端
            mqtt_client->connectToHost();

            if(mqtt_client->state()==QMqttClient::Disconnected)//判断是否连接上了mqtt_client->state()是一个连接状态查询的函数
            {
                qDebug()<<mqtt_client->error();
            }
            else if(mqtt_client->state()==QMqttClient::Connecting)
            {
                ui->pushButton_connect->setText("close");
                ui->label_state->setText("Connect");
                Subcribe();
            }
        }
        else
        {
            mqtt_client->disconnectFromHost();
            ui->pushButton_connect->setText("link");
            ui->label_state->setText("DisConnect");
        }
    });

}

void MainWindow::Subcribe()
{
    if(mqtt_client->state()==QMqttClient::Connecting)
    {
        qDebug()<<"connect success";
        mqtt_client->subscribe(m_topic_get);
        connect(mqtt_client, &QMqttClient::messageReceived,this, &MainWindow::receiveMess); //QT5的风格,更加简洁,更加安全
    }//void receiveMess(QByteArray message,QMqttTopicName name);此处的receiveMess是定义好的,此处直接将messageReceived函数的两个参数按顺序传给后面函数的两个参数


}

void MainWindow::Publish(QString topic)//发送消息到云端  {"params":{"temp":137}} 发送消息格式
{
    connect(ui->pushButton_publish,&QPushButton::clicked,this,[=](){
        if(ui->lineEdit_publish->text()!="")
        {
            // 打印用户输入的内容
            qDebug() << "User input:" << ui->lineEdit_publish->text();
            if (mqtt_client->publish(topic, ui->lineEdit_publish->text().toUtf8()) == -1)
            {

                   QMessageBox::critical(this, QLatin1String("Error"), QLatin1String("Could not publish message"));//显示对话框的
            }
        }
    });

}


void MainWindow::AnalyzeJson(const QString& jsonString)//Json字符解析函数,从接收的字符串中解析出自己需要的变量值
{


    try {
            // 将QString转换为std::string
            std::string str = jsonString.toStdString();

            // 解析JSON字符串
            auto j = json::parse(str);

            // 获取temp的值
          if (j.contains("items") && j["items"].contains("temp"))//此处的temp是自己在阿里云上定义的标识符,下面两个也是同理
          {
                 int tempValue = j["items"]["temp"]["value"];
                 qDebug() << "Temperature value:" << tempValue;
            }
          else
          {
                  qWarning() << "Temperature data not found in JSON";
          }

           // 获取Weight的值
           if (j.contains("items") && j["items"].contains("Weight"))
           {
             int weightValue = j["items"]["Weight"]["value"];
             qDebug() << "Weight value:" << weightValue;
             // 更新textEdit_weight的内容
             textEdit_weight->setText(QString::number(weightValue));
            }
           else
           {
             qWarning() << "Weight data not found in JSON";
            }


           // 获取ID的值
           if (j.contains("items") && j["items"].contains("ID")) {
               std::string idValue = j["items"]["ID"]["value"];
               qDebug() << "ID value:" << QString::fromStdString(idValue);
               // 更新textEdit_id的内容
               textEdit_ID->setText(QString::fromStdString(idValue));
             } else {
                 qWarning() << "ID data not found in JSON";
             }

//           if(j.contains("items") && j["items"].contains("ID"))
//           {
//             std::string ID = j["items"]["ID"]["value"];

//           }
         }
            catch (const json::exception& e) {
           qCritical() << "Error parsing JSON:" << e.what();
       }


}

void MainWindow::Date()//显示时间日期的模块
{
        QFont font("Arial", 10, QFont::Bold);//设置字体
        ui->lineEdit_Date->setFont(font);

        // 设置文本颜色
        QPalette palette;
        palette.setColor(QPalette::Text, Qt::red); // 设置文本颜色为红色
        ui->lineEdit_Date->setPalette(palette);

//        setCentralWidget(ui->lineEdit_Date);//将次控件作为中央部件,设置后,其它部件就会消失

        QDateTime currentDateTime = QDateTime::currentDateTime();
        QString currentTime = currentDateTime.toString("yyyy-MM-dd hh:mm:ss");
        ui->lineEdit_Date->setText(currentTime);

}

void MainWindow::receiveMess(QByteArray message, QMqttTopicName name)//接收信息码,并传给解析函数
{
    Q_UNUSED(name);
    QString msg=QString::fromUtf8(message);;//转码,转为UTF-8的编码格式

    qDebug()<<msg;//打印接收到的信息
    ui->textBrowser_recv->append(msg);//打印到显示框里

     AnalyzeJson(msg);//调用解析函数
}

六、资源下载

我前面的那些配置,可能不是每个人按着做下来都对,配置过程总是问题不断,千奇百怪,大家可以去多看看其他博主的,我也是从很多篇里面配出来的环境,问题有很多,大家看的时候,可以多看看评论区。我自己写文章,也是以笔记为主,我会尽量齐全,但还是也不可避免有什么疏忽,请大家一定见谅。

上面其实就是我的所有代码了,如果大家自己将前面的配置都完成了,就不用下文件了,下了也是多余。这个文件如果你不是和我相同版本的话,就是一个参考学习的作用 。

https://download.csdn.net/download/weixin_54210362/89810091?spm=1001.2014.3001.5501icon-default.png?t=O83Ahttps://download.csdn.net/download/weixin_54210362/89810091?spm=1001.2014.3001.5501

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2175005.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

找不到msvcp110.dll怎么办,总结6种解决msvcp110.dll的方法

在电脑使用过程中&#xff0c;我们可能会遇到各种各样的问题&#xff0c;其中之一就是系统提示某个文件丢失。msvcp110.dll丢失是一个比较常见的问题&#xff0c;它可能导致某些程序无法正常运行。那么&#xff0c;如何解决这个问题呢&#xff1f;本文将详细介绍6种修复msvcp11…

手把手教你用PyTorch从零训练自己的大模型(非常详细)零基础入门到精通,收藏这一篇就够了

长按关注《AI科技论谈》 LLM是如今大多数AI聊天机器人的核心基础&#xff0c;例如ChatGPT、Gemini、MetaAI、Mistral AI等。这些LLM背后的核心是Transformer架构。 本文介绍如何一步步使用PyTorch从零开始构建和训练一个大型语言模型&#xff08;LLM&#xff09;。该模型以Tra…

OpenHarmony标准系统上实现对rk系列芯片NPU的支持(npu使用)

在上篇文章中&#xff0c;我们学习了移植rk的npu驱动到OpenHarmony提供的内核。本文我们来学习如何在OpenHarmony标准系统rk系列芯片如何使用npu OpenHarmony RK系列芯片运行npu测试用例 在移植npu驱动到OpenHarmony之后&#xff0c;来运行npu样例进行简单测试 1.O 测试准备…

【球形空间产生器】

题目 代码 #pragma GCC optimize(3) #include <bits/stdc.h> using namespace std; const double eps 1e-6; const int N 12; double g[N][N]; double ss[N]; int n; void gauss() {int c, r, t;for(c 1, r 1; c < n; c){int t r;for(int i r1; i < n; i)i…

Wayfair封号的常见原因及解决方案解析

近期关于Wayfair账号封禁的问题引发了广泛讨论。许多用户报告称&#xff0c;他们的Wayfair账户被突然封禁&#xff0c;这一现象不仅影响了用户的购物体验&#xff0c;也对Wayfair的品牌形象造成了一定的冲击。本文将深入探讨Wayfair封号的原因&#xff0c;并提出相应的解决方案…

【SpringCloud】服务注册/服务发现-Eureka

服务注册/服务发现-Eureka 1. 背景1.1 问题描述1.2 解决思路1.3 什么是注册中⼼1.4 CAP理论1.5 常⻅的注册中⼼ 2. Eureka 介绍3. 搭建Eureka Server 1. 背景 1.1 问题描述 上个章节的例⼦中可以看到, 远程调⽤时, 我们的URL是写死的 String url "http://127.0.0.1:90…

Flink CDC实时同步MySQL到Doris

文章目录 1.开启Flink集群2.MySQL准备数据并开启Binlog3.FlinkCDC 提交任务到集群任务提交同步变更库表迁移 问题总结 Apache Flink CDC&#xff08;Change Data Capture&#xff09;是一个用于捕获和跟踪数据库更改的技术&#xff0c;它能够实时地从数据库中获取数据变更&…

★ C++进阶篇 ★ map和set

Ciallo&#xff5e;(∠・ω< )⌒☆ ~ 今天&#xff0c;我将继续和大家一起学习C进阶篇第四章----map和set ~ ❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️ 澄岚主页&#xff1a;椎名澄嵐-CSDN博客 C基础篇专栏&#xff1a;★ C基础篇 ★_椎名澄嵐的博客-CSDN博…

AVLTree【c++实现】

目录 AVL树1.AVL树的概念2.AVLTree节点的定义3.AVLTree的插入4.AVLTree的旋转4.1左单旋4.2右单旋4.3左右双旋4.4右左双旋 5.AVLTree的验证6.AVLTree的性能 AVL树 AVLTree的代码实现连接&#xff1a; AVLTree 代码链接 1.AVL树的概念 学习了二叉搜索树之后&#xff0c;我们知…

18年408数据结构

第一题&#xff1a; 解析&#xff1a;这道题很简单&#xff0c;按部就班的做就可以了。 画出S1&#xff0c;S2两个栈的情况&#xff1a; S1: S2: 2 3 - 8 * 5 从S1中依次弹出两个操作数2和3&a…

甄选范文“论企业应用系统的数据持久层架构设计”,软考高级论文,系统架构设计师论文

论文真题 数据持久层(Data Persistence Layer)通常位于企业应用系统的业务逻辑层和数据源层之间,为整个项目提供一个高层、统一、安全、并发的数据持久机制,完成对各种数据进行持久化的编程工作,并为系统业务逻辑层提供服务。它能够使程序员避免手工编写访问数据源的方法…

IDEA 高版本创建 Spring Boot 项目选不到 java 8

一、场景分析 现在高版本的 IDEA&#xff0c;创建 Spring Boot 项目时常常会选不到 Java 8&#xff1a; 直接使用 Java 17 新建项目&#xff0c;又会报错&#xff1a; Selected version of Java 17 is not supported by the project SDK 1.8. Either choose a lower version o…

Linux增加一个回收站功能(实用功能)

在linux中,默认是没有回收站的概念的,文件被删除之后,就没有了,很难进行恢复,本章教程,教你如何在linux中安装一个回收站功能,让你的文件即使删掉了,也有即使找回来。 一、安装插件 需要注意的是, python版本需要大于3.8,否则安装之后可能无法使用。 1、下载插件 ht…

基于Qt的多功能串口通信工具分享:实时数据收发与波形绘制

需要工程源码请私信 基于 Qt 框架开发的多功能串口通信工具&#xff0c;旨在为用户提供稳定、流畅的串口数据收发体验。该工具不仅支持基本的串口通信功能&#xff0c;还集成了定时发送、多线程数据处理、粘包问题解决、实时波形绘制等多种高级功能。通过使用 QSerialPort 进行…

录屏小白福音!三款神器助你轻松上手

生活工作中&#xff0c;需要借助录屏功能越来越家常便饭了&#xff0c;选择录屏软件时&#xff0c;主要考虑的是软件的易用性、功能以及用户评价等因素。以下是如何进行录屏的步骤&#xff0c;以及推荐的四个录屏软件的使用说明&#xff1a;关于如何录屏的步骤操作&#xff0c;…

使用 PowerShell 命令更改 RDP 远程桌面端口(无需修改防火墙设置)

节选自原文&#xff1a;Windows远程桌面一站式指南 | BOBO Blog 原文目录 什么是RDP&#xfffc;开启远程桌面 检查系统版本启用远程桌面连接Windows 在Windows电脑上在MAC电脑上在Android或iOS移动设备上主机名连接 自定义电脑名通过主机名远程桌面使用Hosts文件自定义远程主…

(undone) MIT6.824 Lecture1 笔记

参考1MIT课程视频&#xff1a;https://www.bilibili.com/video/BV16f4y1z7kn/?spm_id_from333.337.search-card.all.click&vd_source7a1a0bc74158c6993c7355c5490fc600 参考2某大佬笔记&#xff1a;https://ashiamd.github.io/docsify-notes/#/study/%E5%88%86%E5%B8%83%…

TDSQL-C电商可视化,重塑电商决策新纪元

前言&#xff1a; 在数字化浪潮席卷全球的今天&#xff0c;电子商务行业以其独特的魅力和无限潜力&#xff0c;成为了推动全球经济增长的重要引擎。然而&#xff0c;随着业务规模的急剧扩张&#xff0c;海量数据的涌现给电商企业带来了前所未有的挑战与机遇。如何高效地处理、…

如何从飞机、电报中提取数据

电报&#xff0c;通常简称TG&#xff0c;是一个跨平台的即时通讯软件。客户端是开源的&#xff0c;而服务器是专有的。用户可以交换加密的、自毁的信息&#xff08;类似于“阅读后烧伤”&#xff09;&#xff0c;并共享各种文件&#xff0c;包括照片和视频。它的安全性很高&…

软件设计之SSM(1)

软件设计之SSM(1) 路线图推荐&#xff1a; 【Java学习路线-极速版】【Java架构师技术图谱】 尚硅谷新版SSM框架全套视频教程&#xff0c;Spring6SpringBoot3最新SSM企业级开发 资料可以去尚硅谷官网免费领取 学习内容&#xff1a; Spring框架结构SpringIoC容器SpringIoC实践…