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目录下会有已经 添加完成的图片文件