MQTT 是当前最主流的物联网通信协议,需要物联网云平台,例如华为云、阿里云、移动OneNET都支持mqtt。而Hi3861则是一款专为IoT应用场景打造的芯片。本节主要讲如何在鸿蒙系统中通过移植第3方软件包 paho mqtt去实现MQTT协议功能,最后会给出测试验证。为后续的物联网项目打好基础。

友情预告,本节内容较多,源码也贴出来了,大家最好先看一遍,然后再操作一次。

相关源码已经打包上传,顺便上传了一个测试OK的固件,大家可以直接下载附件直接测试。解压后会得到5个压缩包,继续解压即可

3.9.1 MQTT介绍

MQTT 全称为 Message Queuing Telemetry Transport(消息队列遥测传输)是一种基于发布/订阅范式的二进制“轻量级”消息协议,由IB公司发布。针对于网络受限和嵌入式设备而设计的一种数据传输协议。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。MQTT模型如图所示。

更多MQTT协议的介绍见这篇文章: MQTT 协议开发入门

3.9.2 移植 paho mqtt软件包

1. 下载paho mqtt软件包,添加到鸿蒙代码中

paho mqtt-c 是基于C语言实现的MQTT客户端,非常适合用在嵌入式设备上。首先下载源码:

https://github.com/eclipse/paho.mqtt.embedded-c

下载之后解压,会得到这么一个文件夹:

我们在鸿蒙系统源码的 third_party 文件夹下创建一个 pahomqtt 文件夹,然后把解压后的所有文件都拷贝到 pahomqtt 文件夹下,目录结构大致如下:

下一步,我们在pahomqtt 文件夹下面新建BUILD.gn文件,用来构建编译。其内容如下:

# Copyright (c) 2020 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.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编译的时候,编译 paho mqtt软件包

打开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 函数,内容修改后如下:

int transport_sendPacketBuffer(int sock, unsigned char* buf, int buflen)
{int rc = 0;rc = send(sock, buf, buflen, 0);return rc;
}

(3)后面编译的时候会报错说 close 函数不存在,我们修改 transport_close 函数,修改后内容如下:

int transport_close(int sock)
{
int rc;rc = shutdown(sock, SHUT_WR);rc = recv(sock, NULL, (size_t)0, 0);rc = lwip_close(sock);return rc;
}

(4)修改完 transport.c 文件后,大家编译的时候估计会遇到很多编译错误,都是某个局部变量未使用那种,大家可以修改就行。

类似于这样的,提示 buflen 未使用的错误,大家只需要在代码中随便写个buflen = buflen ; 即可。

3.9.3 编写测试代码

测试代码比较好写。主要是3个文件,内容我都贴出来了:

(1)BUILD.gn文件内容:

# Copyright (c) 2020 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.static_library("mqtt_test_at") {sources = ["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功能。代码内容如下:

#include <stdio.h>#include <unistd.h>#include "ohos_init.h"
#include "cmsis_os2.h"#include <unistd.h>#include <at.h>
#include <hi_at.h>#include "hi_wifi_api.h"#include "mqtt_test.h"void mqtt_test_thread(void * argv)
{argv = argv;mqtt_test();}hi_u32 at_exe_mqtt_test_cmd(void)
{osThreadAttr_t attr;attr.name = "wifi_config_thread";attr.attr_bits = 0U;attr.cb_mem = NULL;attr.cb_size = 0U;attr.stack_mem = NULL;attr.stack_size = 4096;attr.priority = 36;if (osThreadNew((osThreadFunc_t)mqtt_test_thread, NULL, &attr) == NULL) {printf("[LedExample] Falied to create LedTask!\n");}AT_RESPONSE_OK;return HI_ERR_SUCCESS;
}const at_cmd_func g_at_mqtt_func_tbl[] = {{"+MQTTTEST", 9, HI_NULL, HI_NULL, HI_NULL, (at_call_back_func)at_exe_mqtt_test_cmd},
};void AtExampleEntry(void)
{hi_at_register_cmd(g_at_mqtt_func_tbl, sizeof(g_at_mqtt_func_tbl)/sizeof(g_at_mqtt_func_tbl[0]));
}SYS_RUN(AtExampleEntry);

(3)mqtt_test.c 文件则是编写了一个简单的MQTT测试代码

,具体代码讲解,后面会重新开一篇。其中测试用的mqtt服务器是我自己的服务器:106.13.62.194

大家也可以改成自己的,也可以直接用我个人的mqtt服务器。

#include <stdio.h>#include <unistd.h>#include "ohos_init.h"
#include "cmsis_os2.h"#include <unistd.h>
#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"int toStop = 0;int mqtt_connect(void)
{MQTTPacket_connectData data = MQTTPacket_connectData_initializer;int rc = 0;int mysock = 0;unsigned char buf[200];int buflen = sizeof(buf);int msgid = 1;MQTTString topicString = MQTTString_initializer;int req_qos = 0;char* payload = "hello HarmonyOS";int payloadlen = strlen(payload);int len = 0;char *host = "106.13.62.194";//char *host = "192.168.1.102";int port = 1883;mysock = transport_open(host, port);if(mysock < 0)return mysock;printf("Sending to hostname %s port %d\n", host, port);data.clientID.cstring = "me";data.keepAliveInterval = 20;data.cleansession = 1;data.username.cstring = "testuser";data.password.cstring = "testpassword";len = MQTTSerialize_connect(buf, buflen, &data);rc = transport_sendPacketBuffer(mysock, buf, len);/* wait for connack */if (MQTTPacket_read(buf, buflen, transport_getdata) == CONNACK){unsigned char sessionPresent, connack_rc;if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) != 1 || connack_rc != 0){printf("Unable to connect, return code %d\n", connack_rc);goto exit;}}elsegoto exit;/* subscribe */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)  /* wait for suback */{unsigned short submsgid;int subcount;int granted_qos;rc = MQTTDeserialize_suback(&submsgid, 1, &subcount, &granted_qos, buf, buflen);if (granted_qos != 0){printf("granted qos != 0, %d\n", granted_qos);goto exit;}}elsegoto exit;/* loop getting msgs on subscribed topic */topicString.cstring = "pubtopic";while (!toStop){/* transport_getdata() has a built-in 1 second timeout,your mileage will vary */if (MQTTPacket_read(buf, buflen, transport_getdata) == PUBLISH){unsigned char dup;int qos;unsigned char retained;unsigned short msgid;int payloadlen_in;unsigned char* payload_in;int rc;MQTTString receivedTopic;rc = MQTTDeserialize_publish(&dup, &qos, &retained, &msgid, &receivedTopic,&payload_in, &payloadlen_in, buf, buflen);printf("message arrived %.*s\n", payloadlen_in, payload_in);rc = rc;}printf("publishing reading\n");len = MQTTSerialize_publish(buf, buflen, 0, 0, 0, 0, topicString, (unsigned char*)payload, payloadlen);rc = transport_sendPacketBuffer(mysock, buf, len);}printf("disconnecting\n");len = MQTTSerialize_disconnect(buf, buflen);rc = transport_sendPacketBuffer(mysock, buf, len);
exit:transport_close(mysock);rc = rc;return 0;
}void mqtt_test(void)
{mqtt_connect();
}

mqtt_test.h文件内容:

#ifndef __MQTT_TEST_H__
#define __MQTT_TEST_H__void mqtt_test(void);#endif /* __MQTT_TEST_H__ */

到这里就完成了代码部分,可以开始编译了。

3.9.4 MQTT实验

这里我们需要先下载一个 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,消息内容为 hello HarmonyOS ! ,说明实验成功。

3.9.5 总结

这一次的内容比较多,其中总结起来就4步:

(1)添加第三方软件包 paho mqtt,关于如何添加第3方软件包,我之前有一篇文章已经讲了。

可以参考:如何往鸿蒙系统源码中添加第三方软件包

(2)移植 paho mqtt

(3)编写测试代码,这里我们用的是注册AT指令的方式,方便大家使用AT指令测试。

(4)测试,这里用电脑装mqtt客户端程序,去验证。

如何在鸿蒙系统中移植 Paho-MQTT 实现MQTT协议相关推荐

  1. Kanzi制作的应用能在鸿蒙系统中运行吗?

    物联网技术近年来得到了长足的发展和普及,其实际应用包括智能家居.智慧交通.无人驾驶等.而随着这些的广泛应用,要实现万物互联,就需要一种新的操作系统. 这时候,鸿蒙出现了! 图片来自网络 01 如果说2 ...

  2. 鸿蒙系统的结构图,一图看懂鸿蒙系统中的JS开发框架!

    原标题:一图看懂鸿蒙系统中的JS开发框架! " 前端这两年玩起来了三国杀,Vue,React,Angular 三足鼎立,其中 Vue 派系在国内打的 Angular 找不到北了. 因此,小程 ...

  3. 奇舞周刊第 363 期:鸿蒙系统中的 JS 开发框架

    记得点击文章末尾的" 阅读原文 "查看哟~ 下面先一起看下本期周刊 摘要 吧~ 奇舞推荐 ■ ■ ■ 硬核看房利器--Web 全景的实现 从文字到图片到声音再到视频,是目前所广泛使 ...

  4. 苹果遭集体诉讼;华为或年底推出鸿蒙系统中低端智能手机;Facebook雇人记录用户语音通话以改善AI技术……...

    戳蓝字"CSDN云计算"关注我们哦! 嗨,大家好,重磅君带来的[云重磅]特别栏目,如期而至,每周五第一时间为大家带来重磅新闻.把握技术风向标,了解行业应用与实践,就交给我重磅君吧! ...

  5. 鸿蒙系统中的 WebView 加载H5页面出现net::ERR_CLEARTEXT_NOT_PERMITTED的解决方法

    目前在学习鸿蒙系统开发相关的应用,在加载H5页面的时候,在页面上显示出现这也错误提示 net::ERR_CLEARTEXT_NOT_PERMITTED,百度了一番,显示的结果都是在安卓系统上的解决办法 ...

  6. 揭秘鸿蒙系统中的 JS 开发框架

    作者 | justjavac 来源 | justjavac 今天鸿蒙终于发布了,开发者们也终于"沸腾"了. 源码托管在国内知名开源平台码云上,https://gitee.com/o ...

  7. 鸿蒙系统中的 JS 开发框架

    今天鸿蒙终于发布了,开发者们也终于"沸腾"了. 源码托管在国内知名开源平台码云上,https://gitee.com/openharmony 我也第一时间下载了源码,研究了一个晚上 ...

  8. STM32F407中的RT-thread系统中移植LCD的程序-FSMC控制

    环境 开发板:正点原子探索者 芯片:STM32F407ZGT6 系统:RT-Thread 屏幕型号:TFTLCD 55510 4.3寸 开发软件:Keil,CubeMX, Env 目的 现在将裸板上的 ...

  9. 华为的鸿蒙系统是安卓吗,华为鸿蒙,一个本属于2025年的产品

    本文作者:老局长,头图来自:视觉中国 2020年9月10日,在东莞的松山湖,华为在"全球开发者大会"上高调地发布了"鸿蒙OS 2.0"操作系统. 去年差不多也是 ...

最新文章

  1. android仿微博头像_Android 仿instagram和微博的头像点击加载动画
  2. Terrarium 1.2
  3. macos 安装python3.8 版本_用python安装cutadapt程序
  4. oracle 0 函数吗,Oracle9.2.0.1版函数编译一个小问题
  5. Nginx的安全控制及SSL加密介绍
  6. 苏州,遇见NXP痞子衡
  7. CVE-2019-0708漏洞补丁KB4499175
  8. 《图解算法》学习之算法复杂度、运行时间
  9. 温度反转效应(文末附2018数字IC后端最新校招笔试题目)
  10. @Autowired和@Resource的区别
  11. android 拨打带有分机号的电话
  12. Mac电脑:您的安全性偏好设置仅允许安装来自App Store和被认可的开发者的应用(解决方法)
  13. 大数据平台搭建及集群规划
  14. R语言与多元线性回归方程及各种检验
  15. 盲子强巴(连载)二、
  16. Pinbox 使用快捷键打开网页
  17. 【UPCOJ】10155问题 S: 近似排序
  18. python 如何安装numpy库?
  19. imx6 修改CPU频率
  20. 可选参数和非可选参数python_python – Argparse:必需的参数列在“可选参数”下?...

热门文章

  1. 2022 CCF BDCI 返乡发展人群预测 [0.9117+]
  2. (震撼实拍)垃圾场里发奋学习的兄妹俩
  3. 以下名字 不能作为c语言标识符的是,(完整版)《C语言程序设计》复习参考答案...
  4. 全国手机短信中心号码
  5. 国产自研芯片取得的进展,连外媒都认可了,ARM真怕了
  6. 查看虚拟机vmware下linux的ip
  7. 产业分析:短视频平台研究报告
  8. 基于SPR-Fano共振的光纤传感器研究
  9. aspectj框架切入点表达式
  10. linux中.la是什么文件,linux下的so、o、lo、a、la文件有什么区别?