c# - 将设备到云消息从 Azure IoT 中心路由到 Azure Blob 存储

标签 c# azure azure-blob-storage iot azure-iot-hub

我有一个 IoT 设备每 5 分钟向 Azure IoT 中心发送一次消息。我想将每条消息保存在 Azure Blob 存储容器中。在 azure 门户内的消息路由部分中,我创建了一条像这样的新路由。 New route in Azure IoT Hub 接下来,我创建了一个像这样的自定义端点: Custom endpoint 通过这样做,我可以将消息保存在 Blob 存储中。 我想做的是创建一条动态路线。我希望每条发送的消息都保存在此路径中:{iothub}/{deviceId}/{messageParameter}/{partition}/{YYYY}/{MM}/{DD}/{HH}/{mm } 其中 deviceId 是在 Azure IoT 中心注册的设备的名称,customValue 是 IoT 设备发送到 Azure 的 json 消息中的属性值物联网中心。 这是我用来发送消息的代码:

public class Sender : ISender
  {
    private static DeviceClient _deviceClient;

    public void SendDeviceToCloudMessage(string deviceId, string iotHubUri, string deviceKey, string message)
    {
      _deviceClient = DeviceClient.Create(iotHubUri,
        new DeviceAuthenticationWithRegistrySymmetricKey(deviceId, deviceKey), TransportType.Mqtt);

      var twin = _deviceClient.GetTwinAsync().ConfigureAwait(false).GetAwaiter().GetResult();
      var desiredProperties = twin.Properties.Desired;
      var messageObj = JObject.Parse(message);
      if (desiredProperties.Contains("TelemetryData"))
      {
        var telemetryData = (TwinCollection)desiredProperties["TelemetryData"];
        telemetryData["Temperature"] = messageObj["Temperature"];
        telemetryData["Humidity"] = messageObj["Humidity"];
        telemetryData["TimeStamp"] = messageObj["TimeStamp"];
      }
      else
      {
        var telemetryData = new TwinCollection();
        telemetryData["Temperature"] = messageObj["Temperature"];
        telemetryData["Humidity"] = messageObj["Humidity"];
        telemetryData["TimeStamp"] = messageObj["TimeStamp"];
        desiredProperties["TelemetryData"] = telemetryData;
      }

      // Update the reported properties with the updated desired properties
      var reportedProperties = new TwinCollection();
      reportedProperties["TelemetryData"] = desiredProperties["TelemetryData"];
      _deviceClient.UpdateReportedPropertiesAsync(reportedProperties).ConfigureAwait(false).GetAwaiter().GetResult();

      using var iotMessage = new Message(Encoding.UTF8.GetBytes(message))
      {
        ContentEncoding = "utf-8",
        ContentType = "application/json",
      };

      // Submit the message to the hub.
      _deviceClient.SendEventAsync(iotMessage).ConfigureAwait(false).GetAwaiter().GetResult();
    }
  }

message 输入是一个 json 字符串,如下所示:

{
  "Temperature": 20,
  "Humidity": 50,
  "TimeStamp": "2023-02-26 14:02:59.7715110 +00:00",
  "MessageId": "MessageIdentifier"
}

这可能吗?或者我需要手动将消息保存在 Azure Blob 存储容器中?

注意:我的目标是保存设备发送的消息,然后能够读取特定设备发送的消息(因此我将 deviceId 放在路径中)相关在发送的消息中找到的特定参数(messageParameter)

最佳答案

正如答案所提到的,Blob 存储的自定义终结点中没有满足您需求的内置 IoT 中心功能。以下示例显示了一种解决方法,其中使用 Azure 事件网格发布/订阅模型将设备遥测数据推送到 Blob 存储:

enter image description here

订阅者是一个 Azure EventGridTrigger 函数,用于处理 blob 名称等。

#r "Newtonsoft.Json"
#r "System.Text.Json"
#r "Azure.Storage.Blobs"
#r "System.Memory.Data"
#r "Azure.Core"

using System;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Microsoft.Extensions.Logging;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Specialized;
using Azure.Storage.Blobs.Models;
using System.Collections.Generic;

public static async Task Run(JObject eventGridEvent, BlobContainerClient blobContainer, ILogger log)
{
    log.LogInformation(eventGridEvent.ToString());

    string iothubname = eventGridEvent["data"]?["properties"]?["iothubname"]?.Value<string>() ?? "unknown";
    string deviceId = eventGridEvent["data"]?["systemProperties"]?["iothub-connection-device-id"]?.Value<string>() ?? "unknown";
    DateTime dt = eventGridEvent["data"]?["systemProperties"]?["iothub-enqueuedtime"]?.Value<DateTime>() ?? default(DateTime);
      
    string blobName = $"{iothubname}/{deviceId}/{dt.ToString("yyyy/MM/dd/HH/mm/ss")}.json";
    log.LogInformation($"blobname = {blobName}"); 

    var tags = new Dictionary<string, string>();
    tags.Add("iothubname", iothubname);
    tags.Add("deviceId", deviceId);
    tags.Add("value", "CustomValue");

    var blobClient = blobContainer.GetBlobClient(blobName);
    await blobClient.UploadAsync(BinaryData.FromString(eventGridEvent["data"]?["body"]?.ToString() ?? eventGridEvent.ToString() ), overwrite: true);
    //blobClient.SetTags(tags);   // option for 'blob index tags'
}

请注意,Azure IoT 中心路由消息可以通过设备孪生中的有用值(例如 $twin.tags.field 或 $twin.properties.desired.value)进行丰富,并在订阅者中将它们用作一部分blob 名称或 blob 索引标记中。

关于c# - 将设备到云消息从 Azure IoT 中心路由到 Azure Blob 存储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75578380/

相关文章:

c# - P/Invoke 到 Mono 上动态加载的库

c# - 如何根据元素的值将xml反序列化为派生类?

c# - 如何取消 Azure 主题中的预定消息

android - 如何使用 Unity 3D 在 Android 应用程序运行时从云/WEB 访问纹理/模型?

c# - 如何查找文件是系统文件还是隐藏文件?

c# - 具有自定义角色授权的 ASP.Net Core 3.0 Windows 身份验证

sql-server - Sqoop从hive导出到sql被卡住

azure - 如何从 azure-active-directory 获取具有特定组声明的 token

c# - 无法以编程方式下载文件 (C#)

c# - 从 blobBaseClient.DownloadToAsync 获取 FullContent