当前位置: 首页 > news >正文

MQTTS连接adafruit平台示例

目录

MQTTS简介

MQTTS特点

Adafruit IO 平台简介

Adafruit IO Feed 数据流介绍

MQTT连接 Adafruit IO 收发数据流程

实现过程

运行结果

总结


本篇文章我们将详细介绍如何在W55MH32芯片上面实现MQTTS协议。并通过实战例程,为大家讲解如何使用W55MH32的MQTTS协议连接Adafruit IO 物联网平台。实现设备与云端的双向数据交互。

该例程用到的其他网络协议,例如 TCP和 DNS以及 DHCP ,请参考相关章节。有关W55MH32的初始化过程,请参考Network install章节,这里将不再详述。

MQTTS简介

MQTTS (MQTT Secure / MQTT over SSL/TLS) 是标准MQTT协议的安全增强版本,通过在TCP连接之上引入SSL/TLS加密层,为物联网通信提供全方位的安全保障。它广泛应用于金融支付、智能家居、医疗健康和工业控制等对数据隐私要求极高的领域。MQTTS协议在保留MQTT轻量、高效特性的同时,解决了公网传输中的数据泄露风险,特别适用于需要通过非安全网络(如公共互联网)传输敏感数据的嵌入式系统。

MQTTS特点

  • 数据加密:MQTTS利用SSL/TLS协议对传输的所有数据包进行加密,有效防止数据在传输过程中被窃听或抓包分析,确保信息的机密性。
  • 身份认证:支持单向认证(客户端验证服务器证书)和双向认证(MTLS,服务器验证客户端证书),能够确保只有合法的设备和服务器才能建立连接。
  • 数据完整性:通过TLS的消息认证机制,确保数据在传输过程中未被恶意篡改或意外损坏,保证指令和数据的准确执行。
  • 无缝兼容:上层应用逻辑(发布/订阅、QoS等)与普通MQTT完全一致,开发者无需修改业务代码,仅需配置安全证书和端口即可实现安全升级。

Adafruit IO 平台简介

Adafruit IO 是由 Adafruit Industries 开发的免费物联网数据平台,在物联网设备与云端应用之间搭建轻量、高效、易用的连接桥梁。该平台支持 MQTT/MQTTS 协议及 RESTful API,可实现传感器数据、设备状态的实时上传与可视化展示,提供丰富的 Dashboard 组件和自动化规则引擎,以支撑创客项目、教育实验及智能硬件原型的快速开发。

Adafruit IO Feed 数据流介绍

Feed(数据流)是 Adafruit IO 平台中用于组织和传输设备数据的核心单元,它定义了数据的名称、类型、存储策略和访问权限,使设备与云端之间的数据交互更加结构化和可管理。在 Adafruit IO 平台中,Feed 是数据管理与应用开发的核心概念,通过 Feed,开发者可以方便地对传感器数据进行分类存储、实时查询和历史回溯。

MQTT连接 Adafruit IO 收发数据流程

接下来,我们在 W55MH32 上实现基于 MQTTS 协议连接 Adafruit IO 平台的功能。整个流程可以分为以下几个步骤:网络参数配置、Adafruit IO 账号信息配置、MQTTS 参数初始化、TLS 安全连接建立、MQTT 连接建立,以及发布/订阅数据。

1. 准备阶段

首先需要登录 Adafruit IO 平台并完成以下配置:

  1. 注册并登录 Adafruit IO 账号
  2. 记录当前账号的用户名
  3. 获取当前账号的 AIO Key
  4. 创建业务所需的 Feed

本例中创建的 Feed 为:

  • temperature
  • humidity
  • led
  • beep

例如:

  • 用户名(Username):你的 Adafruit IO 用户名
  • AIO Key:你的平台访问密钥
  • Feed 名称:例如ledtemperaturebeep

2. 记录参数

在设备接入前,需要记录以下 MQTT 参数:

  • 1. mqttHostUrl
  • 2. port
  • 3. clientid
  • 4. username
  • 5. passwd
  • 6. pubtopic
  • 7. subtopic
mqttconn mqtt_params = { .mqttHostUrl = "io.adafruit.com", .server_ip = {0}, #ifdef MQTTS .port = 8883, #else .port = 1883, #endif .local_port = 5000, .clientid = "5545_adafruit_io_connection", .username = "5545", .passwd = "aio_wLFi94popH35ahVrN1xdKqxzTMIW", .pubtopic = "5545/feeds/temperature", .subtopic = "5545/feeds/led", .pubQoS = QOS0, };

3. 连接、订阅和发布消息

完成参数配置后,设备侧执行如下步骤:

  1. DHCP 获取网络参数
  2. DNS 解析io.adafruit.com
  3. 建立 TCP 连接
  4. 初始化 TLS
  5. 执行 SSL/TLS 握手
  6. 建立 MQTT 连接
  7. 订阅 LED 控制 Topic
  8. 周期性发布传感器数据

4. 接受消息处理

当设备接收到云端消息后,先在messageArrived()中保存接收到的 Topic 和 Payload,然后在do_mqtt()RECV分支中解析消息并执行对应控制。

本例中仅以LED为展示,最终实现了以下控制逻辑:

  • 收到0:LED 点亮
  • 收到1:LED 熄灭

ⓘ请注意:

本工程中板载 LED 为低电平点亮,因此 LED ON 对应的是GPIO_ResetBits(LED_PORT, LED_PIN),LED OFF 对应的是GPIO_SetBits(LED_PORT, LED_PIN)

实现过程

接下来,我们看看在W55MH32上如何实现MQTT连接Adafruit IO平台,并进行订阅、发布消息以及接收消息处理。

步骤1:注册MQTT定时中断函数MilliTimer_Handler()到1ms定时器中断中

void TIM3_IRQHandler(void) { static uint32_t tim3_1ms_count = 0; if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) { tim3_1ms_count++; MilliTimer_Handler(); if (tim3_1ms_count >= 1000) { DHCP_time_handler(); DNS_time_handler(); tim3_1ms_count = 0; } TIM_ClearITPendingBit(TIM3, TIM_IT_Update); } }

步骤2:mqtt初始化

void mqtt_init(uint8_t sn, uint8_t *send_buf, uint8_t *recv_buf) { wiz_NetInfo get_info = {0}; wizchip_getnetinfo(&get_info); if (do_dns(send_buf, (uint8_t *)mqtt_params.mqttHostUrl, mqtt_params.server_ip)) { while (1); } #ifdef MQTTS wiz_tls_socket(&tlsContext, sn, mqtt_params.local_port); wiz_tls_init(&tlsContext, 2000, mqtt_params.mqttHostUrl, NULL, NULL, NULL); NewNetwork(&n, sn); n.mqttread = tls_mqtt_read; n.mqttwrite = tls_mqtt_write; n.disconnect = tls_mqtt_disconnect; connect(tlsContext.socket_fd, (uint8_t *)mqtt_params.server_ip, mqtt_params.port); wiz_tls_connect(&tlsContext, mqtt_params.mqttHostUrl, mqtt_params.port); mbedtls_ssl_conf_read_timeout(tlsContext.conf, 2000); MQTTClientInit(&c, &n, 2000, send_buf, MQTT_ETHERNET_MAX_SIZE, recv_buf, MQTT_ETHERNET_MAX_SIZE); #else NewNetwork(&n, sn); ConnectNetwork(&n, mqtt_params.server_ip, mqtt_params.port); MQTTClientInit(&c, &n, 1000, send_buf, MQTT_ETHERNET_MAX_SIZE, recv_buf, MQTT_ETHERNET_MAX_SIZE); #endif }

步骤3:进入do_mqtt()函数]

void do_mqtt(void) { uint8_t ret; switch (run_status) { case CONN: { ret = MQTTConnect(&c, &data); printf("Connect to the MQTT server: %d.%d.%d.%d:%d\r\n", mqtt_params.server_ip[0], mqtt_params.server_ip[1], mqtt_params.server_ip[2], mqtt_params.server_ip[3], mqtt_params.port); printf("Connected:%s\r\n\r\n", ret == SUCCESSS ? "success" : "failed"); if (ret != SUCCESSS) { run_status = ERR; } else { run_status = SUB; } break; } case SUB: { ret = MQTTSubscribe(&c, mqtt_params.subtopic, mqtt_params.subQoS, messageArrived); printf("Subscribing to %s\r\n", mqtt_params.subtopic); printf("Subscribed:%s\r\n\r\n", ret == SUCCESSS ? "success" : "failed"); if (ret != SUCCESSS) { run_status = ERR; } else { run_status = PUB_MESSAGE; } break; } case PUB_MESSAGE: { if (mqtt_send_flag) { mqtt_send_flag = 0; pubmessage.qos = QOS0; sprintf(pubmessage.payload, "{\"feeds\":{\"led\":%d,\"beep\":%d,\"humidity\":%.2f,\"temperature\":%.2f}}", GPIO_ReadOutputDataBit(LED_PORT, LED_PIN), GPIO_ReadOutputDataBit(BEEP_PORT, BEEP_PIN), SENx.RH, SENx.T); pubmessage.payloadlen = strlen(pubmessage.payload); ret = MQTTPublish(&c, (char *)&(mqtt_params.pubtopic), &pubmessage); if (ret != SUCCESSS) { run_status = ERR; } else { printf("publish:%s,%s\r\n\r\n", mqtt_params.pubtopic, (char *)pubmessage.payload); } } /* no break, continue to KEEPALIVE */ } case KEEPALIVE: { if (MQTTYield(&c, 30) != SUCCESSS) { run_status = ERR; } /* no break, continue to RECV */ } case RECV: { if (mqtt_recv_flag) { mqtt_recv_flag = 0; if (strcmp((char *)mqtt_recv_msg, "0") == 0) { GPIO_ResetBits(LED_PORT, LED_PIN); printf("LED ON\r\n"); } else if (strcmp((char *)mqtt_recv_msg, "1") == 0) { GPIO_SetBits(LED_PORT, LED_PIN); printf("LED OFF\r\n"); } else { json_decode((char *)mqtt_recv_msg); } } break; } case ERR: printf("system ERROR!"); delay_ms(1000); break; default: break; } }

进入该函数后,程序首先根据当前运行状态执行对应的 MQTT 操作。当状态为 CONN 时,程序会调用 MQTTConnect() 尝试连接 Adafruit IO 的 MQTT 服务器;如果连接成功,则将运行状态切换为 SUB,进入主题订阅流程;如果连接失败,则进入 ERR 错误状态,并在串口打印错误信息。当状态进入 RECV 时,程序会对接收到的下行消息进行判断:若消息内容为 0,则点亮 LED;若消息内容为 1,则熄灭 LED;若接收到的是其他格式数据,则继续交由 json_decode() 进行解析处理。

步骤4:接收消息处理机制

void messageArrived(MessageData *md) { static char msg[512] = {0}; sprintf(msg, "%.*s", (int)md->message->payloadlen, (char *)md->message->payload); mqtt_recv_flag = 1; memset(mqtt_recv_msg, 0, sizeof(mqtt_recv_msg)); memcpy(mqtt_recv_msg, msg, strlen(msg)); }

当设备收到 Adafruit IO 平台下发的订阅消息后,会先进入messageArrived()回调函数。该函数负责提取接收到的 Topic 和 Payload,并将消息保存到接收缓冲区,同时置位接收标志。随后,主状态机在RECV分支中检测该标志,对消息内容进行解析,并完成 LED 控制。

case RECV: { if (mqtt_recv_flag) { mqtt_recv_flag = 0; if (strcmp((char *)mqtt_recv_msg, "0") == 0) { GPIO_ResetBits(LED_PORT, LED_PIN); } else if (strcmp((char *)mqtt_recv_msg, "1") == 0) { GPIO_SetBits(LED_PORT, LED_PIN); } } break; }

运行结果

ⓘ请注意:

因为本示例需要访问互联网,请确保 W55MH32 的网络环境及配置能够正常访问互联网。

烧录例程运行后,程序首先进行 PHY 链路检测,然后通过 DHCP 获取网络参数,并完成 DNS 解析与 TLS 握手,最后连接 Adafruit IO 平台的 MQTT 服务器进行通信测试。连接成功后,设备会订阅 5545/feeds/led 主题,并周期性向 5545/feeds/temperature 主题发布温湿度及状态数据;当平台下发 LED 控制消息时,设备可正确接收并执行对应控制操作,如下图所示:

然后我们在 Adafruit IO 平台的 led Feed 页面中写入控制数据,对板载 LED 状态进行远程控制。此时 W55MH32 会接收到平台下发的订阅消息,并根据消息内容执行对应操作。当写入 0 时,设备执行 LED ON;当写入 1 时,设备执行 LED OFF,如下图所示:

从串口输出结果可以看出,设备已经成功接收到 Adafruit IO 平台下发的控制消息,并根据消息内容完成 LED 亮灭控制。同时,平台侧也能够记录对应的 Feed 数据变化情况,如下图所示:

总结

本文讲解了如何在 W55MH32 芯片上实现 MQTT 协议,并连接 Adafruit IO 平台,通过实战例程展示了从准备工作、网络配置、TLS 安全连接建立、MQTT 消息订阅、发布及接收处理的完整过程。文章详细介绍了 MQTT 协议的基本概念、发布/订阅模式以及 Adafruit IO 平台的接入方式,同时结合实际测试验证了设备与平台之间的数据交互功能。

下一篇文章将继续介绍 RT-Thread + TCP 相关示例,讲解如何在 W55MH32 平台上基于 RT-Thread 实现 TCP 通信功能,进一步展示设备在网络数据收发场景下的应用方法,敬请期待!

http://www.jsqmd.com/news/730206/

相关文章:

  • 对比直接使用官方 API,通过 Taotoken 聚合调用带来的管理便利
  • 春季儿童长高攻略:抓住长高黄金期
  • 3D模型渐进式对齐技术Interp3D解析与应用
  • 2026年保姆级教程|4000内全配重电钢琴测评,新手避坑不毁手型
  • AI自动化集成:atlassian-skill实现Jira与Confluence智能操作
  • 失业创业决定:10年程序员,我决定给自己打工
  • 几乎适用于所有传感器——通用数据采集器的接口与测量能力详解|笛远科技
  • 吉林省 CPPM 报名(美国采购协会)SCMP 报名(中物联)授权招生报名中心及联系方式 - 众智商学院课程中心
  • 3步快速上手:Windows虚拟串口驱动完全指南
  • 9.【Verilog】Verilog 延迟反标注
  • 如何彻底解决华硕笔记本显示色彩异常问题:G-Helper终极修复指南
  • AI编程新范式:用cursor-flow实现结构化、可复现的AI辅助开发流程
  • 混合信号IC设计验证:挑战与HiPer仿真解决方案
  • 2026年3M广告灯箱实力厂商调研:聚隆运灯箱为何成为连锁品牌优选解决方案?
  • 大厂不会告诉你的秘密:你的AI对话背后,一半的GPU算力都在“空转”
  • 如何快速上手MIT App Inventor:零基础开发Android和iOS应用的完整指南
  • 【花雕学编程】Arduino BLDC 之机器人双超声波PID跟随系统
  • 【入门实战】5分钟上手 ai-light-report:用自然语言驱动你的第一张智能报表
  • 算法第二十一天
  • 别再只聊BERT了!重新审视GPT-1:为什么说‘预训练+微调’的范式革新比模型结构更重要?
  • Arm SVE2指令集STNT1W:非临时存储优化技术解析
  • 广和通L610 OpenCPU开发踩坑实录:从Coolwatcher抓LOG到解决MQTT连接超时
  • 独立站搭建多少钱?
  • 10.【Verilog】Verilog 同步与异步
  • Gateway+OpenFeign 踩坑总结
  • Little Navmap核心技术深度解析:飞行导航地图渲染与数据处理架构
  • 5分钟掌握ncmdump:3步解密网易云音乐NCM文件的完整指南
  • 告别Inception V3:用PyTorch手把手复现Xception,理解深度可分离卷积的威力
  • 潮湿/旋转设备福音:手把手教你用HC-05蓝牙给STC单片机无线升级程序(附完整代码)
  • PSEDG-8多功能心电测试系统:脑机接口心电模块精准校准首选