# 存储位置信息数据 ![本课的手绘笔记概览](../../../../../translated_images/lesson-12.ca7f53039712a3ec14ad6474d8445361c84adab643edc53fa6269b77895606bb.zh.jpg) > 手绘笔记由 [Nitya Narasimhan](https://github.com/nitya) 提供。点击图片查看大图。 ## 课前测验 [课前测验](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/23) ## 简介 在上一课中,你学习了如何使用 GPS 传感器捕获位置信息数据。为了将这些数据用于可视化一辆满载食物的卡车的位置及其行程,需要将数据发送到云端的 IoT 服务,并存储在某个地方。 在本课中,你将学习存储 IoT 数据的不同方法,并学习如何使用无服务器代码存储来自 IoT 服务的数据。 本课内容包括: * [结构化数据和非结构化数据](../../../../../3-transport/lessons/2-store-location-data) * [将 GPS 数据发送到 IoT Hub](../../../../../3-transport/lessons/2-store-location-data) * [热路径、温路径和冷路径](../../../../../3-transport/lessons/2-store-location-data) * [使用无服务器代码处理 GPS 事件](../../../../../3-transport/lessons/2-store-location-data) * [Azure 存储账户](../../../../../3-transport/lessons/2-store-location-data) * [将无服务器代码连接到存储](../../../../../3-transport/lessons/2-store-location-data) ## 结构化数据和非结构化数据 计算机系统处理数据,而这些数据的形状和大小各不相同。数据可以是单个数字、大量文本、视频和图像,或者 IoT 数据。通常,数据可以分为两类——*结构化数据* 和 *非结构化数据*。 * **结构化数据** 是具有明确、固定结构的数据,通常映射到具有关系的数据表。例如,一个人的详细信息,包括姓名、出生日期和地址。 * **非结构化数据** 是没有明确、固定结构的数据,包括结构可能经常变化的数据。例如,文档如书面文件或电子表格。 ✅ 进行一些研究:你能想到其他结构化和非结构化数据的例子吗? > 💁 还有一种半结构化数据,它是有结构的,但不适合固定的数据表。 IoT 数据通常被认为是非结构化数据。 想象一下,你为一个大型商业农场的车队添加了 IoT 设备。你可能希望为不同类型的车辆使用不同的设备。例如: * 对于像拖拉机这样的农用车辆,你需要 GPS 数据以确保它们在正确的田地上工作。 * 对于将食物运送到仓库的送货卡车,你需要 GPS 数据以及速度和加速度数据,以确保司机安全驾驶,还需要驾驶员身份和启动/停止数据,以确保司机遵守当地的工作时间法律。 * 对于冷藏卡车,你还需要温度数据,以确保食物在运输过程中不会过热或过冷而变质。 这些数据可能会不断变化。例如,如果 IoT 设备位于卡车驾驶室中,那么它发送的数据可能会随着挂车的变化而变化,例如只有在使用冷藏挂车时才发送温度数据。 ✅ 还有哪些 IoT 数据可能会被捕获?想一想卡车可能运输的货物类型,以及维护数据。 这些数据因车辆而异,但它们都会被发送到同一个 IoT 服务进行处理。IoT 服务需要能够处理这些非结构化数据,并以一种既能搜索或分析,又能适应数据不同结构的方式存储它们。 ### SQL 与 NoSQL 存储 数据库是允许你存储和查询数据的服务。数据库分为两种类型——SQL 和 NoSQL。 #### SQL 数据库 最早的数据库是关系型数据库管理系统(RDBMS),也称为关系型数据库。这些数据库也被称为 SQL 数据库,因为它们使用结构化查询语言(SQL)来添加、删除、更新或查询数据。这些数据库由一个模式组成——一组定义良好的数据表,类似于电子表格。每个表有多个命名列。当你插入数据时,你会向表中添加一行,将值放入每列中。这种方式使数据保持非常严格的结构——尽管你可以留空某些列,但如果你想添加新列,则必须在数据库中执行此操作,并为现有行填充值。这些数据库是关系型的——一个表可以与另一个表有关系。 ![一个关系型数据库,其中用户表的 ID 与购买表的用户 ID 列相关联,产品表的 ID 与购买表的产品 ID 相关联](../../../../../translated_images/sql-database.be160f12bfccefd3ca718a66468c2c4c89c53e5aad4c295324d576da87f9dfdd.zh.png) 例如,如果你在一个表中存储用户的个人详细信息,你会为每个用户分配某种内部唯一 ID,该 ID 用于包含用户姓名和地址的表中的一行。如果你想在另一个表中存储该用户的其他详细信息,例如他们的购买记录,你会在新表中为该用户的 ID 添加一列。当你查找用户时,可以使用他们的 ID 从一个表中获取他们的个人详细信息,从另一个表中获取他们的购买记录。 SQL 数据库非常适合存储结构化数据,并且当你希望确保数据符合你的模式时非常有用。 ✅ 如果你之前没有使用过 SQL,请花点时间阅读 [Wikipedia 上的 SQL 页面](https://wikipedia.org/wiki/SQL)。 一些知名的 SQL 数据库包括 Microsoft SQL Server、MySQL 和 PostgreSQL。 ✅ 进行一些研究:阅读这些 SQL 数据库及其功能。 #### NoSQL 数据库 NoSQL 数据库之所以被称为 NoSQL,是因为它们没有 SQL 数据库的严格结构。它们也被称为文档数据库,因为它们可以存储非结构化数据,例如文档。 > 💁 尽管名字叫 NoSQL,但一些 NoSQL 数据库允许你使用 SQL 查询数据。 ![NoSQL 数据库中的文件夹中的文档](../../../../../translated_images/noqsl-database.62d24ccf5b73f60d35c245a8533f1c7147c0928e955b82cb290b2e184bb434df.zh.png) NoSQL 数据库没有预定义的模式来限制数据的存储方式,你可以插入任何非结构化数据,通常使用 JSON 文档。这些文档可以像计算机上的文件一样组织成文件夹。每个文档可以与其他文档有不同的字段——例如,如果你存储农用车辆的 IoT 数据,有些可能有加速度计和速度数据的字段,另一些可能有挂车温度的字段。如果你想添加一种新型卡车,例如带有内置秤以跟踪所载货物重量的卡车,那么你的 IoT 设备可以添加这个新字段,并且可以在无需更改数据库的情况下存储它。 一些知名的 NoSQL 数据库包括 Azure CosmosDB、MongoDB 和 CouchDB。 ✅ 进行一些研究:阅读这些 NoSQL 数据库及其功能。 在本课中,你将使用 NoSQL 存储来存储 IoT 数据。 ## 将 GPS 数据发送到 IoT Hub 在上一课中,你从连接到 IoT 设备的 GPS 传感器捕获了 GPS 数据。为了在云端存储这些 IoT 数据,你需要将其发送到 IoT 服务。你将再次使用 Azure IoT Hub,这是你在前一个项目中使用的同一个 IoT 云服务。 ![将 GPS 遥测数据从 IoT 设备发送到 IoT Hub](../../../../../translated_images/gps-telemetry-iot-hub.8115335d51cd2c1285d20e9d1b18cf685e59a8e093e7797291ef173445af6f3d.zh.png) ### 任务 - 将 GPS 数据发送到 IoT Hub 1. 使用免费层创建一个新的 IoT Hub。 > ⚠️ 如果需要,可以参考 [项目 2,第 4 课中创建 IoT Hub 的说明](../../../2-farm/lessons/4-migrate-your-plant-to-the-cloud/README.md#create-an-iot-service-in-the-cloud)。 记得创建一个新的资源组。将新资源组命名为 `gps-sensor`,并为新的 IoT Hub 取一个基于 `gps-sensor` 的唯一名称,例如 `gps-sensor-<你的名字>`。 > 💁 如果你仍然保留了前一个项目中的 IoT Hub,可以重复使用它。记得在创建其他服务时使用该 IoT Hub 的名称及其所在的资源组。 1. 在 IoT Hub 中添加一个新设备。将此设备命名为 `gps-sensor`。获取该设备的连接字符串。 1. 更新你的设备代码,使用上一步中的设备连接字符串将 GPS 数据发送到新的 IoT Hub。 > ⚠️ 如果需要,可以参考 [项目 2,第 4 课中将设备连接到 IoT 的说明](../../../2-farm/lessons/4-migrate-your-plant-to-the-cloud/README.md#connect-your-device-to-the-iot-service)。 1. 发送 GPS 数据时,请以以下 JSON 格式发送: ```json { "gps" : { "lat" : , "lon" : } } ``` 1. 每分钟发送一次 GPS 数据,以免用完每日消息配额。 如果你使用的是 Wio Terminal,请记得添加所有必要的库,并使用 NTP 服务器设置时间。你的代码还需要确保在发送 GPS 位置之前已从串口读取所有数据,使用上一课中的现有代码。使用以下代码构建 JSON 文档: ```cpp DynamicJsonDocument doc(1024); doc["gps"]["lat"] = gps.location.lat(); doc["gps"]["lon"] = gps.location.lng(); ``` 如果你使用的是虚拟 IoT 设备,请记得使用虚拟环境安装所有必要的库。 对于 Raspberry Pi 和虚拟 IoT 设备,请使用上一课中的现有代码获取纬度和经度值,然后使用以下代码以正确的 JSON 格式发送它们: ```python message_json = { "gps" : { "lat":lat, "lon":lon } } print("Sending telemetry", message_json) message = Message(json.dumps(message_json)) ``` > 💁 你可以在 [code/wio-terminal](../../../../../3-transport/lessons/2-store-location-data/code/wio-terminal)、[code/pi](../../../../../3-transport/lessons/2-store-location-data/code/pi) 或 [code/virtual-device](../../../../../3-transport/lessons/2-store-location-data/code/virtual-device) 文件夹中找到此代码。 运行你的设备代码,并使用 `az iot hub monitor-events` CLI 命令确保消息正在流入 IoT Hub。 ## 热路径、温路径和冷路径 从 IoT 设备流向云端的数据并不总是实时处理的。有些数据需要实时处理,有些数据可以稍后处理,还有些数据可以更晚处理。数据流向不同服务以在不同时间处理的方式被称为热路径、温路径和冷路径。 ### 热路径 热路径指需要实时或接近实时处理的数据。你可以使用热路径数据进行警报,例如当车辆接近仓库时,或者冷藏卡车的温度过高时发出警报。 要使用热路径数据,你的代码需要在云服务接收到事件时立即响应。 ### 温路径 温路径指可以在接收到数据后稍作延迟再处理的数据,例如用于报告或短期分析。你可以使用温路径数据生成每日车辆里程报告,使用前一天收集的数据。 温路径数据在被云服务接收后会存储在某种可以快速访问的存储中。 ### 冷路径 冷路径指历史数据,长期存储的数据可以在需要时处理。例如,你可以使用冷路径生成年度车辆里程报告,或者对路线进行分析以找到减少燃料成本的最优路线。 冷路径数据存储在数据仓库中——这些数据库专为存储大量不会更改的数据而设计,可以快速轻松地查询。通常,你的云应用程序会定期运行一个任务(每天、每周或每月)将数据从温路径存储移动到数据仓库。 ✅ 回想一下你在这些课程中捕获的数据。它是热路径、温路径还是冷路径数据? ## 使用无服务器代码处理 GPS 事件 一旦数据流入你的 IoT Hub,你可以编写一些无服务器代码来监听发布到 Event-Hub 兼容端点的事件。这是温路径——这些数据将被存储,并在下一课中用于报告行程。 ![将 GPS 遥测数据从 IoT 设备发送到 IoT Hub,然后通过事件中心触发器发送到 Azure Functions](../../../../../translated_images/gps-telemetry-iot-hub-functions.24d3fa5592455e9f4e2fe73856b40c3915a292b90263c31d652acfd976cfedd8.zh.png) ### 任务 - 使用无服务器代码处理 GPS 事件 1. 使用 Azure Functions CLI 创建一个 Azure Functions 应用。使用 Python 运行时,并在名为 `gps-trigger` 的文件夹中创建它,同时将 Functions App 项目名称也命名为 `gps-trigger`。确保创建一个虚拟环境以供使用。 > ⚠️ 如果需要,可以参考[从项目 2,第 5 课创建 Azure Functions 项目的说明](../../../2-farm/lessons/5-migrate-application-to-the-cloud/README.md#create-a-serverless-application)。 1. 添加一个 IoT Hub 事件触发器,使用 IoT Hub 的 Event Hub 兼容端点。 > ⚠️ 如果需要,可以参考[项目 2,第 5 课中创建 IoT Hub 事件触发器的说明](../../../2-farm/lessons/5-migrate-application-to-the-cloud/README.md#create-an-iot-hub-event-trigger)。 1. 在 `local.settings.json` 文件中设置 Event Hub 兼容端点的连接字符串,并在 `function.json` 文件中使用该条目的键。 1. 使用 Azurite 应用作为本地存储模拟器。 1. 运行你的 Functions 应用,确保它能够接收来自 GPS 设备的事件。确保你的 IoT 设备也在运行并发送 GPS 数据。 ```output Python EventHub trigger processed an event: {"gps": {"lat": 47.73481, "lon": -122.25701}} ``` ## Azure 存储账户 ![Azure 存储标志](../../../../../translated_images/azure-storage-logo.605c0f602c640d482a80f1b35a2629a32d595711b7ab1d7ceea843250615ff32.zh.png) Azure 存储账户是一种通用存储服务,可以以多种方式存储数据。你可以将数据存储为 Blob、队列、表或文件,并且可以同时使用这些方式。 ### Blob 存储 *Blob* 这个词的意思是二进制大对象,但它已经成为任何非结构化数据的代名词。你可以将任何数据存储在 Blob 存储中,从包含 IoT 数据的 JSON 文档到图片和视频文件。Blob 存储有 *容器* 的概念,容器是命名的存储桶,用于存储数据,类似于关系数据库中的表。这些容器可以包含一个或多个文件夹来存储 Blob,每个文件夹还可以包含其他文件夹,类似于计算机硬盘上的文件存储方式。 在本课中,你将使用 Blob 存储来存储 IoT 数据。 ✅ 做一些研究:阅读 [Azure Blob 存储](https://docs.microsoft.com/azure/storage/blobs/storage-blobs-overview?WT.mc_id=academic-17441-jabenn) ### 表存储 表存储允许你存储半结构化数据。表存储实际上是一个 NoSQL 数据库,因此不需要预先定义表集,但它被设计为在一个或多个表中存储数据,每行都有唯一的键。 ✅ 做一些研究:阅读 [Azure 表存储](https://docs.microsoft.com/azure/storage/tables/table-storage-overview?WT.mc_id=academic-17441-jabenn) ### 队列存储 队列存储允许你在队列中存储大小最多为 64KB 的消息。你可以将消息添加到队列的末尾,并从队列的开头读取。只要存储空间足够,队列会无限期存储消息,因此可以长期存储消息,然后在需要时读取。例如,如果你想运行一个每月的任务来处理 GPS 数据,可以每天将数据添加到队列中,然后在月底处理队列中的所有消息。 ✅ 做一些研究:阅读 [Azure 队列存储](https://docs.microsoft.com/azure/storage/queues/storage-queues-introduction?WT.mc_id=academic-17441-jabenn) ### 文件存储 文件存储是云中的文件存储,任何应用程序或设备都可以使用行业标准协议连接。你可以将文件写入文件存储,然后将其挂载为 PC 或 Mac 上的驱动器。 ✅ 做一些研究:阅读 [Azure 文件存储](https://docs.microsoft.com/azure/storage/files/storage-files-introduction?WT.mc_id=academic-17441-jabenn) ## 将无服务器代码连接到存储 你的 Functions 应用现在需要连接到 Blob 存储,以存储来自 IoT Hub 的消息。有两种方法可以实现: * 在函数代码中,使用 Blob 存储的 Python SDK 连接到 Blob 存储并将数据写入 Blob。 * 使用输出函数绑定,将函数的返回值绑定到 Blob 存储,并自动保存 Blob。 在本课中,你将使用 Python SDK 来了解如何与 Blob 存储交互。 ![将 GPS 遥测数据从 IoT 设备发送到 IoT Hub,再通过事件触发器发送到 Azure Functions,最后保存到 Blob 存储](../../../../../translated_images/save-telemetry-to-storage-from-functions.ed3b1820980097f143d9f0570072da11304c2bc7906359dfa075b4d9b253c20f.zh.png) 数据将以以下格式保存为 JSON Blob: ```json { "device_id": , "timestamp" :