OpenHarmony开发之MQTT讲解
相信MQTT这个名称大家都不陌生,物联网的开发必然会遇到MQTT相关知识的应用。那么什么是MQTT?它有什么特点?它能解决什么问题?它是如何工作的?OpenAtom OpenHarmony(以下简称“OpenHarmony”)的物联网开发者要如何使用及验证MQTT功能?接下来的内容将一一为你解答。下图为MQTT通信模型。
什么是MQTT
MQTT(Message Queuing Telemetry Transport消息队列遥测传输)是一种物联网协议,是一种客户端与服务端架构的发布/订阅模式的消息传输协议,旨在为低带宽和不稳定的网络环境中的物联网设备提供可靠的网络服务。MQTT是专门针对物联网开发的轻量级传输协议。MQTT协议针对低带宽网络,低计算能力的设备,做了特殊的优化,使得其能适应各种物联网应用场景。目前它已广泛应用于车联网、智能家居、即时聊天应用和工业互联网等领域。
MQTT的基本原理
在MQTT通讯中,有两个最为重要的角色。它们分别是服务端和客户端。
MQTT服务端
MQTT服务端通常是一台服务器。它是MQTT信息传输的枢纽,负责将MQTT客户端发送来的信息传递给MQTT客户端。MQTT服务端还负责管理MQTT客户端。确保客户端之间的通讯顺畅,保证MQTT消息得以正确接收和准确投递。
MQTT客户端
MQTT客户端可以向服务端发布信息,也可以从服务端收取信息。我们把客户端发送信息的行为称为“发布”信息。而客户端要想从服务端收取信息,则首先要向服务端“订阅”信息。“订阅”信息这一操作很像我们在视频网站订阅某一部电视剧。当这部电视剧上新后,视频网站会向订阅了该剧的用户发送信息,告诉他们有新剧上线了。
MQTT主题
刚刚我们在讲解MQTT客户端订阅信息时,使用了用户在视频网站订阅电视剧这个例子。在MQTT通讯中,客户端所订阅的肯定不是一部部电视剧,而是一个个“主题”。MQTT服务端在管理MQTT信息通讯时,就是使用“主题”来控制的。为了便于您更好理解服务端是如何通过主题来控制客户端之间的信息通讯,我们来看看下图示例:
以上图示中一共有三个MQTT客户端。它们分别是汽车、手机和电脑。在管理MQTT通讯时,MQTT服务端使用了“主题”来对信息进行管理。比如上图所示,假设我们需要利用手机和电脑获取汽车的速度,那么我们首先要利用电脑和手机向MQTT服务器订阅主题“汽车速度”。接下来,当汽车客户端向服务端的“汽车速度”主题发布信息后,服务端就会首先检查以下都有哪些客户端订阅了“汽车速度”这一主题的信息。当它发现订阅了该主题的客户端有一个手机和一台电脑,于是服务端就会将刚刚收到的“汽车速度”信息转发给订阅了该主题的手机和电脑客户端。
以上实例中,汽车是“汽车速度”主题的发布者,而手机和电脑则是该主题的订阅者。
值得注意的是,MQTT客户端在通讯时,往往角色不是单一的。它既可以作为信息发布者也可以同时作为信息订阅者。如下图所示:
上图中的所有客户端都是围绕“空调温度”这一主题进行通讯的。对于“空调温度”这一主题,手机和电脑客户端成为了MQTT信息的发布者而汽车则成为了MQTT信息的订阅者(接收者)。
(以上讲解参考链接:太极创客http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-tuttorial/mqtt-tutorial/2-mqtt-basics/)
可以看到,针对不同的主题,MQTT客户端可以切换自己的角色。它们可能对主题A来说是信息发布者,但是对于主题B就成了信息订阅者。
MQTT客户端开发流程
以下采用小熊派的Paho MQTT样例,简要说明MQTT的开发流程。
样例代码在OpenHarmony源码目录/device/board/bearpi/bearpi_hm_nano/app/D5_iot_mqtt,源码下载路径参考文章末尾。开发应用主要涉及以下几个API应用:
MQTT的流程主要由四个步骤组成:
1、创建客户端对象;
2、连接服务器;
3、订阅主题;
4、发布主题。
//订阅的回调函数
void messageArrived(MessageData *data)
{
printf("Message arrived on topic %.*s: %.*s\n", data->topicName->lenstring.len,
data->topicName->lenstring.data, data->message->payloadlen, data->message->payload);
}
//主流程函数
static void MQTTDemoTask(void)
{
WifiConnect("BearPi", "123456789");
printf("Starting ...\n");
int rc, count = 0;
MQTTClient client; NetworkInit(&network);
printf("NetworkConnect ...\n"); NetworkConnect(&network, MQTT_SERVERIP, MQTT_SERVERPORT);//本地电脑作为消息代理 此处为电脑IP
printf("MQTTClientInit ...\n");
//1-------------创建客户端对象
MQTTClientInit(&client, &network, MQTT_CMD_TIMEOUT_MS, sendBuf, sizeof(sendBuf), readBuf, sizeof(readBuf)); MQTTString clientId = MQTTString_initializer;
clientId.cstring = "bearpi"; MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
data.clientID = clientId;
data.willFlag = 0;
data.MQTTVersion = MQTT_VERSION;
data.keepAliveInterval = MQTT_KEEP_ALIVE_MS;
data.cleansession = 1; printf("MQTTConnect ...\n");
//2-------------连接服务端
rc = MQTTConnect(&client, &data);
if (rc != 0) {
printf("MQTTConnect: %d\n", rc);
NetworkDisconnect(&network);
MQTTDisconnect(&client);
osDelay(MQTT_DELAY_2S);
} printf("MQTTSubscribe ...\n");
//3-------------订阅主题substopic
rc = MQTTSubscribe(&client, "substopic", MQTT_QOS, messageArrived);
if (rc != 0) {
printf("MQTTSubscribe: %d\n", rc);
osDelay(MQTT_DELAY_2S);
}
while (++count) {
MQTTMessage message;
char payload[30]; message.qos = MQTT_QOS;
message.retained = 0;
message.payload = payload;
(void)sprintf_s(payload, sizeof(payload), "message number %d", count);
message.payloadlen = strlen(payload);
//4------------发布pubtopic主题
if ((rc = MQTTPublish(&client, "pubtopic", &message)) != 0) {
printf("Return code from MQTT publish is %d\n", rc);
NetworkDisconnect(&network);
MQTTDisconnect(&client);
}
osDelay(MQTT_DELAY_500_MS);
}
}
小熊派开发板MQTT客户端代码一直循环发送主题为pubtopic的信息,信息内容为("message number %d", count),每次信息count++;
同时开发板客户端也在订阅主题为substopic的信息,一旦接收到substopic信息就会调用回调函数,串口打印出substopic主题的内容。
MQTT实操验证
如何验证MQTT客户端代码是否正常?验证过程主要涉及以下几点:
1、下载消息代理Mosquitto软件,并配置Mosquitto;
2、下载EclipsePahoMQTT工具,并用该工具创建一个客户端,我们简称客户A;
3、修改小熊派客户端MQTT代码相关配置,与第一步配置Mosquitto相匹配,小熊派客户端我们简称客户B。
简要说明下本次验证中涉及的各个模块的作用:
1、消息代理Mosquitto:可以理解为它就是MQTT服务器,所有客户端的消息(发布/订阅)都是与它通信;它负责接收及分发所有信息;
2、EclipsePahoMQTT工具创建的客户端A:我们用来与小熊派创建的客户端B进行信息交互(发布/订阅)。
详细细节:
1、下载消息代理Mosquitto软件,并配置Mosquitto:
(1)点击下载网址(https://mosquitto.org/download/),选择合适的版本,并安装(记录安装路径);
(2)安装好后,配置Mosquitto,并开启Mosquitto服务:
在Mosquitto软件的安装路径找到mosquitto.conf,打开并作如下修改:
192.168.120.137是本电脑的IP;1883指本次用来验证的服务端口号(本电脑IP192.168.120.137可以有多个服务端口);allow_anonymous true指允许客户端匿名登录;
修改配置后,在安装目录打开命令窗口,输入.\mosquitto -c .\mosquitto.conf -v。服务器启动成功后,如下图显示mosquitto version 2.0.11 starting.
2、下载EclipsePahoMQTT工具,创建客户端A,并连接服务器:
3、修改小熊派客户端MQTT代码相关配置,与第一步配置Mosquitto相匹配,小熊派客户端我们简称客户B:
修改连接端代码:
NetworkConnect(&network, 192.168.120.137, 1883);//本地电脑作为消息代理 此处为电脑IP Mosquitto相匹配
4、烧录代码,并操作(发布\订阅)通信:
客户端B做了两件事情:1、一直循环发送主题为pubtopic的信息,信息内容是("message number %d", count);2、订阅了主题为substopic的信息,一旦服务器有该主题信息就会发送给客户端B,客户端B会把substopic的内容打印。
客户端A也做了两件事:1、订阅主题为pubtopic的信息;2、发布一条主题为substopic的信息,内容为“Hello OpenHarmony!”。
结合客户端B(小熊派开发板)部分代码:
printf("Starting ...\n");
NetworkInit(&network);
printf("NetworkConnect ...\n");
NetworkConnect(&network, MQTT_SERVERIP, MQTT_SERVERPORT);//本地电脑作
printf("MQTTClientInit ...\n");
//1-------------创建客户端对象
MQTTClientInit(&client, &network, MQTT_CMD_TIMEOUT_MS, sendBuf, sizeof(sendBuf), readBuf, sizeof(readBuf)); printf("MQTTConnect ...\n");
//2-------------连接服务端
rc = MQTTConnect(&client, &data); printf("MQTTSubscribe ...\n");
//3-------------订阅主题substopic
rc = MQTTSubscribe(&client, "substopic", MQTT_QOS, messageArrived);
(void)sprintf_s(payload, sizeof(payload), "message number %d", count);
//4------------循环发布pubtopic主题 内容为message number+connt的计数值
MQTTPublish(&client, "pubtopic", &message)
//订阅的回调函数输出以下内容
printf("Message arrived on topic %.*s: %.*s\n", data->topicName->lenstring.len,
data->topicName->lenstring.data, data->message->payloadlen, data->message->payload);
客户B:开发板烧录好代码后,电脑串口工具连接开发板,会有连接MQTT及订阅的信息(参照以上代码),如下图:
客户A:显示如下图:
总结
本文从讲解MQTT它是什么?原理是什么?到MQTT的应用开发(API函数接口调用例程),再到MQTT的验证(Mosquitto软件及EclipsePahoMQTT工具的使用)三个方面介绍了MQTT。希望通过本文介绍让大家对MQTT有个感性认识。
需要说明的是通常我们使用的是MQTT的解决方案,即MQTT的一系列操作被封装了,例如知识体系的智慧家居样例,在与华为IOT平台通信中,它们内部实现是基于MQTT协议搭建的。(智慧家居与华为IOT平台的相关介绍,请查看文末链接)
本文章是OpenHarmony知识体系工作组(相关链接在文章末尾)为广大开发者分享的文章。同时知识体系工作组结合日常生活,给开发者规划了各种场景的Demo样例,如智能家居场景、影音娱乐场景、运动健康场景等;欢迎广大开发者一同参与OpenHarmony的开发,一起完善样例,相互学习,相互进步。
相关链接
小熊派开发板学习路径:
https://growing.openharmony.cn/mainPlay/learnPathMaps?id=19
小熊派开发板MQTT文档:
Windows + mosquitto搭建MQTT Broker:
https://blog.csdn.net/wallace89/article/details/125617330
OpenHarmony源码获取:
https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/get-code/sourcecode-acquire.md
OpenHarmony三方库MQTT:
https://gitee.com/openharmony-tpc/talkweb_mqtt
OpenHarmony知识体系工作组智慧家居开发样例
https://gitee.com/openharmony-sig/knowledge_demo_smart_home
使用MQTT协议连华为IOT平台
OpenHarmony开发之MQTT讲解的更多相关文章
- 安卓开发之mqtt协议
首先物联网协议mqtt协议是基于tcp/ip协议的,使用了官方的mqttclient框架/**初始化mqttclient*/private void init() { try { //MQTT的连接设 ...
- UWP开发之Mvvmlight实践七:如何查找设备(Mobile模拟器、实体手机、PC)中应用的Log等文件
在开发中或者后期测试乃至最后交付使用的时候,如果应用出问题了我们一般的做法就是查看Log文件.上章也提到了查看Log文件,这章重点讲解下如何查看Log文件?如何找到我们需要的Packages安装包目录 ...
- Cocos2d-x 3.x游戏开发之旅
Cocos2d-x 3.x游戏开发之旅 钟迪龙 著 ISBN 978-7-121-24276-2 2014年10月出版 定价:79.00元 516页 16开 内容提要 <Cocos2d-x ...
- iOS开发之Socket通信实战--Request请求数据包编码模块
实际上在iOS很多应用开发中,大部分用的网络通信都是http/https协议,除非有特殊的需求会用到Socket网络协议进行网络数 据传输,这时候在iOS客户端就需要很好的第三方CocoaAsyncS ...
- 基于xmpp openfire smack开发之Android客户端开发[3]
在上两篇文章中,我们依次介绍openfire部署以及smack常用API的使用,这一节中我们着力介绍如何基于asmack开发一个Android的客户端,本篇的重点在实践,讲解和原理环节,大家可以参考前 ...
- iOS多线程开发之GCD(中篇)
前文回顾: 上篇博客讲到GCD的实现是由队列和任务两部分组成,其中获取队列的方式有两种,第一种是通过GCD的API的dispatch_queue_create函数生成Dispatch Queue:第二 ...
- python开发之路:python数据类型(老王版)
python开发之路:python数据类型 你辞职当了某类似微博的社交网站的底层python开发主管,官还算高. 一次老板让你编写一个登陆的程序.咔嚓,编出来了.执行一看,我的妈,报错? 这次你又让媳 ...
- Java 多线程开发之 Callable 与线程池
前言 我们常见的创建线程的方式有 2 种:继承 Thread 和 实现 Runnable 接口. 其实,在 JDK 中还提供了另外 2 种 API 让开发者使用. 二.简单介绍 2.1 Callabl ...
- [整理]Unity3D游戏开发之Lua
原文1:[Unity3D]Unity3D游戏开发之Lua与游戏的不解之缘(上) 各位朋友,大家好,我是秦元培,欢迎大家关注我的博客,我地博客地址是blog.csdn.net/qinyuanpei.如果 ...
- 李洪强iOS开发之iOS工具收集
李洪强iOS开发之iOS工具收集 项目 简述 日期 我是怎么慢慢变懒的 : Jenkins + 蒲公英 使用Jenkins + 蒲公英使得项目打包给测试人员自动化,大大节省了劳动力 2015.04.1 ...
随机推荐
- vscode添加gitbash终端方法
1.打开vscode 2.点击文件,ctrl+, 3.搜索shell windows { ... // 添加如下代码 "terminal.integrated.profiles.window ...
- 并发与并行的区别---python
并发与并行的区别 Erlang 之父 Joe Armstrong 用一张5岁小孩都能看懂的图解释了并发与并行的区别 并发是两个队列交替使用一台咖啡机,并行是两个队列同时使用两台咖啡机 如果是串行,一个 ...
- 04-Redis系列之-持久化(RDB,AOF)
持久化的作用 什么是持久化 redis的所有数据保存在内存中,对数据的更新将异步的保存到硬盘上 持久化的实现方式 快照:某时某刻数据的一个完整备份(mysql的Dump,redis的RDB) 写日志: ...
- 如何在矩池云使用 Poetry 管理项目环境
官网介绍:Poetry is a tool for dependency management and packaging in Python. It allows you to declare th ...
- You can't specify target table for update in FROM clause
mysql中You can't specify target table for update in FROM clause错误的意思是说,不能先select出同一表中的某些值,再update这个表( ...
- 【Azure Redis】Redis客户端出现15分钟的超时异常
问题描述 客户端使用 Lettuce.io 连接 Azure Redis,出现了长达15分钟的Timeout异常. 问题解答 Azure Redis作为PaaS服务,由于一些平台的升级操作而引发的故障 ...
- C++ //常用算法 binary_serach //查找指定的元素 //无序序列中不可用
1 //常用算法 binary_serach 2 //查找指定的元素 3 //无序序列中不可用 4 5 6 #include<iostream> 7 #include<algorit ...
- vscode 文件上传快捷键 shift+alt+s (ftp专用)插件用的 ftp-sync
vscode 文件上传快捷键 shift+alt+s (ftp专用)插件用的 ftp-sync { "key": "shift+alt+s", "co ...
- 关闭 nginx | taskkill /f /t /im nginx.exe
stop.bat taskkill /f /t /im nginx.exe pause
- C++字符串编码转换
C++中字符串有很多种类,详情参考C++中的字符串类型.本文主要以string类型为例,讲一下字符串的编码,选择string主要是因为: byte是字符串二进制编码的最小结构,字符串本质上就是一个by ...