尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
智慧农业数据采集从零到一:MQTT 接入边缘网关完整教程(附实测可运行代码)
智慧农业数据采集从零到一MQTT 接入边缘网关完整教程附实测可运行代码前言做农业物联网项目第一个卡点几乎永远是同一个现场传感器采集到的数据怎么稳定地送进你的数据库。本文用一个完整示例走通这条链路——边缘网关 → MQTT Broker → Python 订阅端 → SQLite 落库。读完你能得到三样东西一套可以直接复制运行的采集脚本paho-mqtt 2.x 版本不踩 1.x 的弃用坑一个能在本机跑起来的 Broker 环境Docker 一条命令现场部署时最容易翻车的三个点以及它们的判断方法适合人群需要快速把采集链路跑通的开发者、运维、以及做农业物联网集成的工程师。环境准备软件环境与版本Python 3.11、paho-mqtt 2.1.0、Docker用于起 EMQX Broker。三者版本必须对齐尤其是 paho-mqtt 的 2.x 与 1.x 在回调函数签名上不兼容这是新手报错的第一大来源。先建一个干净的虚拟环境避免污染系统 Pythonuv venv .venvsource.venv/bin/activate uv pipinstallpaho-mqtt2.1.0python-cimport paho.mqtt as p; print(paho-mqtt, p.__version__)Broker 用 EMQX 起在本机一条命令即可dockerrun-d--nameemqx-demo-p1883:1883 emqx/emqx:6.1.0等 3 到 5 秒 EMQX 完成初始化后用nc -z 127.0.0.1 1883确认端口已监听。这一步不要省Broker 没起来时客户端报的是连接被拒和网络不通的报错完全不同先确认端口能大大缩短排查时间。如果你的 Broker 在外网或者已经有鉴权把连接参数改成环境变量注入不要写死在代码里——这个习惯在后续多环境部署时会省掉大量改动。分步实现第一步定义消息格式与主题主题设计遵循一个原则把可变的部分放到层级里把固定的部分放到前缀这样订阅端可以用通配符一次订阅所有设备。主题格式定为hoyotech/agriculture/{网关编号}/sensor/data订阅端使用hoyotech/agriculture//sensor/data加号是单层通配符只匹配一层正好对上网关编号。消息体用 JSON字段保持扁平网关编号、传感器类型、数值、采集时间。扁平结构的好处是数据库表可以一步建好不需要处理嵌套解析。第二步写完整采集脚本下面这段是完整可运行版本包含建表、连接、订阅、解析、落库五个动作跑完会打印接收到的数据并把结果写入 SQLiteimportjson,os,sqlite3,threading,timefromdatetimeimportdatetimeimportpaho.mqtt.clientasmqtt BROKERos.getenv(MQTT_BROKER,127.0.0.1)PORTint(os.getenv(MQTT_PORT,1883))TOPIChoyotech/agriculture//sensor/dataDB_FILEos.getenv(MQTT_DB,/tmp/agriculture_data.db)definit_db():withsqlite3.connect(DB_FILE)asconn:conn.execute(CREATE TABLE IF NOT EXISTS sensor_data( id INTEGER PRIMARY KEY AUTOINCREMENT, gateway_sn TEXT, sensor_type TEXT, value REAL, collect_time TEXT))defsave_data(gw,st,val,ts):withsqlite3.connect(DB_FILE)asconn:conn.execute(INSERT INTO sensor_data(gateway_sn,sensor_type,value,collect_time) VALUES(?,?,?,?),(gw,st,val,ts))gotthreading.Event()defon_connect(client,userdata,flags,reason_code,properties):ifreason_code0:client.subscribe(TOPIC,qos1)print(已连接并订阅,TOPIC,flushTrue)else:print(接入失败,reason_code,flushTrue)defon_message(client,userdata,msg):djson.loads(msg.payload.decode())save_data(d[gateway_sn],d[sensor_type],d[value],d.get(timestamp))print(接收成功,d[gateway_sn],d[sensor_type],d[value],flushTrue)got.set()init_db()submqtt.Client(mqtt.CallbackAPIVersion.VERSION2,client_idsub_demo)sub.on_connect,sub.on_messageon_connect,on_message sub.connect(BROKER,PORT,keepalive60)sub.loop_start()time.sleep(0.5)pubmqtt.Client(mqtt.CallbackAPIVersion.VERSION2,client_idgw_sim)pub.connect(BROKER,PORT,keepalive60)pub.loop_start()pub.publish(hoyotech/agriculture/GW-2026-001/sensor/data,json.dumps({gateway_sn:GW-2026-001,sensor_type:soil_moisture,value:38.5,timestamp:datetime.now().isoformat()}),qos1).wait_for_publish(5)got.wait(8)pub.loop_stop();pub.disconnect()sub.loop_stop();sub.disconnect()withsqlite3.connect(DB_FILE)asconn:print(库内数据,conn.execute(SELECT gateway_sn,sensor_type,value FROM sensor_data).fetchall())print(RESULT: PASS,flushTrue)# expect: 接收成功# expect: RESULT: PASS 三个细节值得单独说明。第一mqtt.Client 必须传 CallbackAPIVersion.VERSION2否则在 paho-mqtt2.x 上走的是已弃用的 v1 回调日志里会持续输出弃用告警。第二v2 的 on_connect 是五个参数第四个是 reason_code 对象用 0 判断成功依然有效。第三落库用 with 管理连接异常时自动回滚比手动 close 稳。### 第三步先订阅后发布很多人写测试脚本时先发布再订阅结果消息被丢。MQTT 的 QoS1 只保证到达 Broker不保证在你订阅之前就缓存住——除非用保留消息。所以脚本里先启动订阅端并 sleep 半秒再发消息这个顺序不能颠倒。## 效果验证在装好 EMQX 的本机直接运行上面的脚本实测输出已连接并订阅 hoyotech/agriculture//sensor/data接收成功 GW-2026-001 soil_moisture 38.5库内数据 [(‘GW-2026-001’, ‘soil_moisture’, 38.5)]RESULT: PASS看到 RESULT: PASS 就算打通了。如果要验证真实设备把 pub 部分删掉把网关指向同一个 Broker 即可其余代码不用改。 ## 常见问题 **报 socket.gaierror: nodename nor servname provided**Broker 域名解析失败。八成是教程里抄了一个不存在的演示域名或者内网 DNS 没配。先用 dig short 你的域名 确认有 A 记录再连。 **报 Callback API version 1 is deprecated**paho-mqtt 装了 2.x 但用了 v1 写法。改成 mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id...)并把 on_connect 补成五参签名。 **能连上但收不到消息**先看主题通配符层级对不对 只匹配一层# 才匹配多层再看 QoS 与订阅时机。用 mosquitto_sub -h 127.0.0.1 -t # -v 抓全量消息能立刻区分是发布端没发还是订阅端没收到。 **数据偶发写入失败**SQLite 单文件锁在并发写入下会报 database locked。采集端只保留一个写入连接或者换用 WAL 模式能消掉绝大多数偶发失败。 ## 扩展优化 链路通了之后三个方向值得继续做一是把 Broker 换成带鉴权与 ACL 的部署现场设备用一机一密二是本地加一个磁盘缓冲队列断网时先落本地、恢复后补传这是野外部署的必备能力三是把 SQLite 换成时序数据库数据量上到千万级之后查询性能差距会非常明显。 代码里的连接参数都已经走环境变量切环境不需要改一行代码——这是给后续迁移留的口子。
RELATED

相关推荐

RocketMQ 集群特性

RocketMQ 集群特性

摘要:本文重点梳理 Dledger 文件一致性协议(含 Raft 原理与 RocketMQ 实现)、主从节点切换的高可用集群、BrokerContainer 容器式运行机制。 一、Dledger 文件一致性协议 1. Dledger 高可用集群下的消息一致性问题 RocketMQ 提供两种集群机…

📅 2026/10/23 9:17:19
基于微信小程序的ACG手办商店系统(毕设源码+文档)

基于微信小程序的ACG手办商店系统(毕设源码+文档)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

📅 2026/10/23 9:17:19
Java在AI时代不会消亡:停更事件背后的真实技术演进与选型策略

Java在AI时代不会消亡:停更事件背后的真实技术演进与选型策略

最近在技术社区看到这个标题,说实话我第一反应是有点哭笑不得。Java群体本来就容易在大模型浪潮里感到焦虑,再配上"某国产适配组件停更"这种消息,很容易被渲染成"Java真的要完了"。但如果你把这个消息放在整个技术版图里…

📅 2026/10/23 9:12:18
MORE NEWS

更多资讯

📰

FGO-py 实战指南:自动爬塔 + 自动每周任务,睡前挂上它一晚刷完

FGO-py 实战指南:自动爬塔 自动每周任务,睡前挂上它一晚刷完 【免费下载链接】FGO-py 自动爬塔! 自动每周任务! 全自动免配置跨平台的Fate/Grand Order助手.启动脚本,上床睡觉,养肝护发,满加成圣诞了解一下? 项目地址: https://gitcode.com/GitHub_T…

📰

Oh My Zsh 插件文档完全指南:从安装到自定义的 10 分钟上手路径

Oh My Zsh 插件文档完全指南:从安装到自定义的 10 分钟上手路径 【免费下载链接】ohmyzsh 🙃 A delightful community-driven (with 2,500 contributors) framework for managing your zsh configuration. Includes 300 optional plugins (rails, git, m…

📰

如何先写和弦再填旋律:YuE2 Studio 和弦床(Chord Bed)工作流全解析

【免费下载链接】YuE2-Studio Local AI song generator with an editable score — YuE2 on your GPU: full songs with vocals, sheet music, covers, exact replay. Native Windows app, no Python, installer with auto-update. 项目地址: https://gitcode.com/g…

📰

把微信聊天记录永久保存:WeChatMsg 五个目标跑通

把微信聊天记录永久保存:WeChatMsg 五个目标跑通 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/WeChatMsg …

📰

FreeRDP命令行实战:Windows远程桌面批量连接与参数配置指南

上周有个做运维的朋友甩过来一句抱怨:手头二十多台 Windows 机器的远程会话,每天要一台台点开系统自带的远程桌面连接、填地址、填账号、点确定,一天下来手指头都酸了,更别提还要在几个会话之间来回切着看日志。他问我有没有办法把…

📰

Linux安装微信的真相:四大路径实测与决策指南

1. 为什么“在Linux系统中安装微信”是个高频却总被误答的问题 “如何在Linux系统中安装微信”——这个搜索词每天在各大技术社区、问答平台和新手群组里出现数百次。它看起来简单,但背后藏着一个典型的认知断层:多数提问者真正想问的,不是“…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

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

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

📞 💬