连接设备到互联网 本课概览图 图解笔记由 Nitya Narasimhan 创作。点击图片查看大图。 此课程是作为 Hello IoT 系列的一部分,由 Microsoft Reactor 提供。课程分为两部分视频 - 一小时的主课程和一小时的办公时间,深入讲解课程内容并回答问题。 第4课:连接设备到互联网 第4课:连接设备到互联网 - 办公时间 点击上方图片观看视频 预习测验 预习测验 引言 物联网(IoT)中的“互联网”是指能够使许多物联网设备功能得以实现的云服务和连接,从传感器收集数据到通过执行器发送控制消息。物联网设备通常使用标准通信协议连接到单一的云物联网服务,并且该服务与其他物联网应用相连,包括用于处理数据的AI服务,以及用于控制或报告的Web应用程序。

图解笔记由 Nitya Narasimhan 创作。点击图片查看大图。
此课程是作为 Hello IoT 系列的一部分,由 Microsoft Reactor 提供。课程分为两部分视频 - 一小时的主课程和一小时的办公时间,深入讲解课程内容并回答问题。
点击上方图片观看视频
物联网(IoT)中的“互联网”是指能够使许多物联网设备功能得以实现的云服务和连接,从传感器收集数据到通过执行器发送控制消息。物联网设备通常使用标准通信协议连接到单一的云物联网服务,并且该服务与其他物联网应用相连,包括用于处理数据的AI服务,以及用于控制或报告的Web应用程序。
来自传感器的数据被称为遥测数据。
物联网设备可以从云接收消息。这些消息通常包含命令,即指示执行内部操作(如重启或更新固件)或使用执行器的操作(如打开灯光)的指令。
本课程介绍了物联网设备可以使用的几种通信协议以及它们可能发送或接收的数据类型。你还将动手实践这些技术,将互联网控制添加到你的夜灯中,将LED控制逻辑移动到本地运行的“服务器”代码中。
在本课中,我们将涵盖:
有许多流行的通信协议用于物联网设备与互联网之间的通信。其中最受欢迎的是基于发布/订阅模式的消息传递,通过某种类型的代理进行。物联网设备连接到代理并发布遥测数据,订阅命令。云服务也连接到代理,订阅所有遥测消息,并向特定设备或一组设备发布命令。

MQTT 是最流行的物联网设备通信协议,并将在本课程中介绍。其他协议还包括AMQP和HTTP/HTTPS。
MQTT 是一种轻量级的、开放标准的消息传递协议,可以在设备之间发送消息。它于1999年设计用于监测石油管道,然后在15年后作为开放标准由IBM发布。
MQTT有一个单一的代理和多个客户端。所有客户端都连接到代理,代理负责路由消息到相关客户端。消息通过命名的主题进行路由,而不是直接发送给单个客户端。客户端可以发布到一个主题,任何订阅该主题的客户端都会收到消息。

✅ 做一些研究。如果你有很多物联网设备,如何确保你的MQTT代理能够处理所有消息?
将互联网控制添加到你的夜灯的第一步是将其连接到MQTT代理。
将设备连接到MQTT代理。
在本课程的这一部分,你将把物联网夜灯连接到互联网,使其可以远程控制。稍后在这节课中,你的物联网设备将通过MQTT向公共MQTT代理发送光强度遥测数据,然后由你编写的某些服务器代码接收。这代码会检查光强度并发送命令消息给设备,指示其开启或关闭LED。
这种设置的实际应用场景可能是,在拥有大量灯具的地方(如体育场),在决定开灯之前先收集多个光传感器的数据。这样,如果只有一个传感器被云层或鸟类遮挡,而其他传感器检测到足够的光线,就不会触发开灯。
✅ 还有哪些情况需要评估多个传感器的数据才能发送命令?
为了避免在本任务中设置MQTT代理的复杂性,你可以使用一个公开的测试服务器,该服务器运行Eclipse Mosquitto,这是一个开源的MQTT代理。这个测试代理在test.mosquitto.org上公开可用,无需设置账户,非常适合测试MQTT客户端和服务器。
这个测试代理是公开的且不安全。任何人都可以监听你发布的内容,因此不应在此发布任何需要保密的数据。

按照下面的相关步骤将设备连接到MQTT代理:
主题可以具有层次结构,客户端可以使用通配符订阅不同层次的主题。例如,你可以将温度遥测消息发送到/telemetry/temperature主题,湿度消息发送到/telemetry/humidity主题,然后在你的云应用程序中订阅/telemetry/*主题以接收温度和湿度遥测消息。
消息可以通过服务质量(QoS)发送,这决定了消息被接收的保证程度。
✅ 在什么情况下需要保证交付的消息而不是“发即忘”的消息?
尽管名称为消息队列(MQTT的缩写),但它实际上并不支持消息队列。这意味着如果客户端断开连接,然后重新连接,它将不会收到断开期间发送的消息,除非它已经开始处理这些消息(使用QoS过程)。消息可以设置保留标志。如果设置了该标志,MQTT代理将存储该主题上最后发送的消息,并在稍后订阅该主题的客户端接收该消息。这样,客户端总是会得到最新消息。
MQTT还支持保持活动功能,可以在消息间隔较长时检查连接是否仍然活跃。
来自Eclipse基金会的Mosquitto 提供了一个免费的MQTT代理,你可以自行实验MQTT,以及一个可用于测试代码的公共MQTT代理,托管在test.mosquitto.org。
MQTT连接可以是公开的和开放的,也可以通过用户名和密码或证书加密和保护。
MQTT通过TCP/IP进行通信,这是HTTP使用的同一底层网络协议,但使用不同的端口。你还可以使用MQTT通过WebSocket与浏览器中运行的Web应用程序通信,或者在防火墙或其他网络规则阻止标准MQTT连接的情况下使用。
遥测一词源自希腊语,意为远程测量。遥测是远程获取传感器数据并将其发送到云端的过程。
最早的遥测设备之一是在1874年发明的法国设备,它通过物理电线将实时天气和雪深从蒙布朗山发送到巴黎。当时无线技术尚未出现。
让我们回顾一下第一课中的智能恒温器示例。

恒温器使用温度传感器获取遥测数据。它很可能内置一个温度传感器,并且可能通过诸如蓝牙低功耗(BLE)等无线协议连接到多个外部温度传感器。
它可以发送的遥测数据示例可能如下:
| 名称 | 值 | 描述 |
|---|---|---|
thermostat_temperature |
18°C | 恒温器内置温度传感器测量的温度 |
livingroom_temperature |
19°C | 被命名为livingroom的房间传感器测量的温度 |
bedroom_temperature |
21°C | 被命名为bedroom的房间传感器测量的温度 |
云服务可以使用这些遥测数据来决定发送什么命令来控制加热。
将互联网控制添加到你的夜灯的下一步是将光强度遥测数据发送到MQTT代理上的遥测主题。
将光强度遥测数据发送到MQTT代理。
数据以JSON编码发送——这是一种使用键值对的标准文本编码数据格式。
✅ 如果你以前没有接触过JSON,可以在JSON.org文档中了解更多。
按照下面的相关步骤将遥测数据从设备发送到MQTT代理:
如果没有东西去接收遥测数据,发送遥测数据就没有意义了。光强度遥测数据需要有东西去接收并处理这些数据。这个“服务器”代码是你部署到云服务作为更大物联网应用的一部分的代码,但在本课程中,你将在这个代码在你的电脑(或如果你直接在树莓派上编写代码则在树莓派上)上运行。服务器代码由一个监听MQTT遥测消息的Python应用程序组成,消息包括光强度。稍后在这节课中,你将让它回复带有指示开启或关闭LED的指令的消息。
✅ 做一些研究:如果没有监听器,MQTT消息会发生什么?
如果你的本地环境中还没有安装Python和VS Code,你需要安装它们两个来编写服务器代码。如果你正在使用虚拟物联网设备,或者正在你的树莓派上工作,则可以跳过这一步,因为你应该已经安装并配置好了这些工具。
安装Python和VS Code。
安装Python。请参阅Python下载页面上的说明以安装最新版本的Python。
安装Visual Studio Code (VS Code)。这是你将用于编写Python虚拟设备代码的编辑器。请参阅VS Code文档上的说明以安装VS Code。
如果你有自己偏好的Python IDE或编辑器,你可以自由选择使用。但是,课程将基于使用VS Code提供说明。
安装VS Code的Pylance扩展。这是VS Code的一个扩展,提供Python语言支持。请参阅Pylance扩展文档上的说明以在VS Code中安装此扩展。
以下是对给定Markdown文件的翻译,确保翻译自然流畅,同时保留了注释、代码块、警告等元素:
默认情况下,当你安装一个包时,它会在你的计算机上全局可用。这可能会导致包版本的问题,比如一个应用程序依赖于一个特定版本的包,但当你为另一个应用安装了新版本的包时,这个版本可能会破坏之前的版本。为了解决这个问题,你可以使用一个Python虚拟环境,本质上是在一个专用文件夹中的Python副本。当你在这个环境中安装pip包时,这些包只会安装到该文件夹中。
配置一个Python虚拟环境并安装MQTT pip包。
在终端或命令行中,选择一个位置运行以下命令以创建并导航到一个新的目录:
mkdir my_project && cd my_project
现在运行以下命令,在.venv文件夹中创建一个虚拟环境:
python3 -m venv .venv
你需要显式调用
python3,因为python会使用Python 2而不是Python 3。
激活虚拟环境:
在Windows上:
如果你正在使用命令提示符或通过Windows终端使用的命令提示符,运行:
.venv\Scripts\activate.bat
如果你正在使用PowerShell,运行:
.venv\Scripts\Activate.ps1
在macOS或Linux上,运行:
source .venv/bin/activate
这些命令应该在同一位置运行,用于创建虚拟环境的命令。运行
python命令将使用创建虚拟环境时使用的Python版本。运行以下命令来获取版本:
```bash python --version ```
输出类似于以下内容:
```bash Python 3.8.5 ```
你的Python版本可能不同——只要版本在3.6及以上即可。如果不满足条件,请删除此文件夹,安装较新版本的Python并重试。
运行以下命令安装Paho-MQTT的pip包,这是一个流行的MQTT库。
pip install paho-mqtt
这个pip包仅安装在虚拟环境中,并不会在外部可用。
现在可以使用Python编写服务器代码。
编写服务器代码。
在终端或命令行中,运行以下命令在虚拟环境中创建一个名为app.py的Python文件:
在Windows上运行:
echo "" > app.py
在macOS或Linux上运行:
touch app.py
在VS Code中打开当前文件夹:
code .
当VS Code启动时,它将激活Python虚拟环境。这将在底部状态栏中报告:

如果当VS Code启动时VS Code终端已经在运行,则它将没有激活虚拟环境。最简单的方法是使用Kill the active terminal instance按钮关闭终端:

启动一个新的VS Code终端,通过选择终端 -> 新建终端,或者按Ctrl + (Ctrl + 后跟.venv也会出现在提示符中):
python app.py
打开VS Code资源管理器中的app.py文件并添加以下代码:
import paho.mqtt.client as mqtt def on_connect(client, userdata, flags, rc): print("Connected with result code " + str(rc)) def on_message(client, userdata, msg): print(f"Message received: {msg.payload.decode()}") light_level = int(msg.payload.decode()) if light_level < 300: client.publish("commands", '{"led_on": true}') else: client.publish("commands", '{"led_on": false}') client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message client.connect("localhost", 1883, 60) client.subscribe("telemetry") client.loop_forever()
替换<ID>为实际设备ID。当接收到handle_telemetry函数被调用时,打印接收到的消息到控制台。
最后一个无限循环保持应用程序运行。MQTT客户端在一个后台线程中监听消息,并且在主应用程序运行期间一直运行。
在VS Code终端中运行以下命令来运行你的Python应用程序:
python app.py
应用程序将开始监听来自物联网设备的消息。
确保你的设备正在运行并发送遥测消息。调整物理或虚拟设备检测到的光照水平。接收到的消息将打印到终端。
python app.py
app.py文件在nightlight虚拟环境中运行,以便app.py文件在nightlight-server虚拟环境中接收发送的消息。
你可以在此找到此代码:code-server/server 文件夹。
遥测数据的一个重要考虑因素是测量和发送数据的频率。答案是——这取决于具体情况。如果你测量得更频繁,你可以更快地响应变化,但同时也会消耗更多的电力、带宽、生成更多的数据,并需要更多的云资源来处理。你需要测量得足够频繁,但也不能太频繁。
对于恒温器来说,每隔几分钟测量一次可能就足够了,因为温度变化并不那么快。如果你只在一天中测量一次,那么你可能会在阳光明媚的日子里对夜间温度进行加热,而如果你每秒测量一次,你将有成千上万不必要的重复温度测量,这会占用用户的互联网速度和带宽(对于带宽有限的用户来说是一个问题),使用更多的电力(对于像远程传感器这样的电池供电设备来说是个问题),并且增加提供商的云计算资源处理和存储的成本。
如果你正在监控工厂中一台机器的数据,如果机器发生故障可能会造成巨大的损失和数百万美元的收入损失,那么可能需要每秒多次测量。浪费带宽总比错过可能指示机器需要停止和修复的遥测数据要好。
在这种情况下,你可以考虑使用边缘设备来先处理遥测数据,以减少对互联网的依赖。
互联网连接可能是不可靠的,断线也很常见。在这种情况下,物联网设备应该如何处理——是否应该丢弃数据,还是应该将其存储起来直到连接恢复?答案仍然是——这取决于具体情况。
对于恒温器来说,一旦新的温度测量值被采集,数据就可以被丢弃。供暖系统并不关心20分钟前的温度是20.5°C,现在的温度是19°C,决定是否开启供暖的是现在的温度。
对于机器来说,你可能希望保留数据,特别是如果它用于寻找趋势。有许多机器学习模型可以通过查看定义时间段内的数据(如过去一小时的数据)来检测异常数据。这通常用于预测性维护,寻找某些东西即将出问题的迹象,以便在发生之前进行维修或更换。你可能希望每个机器的遥测数据都被发送出去,以便对其进行异常检测,因此一旦物联网设备能够重新连接,它将发送所有在互联网中断期间生成的遥测数据。
物联网设备设计者还应考虑物联网设备在互联网中断或信号丢失时是否可以继续使用。智能恒温器在无法向云端发送遥测数据的情况下,仍应能够做出一些有限的决策来控制供暖。

为了使MQTT处理连接丢失的情况,设备和服务器代码需要负责确保消息传递,例如通过要求所有发送的消息都由额外的消息在回复主题上确认,如果没有确认则手动排队稍后重发。
命令是由云端发送给设备的指令,指示其执行某些操作。大多数情况下这涉及通过执行器输出某种形式的输出,但也可以是针对设备本身的指令,例如重启或收集额外的遥测数据并作为响应返回。

恒温器可以接收来自云端的命令以开启供暖。根据来自所有传感器的遥测数据,如果云端服务决定应该开启供暖,就会发送相关的命令。
我们互联网控制的夜灯下一步是让服务器代码发送一个命令回到物联网设备,根据其感应到的光照水平来控制灯光。
在VS Code中打开服务器代码
在声明client_telemetry_topic之后添加以下行以定义要发送命令的主题:
client_command_topic = "commands"
在handle_telemetry函数末尾添加以下代码:
def on_message(client, userdata, msg): print(f"Message received: {msg.payload.decode()}") light_level = int(msg.payload.decode()) if light_level < 300: client.publish(client_command_topic, '{"led_on": true}') else: client.publish(client_command_topic, '{"led_on": false}')
这会发送一个JSON消息到命令主题,其中led_on的值设置为true或false,具体取决于光照是否小于300。如果光照小于300,则发送true以指示设备开启LED。
如前所述运行代码
调整物理或虚拟设备检测到的光照水平。接收到的消息和发送的命令将被写入终端:
python app.py
遥测和命令都是在单个主题上传输的。这意味着多个设备的遥测数据将出现在相同的遥测主题上,而发送到多个设备的命令将出现在相同的命令主题上。如果你想发送到特定设备的命令,你可以使用带有唯一设备ID的主题命名,例如
/commands/device1和/commands/device2。如果你使用的是Mosquitto代理,可以在mosquitto.conf配置文件中添加以下内容:
```conf topic /commands/# split topic_string 1 /commands/ ```
声明:
本文件灏天文库团队进行了翻译。尽管我们力求准确,但请注意,翻译可能包含错误或不准确之处。原文档以其原始语言为准。我们不对因使用此翻译而产生的任何误解或误译负责。