资讯动态

将树莓派土壤湿度传感器接入 Azure IoT Hub:从 MQTT 迁移到云端的完整实战指南(IoT-For-Beginners)

发布时间:2026/9/16 19:20:19 来源:尧图企业网站定制
将树莓派土壤湿度传感器接入 Azure IoT Hub从 MQTT 迁移到云端的完整实战指南IoT-For-Beginners【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners本指南基于 IoT-For-Beginners 项目《将植物迁移到云端》课程中「单板计算机与虚拟 IoT 硬件」一节的完整内容面向使用 Raspberry Pi 或虚拟 IoT 设备的开发者手把手演示如何把上一节基于公共 MQTT 代理的soil-moisture-sensor程序改造成通过 Azure IoT Hub SDK 连接云端包括安装azure-iot-device、建立设备客户端连接、以 JSON 格式发送土壤湿度遥测数据以及通过处理直接方法请求Direct Method实现对继电器的云端远程控制。学完本节你将掌握 IoT 设备与 Azure IoT Hub 之间 D2C设备到云与 C2D云到设备通信的完整代码级实现并能用 Azure CLI 实时监控设备消息、调用设备方法进行验证。背景为什么要把植物从 MQTT 迁移到云在前一课《自动化植物浇水》中你的设备通过公共 MQTT 代理例如test.mosquitto.org发送土壤湿度遥测并接收继电器的开关指令。这种方式对学习原型演示很方便但作为生产环境存在明显短板可靠性免费公共代理没有服务等级保证随时可能下线安全性公共信道任何人都能监听遥测或向你的硬件发送恶意指令性能公共代理仅为少量测试消息设计扛不住大量消息可发现性无法感知当前有哪些设备已连接。而 Azure IoT Hub 等云 IoT 服务解决了这些问题由大型云厂商维护、内置设备级安全认证、支持每天数以百万计的消息并可按需弹性伸缩。本节的关联课程2-farm/lessons/4-migrate-your-plant-to-the-cloud/README.md还详细讲解了云订阅的注册、Azure CLI 安装、资源组与 IoT Hub 的创建、设备注册与连接字符串的获取以及az iot hub monitor-events与az iot hub invoke-device-method两条核心运维命令。本节文档single-board-computer-connect-hub.md则聚焦于设备侧代码的改造。IoT Hub 的四种通信方式在动手改代码之前先明确 IoT Hub 与设备之间的通信模型。它不像 MQTT 那样围绕任意主题发布/订阅而是提供了四种语义明确的通信方式底层实现可以是 MQTT、HTTPS 或 AMQP通信方式方向用途是否需要响应Device-to-CloudD2C消息设备 → Hub发送遥测数据应用代码可从 Hub 读取否Cloud-to-DeviceC2D消息Hub → 设备应用代码向设备下发普通消息否直接方法请求Direct MethodHub → 设备请求设备执行动作如控制执行器是Device Twins双向同步JSON 文档存储设备上报属性与云端期望属性否其中直接方法请求要求设备必须返回响应应用代码才能判断指令是否被成功处理这也是本节继电器的relay_on/relay_off控制所采用的机制。IoT Hub 还会将消息与直接方法请求保留一段可配置的时间默认一天设备断线重连后仍可补收离线期间的消息。任务一安装 SDK 并连接 IoT Hub1. 准备工作用 VS Code 打开上一节遗留的soil-moisture-sensor文件夹。如果你使用的是虚拟 IoT 设备CounterFit 模拟环境请确保终端里已经激活虚拟环境。安装用于与 IoT Hub 通信的 Python SDKpip3 install azure-iot-deviceazure-iot-device是微软官方的 Azure IoT Hub 设备 SDK封装了连接、认证、消息收发与直接方法处理等全部细节。2. 修改导入语句在app.py顶部、已有 import 之下添加from azure.iot.device import IoTHubDeviceClient, Message, MethodResponse这一行从 SDK 引入了三个核心类型IoTHubDeviceClient与 IoT Hub 通信的设备客户端Message表示一条发送到 Hub 的消息遥测MethodResponse直接方法请求的响应对象。同时删除import paho.mqtt.client as mqtt这一行——公共 MQTT 代理的库不再需要。随后把上一节的全部 MQTT 相关代码一并移除包括三个主题名常量client_telemetry_topic、server_command_topic、client_name所有使用mqtt_client的代码创建、连接、订阅、loop_starthandle_command回调函数while True:循环中调用mqtt_client.publish的那一行循环本身保留。对比上一节的代码code-mqtt/pi/soil-moisture-sensor/app.py可以看到旧实现依赖mqtt.Client连接test.mosquitto.org通过自定义主题id /telemetry和id /commands收发消息迁移后这些主题概念完全消失取而代之的是 SDK 的send_message与on_method_request_received两个抽象接口。3. 写入连接字符串并建立客户端在 import 语句下方添加连接字符串用前面课程中通过 Azure CLI 获取的设备连接字符串替换占位符connection_string connection string 官方课程明确提醒把连接字符串硬编码进源码并非最佳实践——它一旦被提交进版本控制就可能被任何人看到。这里仅为教学简洁理想做法是使用环境变量配合python-dotenv之类的工具加载安全主题会在后续课程中详细展开。接下来创建设备客户端对象并连接device_client IoTHubDeviceClient.create_from_connection_string(connection_string) print(Connecting) device_client.connect() print(Connected)create_from_connection_string会根据连接字符串中携带的 Hub 地址、设备 ID 和共享访问密钥SAS完成认证配置connect()为阻塞调用建立与 Hub 的长连接。运行程序即可看到设备成功连上 Hubpiraspberrypi:~/soil-moisture-sensor $ python3 app.py Connecting Connected Soil moisture: 379任务二以 D2C 消息发送遥测设备连上之后就可以把遥测从发布到 MQTT 主题改为发送给 IoT Hub。在while True:循环内、time.sleep(10)之前插入message Message(json.dumps({ soil_moisture: soil_moisture })) device_client.send_message(message)这段代码把 ADC 读到的土壤湿度值序列化为 JSON 字符串包装成 IoT HubMessage对象再通过send_message作为 D2C 消息发送给 Hub。这里使用的soil_moisture变量来自循环开头的soil_moisture adc.read(0)物理设备经 Grove 电容式土壤湿度传感器读取虚拟设备经 CounterFit shim 模拟。任务三用直接方法请求控制继电器1. 定义直接方法处理函数在while True:循环之前添加如下函数def handle_method_request(request): print(Direct method received - , request.name) if request.name relay_on: relay.on() elif request.name relay_off: relay.off()当 IoT Hub 通过直接方法请求调用设备时SDK 会触发该函数request.name即被请求的方法名。这里约定relay_on打开继电器启动水泵relay_off关闭继电器。 课程备注也可以只暴露一个直接方法把继电器期望状态放进方法请求的 payload从request对象中读取。两种设计都可行取决于你的服务端调用习惯。2. 返回处理结果直接方法请求要求设备返回响应让调用方服务端/CLI确认已被处理。在handle_method_request函数末尾追加method_response MethodResponse.create_from_method_request(request, 200) device_client.send_method_response(method_response)MethodResponse.create_from_method_request基于原始请求构建一个携带 HTTP 状态码 200 的响应对象send_method_response将其回传给 IoT Hub——200 表示处理成功。3. 注册回调在函数定义下方把回调挂到客户端上device_client.on_method_request_received handle_method_request此后每当 Hub 调用直接方法handle_method_request都会被自动触发。完整代码对照仓库中的参考实现课程在仓库中提供了两份可直接对照的完整实现你无需从零拼装Raspberry Pi物理 Grove 硬件code/pi/soil-moisture-sensor/app.py虚拟 IoT 设备CounterFit 模拟code/virtual-device/soil-moisture-sensor/app.py以物理设备版本为例整合后的完整结构如下连接字符串需替换为你的真实值import time from grove.adc import ADC from grove.grove_relay import GroveRelay import json from azure.iot.device import IoTHubDeviceClient, Message, MethodResponse connection_string connection_string adc ADC() relay GroveRelay(5) device_client IoTHubDeviceClient.create_from_connection_string(connection_string) print(Connecting) device_client.connect() print(Connected) def handle_method_request(request): print(Direct method received - , request.name) if request.name relay_on: relay.on() elif request.name relay_off: relay.off() method_response MethodResponse.create_from_method_request(request, 200) device_client.send_method_response(method_response) device_client.on_method_request_received handle_method_request while True: soil_moisture adc.read(0) print(Soil moisture:, soil_moisture) message Message(json.dumps({ soil_moisture: soil_moisture })) device_client.send_message(message) time.sleep(10)虚拟设备版本仅在开头多了两行 CounterFit 初始化from counterfit_connection import CounterFitConnection CounterFitConnection.init(127.0.0.1, 5000)并把 Grove 的ADC/GroveRelay替换为counterfit_shims_grove对应模块其余 IoT Hub 相关代码完全一致。如果你的硬件是 Wio TerminalArduino迁移路径略有不同需要在platformio.ini中添加seeed-studio/Seeed Arduino RTC、arduino-libraries/AzureIoTHub、azure/AzureIoTProtocol_MQTT等库依赖并借助 NTP 服务同步时间IoT Hub 的时间型令牌依赖设备时钟。细节见 wio-terminal-connect-hub.md。云端验证监控事件与调用方法设备代码就绪后本节课程还给出了两条用 Azure CLI 验证链路的命令完整背景见 课程 README。监控设备消息——确保设备运行并持续上报湿度然后执行az iot hub monitor-events --hub-name hub_name控制台会实时打印设备发来的消息Starting event monitor, use ctrl-c to stop... { event: { origin: soil-moisture-sensor, module: , interface: , component: , payload: {\soil_moisture\: 376} } }payload内容与设备端Message(json.dumps({ soil_moisture: soil_moisture }))的序列化结果一一对应。若想查看消息自动附带的时间戳等元数据课程中称为 annotations可追加参数az iot hub monitor-events --properties anno --hub-name hub_name输出中会出现iothub-enqueuedtime、iothub-message-source值为Telemetry、x-opt-sequence-number等字段其中时间值采用 UNIX 时间戳自 1970-01-01 00:00:00 起经过的秒数。 课程提示截至撰写时az iot扩展在 Apple Silicon 上尚未完全正常工作此类用户可改用 Visual Studio Code 的 Azure IoT Tools 扩展监控消息。调用直接方法控制继电器——运行az iot hub invoke-device-method --device-id soil-moisture-sensor \ --method-name relay_on \ --method-payload {} \ --hub-name hub_name其中--method-name指定方法名--method-payload以 JSON 传递方法载荷此处为空对象。设备端随即打印并吸合继电器Direct method received - relay_on将--method-name改为relay_off重复执行即可看到继电器断开。思考题免费层配额下的发送频率设计本课结尾留下一个值得在实践中思考的问题IoT Hub 免费层F1每天限 8,000 条消息而当前代码每 10 秒发送一条遥测。以此频率计算一天约产生 8,640 条24 × 3600 ÷ 10已经逼近甚至超出免费层配额。若考虑增加第二台设备配额压力将直接翻倍。合理的优化方向包括调整time.sleep间隔降低上报频率、仅在湿度值显著变化时发送、或按需切换数据上报粒度——这些调整正是把课程原型推向真实可运营系统时必然面对的工程权衡。至此你的土壤湿度传感器程序已经从公共 MQTT 代理平滑迁移到 Azure IoT Hub既保留了原有的继电器控制能力又获得了云服务级的可靠性、安全性与可伸缩性。下一课将在此基础上把遥测进一步接入云函数与存储服务构建完整的云端应用链路。【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价