鸿蒙Hi3861学习十七-Huawei LiteOS-M(MQTT)

news2024/12/26 13:02:58

一、简介

        有关MQTT的相关概念介绍,请看之前的文章,这里不做过多的介绍:MQTT学习总结_t_guest的博客-CSDN博客

        本章节需要使用如下软件:

         Mosquitto(MQTT消息代理工具)

        Eclipsse paho MQTT工具

二、操作说明

        1.下载Mosquitto工具。

        点击Download | Eclipse Mosquitto进入官网。选择自己系统的下载文件。这里使用的是win10 64位系统

         2.添加配置

        安装成功后,以文件的形式打开安装文件夹中的mosquitto.conf文件。

         在Listener处添加需要监听的端口和IP。这里添加的IP为自己电脑的IP。如果不知道自己电脑的IP是多少,可以在win+r输入cmd打开终端,然后在终端中输入ipconfig来查看。

         修改allow_anonymous falseallow_anonymous true,即允许匿名登录

         Ctrl+s保存设置。

        3.启动服务

        在windows的搜索栏里边搜索服务。

         找到Mosquitto Broker服务,并且右键启动该服务。

         成功后,显示如下。

         注:每次修改mosquitto.conf文件后,都需要重新启动Mosquitto Broker服务,这样设置才会生效

        如果设置的IP不对,启动服务时会报异常。

         4.下载Eclipse Paho MQTT工具。

        点击Index of /repositories/paho-releases/org/eclipse/paho/org.eclipse.paho.ui.app/1.1.1选择对应版本进行下载。

         5.新建客户端

        解压后,点击应用文件。

        注:如果此时报错,标明当前环境下未安装JAVA环境,可以参考如下链接进行配置Windows安装JDK详细教程(图文教程) - 知乎。

         打开客户端后,点击左上角的+号新建客户端

         新建成功后会自动生成服务器地址:tcp://localhost:1883。这个就是mosquitto监控的端口。localhost就是自己的主机,所以,也可以将上述链接修改为tcp://192.168.3.199:1883(192.168.3.199是本机IP),同样是可以连接的。

         6.订阅和发布

        点击+号,添加要订阅的主题,并且点击订阅。

         输入要发布的主题,点击发布。

 三、API介绍

        NetworkInit

        函数功能:

        初始化MQTT相关的参数回调

        函数原型:

void NetworkInit(Network* n)

        参数:

        n网络参数,结构体为Network

typedef struct Network
{
	int my_socket;
	int (*mqttread) (struct Network*, unsigned char*, int, int);
	int (*mqttwrite) (struct Network*, unsigned char*, int, int);
} Network;

         my_socket:后续mqtt要使用到的描述符。

        mqttread:mqtt的回调函数

        mqttwrite:mqtt的回调函数

        返回值:

        无

        实例:

Network network;
NetworkInit(&network);

 

        NetworkConnect

        函数功能:

        连接MQTT服务器

        函数原型:

int NetworkConnect(Network* n, char* addr, int port)

        参数:

        n:网络参数描述符

        addr:要连接的服务器IP

        port:要连接的服务器端口

        返回值:

        -1:失败

        0:成功

        实例:

Network network;
NetworkConnect(&network, "192.168.3.15", 1883);

        MQTTClientInit

        函数功能:

        创建一个MQTT客户端实例

        函数原型:

void MQTTClientInit(MQTTClient* c, Network* network, unsigned int command_timeout_ms,
		unsigned char* sendbuf, size_t sendbuf_size, unsigned char* readbuf, size_t readbuf_size)

        参数:

        c客户端描述符,结构体为MQTTClient

typedef struct MQTTClient
{
    unsigned int next_packetid,    //下个包ID
      command_timeout_ms;    //指令超时时间
    size_t buf_size,    //缓冲区大小
      readbuf_size;    //读缓冲区大小
    unsigned char *buf,    //缓冲区指针
      *readbuf;    //读缓冲区指针
    unsigned int keepAliveInterval;    //保活间隔
    char ping_outstanding;    //ping 包
    int isconnected;    //已连接标志
    int cleansession;    //清除回话

    struct MessageHandlers
    {
        const char* topicFilter;    //主题文件
        void (*fp) (MessageData*);    //消息数据
    } messageHandlers[MAX_MESSAGE_HANDLERS];      /* Message handlers are indexed by subscription topic */

    void (*defaultMessageHandler) (MessageData*);    //默认消息回调

    Network* ipstack;    //IP栈
    Timer last_sent, last_received, pingresp_timer;    //最近一次的发送和接收时间戳
#if defined(MQTT_TASK)
    Mutex mutex;    //互斥锁
    Thread thread;    //任务
#endif
} MQTTClient;

         network:网络参数描述符

        command_timeout_ms:指令超时时间

        sendbuf发送缓冲区        

        sendbuf_size:缓冲区大小

        readbuf接收缓冲区

        readbuf_size:缓冲区大小

        返回值:

        无

        实例:

Network network;
MQTTClient client;
static unsigned char sendBuf[1000];
static unsigned char readBuf[1000];
MQTTClientInit(&client, &network, 2000, sendBuf, sizeof(sendBuf), readBuf, sizeof(readBuf));

        MQTTConnect

        函数功能:

        发送一个MQTT连接包到服务器,并且等待连接应答

        函数原型:

int MQTTConnect(MQTTClient* c, MQTTPacket_connectData* options)

        参数:

        c:客户端描述符,MQTTClientInit函数参数。

        options:连接参数,结构体为MQTTPacket_connectData

typedef struct
{
	/** The eyecatcher for this structure.  must be MQTC. */
	char struct_id[4];    //协议名称,固定为“MQTC”
	/** The version number of this structure.  Must be 0 */
	int struct_version;    //结构版本,固定为0
	/** Version of MQTT to be used.  3 = 3.1 4 = 3.1.1
	  */
	unsigned char MQTTVersion;    //MQTT版本
	MQTTString clientID;    //客户端ID
	unsigned short keepAliveInterval;    //保活间隔
	unsigned char cleansession;    //清除回话标志
	unsigned char willFlag;    //遗愿标志
	MQTTPacket_willOptions will;    //遗愿
	MQTTString username;    //用户名
	MQTTString password;    //密码
} MQTTPacket_connectData;

        返回值:

        0:成功

        其他值:失败

        实例:

MQTTClient client;

#define MQTTPacket_connectData_initializer { {'M', 'Q', 'T', 'C'}, 0, 4, {NULL, {0, NULL}}, 60, 1, 0, \
		MQTTPacket_willOptions_initializer, {NULL, {0, NULL}}, {NULL, {0, NULL}} }

#define MQTTString_initializer {NULL, {0, NULL}}

MQTTString clientId = MQTTString_initializer;
clientId.cstring = "Harmony";

MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
data.clientID          = clientId;	//客户端ID
data.willFlag          = 0;	//没有遗愿
data.MQTTVersion       = 3;	//MQTT版本
data.keepAliveInterval = 60;	//保活间隔
data.cleansession      = 1;	//清除会话

MQTTConnect(&client, &data);

        MQTTSubscribe

        函数功能:

        设置订阅参数

        函数原型:

int MQTTSubscribe(MQTTClient* c, const char* topicFilter, enum QoS qos,
       messageHandler messageHandler)

        参数:

        c:客户端描述符,MQTTClientInit函数参数。

        tipicFiter:订阅的主题

        qos:通讯报发送状态

QoS0:至多发送一次(可能会丢包)
QoS1:最少一次(保证包到达,可能会出现重包)
QoS2:只有一次(保证包会到达目的地,且不会出现重包)

        messageHandler:接收消息的回调函数

        返回值:

        0:成功

        其他值:失败

        实例:

MQTTClient client;
MQTTSubscribe(&client, "substopic", QOS2, messageArrived);

        MQTTPublish

        函数功能:

        发送一个MQTT发布包并且等待应答包去完成QoS

        函数原型:

int MQTTPublish(MQTTClient* c, const char* topicName, MQTTMessage* message)

        参数:

        c:客户端描述符,MQTTClientInit函数参数。

        topicName:目标主题

        message:推送的消息,结构体为MQTTMessage

typedef struct MQTTMessage
{
    enum QoS qos;    //QoS值
    unsigned char retained;    //为1时,briker应该保存该条消息,当之后有任何新的订阅主题设备上线时,都会收到这条消息。
    unsigned char dup;    //消息重发标志,为1时,表示这是一条重发的消息
    unsigned short id;    //数据包标识
    void *payload;    //有效数据负载
    size_t payloadlen;    //负载长度
} MQTTMessage;

        返回值:

        0:成功

        其他值:失败

        实例:

MQTTClient client;
MQTTMessage message;
nt rc = 0;

char payload[] = "this is a topic MQTT msg";

message.qos = 2;	//只有一次,
message.retained = 0;	//服务器不保存
message.payload = payload;	//负载
message.payloadlen = strlen(payload);	//长度

if ((rc = MQTTPublish(&client, "pubtopic", &message)) != 0){}    //失败

        MQTTYield

        函数功能:

        MQTT主动获取数据,获取到数据,会触发MQTTSubscribe订阅函数的接收回调

        函数原型:

int MQTTYield(MQTTClient* c, int timeout_ms)

        参数:

        c:客户端描述符,MQTTClientInit函数参数。

        timeout_ms:等待超时时间

        返回值:

        0:成功

        其他值:失败

        实例:

MQTTClient client;
MQTTYield(client,1000);

        注:MQTTYield不只是轮训检查MQTT读消息。在轮训过程中还会检测保活周期如果保活周期到了,就向MQTT服务器发送一个ping包来进行保活。如果在这期间有MQTT数据交互,则重新开始计数。此外需要注意的是,调用该函数后,程序会不停的执行,直到超时时间到。即该函数会占用CPU使用权,导致低优先级的任务无法执行

        NetworkDisconnect

        函数功能:

        网络连接断开,断开SOCKET

        函数原型:

void NetworkDisconnect(Network* n)

        参数:

        n:网络参数描述符,NetworkConnect函数设置

        返回值:

        无

        实例:

Network network;

NetworkDisconnect(&network);

        MQTTDisconnect

        函数功能:

        断开MQTT,向服务器发送断开数据包

        函数原型:

int MQTTDisconnect(MQTTClient* c)

        参数:

        c:客户端描述符,MQTTClientInit 函数初始化

        返回值:

        0:成功

        其他值:失败

        实例:

MQTTClient client;
MQTTDisconnect(&client);

四、实例

        这里创建一个MQTT客户端,与PC端另外一个客户端进行订阅与发布的通信。

        现在BUILD.gn文件中添加如下代码:

    include_dirs = [
        "//utild/native/lite/include",
        "//base/iot_hardware/interfaces/kits/wifiiot_lite",
        "//utils/native/lite/include",
        "//kernel/liteos_m/components/cmsis/2.0",
        "//foundation/communication/interfaces/kits/wifi_lite/wifiservice",
        "//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/",
        "//third_party/cJSON",
        "//third_party/paho_mqtt/MQTTPacket/src",
        "//third_party/paho_mqtt/MQTTClient-C/src",
        "src",
    ]

    deps = [
             "//third_party/paho_mqtt:pahomqtt_static",
    ]
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "ohos_init.h"
#include "cmsis_os2.h"
#include "MQTTClient.h"


#define LOG_I(fmt, args...)   printf("<%8ld> - [MQTT]:"fmt"\r\n",osKernelGetTickCount(),##args);
#define LOG_E(fmt, args...)   printf("<%8ld>-[MQTT_ERR]>>>>>>>>>>>>:"fmt"\r\n",osKernelGetTickCount(), ##args);


static unsigned char sendBuf[1000];
static unsigned char readBuf[1000];

Network network;

void messageArrived(MessageData* data)
{
	LOG_I("Message arrived on topic %.*s: %.*s\n", data->topicName->lenstring.len, data->topicName->lenstring.data,
		data->message->payloadlen, data->message->payload);
}

/* */

#define MQTT_IP		"192.168.3.15"
#define MQTT_PORT	1883

static void MQTT_DemoTask(void)
{
	//连接Wifi
    extern int drv_wifi_connect(const char *ssid, const char *psk);
    drv_wifi_connect("HUAWEI_ZNJJ", "znjj1230");

	LOG_I("wifi connect success,mqtt init starting ...\n");
	int rc, count = 0;
	MQTTClient client;

	NetworkInit(&network);
	LOG_I("NetworkConnect  ...,IP:%s,port:%d\n",MQTT_IP,MQTT_PORT);
begin:	
	NetworkConnect(&network, MQTT_IP, MQTT_PORT);
	LOG_I("MQTTClientInit  ...\n");
	MQTTClientInit(&client, &network, 2000, sendBuf, sizeof(sendBuf), readBuf, sizeof(readBuf));

	MQTTString clientId = MQTTString_initializer;
	clientId.cstring = "Harmony";

	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
  	data.clientID          = clientId;	//客户端ID
	data.willFlag          = 0;	//没有遗愿
	data.MQTTVersion       = 3;	//MQTT版本
	data.keepAliveInterval = 60;	//保活间隔
	data.cleansession      = 1;	//清除会话

	LOG_I("MQTTConnect  ...\n");
	rc = MQTTConnect(&client, &data);
	if (rc != 0) {
		LOG_E("MQTTConnect: %d\n", rc);
		NetworkDisconnect(&network);
		MQTTDisconnect(&client);
		osDelay(200);
		goto begin;
	}

	LOG_I("MQTTSubscribe  ...\n");
	rc = MQTTSubscribe(&client, "substopic", QOS2, messageArrived);
	if (rc != 0) {
		LOG_E("MQTTSubscribe: %d\n", rc);
		osDelay(200);
		goto begin;
	}
	
	LOG_I("MQTTSubscribe success\n");

	while (++count)
	{
		MQTTMessage message;
		char payload[30];

		message.qos = 2;	//只有一次,
		message.retained = 0;	//服务器不保存
		message.payload = payload;	//负载
		sprintf(payload, "message number %d", count);
		message.payloadlen = strlen(payload);	//长度

		if ((rc = MQTTPublish(&client, "pubtopic", &message)) != 0){
			LOG_I("Return code from MQTT publish is %d\n", rc);
			NetworkDisconnect(&network);
			MQTTDisconnect(&client);
			goto begin;
		}
		LOG_I("MQTT publish success");
		osDelay(100);	
	}
}

void app_mqtt_init(void)
{
    osThreadAttr_t attr;

    attr.name = "MQTT_DemoTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 10240;
    attr.priority = osPriorityNormal;

    if (osThreadNew((osThreadFunc_t)MQTT_DemoTask, NULL, &attr) == NULL) {
        LOG_I("[MQTT_Demo] Falied to create MQTT_DemoTask!\n");
    }
}

        这里不停的向“pubtopic”主题发送数据周期为1秒。且订阅“substopic”主题的消息,如果有,则调用messageArrived回调打印数据。

        看结果:

 

         可以看到,芯片的订阅PC的发布芯片的发布PC的订阅

        注:Eclipsse paho MQTT最好在笔记本电脑上使用,台式机可能会无法链接。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/555558.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

十款优质企业级Java微服务开源项目(开源框架,用于学习、毕设、公司项目、私活等,减少开发工作,让您只关注业务!)

Java微服务开源项目 前言一、pig二、zheng三、SpringBlade四、SOP五、matecloud六、mall七、jeecg-boot八、Cloud-Platform九、microservices-platform十、RuoYi-Cloud 前言 这篇文章为大家推荐几款优质的 Java 开源项目框架&#xff0c;可以用于学习&#xff0c;毕业设计&…

【腾讯云FinOps Crane 集训营】 Crane入门

前言 随着云计算的快速发展和云原生应用的兴起&#xff0c;容器技术成为了现代化应用部署和管理的重要工具。 越来越多的公司正在选择将应用运行在云上或者自建的 Kubernetes 集群上&#xff0c;但是许多机构的调研 发现&#xff0c;绝大多数的用户集群资源利用率并不高&…

STM8 使用74HC164外扩IO

背景 在嵌入式开发过程中&#xff0c;经常使用时、甚至设计时候&#xff0c;考虑成本等因素&#xff0c;需要外扩IO。这里就是使用STM8S003F3P6&#xff0c;这个芯片比较常用的&#xff0c;这个芯片封装很小&#xff0c;只有20个管脚的MCU&#xff0c;实际产品上用的非常多。 …

二进制部署高可用k8s集群

第一章、前置知识点 1.1 生产环境部署K8S集群的两种方式 kubeadm Kubeadm是一个K8S部署工具&#xff0c;提供kubeadm init 和 kubeadm join&#xff0c;用于快速部署Kubernetes集群。 二进制包 从GitHub下载发行版的二进制包&#xff0c;手动部署每个组件&#xff0c;组成…

Idea部署Tomcat项目位置问题

Tomcat部署路径问题 1 默认情况 Tomcat安装目录下有webapps,是部署项目的,项目就运行在那里。 但是IDEA会为每个项目都拷贝一份足够的Tomcat文件放在c盘 ${user.home}/.IntelliJIdea/system/tomcat 或者 ${user.home/AppData/Local/JetBrains/IntelliJIdea2021.1/tomcat这样做…

【MySQL新手到通关】第二章 MySQL卸载安装

文章目录 1. MySQL的卸载1.1 停止MySQL服务1.2 软件的卸载 2. MySQL的下载、安装、配置2.1 软件的下载2.2 MySQL8.0 版本的安装2.3 配置MySQL8.02.4 配置MySQL8.0 环境变量2.5 MySQL5.7 版本的安装、配置2.6 安装失败问题 3. MySQL 登录3.1 服务的启动与停止3.2 自带客户端的登…

提高效率与代码重用:使用React Native和小程序容器简化开发

React Native是一个强大的前端跨端框架&#xff0c;可以帮助开发者高效地构建移动应用程序&#xff0c;并充分利用跨平台开发的优势&#xff0c;同时提供接近原生应用程序的性能和用户体验。它具有许多技术上的优势&#xff1a; 跨平台开发&#xff1a;使用React Native&#x…

AIGC持续火爆大模型争相推出,庞大市场造就算力供应模式演变

本图由AI生成 文/王吉伟 近期的AIGC领域仍旧火爆异常。 但火的不只是AIGC应用&#xff0c;还有巨头之间的AI竞赛&#xff0c;以及接连不断上新的AI大模型&#xff08;LLM&#xff0c;Large Language Model&#xff09;。 面对ChatGPT带来的技术冲击&#xff0c;为了研发谷歌多…

Spring事务失效常见的五种方式及其解决方案【源码篇】

一、前言 在Web 开发中&#xff0c;Spring 框架已经成为了众多开发者的首选。Spring 的声明式事务管理是其中最重要的特性之一&#xff0c;它可以帮助我们简化业务逻辑的复杂度&#xff0c;并且确保在出现异常情况时数据的一致性。 事务失效情况很常见&#xff0c;但我们只要…

对计算机方向科研工作者的建议 - 易智编译EaseEditing

如果你正在进行计算机科学研究&#xff0c;以下是一些建议可以帮助你&#xff1a; 确定研究兴趣&#xff1a; 选择一个你感兴趣的研究领域或问题&#xff0c;并确保你对该领域有足够的知识基础和热情。 深入学习&#xff1a; 通过阅读学术论文、参加研讨会和课程&#xff0c;…

有意思的CVE-2022-0337复现

前言 前两天在刷tw&#xff0c;看到了个比较有意思的一个CVE漏洞&#xff0c;价值奖励是10000美&#x1f52a;&#xff0c;比较好奇的是价值10000美&#x1f52a;的漏洞是什么样子的[苦涩]&#xff0c;漏洞利用就是需要在浏览器中进行用户交互才能触发该漏洞&#xff0c;但由于…

vr船舶装配模拟驾驶平台直观形象呈现操作流程和原理

船舶由成千上万种零件构成&#xff0c;需要众多的工业部门共同合作才能够完成这一庞大工程。除特有的船体建造技术外&#xff0c;造船还涉及到机械、电气、冶金、建筑、化学以至工艺美术等各个领域&#xff0c;因此船舶建造是一项劳动密集型、技术密集型和资金密集型的产业。 船…

【OpenAI】DALL·E 2,让我来带你认识一下这位来自AI界的艺术家

个人主页&#xff1a;【&#x1f60a;个人主页】 文章目录 前言什么是DALL-E 2 &#xff1f;介绍的怎么厉害&#xff0c;它又能干啥呢&#xff1f;基本功能新功能编辑变体功能 总结 前言 DALL-E 2 是一种基于语言的人工智能图像生成器&#xff0c;可以根据文本提示创建高质量的…

【学习日记2023.5.22】 之 套餐模块完善

4. 功能模块完善之套餐模块 4.1 新增套餐 4.1.1 需求分析与设计 产品原型 后台系统中可以管理套餐信息&#xff0c;通过 新增功能来添加一个新的套餐&#xff0c;在添加套餐时需要添加套餐对应菜品的信息&#xff0c;并且需要上传套餐图片。 新增套餐原型&#xff1a; 当填…

PMP-项目经理的角色

一、项目经理的作用 项目经理在领导团队达成项目目标方面发挥着至关重要的作用。一般来说&#xff0c;项目经理从项目启动时就开始参与项目直至项目结束&#xff0c;在这个过程中&#xff0c;项目经理发挥着对项目的规划、协调、控制等作用&#xff0c;确保与产品保持一致&…

用 Python 进行办公自动化都需要学习什么知识呢?

Python 自动化办公&#xff0c;无外乎就是 excel&#xff0c;ppt&#xff0c;word&#xff0c;再加上数据分析、爬虫等技能 下面我就来逐一介绍各项技能的基本使用 基本知识 1. Python基础知识&#xff1a; 包括语法、变量、数据类型、条件语句、循环语句、函数等基本概念和用…

代码随想录训练营Day48|● 198.打家劫舍 ● 213.打家劫舍II ● 337.打家劫舍III

目录 学习目标 学习内容 198.打家劫舍 213.打家劫舍II 337.打家劫舍III 学习目标 198.打家劫舍 213.打家劫舍II 337.打家劫舍III 学习内容 198.打家劫舍 198. 打家劫舍 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/house-robber/ class Soluti…

Hexo博客查图片并调整位置大小

Hexo博客查图片并调整位置&大小 &#x1f308;Description&#xff1a; ​ Markdown写文章插入图片&#xff0c;在hexo博客中&#xff0c;图片的大小似乎没有按照个markdown的语法生效&#xff0c;本文将解决此问题。 现有问题描述 obsidian中插入图片的语法&#xff1a; !…

当四款AI大模型遇上考公真题,谁被难倒了?

在当今社会&#xff0c;人工智能&#xff08;AI&#xff09;正以不可思议的速度发展&#xff0c;并在各个领域崭露头角&#xff0c;给人们的生活和工作带来许多便利。AI大模型被誉为人类“第二大脑”&#xff0c;成为人们学习、生活、工作的 “智能助手”。 公务员考试在我国教…

firewalld防火墙

firewalld防火墙 1&#xff1a;firewalld概述 firewalld防火墙是Centos7系统默认的防火墙管理工具&#xff0c;取代了之前的iptables防火墙&#xff0c;也是工作在网络层&#xff0c;属于包过滤防火墙。firewalld和iptables都是用来管理防火墙的工具&#xff08;属于用户态&a…