前言
书接上回,我们已经搭建好了Linux服务器、QT移植好了MQTT库。下一步就是利用QT设计一个MQTT的上位机了。这个上位机实现的功能如下:连接MQTT服务器、订阅主题、发送某个主题的消息、接收某个主题的消息。在本部分,我将会着重讲通讯部分,至于其他界面的设计,大家可以自行百度学习,或等我后续有时间整合笔记。
MQTT通讯简介
「MQTT(Message Queuing Telemetry Transport)」 是一种轻量级的消息传输协议,通常用于在物联网(IoT)和传感器网络中进行通信。它设计用于在低带宽、不稳定或高延迟的网络环境下传输数据,因此非常适用于连接设备之间的通信,尤其是在资源有限的环境中。
MQTT通讯的前提是要在同一个内网环境下。亦或者都连接上外网,在外网环境下通讯。构成其通讯结构的主体分为物理层和软件层。
软件层的主体主要是发布者(Publisher)、订阅者(Subscriber)、主题(Topic)、MQTT 服务端、消息。其中发布者和订阅者,是消息传输的起始点和接收节点(并不是终点),消息是发布者向MQTT服务端广播的信息,主题可以理解为消息的一种属性,用这种属性区分出消息广播的范围。而MQTT服务端,则是处理信息的一个中端。笼统一点,可以把发布者和订阅者都归纳为一个MQTT客户端,毕竟在现实应用场景,我们很可能要订阅不止一个主题,发布不止一个主题的消息,能够执行这一系列操作的对象可称为一个MQTT客户端。
发布者在发布一条消息时,必须指定一个主题,这条消息一经发布,就可以理解为在这个主题的信道发出一个广播信号。而你想接收到这条消息,就必须作为订阅者,订阅这个主题。值得注意的是,发布的消息,不会因为没有订阅者而发送失败,也不会因为订阅者接收到这条而消失。简而言之。无论你有多少个这个主题的订阅者,这个主题的消息一经发布,都能全部收到。(发布无需订阅、接收必须订阅)。
在本项目中物理层则是,一台安装Linux的服务器作为MQTT服务端,51单片机作为一个MQTT客户端,QT程序为另一个MQTT客户端。
QT代码简介
有了前文的铺垫,我们的思路就很清晰了。我们只需要连接上一个MQTT服务端,订阅相关的主题,便可接收到这个主题的消息。发布相关者主题的消息,便可把我们想传递的消息广播出去。接下来就这几步操作,对QT代码做解析。
连接一个服务端
先创建一个QMqttClient 类型的对象m_clinet。后续很多操作都是调用这个对象下的方法。
此处,我创建了一个按键,当按下这个按键的时候,会发出一个点击信号,就会执行上图的槽函数。这里,为了避免重复点击连接出bug。先把连接先断开,然后配置端口(此端口必须为int型,我们通过界面的lineEdit获取)。然后配置地址(地址必须是QString,也是通过界面获取)。最后配置完是连接函数。
创建两个一个信号槽连接,一个是连接信号槽,一个是断开信号槽,对应如下
connect(m_client,&QMqttClient::connected,this,&MainWindow::mqtt_connenct);
#连接信号
connect(m_client,&QMqttClient::disconnected,this,&MainWindow::mqtt_disconnenct);
#断开连接信号
此处主要是执行一些按键的使能和失能,比较重要的是用了个QMessage弹窗提示,连接断开。这部分大家可以自由发挥。主要是要建立好连接mqtt的信号槽函数和断连mqtt的信号槽函数。
订阅一个主题
这里是应该槽函数,按键按下会触发如下槽函数(按键按下实现订阅),主要实现的是订阅一个主题,并连接一个接收到数据的信号和它的槽函数。这里有个bug,就是重复连接多次信号和槽,触发一次信号将会变成多次触发(比如我连接两次信号和槽函数,那么我收到一次信号就会触发两次槽函数)。所以我们先断开一次信号槽函数,然后再是执行订阅(重复订阅一个主题,不会有问题),我这里的主题名为“data”。同时为了保险,我这里加了个判断,获取这个信号的连接状态,如果没连接槽函数才执行连接槽函数,避免重复执行连接信号槽函数。
信号:接收到数据订阅数据的信号 槽:接收到数据后的处理函数
接收到数据的槽函数
void MainWindow::recvMessageSlot(const QByteArray &ba, const QMqttTopicName &topic)
这是接收到数据的槽函数,内部设计比较灵活我就不贴图,主要传递的参数有两个,一个是数组,储存接收到的数据。第二个是接收来自哪个主题,依据以上信息,大家可以自行设计函数逻辑去处理。
发送一个数据
这里也是一个槽函数(按键按下触发此槽函数)。比较简单,定义好topicName和数据,直接用QMqttClient对象里的Publish方法就可以实现。
总结
基于以上便能实现在QT上最基本的MQTT操作,大家也可以基于以上的操作,拓展自己的功能。
这是最终的效果,画图和操作和界面设计,这里就不赘述了。有兴趣的大家可以去自己学一下。