新闻详情

新闻详情

首页 / 资讯中心 / 详情

IoT-For-Beginners 夜间灯项目:在 Raspberry Pi 与虚拟 IoT 设备上订阅 MQTT 命令控制 LED

发布时间:2026/9/16 23:21:02来源:尧图网络
IoT-For-Beginners 夜间灯项目:在 Raspberry Pi 与虚拟 IoT 设备上订阅 MQTT 命令控制 LED
IoT-For-Beginners 夜间灯项目在 Raspberry Pi 与虚拟 IoT 设备上订阅 MQTT 命令控制 LED【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners导读本文聚焦于 IoT-For-Beginners 项目连接互联网这一课中面向单板计算机Raspberry Pi与虚拟 IoT 设备的最后一步通过 MQTT 订阅来自服务器的命令并根据命令控制 LED 亮灭。在本节之前你已经完成了设备连接公共 MQTT 代理、向/telemetry主题发布光照强度遥测数据、以及编写本地服务器代码等三步本节将补全闭环的最后一块拼图——让设备订阅/{id}/commands主题解析 JSON 载荷中的led_on字段把云端逻辑光照阈值判断真正落到硬件执行上。读完本文你将掌握 Paho-MQTT 客户端的事件回调机制on_message、命令主题约定以及完整的遥测上报 → 服务器决策 → 命令下发 → 执行器动作双向消息链路。一、本节在整个互联网控制链路中的位置1.1 完整的消息流第 4 课把夜间灯的本地判断逻辑搬到了服务器端形成一条标准的 publish/subscribe 双向链路设备读取 Grove 光照传感器的数值设备把{light: 值}编码为 JSON发布到/{id}/telemetry主题运行在本地或 Pi 上的服务器代码订阅该遥测主题服务器收到遥测后计算led_on light 300把命令发布到/{id}/commands主题本节完成的部分设备订阅/{id}/commands主题解析led_on调用led.on()/led.off()控制 LED。对应的示意图为 assignment-1-internet-flow.png课程 README 中的任务流程图展示了光照读取、阈值判断与 LED 控制的整体走向。1.2 为什么需要命令机制在 课程 README 中命令commands被定义为云发送给设备、指示其执行某操作的消息多数情况下通过执行器产生输出也可能是针对设备本身的指令如重启、上报额外遥测。本节的场景是典型的云服务基于多路遥测数据做出决策后下发指令——例如体育场场景中只有汇总多个光照传感器数据后才决定是否开灯避免单块云或一只鸟遮住某个传感器就误触发开灯。二、准备工作与运行前提在动手修改代码之前请确认以下前置条件已按 single-board-computer-mqtt.md 完成设备与 MQTT 代理的连接安装paho-mqtt、定义唯一id、创建mqtt_client并调用loop_start()已按 single-board-computer-telemetry.md 完成遥测发布已按课程 README 的Receive telemetry from the MQTT broker与Send commands to the MQTT broker两节完成服务器代码并能向命令主题发布消息使用虚拟 IoT 设备时终端需处于虚拟环境中source ./.venv/bin/activate等并保证 CounterFit 应用正在运行、光照传感器与 LED 已创建在正确引脚上使用 Raspberry Pi 时则无需虚拟环境。 本课使用的公共测试代理test.mosquitto.org运行开源代理 Eclipse Mosquitto无需注册账号。它面向公众且不加密任何人都有可能监听到你发布的消息切勿用于需要保密的任何数据。三、定义命令主题3.1 步骤在 VS Code 中打开夜间灯项目app.py在client_telemetry_topic的定义之后加入一行server_command_topic id /commands3.2 语义说明server_command_topic是设备将订阅、用来接收 LED 命令的 MQTT 主题。它与遥测主题共用同一个id前缀形成命名约定遥测上行主题{id}/telemetry命令下行主题{id}/commands在 code-commands/virtual-device/nightlight/app.py 和 code-commands/pi/nightlight/app.py 中可以看到二者的并列定义client_telemetry_topic id /telemetry server_command_topic id /commandsid必须与设备端、服务器端保持一致。课程 README 特别强调服务器端必须使用与设备相同的 ID否则订阅/发布将落到错误的主题上。由于test.mosquitto.org是公共代理、有大量学习者同时使用唯一 ID 能避免客户端名与主题相互冲突官方建议用 GUIDGen 之类的工具生成。四、编写命令处理回调4.1 核心代码在mqtt_client.loop_start()一行的下方、主循环while True:之前加入以下代码def handle_command(client, userdata, message): payload json.loads(message.payload.decode()) print(Message received:, payload) if payload[led_on]: led.on() else: led.off() mqtt_client.subscribe(server_command_topic) mqtt_client.on_message handle_command4.2 逐行剖析回调函数签名Paho-MQTT 的回调约定为(client, userdata, message)。其中client触发回调的客户端实例userdataClient()构造时可传入的用户自定义数据本项目中未使用保持Nonemessage封装了主题、载荷与 QoS 的消息对象。JSON 解码message.payload是 MQTT 传输的原始字节串message.payload.decode()先按 UTF-8 还原为字符串json.loads(...)再将其解析为 Python 字典。随后打印payload便于在终端观察收到的命令内容。执行器控制从字典中读取payload[led_on]当值为True时调用led.on()否则调用led.off()。这正是课程 README 所述服务器把led_on置为 true 或 false取决于光照是否小于 300的设备端落地逻辑。订阅与回调绑定mqtt_client.subscribe(server_command_topic) mqtt_client.on_message handle_command第一行让客户端订阅命令主题在此之前调用的loop_start()已在后台线程启动消息循环第二行把handle_command注册为收到消息时的处理函数。 重要语义on_message处理器会为所有已订阅主题上的消息触发。如果以后需要监听多个主题可以从传入处理函数的message对象中取出消息实际发送到的主题message.topic再按主题分发处理逻辑。本课当前只有一个命令主题因此直接解析即可。4.3 完整设备代码虚拟设备版将上述片段融入前几节的代码后完整的 虚拟设备 app.py 如下import time from counterfit_connection import CounterFitConnection from counterfit_shims_grove.grove_light_sensor_v1_2 import GroveLightSensor from counterfit_shims_grove.grove_led import GroveLed import json import paho.mqtt.client as mqtt CounterFitConnection.init(127.0.0.1, 5000) light_sensor GroveLightSensor(0) led GroveLed(5) id ID client_telemetry_topic id /telemetry server_command_topic id /commands client_name id nightlight_client mqtt_client mqtt.Client(client_name) mqtt_client.connect(test.mosquitto.org) mqtt_client.loop_start() def handle_command(client, userdata, message): payload json.loads(message.payload.decode()) print(Message received:, payload) if payload[led_on]: led.on() else: led.off() mqtt_client.subscribe(server_command_topic) mqtt_client.on_message handle_command while True: light light_sensor.light print(Light level:, light) mqtt_client.publish(client_telemetry_topic, json.dumps({light : light})) time.sleep(5)Raspberry Pi 版本见 code-commands/pi/nightlight/app.py二者结构完全一致仅传感器/LED 的导入来源不同Pi 直接使用grove物理库虚拟设备使用counterfit_shims_grove垫片库。从源码结构可以看出主循环每 5 秒读取一次光照并发布遥测命令的接收则由后台线程的loop_start()驱动不阻塞主循环——这正是 MQTT 客户端发布与订阅并存的典型写法。五、配套的服务器端命令下发代码为了让命令真正被发送出来服务器端code-commands/server/app.py实现了对应的收遥测、发命令逻辑import json import time import paho.mqtt.client as mqtt id ID client_telemetry_topic id /telemetry server_command_topic id /commands client_name id nightlight_server mqtt_client mqtt.Client(client_name) mqtt_client.connect(test.mosquitto.org) mqtt_client.loop_start() def handle_telemetry(client, userdata, message): payload json.loads(message.payload.decode()) print(Message received:, payload) command { led_on : payload[light] 300 } print(Sending message:, command) client.publish(server_command_topic, json.dumps(command)) mqtt_client.subscribe(client_telemetry_topic) mqtt_client.on_message handle_telemetry while True: time.sleep(2)要点服务器订阅client_telemetry_topic遥测主题收到遥测后计算payload[light] 300光照小于 300→led_on: True→ 设备开灯光照不小于 300→led_on: False→ 设备关灯。命令以 JSON 文档发布到server_command_topic设备端的handle_command恰好消费该主题形成端到端闭环。服务器主循环time.sleep(2)仅用于保持进程存活消息处理完全由后台线程回调完成。 值得注意本例中所有设备共用/{id}/telemetry与/{id}/commands各一个主题。若想对特定设备单独下发命令可以按设备 ID 拆分主题如/commands/device1、/commands/device2让每个设备只订阅属于自己的命令主题。六、运行与验证6.1 运行步骤设备端以与上一节遥测发布完全相同的方式运行app.py。使用虚拟设备时确保 CounterFit 应用正在运行、光照传感器与 LED 已创建在正确引脚上。服务器端在nightlight-server目录的虚拟环境中运行服务器app.py。改变物理或虚拟设备感知到的光照强度。6.2 预期结果终端会同时打印收到的消息遥测与发送的命令服务器端以及设备端打印的Message received:命令载荷LED 随光照强度自动亮起/熄灭光照低于阈值时点亮恢复充足光照时熄灭。课程 README 给出的服务器端参考输出为(.venv) ➜ nightlight-server python app.py Message received: {light: 0} Sending message: {led_on: True} Message received: {light: 400} Sending message: {led_on: False}遥测发布阶段设备端参考输出为(.venv) ➜ nightlight python app.py MQTT connected! Sending telemetry {light: 0} Sending telemetry {light: 0}⚠️ 注意设备端app.py在nightlight虚拟环境中必须持续运行服务器端app.py在nightlight-server虚拟环境中才能收到其发送的消息两段进程需要同时在线。七、从源码看 MQTT 命令机制的底层原理结合仓库源码与课程 README可以提炼出本课依赖的几个 MQTT 核心机制便于理解handle_command为什么这样写7.1 发布/订阅模型MQTT 有一个代理broker和多个客户端所有客户端都连接代理代理按命名主题路由消息而不是直接发送给某个客户端。设备向主题发布遥测、订阅命令云服务订阅全部遥测、向特定设备或设备组发布命令。示意图见 pub-sub.png 与 mqtt.png。本课设备代码中的subscribe(server_command_topic)与publish(client_telemetry_topic, ...)正是这一模型的最小实现。7.2 主题层级与通配符主题支持层级客户端可用通配符订阅不同层级如/telemetry/*同时接收温度与湿度遥测。本课命令主题/{id}/commands即一个具体层级若要分设备下发可扩展为/commands/device1等形式。7.3 QoS 与消息投递MQTT 消息可携带服务质量QoS等级至多一次只发送一次不做确认fire and forget至少一次发送方重试直到收到确认恰好一次发送方与接收方两层握手确保只收到一份拷贝。本课示例使用默认 QoS适合教学演示真实生产场景需根据消息重要性选择等级。7.4 保留消息与心跳MQTT 支持在消息上设置 retained 标志设置后代理会保存该主题的最后一条消息并在新客户端订阅时立即推送给它保证新订阅者总能拿到最新值。此外 MQTT 还有 keep alive 心跳机制用于在消息间隔较长时探测连接是否存活。7.5 断线语义需要注意MQTT 虽名为Message Queueing但并不真正支持消息队列——设备断线重连后收不到断线期间的消息正在按 QoS 流程处理中的除外。课程 README 也讨论了断网场景对恒温器这类新值覆盖旧值的数据可以丢弃而对需要做趋势分析/异常检测的机器遥测则需在重连后补发。若要求命令严格按序、必达设备与服务器需自行在回复主题上做确认并排队重放。八、小结与可继续探索的路径至此你已经成功编程让你的设备响应来自 MQTT 代理的命令定义命令主题 → 编写 JSON 解析回调 → 绑定on_message→ 控制 LED。这是互联网控制的夜间灯任务的收尾也构成了一整条可复用的 IoT 双向通信骨架。本仓库中可继续深入阅读的资料本课主文档1-getting-started/lessons/4-connect-internet/README.md协议、遥测、命令、断线处理、课后挑战本节的 Arduino/Wio Terminal 对应实现wio-terminal-commands.mdC 版命令订阅便于对比两种平台的回调模式设备连接与遥测的前置环节single-board-computer-mqtt.md、single-board-computer-telemetry.md任务作业assignment.md比较 MQTT 与其他通信协议如果想进一步实验可以按课程 README 的建议自行运行 Mosquitto 代理并通过mosquitto.conf开放匿名连接与外部访问listener 1883 0.0.0.0allow_anonymous true把设备与服务器代码中的代理地址从test.mosquitto.org换成本地代理观察完整消息流在自有环境下的表现。【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Python面向对象编程:类的基础与高级特性详解 2026/9/17 0:00:18

Python面向对象编程:类的基础与高级特性详解

1. Python类的基础概念与核心语法在Python中,类(Class)是面向对象编程(OOP)的基础构建块。它允许我们将数据和操作数据的方法捆绑在一起,形成一个独立的逻辑单元。让我们从最基本的类定义开始讲起。1.1 类的定义与实例化定义一个类需要使用class关键字&a…

阅读更多 →
VHawk-Lint实战:FPGA静态代码检查如何补齐仿真验证的盲区 2026/9/17 0:00:18

VHawk-Lint实战:FPGA静态代码检查如何补齐仿真验证的盲区

做FPGA开发这些年,我最大的感受是:仿真跑得再欢,也不如代码规范本身不出事。去年接手一个通信基带项目,RTL代码量冲到几十万行,每次上板前集成仿真要跑大半天,结果ovl断言报出来的是个三年前遗留的多驱动—…

阅读更多 →
MATLAB手写紧束缚模型计算石墨烯能带结构 2026/9/17 0:00:18

MATLAB手写紧束缚模型计算石墨烯能带结构

简介:本资源是一套面向凝聚态物理与计算材料学初学者及研究者的石墨烯能带结构仿真MATLAB代码集,聚焦于理解石墨烯电子性质的核心——线性色散关系与Dirac点特征。代码基于紧束缚模型,完整覆盖晶格建模、布里渊区定义、薛定谔方程数值求解及能…

阅读更多 →
SpringBoot+Vue人事系统实战:解决HR数据断点与事务一致性 2026/9/17 0:00:18

SpringBoot+Vue人事系统实战:解决HR数据断点与事务一致性

简介:本资源是一套基于SpringBoot后端与Vue.js前端构建的完整人事管理系统,专为计算机专业本科生毕业设计及课程实践打造,面向正在完成毕设、期末大作业或项目实战训练的学习者。系统覆盖员工信息管理、考勤、薪资核算等核心HR模块&#xff0…

阅读更多 →
AWS无服务器应用开发指南:从Lambda到SAM的架构与实践 2026/9/17 0:00:18

AWS无服务器应用开发指南:从Lambda到SAM的架构与实践

从一份目录开始,重新理解AWS无服务器应用开发很多人学AWS无服务器,第一反应是去翻Lambda的API文档,或者找几个现成的SAM模板直接部署。这种学法不是不可以,但容易陷入一个怪圈:函数能跑通,却说不清楚整个架…

阅读更多 →
BrowserAct 多网页抓取指令丢失?TaoToken 这样改模型通道 2026/9/16 23:57:16

BrowserAct 多网页抓取指令丢失?TaoToken 这样改模型通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞