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

润和星闪WS63E的MQTT示例程序存在的潜在问题

目录

引言

程序简介

代码结构分析

核心函数分析

MQTT 连接与通信

数据采集与处理

任务管理

问题分析

结构体修改引发线程间通信失效的原因分析

关键问题点

解决方案

1. 调整消息队列最大长度

2. 确保消息读取时缓冲区足够大

3. 动态检查和适应结构体大小

4. 增强错误检查

结语


引言

润和在其星闪开发套件中提供了一个MQTT的示例,该程序可以采集温湿度信息并上传华为云平台,是学习华为云的一个很好的例子。

有个学生想在该示例基础上添加压力传感器信息,在下面的结构体中添加了char pressure[10]:

typedef struct {int msg_type;char temp[10];char humi[10];char *receive_payload;
} MQTT_msg;

添加后程序不工作了,两个线程不能正确运行了,没有输出打印信息。今天分享一下程序存在的问题,供大家参考。 

程序简介

先简单的介绍一下这个程序。这是一个基于华为云 IoT 平台的 MQTT 通信应用程序,运行在嵌入式设备上。主要功能是通过 WiFi 连接网络,使用 MQTT 协议与云端通信,采集环境温湿度数据并上报,同时接收云端指令控制设备(如蜂鸣器)。

代码结构分析

程序由多个功能模块组成:

  1. MQTT 通信模块

    • 包含连接、发布、订阅等核心功能
    • 使用回调函数处理消息到达、连接丢失等事件
  2. WiFi 连接模块

    • 负责建立与指定 WiFi 热点的连接
  3. 环境数据采集模块

    • 通过 AHT20 传感器采集温度和湿度数据
  4. JSON 处理模块

    • 实现数据的 JSON 格式编码和解码
  5. PWM 控制模块

    • 控制外设(如蜂鸣器)的 PWM 输出
  6. 任务管理模块

    • 创建和管理多个任务线程

核心函数分析

MQTT 连接与通信

int mqtt_connect(void)
  • 初始化 MQTT 客户端并连接到华为云 IoT 平台
  • 设置连接参数,包括保活间隔、用户名和密码
  • 注册回调函数处理连接丢失、消息到达和消息确认
  • 将环境数据(温度、湿度)封装为 JSON 格式
  • 发布消息到指定主题
int msgArrved(void *context, char *topic_name, int topic_len, MQTTClient_message *message)
  • 消息到达回调函数
  • 将接收到的消息放入消息队列,供后续处理

数据采集与处理

void environment_task_entry(void)
  • 环境数据采集任务
  • 初始化 AHT20 传感器并循环读取温湿度数据
  • 将数据封装为消息结构体并发送到队列

任务管理

static void mqtt_sample_entry(void)
  • 应用入口函数
  • 创建消息队列和两个任务线程:
    • mqtt_task:处理 MQTT 通信
    • environment_task_entry:采集环境数据

问题分析

结构体修改引发线程间通信失效的原因分析

当在MQTT_msg结构体中增加char pressure[10];成员后,线程间通信失效的主要原因是消息队列的消息长度配置与实际消息大小不匹配

关键问题点

  1. 消息队列创建时的固定长度

    #define MSG_MAX_LEN 28
    ret = osal_msg_queue_create("name", MSG_QUEUE_SIZE, &g_msg_queue, 0, MSG_MAX_LEN);
    
     
    • MSG_MAX_LEN被定义为 28 字节,这是原始结构体的大小
    • 增加pressure[10]成员后,结构体大小变为 38 字节,超出了队列的最大长度
  2. 消息队列读写操作

    // 写入消息
    uint32_t ret = osal_msg_queue_write_copy(g_msg_queue, receive_msg, sizeof(MQTT_msg), OSAL_WAIT_FOREVER);// 读取消息
    uint32_t resize = 32; // 初始大小设置不足
    ret = osal_msg_queue_read_copy(g_msg_queue, report_msg, &resize, OSAL_WAIT_FOREVER);
    
     
    • 写入时使用sizeof(MQTT_msg)(新大小 38 字节)
    • 读取时初始resize为 32 字节,且未正确更新为结构体实际大小

解决方案

1. 调整消息队列最大长度

#define MSG_MAX_LEN 40  // 根据新结构体大小调整

2. 确保消息读取时缓冲区足够大

uint32_t resize = sizeof(MQTT_msg);  // 使用正确的结构体大小
ret = osal_msg_queue_read_copy(g_msg_queue, report_msg, &resize, OSAL_WAIT_FOREVER);

3. 动态检查和适应结构体大小

// 创建队列时使用动态计算的大小
ret = osal_msg_queue_create("name", MSG_QUEUE_SIZE, &g_msg_queue, 0, sizeof(MQTT_msg));// 读取消息前确认缓冲区大小
MQTT_msg *report_msg = osal_kmalloc(sizeof(MQTT_msg), 0);
uint32_t resize = sizeof(MQTT_msg);

4. 增强错误检查

if (resize < sizeof(MQTT_msg)) {printf("Error: Message buffer size is insufficient!\n");// 处理错误情况
}

经过以上修改后,现在程序执行正常了。

结语

这个错误比较隐蔽,因为没有啥提示信息。应该说润和的示例程序不太规范,没有考虑程序扩充的问题,部分地方甚至采用了硬编码,而不是完全用宏来定义的。类似这样的问题,值得我们每个人格外小心。

http://www.xdnf.cn/news/9366.html

相关文章:

  • 经典查找算法合集(下)
  • 行为型:命令模式
  • 多语言实现插值查找算法
  • 理解vue-cli中的webpack
  • Minktec 柔性弯曲传感器,灵敏捕捉坐姿弓背、精准监测行走姿态,守护儿童背部健康,为科学健身提供数据支撑,开启职业健康与背痛 AI 干预新方向。
  • vue + ant-design + xlsx 实现Excel多Sheet页导出功能
  • 如何通过ETL对WebService进行调用
  • 顶会新方向:卡尔曼滤波+目标检测
  • Java 程序求圆弧段的面积(Program to find area of a Circular Segment)
  • Mico 1.33.1 | 解锁高级版 上千种自定义组件 动态壁纸
  • Java String函数的使用
  • 016搜索之广度优先BFS——算法备赛
  • word中表格拉不动以及插入图片有间距
  • MySQL的参数 innodb_force_recovery 详解
  • vue3+element-plus el-date-picker日期、年份筛选设置本周、本月、近3年等快捷筛选
  • JavaEE初阶-网络编程
  • 使用Mathematica绘制随机多项式的根
  • OpenCV---findCountours
  • [java八股文][JavaSpring面试篇]SpringBoot
  • 前端Vue3列表滑动无限加载实现
  • 佰力博科技与您谈谈高温介电温谱仪如何保养
  • ROS2学习(15)------ROS2 TF2 机器人坐标系管理器
  • MySQL问题:MySQL中使用索引一定有效吗?如何排查索引效果
  • LeetCode-栈-最小栈
  • 现代 CSS 高阶技巧:实现平滑内凹圆角的工程化实践
  • UDP 传输时间(延迟)
  • 关于Oracle SGA内存抖动
  • FastAPI 异常处理
  • vscode ssh远程服务端设置
  • OpenCV视觉图片调整:从基础到实战的技术指南