更多内容请访问:与华为官方共建的鸿蒙技术社区https://harmonyos.51cto.com/#zzMQTT是目前最主流的互联网物联网通信协议需要物联网云平台,比如华为云、阿里云、移动OneNET都支持mqtt。Hi3861是一款专为物联网应用场景设计的芯片。本节主要讲如何通过在鸿蒙系统中移植第三方软件包pahomqtt实现MQTT协议功能,最后给出测试验证。为后续的物联网项目打下坚实的基础。友情提示,本节内容很多,源码也贴出来了。你最好先看一下,然后再操作。相关源码已打包上传。顺便上传了一个test-OK的固件。可以直接下载附件直接测试。解压后会得到5个压缩包,继续解压即可。3.9.1MQTT简介MQTT的全称是消息队列遥测传输(MessageQueueTelemetryTransport),是一种基于发布/订阅范式的二进制“轻量级”消息协议,由IB公司发布。专为网络受限和嵌入式设备设计的数据传输协议。MQTT最大的优势在于它可以以极少的代码和有限的带宽为连接的远程设备提供实时可靠的消息服务。作为一种低开销、低带宽的即时通讯协议,它在物联网、小型设备和移动应用中有着广泛的应用。MQTT模型如图所示。关于MQTT协议的更多信息,请参见这篇文章:MQTT协议开发介绍3.9.2移植pahomqtt软件包1、下载pahomqtt软件包,添加到鸿蒙代码中。pahomqtt-c是一个基于C语言的MQTT客户端。非常适合在嵌入式设备上使用。首先下载源码:https://github.com/eclipse/paho.mqtt.embedded-c下载解压后会得到这样一个文件夹:我们在鸿蒙系统源码的third_party文件夹下新建一个pahomqtt文件夹,然后把所有解压后的文件复制到pahomqtt文件夹下,目录结构大致如下:接下来我们在pahomqtt文件夹下新建BUILD.gn文件进行构建编译。其内容如下:#Copyright(c)2020HuaweiDeviceCo.,Ltd.#LicensedundertheApacheLicense,Version2.0(the"License");#youmaynotusethisfileexceptincompliancewiththeLicense.#YoumayobtainacopyoftheLicenseat##http://www.apache.org/licenses/LICENSE-2.0##Unlessrequiredbyapplicablelaworagreedtoinwriting,software#distributedundertheLicenseisdistributedonan"ASIS"BASIS,#WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.#SeetheLicenseforthespecificlanguagegoverningpermissionsand#limitationsundertheLicense.import("//build/lite/config/component/lite_component.gni")import("//build/lite/ndk目录ndk.gni")config("pahomqtt_config"){include_dirs=["MQTTPacket/src","MQTTPacket/samples","//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include","//kernel/liteos_m/components/cmsis/2.0",]}pahomqtt_sources=["MQTTPacket/samples/transport.c","MQTTPacket/src/MQTTConnectClient.c","MQTTPacket/src/MQTTConnectServer.c","MQTTPacket/src/MQTTDeserializePublish.c","MQTTPacket/src/MQTTFormat.c","MQTTPacket/src/MQTTPacket.c","MQTTPacket/src/MQTTSerializePublish.c","MQTTPacket/src/MQTTSubscribeClient.c","MQTTPacket/src/MQTTSubscribeServer.c","MQTTPacket/src/MQTTUnsubscribeClient.c","MQTTPacket/src/MQTTUnsubscribeServer.c",]lite_library("pahomqtt_static"){target_type="static_library"sources=pahomqtt_sourcespublic_configs=[":pahomqtt_config"]}lite_library("pahomqtt_shared"){target_type="shared_library"sources=pahomqtt_sourcespublic_configs=[":pahomqtt_config"]}ndk_lib("pahomqtt_ndk"){if(board_name!="hi3861v100"){lib_extension=".so"deps=[":pahomqtt_shared"]}else{deps=[":pahomqtt_static"]}head_files=["//third_party/pahomqtt"]}2。编译hi3861时,编译pahomqtt包,打开vendor\hisi\hi3861\hi3861\BUILD.gn文件,在lite_component("sdk")中添加"//third_party/pahomqtt:pahomqtt_static",修改后文件内容如下:完成以上修改后,就可以开始编译了,可惜。.你会发现很多编译错误。不过没关系,我们一一解决。3、移植,修改编译错误,打开third_party\pahomqtt\MQTTPacket\samples\transport.c文件。这个文件也是我们主要的移植文件。我们需要实现socket相关的操作,包括发送和接收数据。其实移植只要3步。(1)首先,我们导入几个头文件#include"lwip/ip_addr.h"#include"lwip/netifapi.h"#include"lwip/sockets.h"(2)其次,修改transport_sendPacketBuffer函数,修改内容如下:inttransport_sendPacketBuffer(intsock,unsignedchar*buf,intbuflen){intrc=0;rc=send(sock,buf,buflen,0);returnrc;}(3)后面编译的时候会报错说关闭功能不存在。我们修改transport_close函数,修改内容如下:inttransport_close(intsock){intrc;rc=shutdown(sock,SHUT_WR);rc=recv(sock,NULL,(size_t)0,0);rc=lwip_close(sock);returnrc;}(4)修改transport.c文件后,编译的时候可能会遇到很多编译错误,因为有些局部变量没有用到,可以修改。类似这样,提示没有使用buflen的错误。你只需要写buflen=buflen;在代码中。3.9.3编写测试代码编写测试代码比较容易。主要是3个文件,内容我都贴出来了:(1)BUILD.gn文件内容:#Copyright(c)2020HuaweiDeviceCo.,Ltd.#LicensedundertheApacheLicense,Version2.0(the"License");#youmaynotusethisfileexceptincompliancewiththeLicensea.#oftheLicensea.##http://www.apache.org/licenses/LICENSE-2.0##Unlessrequiredbyapplicablelaworagreedtoinwriting,software#distributedundertheLicenseisdistributedonan"ASIS"BASIS,#WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.#SeetheLicenseforthespecificlanguagegoverningpermissionsand#limitationsundertheLicense.static_library_test("atmqt"){}mqtt_test.c","at_entry.c"]include_dirs=["//utils/native/lite/include","//kernel/liteos_m/components/cmsis/2.0","//base/iot_hardware/interfaces/kits/wifiiot_lite","//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include","//foundation/communication/interfaces/kits/wifi_lite/wifiservice","//third_party/pahomqtt/MQTTPacket/src","//third_party/pahomqtt/MQTTPacket/samples","//vendor\hisi\hi3861\hi3861\components\at\src"]}(2)at_entry.c文件主要用于注册一个AT指令后,后面可以使用AT+MQTTTEST指令测试MQTT功能其中,测试使用的mqtt服务器是我自己的服务器:106.13.62.194,大家也可以改成自己的,也可以直接使用我个人的mqtt服务器。#include#include#include"ohos_init.h"#include"cmsis_os2.h"#include#include"hi_wifi_api.h"//#include"wifi_sta.h"#include"lwip/ip_addr.h"#include"lwip/netifapi.h"#include"lwip/sockets.h"#include"MQTTPacket.h"#include"transport.h"inttoStop=0;intmqtt_connect(void){MQTTPacket_connectDatadata=MQTTPacket_connectData_initializer;intrc=0;intmysock=0;unsignedcharbuf[200];intbuflen=sizeof(buf);intmsgid=1;MQTTStringtopicString=MQTTString_initializer;intreq_qos=0;char*payload="helloHarmonyOS";intpayloadlen=strlen(payload);intlen=0;char*host="106.13.62.194";//char*host="192.168.1.102";intport=1883;mysock=transport_open(host,port);if(mysock<0)returnmysock;printf("Sendingtohostname%sport%d\n",host,port);data.clientID.cstring="我";data.keepAliveInterval=20;data.cleansession=1;data.username.cstring="测试用户";数据.password.cstring="testpassword";len=MQTTSerialize_connect(buf,buflen,&data);rc=transport_sendPacketBuffer(mysock,buf,len);/*waitforconnack*/if(MQTTPacket_read(buf,buflen,transport_getdata)==CONNACK){unsignedcharsessionPresent,connack_rc;if(MQTTDeserialize_connack(&sessionPresent,&connack_rc,buf,buflen)!=1||connack_rc!=0){printf("Unabletoconnect,returncode%d\n",connack_rc);gotoexit;}}elsegotoexit;/*订阅*/topicString.cstring="substopic";len=MQTTSerialize_subscribe(buf,buflen,0,msgid,1,&topicString,&req_qos);rc=transport_sendPacketBuffer(mysock,buf,len);if(MQTTPacket_read(buf,buflen,transport_getdata)==SUBACK)/*waitforsuback*/{unsignedshortsubmsgid;intsubcount;intgranted_qos;rc=MQTTDeserialize_suback(&submsgid,1,&subcount,&granted_qos,buf,buflen);if(granted_qos!=0){printf("grantedqos!=0,%d\n",granted_qos);gotoexit;}}elsegotoexit;/*loopgettingmsgsonsubscribedtopic*/topicString.cstring="pubtopic";while(!toStop){/*transport_getdata()具有内置的1秒超时,您的里程会有所不同*/if(MQTTPacket_read(buf,buflen,transport_getdata)==PUBLISH){unsignedchardup;intqos;unsignedcharretained;unsignedshortmsgid;intpayloadlen_in;unsignedchar*payload_in;intrc;MQTTStringreceivedTopic;rc=MQTTDeserialize_publish(&dup,&qos,&retained,&msgid,&receivedTopic,&payload_in,&payloadlen_in,buf,buflen);printf("messagearrived%.*s\n",payloadlen_in,payload_in);rc=rc;}printf("publishingreading\n");len=MQTTSerialize_publish(buf,buflen,0,0,0,0,topicString,(unsignedchar*)payload,payloadlen);rc=transport_sendPacketBuffer(mysock,buf,len);}printf("断开\n");len=MQTTSerialize_disconnect(buf,buflen);rc=transport_sendPacketBuffer(mysock,buf,len);exit:transport_close(mysock);rc=rc;return0;}voidmqtt_test(void){mqtt_connect();}mqtt_test.h文件内容:#ifndef__MQTT_TEST_H__#define__MQTT_TEST_H__voidmqtt_test(void);#endif/*__MQTT_TEST_H__*/到这里代码部分就完成了,可以开始编译了3.9.4MQTT实验这里我们需要先在Windows电脑上下载一个MQTT客户端,这样我们就可以在电脑上使用了订阅开发板的MQTT主题信息没有了。电脑版mqtt客户端下载链接:https://repo.eclipse.org/content/repositories/paho-releases/org/eclipse/paho/org.eclipse.paho.ui.app/1.1.1/我们选择这个:完成后打开软件,按图操作:运行后,我们将编译好的程序烧写到开发板上,输入以下串口命令,将开发板连入网络,因为MQTT功能需要网络支持。输入以下串口指令:AT+STARTSTA开启STA模式AT+CONN="12-203",,2,"07686582488"连接路由器,注意wifi热点名称和密码使用自己的AT+DHCP=wlan0,1获取IP地址AT+IFCFG打印查看IP地址串口命令响应如下:连接路由器成功后,请确保路由器可以上网。然后我们输入我们MQTT测试的AT指令:AT+MQTTTEST应该可以看到如下打印:此时我们去查看我们电脑上的MQTT客户端软件,可以看到右边已经收到了MQTT信息,主题不是pubtopic,message内容是helloHarmonyOS!,说明实验成功。3.9.5小结本次内容比较多,总结起来有4个步骤:(1)添加第三方软件包pahomqtt。关于如何添加第三方软件包,我之前在一篇文章中已经讲过了。可以参考:鸿蒙系统源码如何添加第三方软件包(二)移植pahomqtt(三)编写测试代码,这里我们采用注册AT命令的方式,方便大家使用AT用于测试的命令。(4)测试,这里使用电脑安装mqtt客户端程序进行验证。了解更多请访问:与华为官方共建鸿蒙科技社区https://harmonyos.51cto.com/#zz
