W5100S_EVB_PICO 做MQTT测试(十二)

news2024/12/24 20:13:53

前言

上一章我们用W5100S_EVB_PICO 开发板做Ping测试,那么本章我们进行W5100S_EVB_PICO MQTT的测试。

什么是mqtt?

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的“轻量级”通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。

MQTT最大优点在于,用极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。

作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。

连接方式

使开发板和我们的电脑处于同一网段:

  • 开发板(设备)通过线直连主机(PC)
  • 开发板和主机都接在路由器LAN口

测试工具

  • MQTTX调试工具

MQTT主要控制报文

固定报头 Fixed header

每个MQTT控制报文都包含一个固定报头。

Bit

7

6

5

4

3

2

1

0

byte 1

MQTT控制报文的类型

用于指定控制报文类型的标志位

byte 2...

剩余长度

MQTT控制报文的类型 MQTT Control Packet type

位置:第1个字节,二进制位7-4

名字

报文流动方向

描述

Reserved

0

禁止

保留

CONNECT

1

客户端到服务端

客户端请求连接服务端

CONNACK

2

服务端到客户端

连接报文确认

PUBLISH

3

两个方向都允许

发布消息

PUBACK

4

两个方向都允许

QoS 1消息发布收到确认

PUBREC

5

两个方向都允许

发布收到(保证交付第一步)

PUBREL

6

两个方向都允许

发布释放(保证交付第二步)

PUBCOMP

7

两个方向都允许

QoS 2消息发布完成(保证交互第三步)

SUBSCRIBE

8

客户端到服务端

客户端订阅请求

SUBACK

9

服务端到客户端

订阅请求报文确认

UNSUBSCRIBE

10

客户端到服务端

客户端取消订阅请求

UNSUBACK

11

服务端到客户端

取消订阅报文确认

PINGREQ

12

客户端到服务端

心跳请求

PINGRESP

13

服务端到客户端

心跳响应

DISCONNECT

14

客户端到服务端

客户端断开连接

Reserved

15

禁止

保留

标志 Flags

固定报头第1个字节的剩余的4位 [3-0]包含每个MQTT控制报文类型特定的标志如果收到非法的标志,接收者必须关闭网络连接。

控制报文

固定报头标志

Bit 3

Bit 2

Bit 1

Bit 0

CONNECT

Reserved

0

0

0

0

CONNACK

Reserved

0

0

0

0

PUBLISH

Used in MQTT 3.1.1

DUP1

QoS2

QoS2

RETAIN3

PUBACK

Reserved

0

0

0

0

PUBREC

Reserved

0

0

0

0

PUBREL

Reserved

0

0

1

0

PUBCOMP

Reserved

0

0

0

0

SUBSCRIBE

Reserved

0

0

1

0

SUBACK

Reserved

0

0

0

0

UNSUBSCRIBE

Reserved

0

0

1

0

UNSUBACK

Reserved

0

0

0

0

PINGREQ

Reserved

0

0

0

0

PINGRESP

Reserved

0

0

0

0

DISCONNECT

Reserved

0

0

0

0

  1. DUP1 =控制报文的重复分发标志
  2. QoS2 = PUBLISH报文的服务质量等级
  3. RETAIN3 = PUBLISH报文的保留标志

剩余长度 Remaining Length(包括可变报头和负载的数据的长度)

使用变成编码(1到4个字节表示,即最大可表示256M,每个字节可编码128个数值+1个延续位(最高位是延续位表示是否有更多字节,低7位表示128个数值)):

字节数

最小值

最大值

1

0 (0x00)

127 (0x7F)

2

128 (0x80, 0x01)

16 383 (0xFF, 0x7F)

3

16 384 (0x80, 0x80, 0x01)

2 097 151 (0xFF, 0xFF, 0x7F)

4

2 097 152 (0x80, 0x80, 0x80, 0x01)

268 435 455 (0xFF, 0xFF, 0xFF, 0x7F)

可变报头 Variable header

可变报头的内容根据 控制报文类型 的不同而不同。(特别注意:部分控制报文需要 报文标识符字段)

控制报文

报文标识符字段

CONNECT

不需要

CONNACK

不需要

PUBLISH

需要(如果QoS > 0)

PUBACK

需要

PUBREC

需要

PUBREL

需要

PUBCOMP

需要

SUBSCRIBE

需要

SUBACK

需要

UNSUBSCRIBE

需要

UNSUBACK

需要

PINGREQ

不需要

PINGRESP

不需要

DISCONNECT

不需要

PUBACK, PUBREC, PUBREL报文必须包含与最初发送的PUBLISH报文相同的报文标识符,以此来标识是同一条信息如果一个客户端要重发这个特殊的控制报文,在随后重发那个报文时,它必须使用相同的标识符。

当客户端处理完这个报文对应的确认后,这个报文标识符就释放可重用。QoS 1的PUBLISH对应的是PUBACK,QoS 2的PUBLISH对应的是PUBCOMP

有效载荷 Payload

有效载荷是除控制报文格式以外的有效信息,CONNECT、PUBLISH、SUBSCRIBE等需要传递有效信息的协议帧都需要。

控制报文

有效载荷

CONNECT

需要

CONNACK

不需要

PUBLISH

可选

PUBACK

不需要

PUBREC

不需要

PUBREL

不需要

PUBCOMP

不需要

SUBSCRIBE

需要

SUBACK

需要

UNSUBSCRIBE

需要

UNSUBACK

不需要

PINGREQ

不需要

PINGRESP

不需要

DISCONNECT

不需要

官方协议文档:docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf

测试

1.相关代码

我们打开例程中库文件的mqttx_client.c文件用到如下所示几个函数:

mqtt_init是对mqtt的信息进行初始化,把配置信息填入;messageArrived函数主要作用是讲发布和订阅的信息进行判断打印keep_alive函数是一个心跳包,如果超过设定值没有发送心跳包就进行mqtt_init函数初始化。

void mqtt_init(void)
{
    int ret;

    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    NewNetwork(&n, 1);
    ConnectNetwork(&n, mqtt_params.server_ip, 1883);
    MQTTClientInit(&c, &n, 1000, mqtt_send_buff, MQTT_SEND_BUFF_SIZE, mqtt_recv_buff, MQTT_RECV_BUFF_SIZE);
    data.willFlag = 0;
    data.MQTTVersion = 3;
    data.clientID.cstring = mqtt_params.clientid;
    data.username.cstring = mqtt_params.username;
    data.password.cstring = mqtt_params.passwd;
    data.keepAliveInterval = 30;
    data.cleansession = 1;
    connOK = MQTTConnect(&c, &data);
    printf("Connected:%s\r\n", connOK == 0 ? "success" : "failed");
    printf("Subscribing to %s\r\n", mqtt_params.subtopic1);
    ret = MQTTSubscribe(&c, mqtt_params.subtopic1, mqtt_params.QOS, messageArrived);
    printf("Subscribed:%s\r\n", ret == 0 ? "success" : "failed");
   
    sleep_ms(300);
    MQTTMessage pubmessage={
        .qos=QOS2,
        .dup=0,
        .retained=0,
        .id=0,
    };
    pubmessage.payload="hello mqtt!\r\n";
    pubmessage.payloadlen=strlen(pubmessage.payload);
    MQTTPublish(&c,mqtt_params.pubtopic,&pubmessage);
}
void messageArrived(MessageData* md)
{
    unsigned char messagebuffer[512];
    MQTTMessage* message = md->message;
    if (mqtt_params.QOS)
    {
        memcpy(messagebuffer,(char*)message->payload,(int)message->payloadlen);
        *(messagebuffer + (int)message->payloadlen + 1) = '\n';
        printf("%s\r\n",messagebuffer);
    }
    if (mqtt_params.QOS)
        printf("%.*s", (int)message->payloadlen, (char*)message->payload);
    else
        printf("%s%.*s%s%s", "RX:",(int)message->payloadlen, (char*)message->payload, mqtt_params.QOS,"\r\n");
}
void keep_alive(void)
{
    if (!connOK)
    {
        if (MQTTYield(&c, 30))
        {
            mqtt_init();
        }
    }
}
  • 网络配置信息和之前的一样,还多加了mqtt的连接参数,其中的参数主要包括服务器ip,端口号,客户端id,用户名和密码(由于是本地测试,可以不需要设置用户名和密码)然后就是发布和订阅消息(必须和服务器上的一致)然后是QOS等级设置。
#define SOCKET_ID 0
#define ETHERNET_BUF_MAX_SIZE (1024 * 2)

#define MQTT_SEND_BUFF_SIZE 2048
#define MQTT_RECV_BUFF_SIZE 2048
uint8_t mqtt_send_buff[MQTT_SEND_BUFF_SIZE] = {0};
uint8_t mqtt_recv_buff[MQTT_RECV_BUFF_SIZE] = {0};
typedef struct MQTTCONNECTION
{
    char mqttHostUrl[1024];
    int port;
    char clientid[1024];
    char username[1024];
    char passwd[1024];
    uint8_t server_ip[4];
    char pubtopic[255];
    char subtopic1[255];
    int QOS;
} mqttconn;
mqttconn mqtt_params = {
    .server_ip = {54,244,173,190},
    .port = 1883,
    .clientid = "9a1d7719a8ac40d29311f26c5c5469dc",
    .username = "mqtt_username",
    .passwd = "123456",
    .pubtopic = "1234",
    .subtopic1 = "2345",
    .QOS = 0,
};
unsigned char *data_ptr = NULL;
void network_init(void);
wiz_NetInfo net_info = {
    .mac = {0x00, 0x08, 0xdc, 0x16, 0xed, 0x2e},
    .ip = {192, 168, 124, 10},
    .sn = {255, 255, 255, 0},
    .gw = {192, 168, 124, 1},
    .dns = {8, 8, 8, 8},
    .dhcp = NETINFO_STATIC};
MQTTClient c = {0};
Network n = {0};
int connOK;
bool repeating_timer_callback(struct repeating_timer *t);
void mqtt_init(void);
void messageArrived(MessageData *md);
void keep_alive(void);
wiz_NetInfo get_info;
static uint8_t ethernet_buf[ETHERNET_BUF_MAX_SIZE] = {0,};
static uint8_t destip[4]={192, 168, 124, 1};
static uint16_t destport = 8080;
static uint16_t local_port =8000;
int main()                                                          
{   
    struct repeating_timer timer;
    stdio_init_all();
    sleep_ms(2000);
    wizchip_initialize();
    wizchip_setnetinfo(&net_info);
    print_network_information(net_info);
    add_repeating_timer_ms(1, repeating_timer_callback, NULL, &timer);
    mqtt_init();
    while(true)
    {
        // loopback_udpc(SOCKET_ID, ethernet_buf, destip, destport);
        keep_alive();
        sleep_ms(10);
    }
    
}
bool repeating_timer_callback(struct repeating_timer *t)
{
    MilliTimer_Handler();
    return true;
}
  • 打开MQTTX工具信息配置好mqtt的信息(代码的信息是根据这里的进行填写)

  • 订阅和发布(对应代码上的订阅与发布信息)

2.测试现象

  • 我们可以看到串口打印信息中打印了网络连接上且配置好网络信息,最后连接上了mqttx上的mqtt公共服务器

  • 然后我们打开mqttx可以到由W5100S_EVB_PICO发来的“hello mqtt”,表示订阅成功。

  • 然后用mqttx切换到发布消息,然后将信息发送给W5100S_EVB_PICO

  • 最后可以看到串口打印了mqttx下发的消息,表示发布成功。

相关链接: 

本章例程链接:mqtt_cliten example

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

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

相关文章

Linux xargs命令继续学习

之前学习过Linux xargs,对此非常的不熟悉,下面继续学习一下; xargs 可以将管道或标准输入(stdin)数据转换成命令行参数,也能够从文件的输出中读取数据; xargs也可以给命令传递参数;…

【Linux】地址空间概念

目录 前言: 地址空间回顾 验证:一个变量是否会有两个值? 一. 什么是地址空间 虚拟地址与物理地址之间的关系 二. 地址空间是如何设计的 1. 回答一个变量两个值 2.扩展 继续深入理解 三. 为什么要有地址空间 原因: 1. 使…

触摸屏与多台 PLC之间无线Ethernet通信

在实际系统中,同一个车间里分布多台PLC,由触摸屏集中控制。通常所有设备距离在几十米到上百米不等。在有通讯需求的时候,如果布线的话,工程量较大且不美观,这种情况下比较适合采用无线通信方式。本方案以威纶通触摸屏和…

解决解析maven依赖加载卡住问题

首先找到用户设置文件的位置&#xff1a; 根据位置查找文件&#xff0c;没有则创建。 修改maven的默认镜像为阿里云镜像。 <mirror><id>alimaven</id><name>aliyun maven</name><url>http://maven.aliyun.com/nexus/content/groups/pub…

直播进入新风口:XR虚拟直播市场火爆,未来发展势不可挡

&#xfeff; 近年来&#xff0c;直播行业随着技术的不断发展&#xff0c;呈现出了蓬勃的发展态势。在这个竞争日益激烈的直播行业中&#xff0c;XR虚拟直播成为了最新的风口。XR虚拟直播是一种新型的直播形式&#xff0c;通过虚拟现实技术&#xff0c;让用户置身于直播现场&a…

使用生成式 AI 增强亚马逊云科技智能文档处理

数据分类、提取和分析对于处理大量文档的组织来说可能具有挑战性。传统的文档处理解决方案是手动的、昂贵的、容易出错的,并且难以扩展。利用 Amazon Textract 等 AI 服务,亚马逊云科技智能文档处理(IDP)允许您利用业界领先的机器学习(ML)技术来快速准确地处理任何扫描文档或图…

MySQL 枚举类型如何定义比较好 tinyint?enum?varchar?

enum介绍 先来介绍一下enum类型吧。 ENUM 是一个字符串对象&#xff0c;其值通常选自一个允许值列表中&#xff0c;该列表在表创建时的列规格说明中被明确地列举。&#xff08;建表的时候写到建表语句里&#xff09; 虽然表面是字符串值&#xff0c;但其内部是数字索引&…

Nvidia vpi2 不是最新版本问题

问题&#xff1a; 根据官方手册&#xff1a;VPI - Vision Programming Interface: Installation安装的vpi2有可能不是最新版本&#xff0c;主要原因是手册中的添加的源不是最新的。 解决方法&#xff1a; 在 Index网址中搜索 vpi&#xff0c;如下 可以看到&#xff0c;最新的…

【数字通信原理】笔记(持续更新ing)

通信原理学习笔记&#xff0c;课程见b站: 由于教材不同&#xff0c;我们的课程使用的是《数字通信原理》主编:李白萍 版本&#xff0c;因此此笔记以我们的教材为主整理up主的笔记。 详情见:通信原理 文章目录 第一章 绪论1. 通信的基本概念2. 信息的量度3. 通信系统的性能指标 …

Mars3d图层树//图层管理加载时设置默认折叠的状态

问题&#xff1a;Mars3d图层树//图层管理加载时设置默认折叠的状态。 设置参考&#xff1a; 有个参数 open:false&#xff0c;写在对应的图层配置下&#xff0c;比如某个节点不展示&#xff0c;就对这个节点配置下。 如果全局&#xff0c;可以搜下这个widget内的代码&#xff…

YOLO目标检测——赛马数据集下载分享

目标检测赛马数据集在马匹竞赛、马匹健康监测、马匹行为研究、马匹安全监控和马匹图像检索等应用场景中具有广泛的应用潜力&#xff0c;可以为马匹产业的发展和管理提供有力支持 数据集点击下载&#xff1a;YOLO赛马数据集640图片标框.rar 更多数据集下载和效果展示&#x…

Nature Medicine:GWAS揭示抑郁症与其他精神疾病风险之间的关联

几乎五分之一的丹麦人在一生中经历过抑郁症。奥尔胡斯大学的一项新研究现在表明&#xff0c;抑郁症的遗传风险与其他精神病诊断的遗传风险增加相关。这项研究于2023年7月18日发表在《Nature Medicine》&#xff08;IF202282.9&#xff09;杂志上。 研究人员分析了130万人&#…

高光谱图像超分辨率-总

高光谱图像超分辨率 高光谱图像超分辨率 高光谱图像超分辨率一、基础内容1.1 高光谱图像特点1.2 研究现状1.3 高光谱图像数据集1.4 评价指标1.5 Wald**协议**二、文献阅读清单2.1 综述+先锋工作1.提出解混的思想。2.随机混合模型在高光谱分辨率增强中的应用。3.遥感中的多光谱和…

MySQL基础(六)流程控制、游标、触发器、窗口函数

目录 定义条件与处理程序 定义条件 定义处理程序 流程控制 IF 分支结构之 CASE 循环结构之LOOP 循环结构之WHILE 循环结构之REPEAT 跳转语句leave和iterate 游标 使用游标步骤 全局变量的持久化 触发器 触发器的使用 查看触发器 删除触发器 定义条件与处理程序 …

基于 LLM 的知识图谱另类实践

本文整理自社区用户陈卓见在「夜谈 LLM」主题分享上的演讲&#xff0c;主要包括以下内容&#xff1a; 利用大模型构建知识图谱利用大模型操作结构化数据利用大模型使用工具 利用大模型构建知识图谱 上图是之前&#xff0c;我基于大语言模型构建知识图谱的成品图&#xff0c;主…

【Java从0到1学习】14 Java多线程

1. 多线程概述 人们在日常生活中&#xff0c;很多事情都是可以同时进行的。例如&#xff0c;一个人可以一边听音乐&#xff0c;一边打扫房间&#xff0c;可以一边吃饭&#xff0c;一边看电视。在使用计算机时&#xff0c;很多任务也是可以同时进行的。例如&#xff0c;可以一边…

Android逆向学习(番外一)smali2java部分文件无法反编译的bug与修复方法

Android逆向学习&#xff08;番外一&#xff09;smali2java部分文件无法反编译的bug与修复方法 一、前言 昨天我和往常一样准备着android逆向&#xff08;四&#xff09;的博客&#xff0c;结果发现smali2java对某些文件无法进行逆向&#xff0c;我不知道windows会不会产生这…

安全运营中心(SOC)技术框架

2018年曾经画过一个安全运营体系框架&#xff0c;基本思路是在基础单点技术防护体系基础上&#xff0c;围绕着动态防御、深度分析、实时检测&#xff0c;建立安全运营大数据分析平台&#xff0c;可以算作是解决方案产品的思路。 依据这个体系框架&#xff0c;当时写了《基于主动…

C++零碎记录(三)

作者&#xff1a;小王同学在积累 链接&#xff1a;https://www.zhihu.com/question/437657370/answer/1692846096 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 5. 构造函数和析构函数 5.1 构造函数和析构函数的…

史上最全的计算机发展编年史!!!

今天分享给大家&#xff0c;以供参考。 1614年 苏格兰人约翰纳皮尔&#xff08;John Napier&#xff09;发表了一篇论文&#xff0c;其中提到他发明了一种可以计算四则运算和方根运算的精巧装置。 1623年 威廉契克卡德&#xff08;Wilhelm Schickard&#xff09;制作了一个通过…