QT安卓MQTT温湿度检测(一)

  近期闲来无事,又常常听人谈论MQTT通讯协议,于是花费了2周时间制作了这个小系统,一为巩固所学到的知识,二为日后方便查阅。通过手机APP可以随时检测温湿度数据和简单的控制。共分为3部分,第一部分为QT安卓APP的开发,第二部分为搭建云服务器,第三部分为硬件单片机采集上报数据。APP截图如下:

1、首先下载qmtt https://github.com/emqtt/qmqtt  获得qmtt源码(有的网络环境无法响应github ,可以通过手机网络下载)

 

 

 

 

 2、新建一个QT工程

    1)在pro文件中增加 QT += network

    2)  将mqtt源码目录中的 scr文件中的.h 头文件和.cpp源文件全部拷贝至工程目录下,并添加到工程中

 

 

 

 

3)头文件widget.h

 1 #ifndef WIDGET_H
 2 #define WIDGET_H
 3 
 4 #include <QWidget>
 5 #include "qmqtt.h"
 6 #include <QDebug>
 7 #include <QHostInfo>
 8 #include <QTimer>
 9 #include <QNetworkInterface>
10 
11 namespace Ui {
12 class Widget;
13 }
14 
15 class Widget : public QWidget
16 {
17     Q_OBJECT
18 
19 public:
20     explicit Widget(QWidget *parent = nullptr);
21     ~Widget();
22     void mqttInit(QString domainName, quint16 Port);
23 public slots:
24     void doConnected();//连接成功
25     void doDisconnected();//MQTT连接断开
26     void doDataReceived(QMQTT::Message);//MQTT收到数据
27 
28 private slots:
29     void on_pushButton_clicked();
30     void t1Updata();
31 
32 private:
33     Ui::Widget *ui;
34     QMQTT::Client client;
35     int devStatus = 0;
36     bool setLed = 0;
37     QTimer *t1;
38 
39     QString  strMac;
40 };
41 
42 #endif // WIDGET_H

4)widget.cpp

  1 #include "widget.h"
  2 #include "ui_widget.h"
  3 
  4 Widget::Widget(QWidget *parent) :
  5     QWidget(parent),
  6     ui(new Ui::Widget)
  7 {
  8     ui->setupUi(this);
  9 
 10     //获取当前有效网卡 并于MQTT客户端登录时 的clientID ,方便管理不同手机在服务器所生成的客户端ID
 11 
 12     QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces();//获取所有网卡信息
 13     for (int i = 0; i < ifaces.count(); i++)
 14     {
 15         QNetworkInterface iface = ifaces.at(i);
 16         if ( iface.flags().testFlag(QNetworkInterface::IsUp) && iface.flags().testFlag(QNetworkInterface::IsRunning) && !iface.flags().testFlag(QNetworkInterface::IsLoopBack))
 17         {
 18             for (int j=0; j<iface.addressEntries().count(); j++)
 19             {
 20                 strMac = iface.hardwareAddress();
 21                 i = ifaces.count(); //跳出外层循环
 22                 break;
 23             }
 24         }
 25     }
 26     qDebug() << "mac is ==============="<< strMac;
 27 
 28 
 29     //MQTT客户端参数配置,并登录服务器
 30     mqttInit("服务器地址",1883); 
 31 
 32     //连接槽函数和断开连接槽函数
 33     connect(&client,SIGNAL(connected()),this,SLOT(doConnected()));
 34     connect(&client,SIGNAL(disconnected()),this,SLOT(doDisconnected()));
 35 
 36     
 37     //为APP图片加载图片资源
 38     QImage im;
 39     im.load(":/image/image/hr.png");
 40     ui->label_hrpic->setPixmap(QPixmap::fromImage(im));
 41     
 42     im.load(":/image/image/wd.png");
 43     ui->label_wdpic->setPixmap(QPixmap::fromImage(im));
 44 
 45     im.load(":/image/image/led.png");
 46     ui->label_led->setPixmap(QPixmap::fromImage(im).scaled(120,120));
 47     ui->label_devState->setText("离线");
 48 
 49     ui->groupBox->setStyleSheet("background-color:rgb(100,230,20);border-radius:20px;");
 50     ui->pushButton->setStyleSheet("background-color:rgb(100,230,20);border-radius:20px;");
 51 
 52     
 53     //定时器1用于辅助获取硬件设备的在线状态
 54     t1 = new QTimer();
 55     connect(t1,SIGNAL(timeout()),this,SLOT(t1Updata()));
 56     t1->start(1000);
 57 
 58 
 59 }
 60 
 61 
 62 
 63 Widget::~Widget()
 64 {
 65     delete ui;
 66 }
 67 
 68 /**
 69  * @brief Widget::mqttInit
 70  * @param domainName 服务器地址
 71  * @param Port 端口号
 72  */
 73 void Widget::mqttInit(QString domainName, quint16 Port)
 74 {
 75     QHostInfo info = QHostInfo::fromName(domainName);
 76     QString host = info.addresses().first().toString(); // 代理服务器 IP
 77     qDebug() << host;
 78 
 79 //  client = new QMQTT::Client(QHostAddress(host),Port);
 80 
 81     client.setKeepAlive(100);
 82     client.setHost(QHostAddress(host));
 83     client.setPort(Port);
 84     client.setClientId(strMac);
 85     client.setUsername("tankQTandroid");
 86     client.setPassword("");
 87     client.cleanSession();
 88     client.setVersion(QMQTT::MQTTVersion::V3_1_1); // 设置mqtt版本
 89     connect(&client,SIGNAL(received(QMQTT::Message)),this,SLOT(doDataReceived(QMQTT::Message)));
 90 
 91     client.connectToHost();
 92 }
 93 
 94 /**
 95  * @brief Widget::on_pushButton_clicked 开灯按钮
 96  */
 97 void Widget::on_pushButton_clicked()
 98 {
 99          QString topic = "tank/1"; //已经订阅的主题
100          QByteArray payload;
101          payload[0] = 0xf7;
102          if(setLed == 0)
103          {
104             payload[1] = 0xaa;
105          }
106          else {
107              payload[1] = 0x55;
108          }
109          QMQTT::Message message(136,topic,payload); //初始化发布内容
110          client.publish(message);  //发布消息
111 }
112 
113 /**
114   * @brief Widget::doConnected 连接成功后触发
115   */
116  void Widget::doConnected()
117  {
118 
119      client.subscribe("tank/1"); //订阅主题
120 
121  }
122 
123  /**
124   * @brief Widget::doDisconnected 意外断开后触发
125   */
126  void Widget::doDisconnected()
127  {
128 
129       mqttInit("服务器地址",1883); //重新连接服务器
130  }
131 
132  /**
133   * @brief Widget::doDataReceived //接收到订阅的信息后触发
134   * @param message 
135   */
136  void Widget::doDataReceived(QMQTT::Message message)
137  {
138      QByteArray mes; //mes 5个字节分别为 温度整数 温度小数 湿度整数 湿度小数 灯状态(0xaa/0x55)
139      mes.resize(5);
140      mes = message.payload();
141      qDebug() << "mes size is" << message.payload().size();
142      qDebug() << QString::number(mes[0], 16)<< QString::number(mes[1], 16)<< QString::number(mes[2], 16)<< QString::number(mes[3], 16);
143      if(mes.at(0) != 0xf7) //0xf7 0xaa/0x55为手机端主动发布的开关灯指令消息,此处回传订阅屏蔽处理
144      {
145           ui->label_wd->setText(QString::number(mes[0]) + "." + QString::number(mes[1]) + "");
146           ui->label_hr->setText(QString::number(mes[2])  + "%");
147           if(mes.at(4) == 0xaa)
148           {
149               ui->label_ledStatus->setText("打开");
150               ui->pushButton->setText("关灯");
151               setLed = 1;
152           }
153           else {
154               ui->label_ledStatus->setText("关闭");
155               ui->pushButton->setText("开灯");
156               setLed = 0;
157           }
158      }
159 
160      if(devStatus == 0)  //收到信息后显示在线
161      {
162          devStatus = 1;
163          ui->label_devState->setText("在线"); 
164      }
165      if(devStatus > 1)  //接收信息后复位devStatus 
166      {
167          devStatus = 1;
168      }
169  }
170 void Widget::t1Updata()
171 {
172     if(devStatus > 0)
173     {
174         if(++ devStatus > 5) //如果没有接收到订阅消息 溢出显示离线
175         {
176             ui->label_devState->setText("离线");
177             devStatus = 0;
178         }
179     }
180 }

5)为工程添加图片资源

      右键点击工程项目名字 选择 add new 选择QT> Qt Resource File

 

       右键.prc文件→open with→资源编辑器,打开资源编辑器,在资源编辑器界面单击"添加"按钮,选择"添加前缀",然后将属性栏中的前缀改为"/image",再单击"添加"按钮,"添加文件",在弹出的对话框中选择image中的图片文件。添加完成后.qrc目录下会有已经 添加完成的图片文件

 

posted @ 2022-05-03 14:23  Tankiii  阅读(858)  评论(1编辑  收藏  举报