尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
设备端MQTT开发:Linux/嵌入式设备传感器数据上报实操
设备端MQTT开发Linux/嵌入式设备传感器数据上报实操搭好了 Broker定好了 Topic接下来就是让设备真正开口说话。本文从 Python 到 C 语言覆盖主流设备端开发方案带你跑通传感器数据采集到 MQTT 上报的全流程。一、设备端MQTT开发选型不同硬件平台适合不同的开发语言和 MQTT 库语言MQTT库适用平台特点Pythonpaho-mqttRaspberry Pi / Linux工控机开发快调试方便适合原型和小规模部署C/Cpaho.mqtt.c / mosquittoSTM32 / RTOS / 嵌入式Linux性能高资源占用小适合量产设备Javaeclipse.pahoAndroid工控设备跨平台适合商用工控平板选型建议开发和验证阶段用 Python 快速跑通流程量产部署到资源受限的嵌入式设备时用 C 语言重写核心逻辑。两者可以并行——Python 脚本跑在树莓派上做网关C 程序跑在 STM32 上做采集节点。二、Python paho-mqtt完整实现2.1 安装pipinstallpaho-mqtt2.2 核心API速览importpaho.mqtt.clientasmqtt# 创建客户端clientmqtt.Client(client_idfarm01_gh03_sensor_01)# 设置认证如果Broker开启了认证client.username_pw_set(device_user,device_password)# 设置遗嘱消息掉线时Broker自动发布client.will_set(agriculture/farm01/greenhouse03/sensor/01/status,payload{status: offline},qos1)# 回调函数client.on_connecton_connect# 连接成功回调client.on_messageon_message# 收到消息回调client.on_disconnecton_disconnect# 断开连接回调# 连接Brokerclient.connect(192.168.1.100,1883,keepalive60)# 订阅Topicclient.subscribe(agriculture/farm01/greenhouse03/controller//command)# 发布消息client.publish(agriculture/farm01/greenhouse03/sensor/temperature,payload{temp: 25.3, ts: 1704067200},qos1)# 启动网络循环保持心跳 处理回调client.loop_start()# 后台线程运行# 或 client.loop_forever() # 阻塞运行2.3 回调函数说明paho-mqtt 采用异步回调模式核心回调函数有三个on_connect连接 Broker 成功后触发通常在这里执行订阅操作。on_message收到订阅消息后触发在这里处理收到的指令或数据。on_disconnect连接断开后触发在这里记录日志和触发重连。三、传感器数据采集到MQTT发布全流程下面是一个完整的智慧农业传感器上报程序涵盖 DHT22 温湿度传感器数据采集、JSON 封装、MQTT 发布、定时循环的全流程。#!/usr/bin/env python3 智慧农业传感器数据上报程序 硬件Raspberry Pi DHT22温湿度传感器 土壤湿度传感器 功能定时采集传感器数据通过MQTT上报到服务器 importjsonimporttimeimportloggingimportpaho.mqtt.clientasmqttfromdatetimeimportdatetime# 尝试导入传感器库开发环境可能没有硬件用模拟数据try:importAdafruit_DHT SENSOR_AVAILABLETrueexceptImportError:SENSOR_AVAILABLEFalselogging.warning(传感器库未安装将使用模拟数据)# 配置 BROKER_HOST192.168.1.100BROKER_PORT1883KEEPALIVE60FARM_IDfarm01GREENHOUSE_IDgreenhouse03DEVICE_IDsensor_01# Topic定义TOPIC_TEMPfagriculture/{FARM_ID}/{GREENHOUSE_ID}/sensor/temperatureTOPIC_HUMIDITYfagriculture/{FARM_ID}/{GREENHOUSE_ID}/sensor/humidityTOPIC_SOILfagriculture/{FARM_ID}/{GREENHOUSE_ID}/sensor/soil_moistureTOPIC_STATUSfagriculture/{FARM_ID}/{GREENHOUSE_ID}/sensor/{DEVICE_ID}/status# 采集间隔秒REPORT_INTERVAL30# MQTT回调 defon_connect(client,userdata,flags,rc):连接成功回调ifrc0:logging.info(连接Broker成功)# 上线通知client.publish(TOPIC_STATUS,json.dumps({status:online,ip:get_local_ip(),ts:datetime.now().isoformat()}),qos1)else:logging.error(f连接失败错误码:{rc})defon_disconnect(client,userdata,rc):断开连接回调ifrc!0:logging.warning(f意外断开连接rc{rc}将自动重连)else:logging.info(主动断开连接)defon_message(client,userdata,msg):收到消息回调处理下发指令logging.info(f收到消息: topic{msg.topic}, payload{msg.payload.decode()})# 传感器采集 defread_dht22():读取DHT22温湿度传感器ifSENSOR_AVAILABLE:humidity,temperatureAdafruit_DHT.read_retry(Adafruit_DHT.DHT22,4)returntemperature,humidityelse:# 模拟数据importrandomreturnround(random.uniform(20,30),1),round(random.uniform(50,70),1)defread_soil_moisture():读取土壤湿度模拟值0-100%ifSENSOR_AVAILABLE:# 实际项目中通过ADC读取模拟电压值并转换passimportrandomreturnround(random.uniform(30,60),1)defget_local_ip():获取本机IP地址importsockettry:ssocket.socket(socket.AF_INET,socket.SOCK_DGRAM)s.connect((8.8.8.8,80))ips.getsockname()[0]s.close()returnipexceptException:returnunknown# 主循环 defmain():logging.basicConfig(levellogging.INFO,format%(asctime)s [%(levelname)s] %(message)s)# 初始化MQTT客户端clientmqtt.Client(client_idf{FARM_ID}_{GREENHOUSE_ID}_{DEVICE_ID})client.username_pw_set(device_user,device_password)# 遗嘱消息设备掉线时自动发布client.will_set(TOPIC_STATUS,json.dumps({status:offline,ts:datetime.now().isoformat()}),qos1)client.on_connecton_connect client.on_disconnecton_disconnect client.on_messageon_message# 启用自动重连指数退避client.reconnect_delay_set(min_delay1,max_delay60)# 连接Brokerclient.connect(BROKER_HOST,BROKER_PORT,KEEPALIVE)client.loop_start()# 后台线程处理网络IOlogging.info(传感器数据上报程序启动)# 定时采集上报循环try:whileTrue:# 1. 采集传感器数据temp,humread_dht22()soilread_soil_moisture()tsdatetime.now().isoformat()# 2. 封装JSON并发布client.publish(TOPIC_TEMP,json.dumps({value:temp,unit:C,ts:ts}),qos1)client.publish(TOPIC_HUMIDITY,json.dumps({value:hum,unit:%,ts:ts}),qos1)client.publish(TOPIC_SOIL,json.dumps({value:soil,unit:%,ts:ts}),qos1)logging.info(f数据上报完成: temp{temp}C, hum{hum}%, soil{soil}%)# 3. 等待下次采集time.sleep(REPORT_INTERVAL)exceptKeyboardInterrupt:logging.info(程序手动停止)finally:# 主动断开前发布离线状态client.publish(TOPIC_STATUS,json.dumps({status:offline,ts:datetime.now().isoformat()}),qos1)client.loop_stop()client.disconnect()if__name____main__:main()代码要点解析遗嘱消息连接时设置了will_set设备意外断线时 Broker 自动发布离线状态服务端无需额外检测。自动重连reconnect_delay_set配置了指数退避重连1s→60s网络恢复后自动重连。QoS 1传感器数据用 QoS 1 发布保证消息至少送达一次不丢数据。业务数据即心跳上报周期 30s Keep Alive 60s每次 PUBLISH 自动充当心跳无需额外发送 PINGREQ。四、嵌入式Linux设备MQTT客户端在 ARM 平台如瑞芯微 RK3566上通常用 C 语言开发配合 paho.mqtt.c 库。4.1 交叉编译paho.mqtt.c# 下载源码gitclone https://github.com/eclipse/paho.mqtt.c.gitcdpaho.mqtt.c# 交叉编译指定ARM工具链mkdirbuildcdbuild cmake..\-DCMAKE_C_COMPILERarm-linux-gnueabihf-gcc\-DCMAKE_CXX_COMPILERarm-linux-gnueabihf-g\-DPAHO_WITH_SSLOFF\-DPAHO_BUILD_STATICON\-DPAHO_BUILD_SHAREDOFF\-DCMAKE_INSTALL_PREFIX/opt/paho-armmakemakeinstall编译后将.a静态库和头文件拷贝到交叉编译工具链的搜索路径中。4.2 C语言MQTT客户端核心框架#includestdio.h#includestdlib.h#includestring.h#includeunistd.h#includeMQTTClient.h#defineBROKER_ADDRESStcp://192.168.1.100:1883#defineCLIENT_IDfarm01_greenhouse03_sensor_01#defineTOPIC_TEMPagriculture/farm01/greenhouse03/sensor/temperature#defineQOS1#defineTIMEOUT10000L// 毫秒intmain(){MQTTClient client;MQTTClient_connectOptions conn_optsMQTTClient_connectOptions_initializer;MQTTClient_message pubmsgMQTTClient_message_initializer;intrc;// 1. 创建客户端if((rcMQTTClient_create(client,BROKER_ADDRESS,CLIENT_ID,MQTTCLIENT_PERSISTENCE_NONE,NULL))!MQTTCLIENT_SUCCESS){printf(创建客户端失败, rc%d\n,rc);return-1;}// 2. 配置连接参数conn_opts.keepAliveInterval60;conn_opts.cleansession1;conn_opts.usernamedevice_user;conn_opts.passworddevice_password;conn_opts.connectTimeout10;// 3. 连接Brokerif((rcMQTTClient_connect(client,conn_opts))!MQTTCLIENT_SUCCESS){printf(连接失败, rc%d\n,rc);return-1;}printf(连接成功\n);// 4. 循环发布传感器数据charpayload[256];while(1){// 读取传感器伪代码floattempread_temperature();floathumread_humidity();// 封装JSONsnprintf(payload,sizeof(payload),{\temp\: %.1f, \hum\: %.1f, \ts\: %ld},temp,hum,time(NULL));// 发布消息pubmsg.payloadpayload;pubmsg.payloadlen(int)strlen(payload);pubmsg.qosQOS;pubmsg.retained0;MQTTClient_publishMessage(client,TOPIC_TEMP,pubmsg,NULL);printf(已发布: %s\n,payload);sleep(30);// 30秒上报一次}// 5. 断开连接并释放资源MQTTClient_disconnect(client,TIMEOUT);MQTTClient_destroy(client);return0;}4.3 守护进程方式运行在嵌入式 Linux 上用 systemd service 让程序开机自启、崩溃自动重启# /etc/systemd/system/agri-sensor.service [Unit] DescriptionSmart Agriculture Sensor Client Afternetwork.target [Service] Typesimple ExecStart/usr/local/bin/agri-sensor Restartalways RestartSec5 Userroot [Install] WantedBymulti-user.targetsystemctlenableagri-sensor# 开机自启systemctl start agri-sensor# 立即启动journalctl-uagri-sensor-f# 查看日志五、设备端常见问题5.1 内存泄漏C 语言中最常见的问题。MQTTClient_message和MQTTClient_deliveryToken等对象用完必须释放。尤其是on_message回调中收到的消息体处理完后要调用MQTTClient_freeMessage释放否则长时间运行内存必爆。5.2 网络切换恢复设备从 Wi-Fi 切换到 4G或反过来时TCP 连接会中断。paho-mqtt 的reconnect_delay_set可以处理自动重连但 C 版本需要自行实现重连逻辑// 断线重连逻辑while(MQTTClient_isConnected(client)0){rcMQTTClient_connect(client,conn_opts);if(rc!MQTTCLIENT_SUCCESS){printf(重连失败, rc%d, %d秒后重试\n,rc,retry_delay);sleep(retry_delay);retry_delay(retry_delay60)?retry_delay*2:60;// 指数退避}else{printf(重连成功\n);retry_delay1;// 重置退避}}5.3 消息队列积压弱网环境下publish可能长时间发不出去。QoS 1/2 的消息会在客户端本地排队积压过多会耗尽内存。解决方案限制本地队列长度超出后丢弃最旧的消息传感器数据丢了无所谓最新的最重要弱网时降低上报频率比如从 30s 降到 60s关键数据用 QoS 1非关键数据用 QoS 0六、设备端MQTT最佳实践ChecklistClient ID 全局唯一农场大棚设备编号组合设置了遗嘱消息LWT掉线自动通知Keep Alive 值根据网络环境设定弱网 30s稳定网络 60s启用自动重连指数退避1s→60s传感器数据用 QoS 1保证不丢业务上报周期 ≤ Keep Alive利用业务数据顶替心跳JSON 格式统一包含 timestamp 字段C 语言程序注意释放 MQTT 对象避免内存泄漏嵌入式设备用 systemd 守护进程运行崩溃自动重启限制本地消息队列长度防止弱网积压
RELATED

相关推荐

STM32C5双ADC交错采样配置实战:从CubeMX到代码调通

STM32C5双ADC交错采样配置实战:从CubeMX到代码调通

做嵌入式这几年,一个很深的体会是:MCU的ADC规格书上写的那几个数字,真等你落到实际项目里,往往要打不少折扣。前段时间我在一个低功耗M33内核的项目上用了STM32C5,板子回来后测电流波形,单看ADC参数觉得绰绰…

📅 2026/10/30 0:01:37
MQTT主题设计规范:智慧农业设备分层Topic设计(设备/大棚/分组)

MQTT主题设计规范:智慧农业设备分层Topic设计(设备/大棚/分组)

MQTT主题设计规范:智慧农业设备分层Topic设计(设备/大棚/分组)Topic 设计是 MQTT 项目中最容易被忽视、却影响最深远的架构决策。改 Topic 结构等于推翻重来——设备端、服务端、前端全得跟着改。本文聊聊怎么设计一套"不后悔"的 T…

📅 2026/11/2 18:28:46
MQTT-EMQX服务部署:Docker搭建高可用MQTT服务器、参数调优

MQTT-EMQX服务部署:Docker搭建高可用MQTT服务器、参数调优

EMQX服务部署:Docker搭建高可用MQTT服务器、参数调优工欲善其事,必先利其器。智慧农业项目要接入成百上千个传感器,第一件事就是把 MQTT Broker 跑起来。本文带你用 Docker 五分钟搭好 EMQX,再聊聊生产环境的调优和集群方案。一、…

📅 2026/11/2 4:42:41
MORE NEWS

更多资讯

📰

波导技术原理与应用全解析

1. 波导基础概念解析 波导作为电磁波传输的核心载体,在现代通信和光学系统中扮演着至关重要的角色。我第一次接触波导是在研究生期间的微波实验室,当时被这种金属管道能够高效传输微波的特性所震撼。与常见的同轴电缆不同,波导通过内部空腔结…

📰

小公司产品经理如何平衡售后与产品设计

1. 产品经理为何沦为"售后":小公司里的角色困境 作为一名在小公司摸爬滚打多年的产品经理,我深刻理解这种"既要当爹又要当妈"的处境。没有标准化的岗位分工,没有完善的售后体系,用户遇到问题第一个想到的就是…

📰

SpringBoot+微信小程序构建电子书城实战

1. 项目背景与核心需求 作为一名长期从事企业级应用开发的工程师,我最近完成了一个基于SpringBoot和微信小程序的电子书城项目"益书君"。这个项目的核心目标是解决传统图书销售行业在移动互联网时代面临的几个痛点: 纸质图书销售受限于物理空…

📰

人工智能知识表示与逻辑推理能力校准指南

简介:本资源为百度人工智能方向的经典笔试真题汇编,面向AI算法岗、知识工程与智能系统方向的求职者及高校相关专业学生,助力系统复习人工智能核心理论与解题方法。文档涵盖语义网络、逻辑推理、知识表示、机器学习基础与自然语言处理等关键知…

📰

中文用户LoRA训练前置指南:SD标签生成工作流

1. 这不是翻译工具,而是一套“标签生成工作流”——专为中文母语者设计的LoRA训练前置系统你打开Stable Diffusion WebUI,点开Dreambooth或Kohya SS训练界面,看到那一整页密密麻麻的英文输入框:caption file template、prompt sty…

📰

K-Means+SVM栅格分区:为蚁群路径规划搜索空间减负

简介:这份PDF面向智能清洁机器人路径规划方向的学习者与研究者,聚焦复杂障碍物环境下栅格地图路径搜索效率偏低的问题,给出一种将K-Means聚类与支持向量机(SVM)结合的栅格分区思路。资源先以栅格法建立环境模型&#x…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬