在 IoT-For-Beginners 中存储 IoT 位置数据:从 GPS 遥测到 Azure Blob 存储的完整实现指南
在 IoT-For-Beginners 中存储 IoT 位置数据从 GPS 遥测到 Azure Blob 存储的完整实现指南【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners导读本篇文章是《IoT-For-Beginners》交通Transport项目第二课《Store location data》的技术实战指南核心解决一个具体问题上一课中 GPS 传感器捕获到的经纬度数据如何发送到 Azure IoT Hub再通过 Serverless 代码落入可查询的存储中从而为下一课的路线可视化提供数据基础。读完本文你将掌握结构化与非结构化数据的判别方法、SQL 与 NoSQL 存储的选型逻辑、热/温/冷数据路径的设计思想以及基于 Azure FunctionsEvent Hub 触发器 Azure Blob Storage 构建 GPS 遥测落库链路的完整可运行方案。本文配套的完整课程代码位于仓库3-transport/lessons/2-store-location-data/code/目录包含wio-terminal、pi、virtual-device三套设备端实现与一套functions云端 Serverless 实现。一、结构化数据与非结构化数据计算机系统处理的数据形态千差万别从单个数值、大段文本到视频图片再到 IoT 遥测数据。按结构特征数据通常可划分为两类结构化数据Structured data具有定义良好、固定不变、严格的表结构通常映射为带关系的数据表。典型例子是个人信息姓名、出生日期、地址。非结构化数据Unstructured data没有严格固定结构结构可以频繁变化。典型例子是文档文本文档或电子表格。半结构化数据Semi-structured data介于两者之间有一定结构但无法固定进数据表例如 JSON 文档。原文档对此也有提示 注记。IoT 数据通常被视为非结构化数据。这一点在运输场景中非常直观假设你要为一家大型商业化农场车队部署 IoT 设备不同车辆需要不同传感器组合拖拉机需要 GPS 数据确认其在正确农田作业运输食品到仓库的货车需要 GPS、速度与加速度数据评估驾驶安全还需要驾驶员身份与启停数据核查工时合规冷藏车还需要温度数据防止食品在运输途中过热或过冷而变质。这些数据随挂车更换而动态变化——例如只有挂上冷藏挂车时才上报温度字段。它们结构各异却都要进入同一个 IoT 服务处理因此 IoT 服务必须能兼容这种多变的结构。这正是本课采用NoSQL 存储的原因。SQL 与 NoSQL 存储数据库是用于存储与查询数据的服务分为 SQL 与 NoSQL 两大类型。SQL 数据库最早出现的数据库是关系型数据库管理系统RDBMSRelational Database Management System因为使用结构化查询语言SQL进行增删改查也称 SQL 数据库。其核心是Schema模式一组定义良好的数据表类似电子表格每张表有多个命名列插入数据即向表添加行并为各列赋值。SQL 数据库是关系型的一张表可以通过键与另一张表建立关联。例如用户个人信息表为每位用户分配唯一 ID购买记录表用该 ID 作为外键关联查询用户时可用 ID 分别从两张表取出其个人信息与购买记录。SQL 数据库的特点决定了它非常适合存储结构化数据以及需要确保数据与 Schema 完全匹配的场景。缺点是结构刚性虽然列可以留空但若要新增一列必须先在数据库层面执行变更并为已有行填充值。常见的 SQL 数据库有 Microsoft SQL Server、MySQL、PostgreSQL 等。NoSQL 数据库NoSQL 数据库名称源于其没有 SQL 数据库那样严格的表结构也常被称为文档数据库Document databases因为它们可以直接存储文档这类非结构化数据。 尽管名字如此部分 NoSQL 数据库仍允许使用 SQL 语法查询数据。NoSQL 数据库没有预定义的 Schema 限制存储方式而是允许插入任意非结构化数据通常为 JSON 文档。文档可组织进类似计算机文件夹的集合中每个文档可以与其他文档拥有完全不同的字段。仍以农场车队为例部分车辆文档含加速度与速度字段部分含挂车温度字段若新增一种带车载称重装置的卡车IoT 设备只需在文档里添加新字段即可数据库无需任何改动。常见 NoSQL 数据库包括 Azure CosmosDB、MongoDB、CouchDB 等。本课将使用 NoSQL 存储来存放 IoT 数据。二、将 GPS 数据发送到 IoT Hub上一课中设备从 GPS 传感器解析出经纬度。要把这些数据存入云端第一步是发送到 IoT 服务。这里沿用前面项目用过的Azure IoT Hub。实操创建 IoT Hub 并发送 GPS 数据创建免费层 IoT Hub。可参照项目 2 第 4 课《在云端创建 IoT 服务》的说明。建议新建资源组并命名为gps-sensorIoT Hub 名称基于gps-sensor取唯一名例如gps-sensor-your name。 若上一个项目的 IoT Hub 仍在可复用后续创建其他服务时记得沿用该 IoT Hub 名称及其资源组。添加新设备在 IoT Hub 中注册设备并命名为gps-sensor复制该设备的连接字符串。更新设备代码使用上述设备连接字符串连接新 IoT Hub参照项目 2 第 4 课《将设备连接到 IoT 服务》。发送 JSON 格式的 GPS 数据结构如下{ gps : { lat : latitude, lon : longitude } }每分钟发送一次避免耗尽每日消息配额。Wio Terminal 端实现仓库中的 Wio Terminal 设备代码 完整实现了上述流程setup()中初始化串口Serial3与 GPS 模块通过connectWiFi()连接 Wi-Fi凭据在 config.h 中以SSID/PASSWORD占位符配置并用initTime()通过 NTP 服务器校准时间见 ntp.h。构造 JSON 文档的核心代码为DynamicJsonDocument doc(1024); doc[gps][lat] gps.location.lat(); doc[gps][lon] gps.location.lng();loop()中先用while (Serial3.available() 0) { send_gps_data(); }确保读完串口缓冲区的全部 NMEA 数据后再发送当前位置最后调用work_delay(60000)实现 60 秒间隔。发送动作经由 AzureIoTHub SDK 的sendTelemetry()完成main.cpp。依赖库清单在 platformio.ini 中声明包括 ArduinoJson 6.17.3、AzureIoTHub 1.6.0、TinyGPSPlus 1.0.2 等。Raspberry Pi 与虚拟 IoT 设备Pi 设备代码 与虚拟设备代码 结构一致用pynmea2.parse()解析 NMEA 句子仅在GGA句式中提取经纬度并用dm_to_sd()将度分格式转为十进制度南纬/西经取负值。随后按 JSON 格式发送message_json { gps : { lat:lat, lon:lon } } print(Sending telemetry, message_json) message Message(json.dumps(message_json))主循环同样是“读完串口全部行 time.sleep(60)”app.py。注意虚拟设备需在虚拟环境中安装counterfit_connection、counterfit_shims_serial、pynmea2、azure-iot-device等依赖。运行设备代码后用az iot hub monitor-eventsCLI 命令确认消息已流入 IoT Hub。三、热路径、温路径与冷路径从 IoT 设备流向云端的数据并非全部需要实时处理有的要实时响应有的可以稍后处理有的则可以长期沉淀。按处理时延的不同数据流可分为热路径Hot path、温路径Warm path、冷路径Cold path路径处理时延典型用途数据去向热路径实时/近实时告警如车辆接近仓库、冷藏车温度过高云服务收到事件后立即响应温路径收到后不久日报、短期分析如基于前一天数据的车辆里程日报存入可快速访问的存储冷路径长期年度里程报告、路线分析以降低油耗数据仓库Data Warehouse冷路径数据通常存放在数据仓库——为存放海量且永不变更、可被快速查询的数据而设计的数据库。一般会在云应用中设置定期作业每天/每周/每月把数据从温路径存储搬入数据仓库。✅ 思考你在前几课捕获的数据分别属于哪条路径本课数据属于温路径数据落库后将在下一课用于路线报告与可视化。四、用 Serverless 代码处理 GPS 事件数据流入 IoT Hub 后可以编写 Serverless 代码监听Event Hub 兼容端点发布的事件——这就是温路径数据将被存储供下一课汇报行程使用。实操创建事件触发器函数用 Azure Functions CLI 创建 Python 运行时函数应用项目文件夹与项目名均为gps-trigger并创建虚拟环境。可参照项目 2 第 5 课《创建 Serverless 应用》。添加使用 IoT Hub Event Hub 兼容端点的IoT Hub 事件触发器可参照项目 2 第 5 课《创建 IoT Hub 事件触发器》。仓库中 function.json 展示了绑定配置的关键{ scriptFile: __init__.py, bindings: [ { type: eventHubTrigger, name: events, direction: in, eventHubName: samples-workitems, connection: IOT_HUB_CONNECTION_STRING, cardinality: many, consumerGroup: $Default, dataType: binary } ] }其中connection指向配置项键名cardinality: many表示批处理接收多个事件dataType: binary表示事件体按二进制处理。 3. 在 local.settings.json 中设置 Event Hub 兼容端点连接字符串并在function.json中使用对应键名{ IsEncrypted: false, Values: { FUNCTIONS_WORKER_RUNTIME: python, AzureWebJobsStorage: UseDevelopmentStoragetrue, IOT_HUB_CONNECTION_STRING: connection string, STORAGE_CONNECTION_STRING: connection string } }使用Azurite作为本地存储模拟器对应AzureWebJobsStorage: UseDevelopmentStoragetrue。保持设备持续发送 GPS 数据运行函数应用验证事件接收Python EventHub trigger processed an event: {gps: {lat: 47.73481, lon: -122.25701}}五、Azure 存储账户四种存储类型Azure 存储账户是一个通用存储服务可同时以Blob、队列、表、文件四种方式存储数据。Blob 存储Blob意为二进制大对象binary large objects如今泛指任意非结构化数据。Blob 存储可存放任何数据——从包含 IoT 数据的 JSON 文档到图片、电影文件。它有容器container的概念命名桶类似关系数据库的表容器内可以有多个文件夹文件夹可嵌套如同计算机硬盘上的文件结构。本课将使用 Blob 存储存放 IoT 数据。表存储表存储用于存储半结构化数据。它本质上是 NoSQL 数据库无需预先定义表集合但数据仍组织在一个或多个表中并以唯一键标识每行。队列存储队列存储允许在队列中存放最大 64KB的消息。消息从队尾追加、从队头读取。只要还有存储空间队列可以无限期保存消息因此支持长期暂存后按需处理。例如想每月跑一次 GPS 数据处理任务可以每天把数据加入队列攒一个月月末一次性从队列消费全部消息。文件存储文件存储是在云端存放文件的服务任何应用或设备都能用行业标准协议接入。可以把文件写入文件存储后作为驱动器挂载到 PC 或 Mac。六、将 Serverless 代码连接到存储函数应用现在需要连接 Blob 存储来保存来自 IoT Hub 的消息。有两条路径在函数代码内使用 Blob 存储 Python SDK 连接并写入 Blob使用输出绑定output binding把函数返回值绑定到 Blob 存储由平台自动保存。本课采用方式 1Python SDK以便直观理解与 Blob 存储的交互作业部分则要求调研方式 2。落库数据将以如下 JSON Blob 格式保存{ device_id: device_id, timestamp : time, gps : { lat : latitude, lon : longitude } }实操连接函数代码到 Blob 存储创建 Azure 存储账户命名为gpsyour name之类。可参照项目 2 第 5 课《创建云资源》上一个项目的存储账户可复用后续也会用它部署函数应用。获取连接字符串az storage account show-connection-string --output table \ --name storage_name在local.settings.json中新增键STORAGE_CONNECTION_STRING填入上一步的值。在 requirements.txt 中添加依赖并在虚拟环境安装azure-storage-blob若安装报错先在虚拟环境中升级 Pippip install --upgrade pip再重试。在触发器函数的__init__.py顶部添加导入仓库中init.py 已给出完整实现import json import os import uuid from azure.storage.blob import BlobServiceClient, PublicAccess各模块职责json用于读写 JSONos用于读取连接字符串uuid用于生成 GPS 读数唯一 IDazure.storage.blob提供 Blob 存储 Python SDK。在main方法之前添加容器辅助函数def get_or_create_container(name): connection_str os.environ[STORAGE_CONNECTION_STRING] blob_service_client BlobServiceClient.from_connection_string(connection_str) for container in blob_service_client.list_containers(): if container.name name: return blob_service_client.get_container_client(container.name) return blob_service_client.create_container(name, public_accessPublicAccess.Container)说明Python Blob SDK 没有“不存在则创建容器”的便捷方法。该函数从local.settings.json云端部署后为 Application Settings读取连接字符串创建BlobServiceClient与存储账户交互遍历账户全部容器查找同名容器找到则返回对应的ContainerClient用于创建 Blob未找到则创建新容器并返回其客户端。新建容器时授予公开访问权限供下一课在地图上可视化 GPS 数据使用。与土壤湿度场景不同这里每个事件都要保存因此在for event in events:循环内、logging语句下方添加device_id event.iothub_metadata[connection-device-id] blob_name f{device_id}/{str(uuid.uuid1())}.json这段代码从事件元数据取设备 ID并据此构造 Blob 名。Blob 支持文件夹结构设备 ID 作为文件夹名使每台设备的所有 GPS 事件归入同一文件夹Blob 名为“文件夹 文档名”以正斜杠分隔类似 Linux/macOS 路径文档名由uuid模块生成的唯一 ID 加.json后缀构成。例如设备gps-sensor的 Blob 名可能为gps-sensor/a9487ac2-b9cf-11eb-b5cd-1e00621e3648.json。在其下方添加container_client get_or_create_container(gps-data) blob container_client.get_blob_client(blob_name)通过get_or_create_container辅助函数获取gps-data容器的客户端再按 Blob 名获取 Blob 客户端对象可指向已有 Blob也可如本例指向新 Blob。继续添加event_body json.loads(event.get_body().decode(utf-8)) blob_body { device_id : device_id, timestamp : event.iothub_metadata[enqueuedtime], gps: event_body[gps] }构造写入 Blob 存储的正文包含设备 ID、遥测进入 IoT Hub 的时间enqueued time以及遥测中的 GPS 坐标。 必须使用消息的enqueued time入队时间而非当前时间以还原消息真实发送时刻——若函数应用当时未运行消息可能已在 Hub 上停留一段时间。最后添加写入逻辑logging.info(fWriting blob to {blob_name} - {blob_body}) blob.upload_blob(json.dumps(blob_body).encode(utf-8))运行函数应用输出中应看到所有 GPS 事件对应的 Blob 写入记录[2021-05-21T01:31:14.325Z] Python EventHub trigger processed an event: {gps: {lat: 47.73092, lon: -122.26206}} ... [2021-05-21T01:31:14.351Z] Writing blob to gps-sensor/4b6089fe-ba8d-11eb-bc7b-1e00621e3648.json - {device_id: gps-sensor, timestamp: 2021-05-21T00:57:53.878Z, gps: {lat: 47.73092, lon: -122.26206}} 注意不要与az iot hub monitor-events监控同时运行。完整实现见仓库 code/functions 目录。实操验证已上传的 Blob查看已创建的 Blob 有两种方式Azure Storage Explorer免费工具可查看与管理存储账户或 CLI。使用 CLI 的步骤获取账户密钥az storage account keys list --output table \ --account-name storage_name复制输出中的key1值。列出容器中的 Blobaz storage blob list --container-name gps-data \ --output table \ --account-name storage_name \ --account-key key1输出示例Name Blob Type Blob Tier Length Content Type Last Modified Snapshot ---------------------------------------------------- ----------- ----------- -------- ------------------------ ------------------------- ---------- gps-sensor/1810d55e-b9cf-11eb-9f5b-1e00621e3648.json BlockBlob Hot 45 application/octet-stream 2021-05-21T00:54:2700:00 gps-sensor/18293e46-b9cf-11eb-9f5b-1e00621e3648.json BlockBlob Hot 45 application/octet-stream 2021-05-21T00:54:2800:00 gps-sensor/1844549c-b9cf-11eb-9f5b-1e00621e3648.json BlockBlob Hot 45 application/octet-stream 2021-05-21T00:54:2800:00 gps-sensor/1894d714-b9cf-11eb-9f5b-1e00621e3648.json BlockBlob Hot 45 application/octet-stream 2021-05-21T00:54:2800:00下载单个 Blobaz storage blob download --container-name gps-data \ --account-name storage_name \ --account-key key1 \ --name blob_name \ --file file_nameblob_name需包含上一步Name列的完整名称含文件夹前缀file_name为本地保存路径。下载后可用 VS Code 打开 JSON 文件内容应包含 GPS 位置详情{device_id: gps-sensor, timestamp: 2021-05-21T00:57:53.878Z, gps: {lat: 47.73092, lon: -122.26206}}实操将函数应用部署到云端本地验证成功后即可部署创建新的 Azure Functions 应用使用之前创建的存储账户命名类似gps-sensor-unique如随机单词或你的名字参照项目 2 第 5 课《创建云资源》。上传IOT_HUB_CONNECTION_STRING与STORAGE_CONNECTION_STRING到 Application Settings参照项目 2 第 5 课《上传 Application Settings》。部署本地函数应用到云端参照项目 2 第 5 课《部署函数应用》。部署后函数从 Application Settings 读取两个连接字符串与本地行为一致。七、挑战应对 GPS 定位误差GPS 数据并非绝对精确定位可能偏差数米在隧道与高楼密集区误差更大。思考卫星导航系统是如何克服这一问题的你的导航设备掌握了哪些数据能让它对当前位置做出更准确的预测八、作业调研函数绑定函数绑定Function bindings允许代码通过从main函数返回值即可把 Blob 保存到 Blob 存储——存储账户、容器等细节配置在function.json中。作业要求阅读 Azure Functions 绑定文档独立配置 Blob 输出绑定让函数返回的 Blob 成功写入存储。建议阅读的文档页Azure Functions 触发器与绑定概念、Azure Blob 存储绑定概览、Azure Blob 存储输出绑定。评估标准assignment.md标准优秀合格待改进配置 Blob 存储输出绑定成功配置输出绑定返回 Blob 并成功写入存储配置了输出绑定或返回了 Blob但未能成功写入存储未能配置输出绑定回顾与自学结构化数据、半结构化数据与非结构化数据的定义与差异Azure Storage 及其四种存储类型Blob、表、队列、文件的适用场景本课核心链路GPS 设备 → IoT HubEvent Hub 兼容端点→ Azure FunctionsEvent Hub 触发器→ Azure Blob Storage按设备分文件夹的 JSON Blob。本课全部代码与配置均可在仓库3-transport/lessons/2-store-location-data/code/下找到设备端见wio-terminal、pi、virtual-device云端见functions。下一课将基于这些落库的 GPS 数据在地图上可视化卡车的完整行程。【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考